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.

diff --git a/doc/user/sansdoc.tgz b/doc/user/sansdoc.tgz new file mode 100644 index 00000000..ebc3db41 Binary files /dev/null and b/doc/user/sansdoc.tgz differ diff --git a/doc/user/sansdocbook.xml b/doc/user/sansdocbook.xml index 9f02cdc6..dfa4329f 100644 --- a/doc/user/sansdocbook.xml +++ b/doc/user/sansdocbook.xml @@ -38,15 +38,33 @@ Switzerland + + + + Dr + Ronny + Vavrin + +
+ + Paul Scherrer Institute PSI + LNS, Laboratory for Neutron Scattering + + Villigen + 5232 + Switzerland +
+
+ 20.April 2007 + Abstract - This manual describes how to set up the small angle neutron scattering instrument at - the SINQ spallation source at PSI and gives a short remainder of important command. - This document can be downloaded - http://sans.web.psi.ch/SANSDoc/SANSDoc.ps.gz - as a gzipped postscript file. + This manual describes how to set up the small angle neutron scattering (SANS) instrument at + the SINQ spallation source at PSI and gives a short reminder of important commands. + This document can be + downloaded as a pdf file. @@ -163,41 +181,6 @@ Executing a macro - - - - FileEval <file> - - - - executes the script in the file <file> (needs absolute path). - - - - - - - BatchRoot [<path>] - - - - defines directory for script files executed by BatchRun. - - - - - - - Batchrun <filename> - - - - executes script file <filename> - located in directory defined by BatchRoot. - - - - exe BatchPath [<path>] @@ -216,8 +199,8 @@ executes script file <filename> - located in directory defined by exe BatchPath. Compared to - BatchRun, this command allows enhanced batch control through + located in directory defined by exe BatchPath. This command + allows enhanced batch control through the SICSBatchEditor. @@ -225,12 +208,36 @@ - Clientput <text> + ClientPut <text> writes <text> - to client. + to the client in which this command was written. + + + + + + + BroadCast <text> + + + + writes <text> + to all clients. + + + + + + + in a terminal window: sanscheck <filename> + + + + checks the batchfile <filename> + for errors and calculates the total of Monis to be measured. @@ -1366,106 +1373,6 @@ -
- Sample holder for electro magnet - - - - - - mz - - - - motor for vertical movement (z). - - - - - - - mom - - - - motor for rotation around vertical axis (omega). - - - - - - - msh [z=<val1>] [omega=<val2>] - - - - is a special SANS command for controlling both axes of the magnet sample holder together. - - - - - - -
-
- Haake temperature controller - - - - - - inihaakearray eimer lnsa10 4000 1 - - - - - evfactory new temperature tcl eimer - - - - initialisation sequence. - - - - - - - temperature - - - - is a valid sample environment device if initialised as above. - - - - - - - temperature list - - - - overview of the temperature controller parameters. Use 'emon unregister temperature' - to avoid out of range error messages. - - - - - - - temperature sensor <val> - - - - selects the controlling sensor. <val> can be - intern or extern. - - - - - - -
Bruker electro magnet @@ -1569,6 +1476,104 @@
+
+ Sample holder for electro magnet + + + + + + mz + + + + motor for vertical movement (z). + + + + + + + mom + + + + motor for rotation around vertical axis (omega). + + + + + + + msh [z=<val1>] [omega=<val2>] + + + + is a special SANS command for controlling both axes of the magnet sample holder together. + + + + + + +
+
+ Haake C25P temperature controller + + + + + + start_sea + + + + + starts the sea server from SICS. + + + + + + + temperature + + + + reads out the current temperature. + + + + + + + drive temperature <val> + + + + changes the set temperature of the thermostat to the value <val>. + + + + + + + in a terminal window: sea + + + + + starts the sea server client from a terminal. Choose Haake as device. The sea server client is the + best way to control and monitor the thermostat manually. Please refer to the + + SEA Wiki page for more information. + + + + + + +
Eurotherm controller @@ -1617,12 +1622,6 @@
-
- ITC-4 and ITC-503 temperature controllers - - *outdated controllers, will be replaced* - -
Analogue and digital input and output @@ -2154,6 +2153,65 @@
+
+ Useful commands + + + + + + gc <measMonis> <totalCounts> + + + + GuessCount: executes a measurement of <measMonis> Monis and extrapolates the measurement time and Monis + for a final value of <totalCounts> counts. A useful tool to estimate the measurement time for a sample. Example: + gc 5 1E7 forces the instrument to measures for 5 Monis and estimates the measurement + time and Monis for 10'000'000 counts. + + + + + + + qrange [x <detdist>] [wl <lambda>] + + + + calculates the q range of the current setting. The detector distance x (in mm) and the wavelength wl + (in nm) can be varied with the optional parameters. Examples: qrange prints the q range of the current + setting, qrange x 6000 wl 0.8 prints the q range of the current + setting with forced values for the detector distance (6000mm) and the wavelength (0.8nm). + + + + + + + sinq + + + + prints the SINQ status in the SICS client which issued the command. + + + + + + + in a terminal window: sanscheck <filename> + + + + checks the batchfile <filename> + for errors and calculates the total of Monis to be measured. + + + + + + +
@@ -2418,8 +2476,7 @@ Define the directory, where you intend to store your batch - files with batchroot /data/lnsg/<username>[/<batchdir>] - resp. with + files with exe batchpath /data/lnsg/<username>[/<batchdir>]. @@ -2553,61 +2610,14 @@ SICS has a built in macro facility. This macro facility is aimed at instrument managers and users alike. Instrument managers may provide customised measurement procedures in this language, users may write batch files in this language. - The macro language is John Ousterhout's - http://cseng.awl.com/authordetail.qry?AuthorID=69 - - Tool Command Language (TCL) http://www.tcltk.com - . + The macro language is + + John Ousterhout's + + Tool Command Language (TCL). A set of important Tcl commands are described in section . - To execute batch files three commands are available: + To execute batch files, the following commands are available: - - - FileEval <batchfile> - - - - This command tries to open the file - batchfile and executes the - script in this file. If not an absolute path name is defined - the SICS server will search in the directory - /home/SANS/bin. However, you - don't have privileges to save files in this directory. For - executing batch files located in a directory of your choice - the commands BatchRoot and - BatchRun resp. - exe BatchPath and - exe are available. - - - - - - BatchRoot [<pathname>] - - - - By this command the directory name, in which SICS is searching - for a batch file, is stored in the SICS variable - BatchRoot. Calling - BatchRoot without parameters - will return the actual contents of the variable. - - - - - - BatchRun <filename> - - - - This command tries to open the file filename - located in the directory defined by - BatchRoot and executes the - script in this file. - - - exe BatchPath [<pathname>] @@ -2631,15 +2641,15 @@ This command tries to open the file filename located in the directory defined by exe BatchPath and executes the - script in this file. Compared to BatchRun, - this command allows enhanced batch control through the + script in this file. + This command allows enhanced batch control through the SICSBatchEditor. If you want to print information from a macro script to a client (about the progress of - the batch job for example), a special command is available: + the batch job for example), special commands are available: @@ -2652,8 +2662,36 @@ + + + BroadCast some text ... + + + + This command writes everything after BroadCast + to all clients. + + + + To check a batchfile for errors and to estimate the total Monis to be measured, a special program + can be executed in a terminal window. Navigate to the folder containing the batchfile and execute + the following command + + + + in a terminal window: sanscheck <filename> + + + + checks the batchfile <filename> + for errors and calculates the total of Monis to be measured. + + + + +
Logging the executed commands @@ -3490,20 +3528,18 @@
TCL command language interface - The macro language implemented in the SICS server is John Ousterhout's - http://cseng.awl.com/authordetail.qry?AuthorID=69 - Tool Command Language (TCL) - http://www.tcltk.com - . Tcl has control constructs, variables of its own, loop constructs, - associative arrays and procedures. Tcl is well documented by several books - http://www.cica.indiana.edu/cica/faq/tcl/tcl.html - , online tutorials and manuals - http://www.scriptics.com/man/tcl8.0/contents.htm - . For getting further - informations on Tcl have a look on the TCL WWW Infohttp://www.sco.com/Technology/tcl/Tcl.html - - of Tcl Web serverhttp://www.tcltk.com - . All SICS commands are + The macro language implemented in the SICS server is + + John Ousterhout's Tool Command Language (TCL). + Tcl has control constructs, variables of its own, loop constructs, + associative arrays and procedures. Tcl is well documented by several + books, + online tutorials and manuals. + For getting further + informations on Tcl have a look on the + TCL WWW Info + of + Tcl Web server. All SICS commands are available in the macro language. Some potentially harmful Tcl commands have been deleted from the standard Tcl interpreter. These are: exec, source, puts, @@ -3511,9 +3547,9 @@ gets and socket. Below only a small subset of the most important Tcl commands like assigning variables, evaluating expressions, control and loop constructs are - described. For complete description of Tcl command have a look on the manual - http://www.scriptics.com/man/tcl8.0/contents.htm - pages or on one of the many books about Tcl/Tk. + described. For complete description of Tcl command have a look on the + manual pages or on one of + the many books about Tcl/Tk.
@@ -4111,7 +4147,7 @@ while {$x<10} { </para> </section> <section> - <title>Change the collimation + Changing the collimation @@ -4299,7 +4335,7 @@ bs x = 2 y ++10 - bsfree + bscfree is a manager command, which releases the beam stop motors, @@ -4343,6 +4379,50 @@ bs x = 2 y ++10
+ +
+ Calculating the q range + The q range of the current setting can comfortably be calculated with the following command: + + + + qrange [x <detdist>] [wl <lambda>] + + + + calculates the q range of the current setting. The detector distance x (in mm) and the wavelength wl + (in nm) can be varied with the optional parameters. Examples: qrange prints the q range of the current + setting, qrange x 6000 wl 0.8 prints the q range of the current + setting with forced values for the detector distance (6000mm) and the wavelength (0.8nm). + + + + + +
+ +
+ Estimating the measurement time + The measurement time of a sample depends on many factors and needs to be estimated for each + sample individually. This procedure is simplified with the command GuessCount. + + + + gc <measMonis> <totalCounts> + + + + GuessCount: executes a measurement of <measMonis> Monis and extrapolates the measurement time and Monis + for a final value of <totalCounts> counts. Example: + gc 5 1E7 forces the instrument to measures for 5 Monis and estimates the measurement + time and Monis for 10'000'000 counts. + + + + + +
+
@@ -4463,53 +4543,6 @@ st pos P1 P1 to bring the sample in position.
-
- Haake temperature controller - - This is sort of a buck full of water equipped with a temperature control system. - The RS-232 interface of this device can only be operated at 4800 baud max. This is - why it has to be connected to the serial printer port of the Macintosh serial port - server computer. This makes the channel number to use for initialisation a 1 always. - The driver for this device has been realised in the Tcl extension language of the - SICS server. A prerequisite for the usage of this device is that the file - hakle.tcl is sourced in the SICS initialisation - file and the command inihaakearray has been - published. Installing the Haake into SICS requires two steps: first create an - array with initialisation parameters, second install the device with - evfactory. A command procedure is supplied for - the first step. Thus the initialisation sequence becomes: - - -inihaakearray <name-of-array> <macintosh-computer> <name> <port> <channel> -evfactory new temperature tcl <name-of-array> - - - An example for the SANS: - - -inihaakearray eimer lnsa10.psi.ch 4000 1 -evfactory new temperature tcl eimer - - - Following this, the thermostat can be controlled with the other environment - control commands. - - - The Haake Thermostat understands a single special subcommand: - sensor. The thermostat may be equipped with an - external sensor for controlling and reading. The subcommand - sensor allows to switch between the two. The - exact syntax is: - - -temperature sensor <val> - - - <val> can be either - intern or - extern. - -
Bruker electromagnet @@ -4668,6 +4701,72 @@ msh.omega = 0.000000 about special SANS commands.
+
+ Haake C25P temperature controller + + This is sort of a bucket full of water equipped with a temperature control system. + It is connected with a blue ethernet cable to the port nr. 8 of the SANS terminal. The + SEA software written by Markus Zolliker is the best way to control and monitor the + thermostat manually; it is started from a terminal window with sea. + Please refer to the + + SEA Wiki page for more information. + + + To add an external Pt100 sensor, plug in the sensor and restart the thermostat and the sea client (choose + 'Haake' as device and check the box 'has sample sensor'). If the external sensor should be used as + reference to control the thermostat, check the box 'control on sample'. + + + + + start_sea + + + + + starts the sea server from SICS. + + + + + + + temperature + + + + reads out the current temperature. + + + + + + + drive temperature <val> + + + + changes the set temperature of the thermostat to the value <val>. + + + + + + + in a terminal window: sea + + + + + starts the sea server client from a terminal. Choose Haake as device. + + + + + + +
Eurotherm temperature controller @@ -4709,11 +4808,6 @@ EVFactory new temperature euro lnsa10.psi.ch 4000 13
-
- ITC-4 and ITC-503 temperature controller - *outdated controllers, will be replaced* - -
@@ -5260,7 +5354,20 @@ EVFactory new temperature euro lnsa10.psi.ch 4000 13
Status of the actual acquisition process - empty + A + webpage + with the actual instrument status is available (only inside the PSI network). + + + sinq + + + prints the SINQ status in the SICS client which issued the command. + + + + +
@@ -5268,16 +5375,27 @@ EVFactory new temperature euro lnsa10.psi.ch 4000 13 Other programs
- PSI2HMI - empty + Grasp + Grasp stands for 'Graphical Reduction and Analysis SANS Program for Matlab' which was developed + by Charles Dewhurst at the Institut Laue-Langevin (ILL) in Grenoble, France. Please refer to the + Grasp webpage. +
BerSANS software package - The Manual of the BerSANS Software Package is available in pdf format as well as a zipped pdf file. + The BerSANS data reduction software has been developed by Uwe Keiderling at the Hahn-Meitner-Institut + (HMI) in Berlin, Germany. + The Manual of the BerSANS Software Package can be + downloaded + as pdf file. +
- sasfit program - empty + SASfit program + SASfit for analyzing and plotting small angle scattering data has been written by Joachim + Kohlbrecher at the Paul Scherrer Institute (PSI) in Villigen, Switzerland. Please refer to the + SASfit webpage. +
diff --git a/doc/user/tasub.htm b/doc/user/tasub.htm index 130cb29e..d5308ebf 100644 --- a/doc/user/tasub.htm +++ b/doc/user/tasub.htm @@ -16,9 +16,9 @@ On a triple axis instrument the parameters incoming energy, Q-position in 3D and Q-E variables ei, ki, ef, kf, en, qh, qk and ql can be driven as virtual motors in SICS.

-

Commands understood by Tasub

+

Commands understood by Tasub

-

Monochromator and Analyzer Parameters +

Monochromator and Analyzer Parameters

Incident and scattered energies are defined by monochromator crystals. In order for the calculations to work, some parameters need to be configured. Monochromator and analyzer @@ -87,6 +87,8 @@ In order to calculate a UB matrix a list of reflections must be maintained. This have the correct angular difference to a previous reflection. This is a help for setting up the instrument or running powder mode. When a UB has been generated from auxiliary reflections, a3, sgu and sgl angles will be incorrect. +

tasub repref id qh qk ql a3 a4 sgu sgl ei ef +
Modifies the reflection with id id to have the values given.

Calculations

diff --git a/drive.c b/drive.c index 4e92e307..ef076664 100644 --- a/drive.c +++ b/drive.c @@ -39,11 +39,10 @@ #include #include #include -#include #include "fortify.h" #include "sics.h" #include "drive.h" -#include "nserver.h" /* for SicsWait */ +#include "nserver.h" /* for SicsWait */ #include "drive.h" #include "splitter.h" #include "status.h" @@ -51,476 +50,412 @@ #include "motor.h" /*---------------------------------------------------------------------------*/ - int Drive(SConnection *pCon, SicsInterp *pInter, char *name, float fNew) - { - CommandList *pObject = NULL; - pObjectDescriptor pDes = NULL; - pIDrivable pInt = NULL; - Dummy *pDum; - char pBueffel[512]; - int iRet; - float fDelta, fPos; - long lTime; - - assert(pCon); - assert(pInter); - - /* check if user is allowed to drive */ - if(!SCMatchRights(pCon,usUser)) - { - sprintf(pBueffel,"Insuficient Privilege to drive %s", - name); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* first try to find the thing to drive */ - pObject = FindCommand(pInter,name); - if(!pObject) - { - sprintf(pBueffel,"Cannot find %s to drive ", name); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* get the Descriptor, this RELIES on the descriptor being the first - thing in the struct - */ - pDum = (Dummy *)pObject->pData; - pDes = pDum->pDescriptor; - if(!pDes) - { - sprintf(pBueffel,"%s is NOT drivable!",pDes->name); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* both scanable and drivable objects can be driven, check this - and act accordingly - */ +int Drive(SConnection * pCon, SicsInterp * pInter, char *name, float fNew) +{ + CommandList *pObject = NULL; + pObjectDescriptor pDes = NULL; + pIDrivable pInt = NULL; + Dummy *pDum; + char pBueffel[512]; + int iRet; + float fDelta, fPos; + long lTime; - pInt = pDes->GetInterface(pDum,DRIVEID); - if(!pInt) - { - sprintf(pBueffel,"%s is NOT drivable!",pDes->name); - SCWrite(pCon,pBueffel,eError); - return 0; - } - if(pInt) - { - iRet = pInt->CheckLimits(pDum,fNew,pBueffel,511); - if(!iRet) - { - SCWrite(pCon,pBueffel,eError); - SCSetInterrupt(pCon,eAbortOperation); - return 0; - } - iRet = StartDevice(GetExecutor(),name,pDes,pDum,pCon,fNew); - if(!iRet) - { - sprintf(pBueffel,"ERROR: cannot start device %s",name); - SCWrite(pCon,pBueffel,eError); - return 0; - } + assert(pCon); + assert(pInter); - /* wait for finish */ - iRet = Wait4Success(GetExecutor()); - fPos = pInt->GetValue(pDum,pCon); - if(iRet == DEVINT) - { - if(SCGetInterrupt(pCon) == eAbortOperation) - { - SCSetInterrupt(pCon,eContinue); - sprintf(pBueffel,"Driving %s aborted at %9.3f",name, fPos); - SCWrite(pCon,pBueffel,eStatus); - } - return 0; - } - else if(iRet == DEVDONE) - { - sprintf(pBueffel,"Driving %s to %9.3f done", name, fPos); - SCWrite(pCon,pBueffel,eStatus); - return 1; - } - else - { - sprintf(pBueffel, - "Driving %s finished with problems, position: %9.3f",name,fPos); - SCWrite(pCon,pBueffel,eStatus); - return 1; - } - } - sprintf(pBueffel,"%s is NOT drivable",pDes->name); - SCWrite(pCon,pBueffel,eError); + /* check if user is allowed to drive */ + if (!SCMatchRights(pCon, usUser)) { + snprintf(pBueffel, 511, "Insuficient Privilege to drive %s", name); + SCWrite(pCon, pBueffel, eError); return 0; - } -/*---------------------------------------------------------------------------*/ - int Start2Run(SConnection *pCon, SicsInterp *pInter, char *name, float fNew) - { - CommandList *pObject = NULL; - pObjectDescriptor pDes = NULL; - pIDrivable pInt = NULL; - Dummy *pDum; - char pBueffel[512]; - int iRet; - float fDelta; - long lTime; - - assert(pCon); - assert(pInter); - - /* check if user is allowed to drive */ - if(!SCMatchRights(pCon,usUser)) - { - sprintf(pBueffel,"Insuficient Privilege to drive %s", - name); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* first try to find the thing to drive */ - pObject = FindCommand(pInter,name); - if(!pObject) - { - sprintf(pBueffel,"Cannot find %s to drive ", name); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* get the Descriptor, this RELIES on the descriptor being the first - thing in the struct - */ - pDum = (Dummy *)pObject->pData; - pDes = pDum->pDescriptor; - if(!pDes) - { - sprintf(pBueffel,"%s is NOT drivable!",pDes->name); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* Only drivable objects can be driven, check this - and act accordingly - */ - pInt = pDes->GetInterface(pDum,DRIVEID); - if(!pInt) - { - sprintf(pBueffel,"%s is NOT drivable!",pDes->name); - SCWrite(pCon,pBueffel,eError); - return 0; - } - if(pInt) - { - iRet = pInt->CheckLimits(pDum,fNew,pBueffel,511); - if(!iRet) - { - SCWrite(pCon,pBueffel,eError); - SCSetInterrupt(pCon,eAbortOperation); - return 0; - } - iRet = StartDevice(GetExecutor(),name,pDes,pDum,pCon,fNew); - if(!iRet) - { - return 0; - } - else - { - return 1; - } - } - else - { - sprintf(pBueffel,"%s is NOT drivable",pDes->name); - SCWrite(pCon,pBueffel,eError); + } + + /* first try to find the thing to drive */ + pObject = FindCommand(pInter, name); + if (!pObject) { + snprintf(pBueffel,511, "Cannot find %s to drive ", name); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* get the Descriptor, this RELIES on the descriptor being the first + thing in the struct + */ + pDum = (Dummy *) pObject->pData; + pDes = pDum->pDescriptor; + if (!pDes) { + snprintf(pBueffel,511, "%s is NOT drivable!", pDes->name); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* both scanable and drivable objects can be driven, check this + and act accordingly + */ + + pInt = pDes->GetInterface(pDum, DRIVEID); + if (!pInt) { + snprintf(pBueffel,511, "%s is NOT drivable!", pDes->name); + SCWrite(pCon, pBueffel, eError); + return 0; + } + if (pInt) { + iRet = pInt->CheckLimits(pDum, fNew, pBueffel, 511); + if (!iRet) { + SCWrite(pCon, pBueffel, eLogError); + SCSetInterrupt(pCon, eAbortOperation); return 0; - } - } + } + iRet = StartDevice(GetExecutor(), name, pDes, pDum, pCon, RUNDRIVE, fNew); + if (!iRet) { + snprintf(pBueffel,511, "ERROR: cannot start device %s", name); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* wait for finish */ + iRet = Wait4Success(GetExecutor()); + fPos = pInt->GetValue(pDum, pCon); + if (iRet == DEVINT) { + if (SCGetInterrupt(pCon) == eAbortOperation) { + SCSetInterrupt(pCon, eContinue); + snprintf(pBueffel, 511, "Driving %s aborted at %9.3f", name, fPos); + SCWrite(pCon, pBueffel, eError); + } + return 0; + } else if (iRet == DEVDONE) { + snprintf(pBueffel, 511, "Driving %s to %9.3f done", name, fPos); + SCWrite(pCon, pBueffel, eValue); + return 1; + } else { + snprintf(pBueffel, 511, + "Driving %s finished with problems, position: %9.3f", name, + fPos); + SCWrite(pCon, pBueffel, eValue); + return 1; + } + } + snprintf(pBueffel, 511, "%s is NOT drivable", pDes->name); + SCWrite(pCon, pBueffel, eError); + return 0; +} + +/*---------------------------------------------------------------------------*/ +int Start2Run(SConnection * pCon, SicsInterp * pInter, char *name, + int level, float fNew) +{ + CommandList *pObject = NULL; + pObjectDescriptor pDes = NULL; + pIDrivable pInt = NULL; + Dummy *pDum; + char pBueffel[512]; + int iRet; + float fDelta; + long lTime; + float target; + + assert(pCon); + assert(pInter); + + /* check if user is allowed to drive */ + if (!SCMatchRights(pCon, usUser)) { + snprintf(pBueffel,511, "Insuficient Privilege to drive %s", name); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* first try to find the thing to drive */ + pObject = FindCommand(pInter, name); + if (!pObject) { + snprintf(pBueffel,511, "Cannot find %s to drive ", name); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* get the Descriptor, this RELIES on the descriptor being the first + thing in the struct + */ + pDum = (Dummy *) pObject->pData; + pDes = pDum->pDescriptor; + if (!pDes) { + snprintf(pBueffel,511, "%s is NOT drivable!", pDes->name); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* Only drivable objects can be driven, check this + and act accordingly + */ + pInt = pDes->GetInterface(pDum, DRIVEID); + if (!pInt) { + snprintf(pBueffel,511, "%s is NOT drivable!", pDes->name); + SCWrite(pCon, pBueffel, eError); + return 0; + } + if (pInt) { + iRet = pInt->CheckLimits(pDum, fNew, pBueffel, 511); + if (!iRet) { + SCWrite(pCon, pBueffel, eError); + SCSetInterrupt(pCon, eAbortOperation); + return 0; + } + iRet = StartDevice(GetExecutor(), name, pDes, pDum, pCon,level, fNew); + if (!iRet) { + return 0; + } else { + return 1; + } + } else { + snprintf(pBueffel,511, "%s is NOT drivable", pDes->name); + SCWrite(pCon, pBueffel, eError); + return 0; + } +} + /*------------------------------------------------------------------------- This is meant to be called specially from DriveWrapper at a stage when we already know, that name is a drivable motor. Thus no error checking is performed. Do not use this in any other context!!!! */ - static float findPosition(SicsInterp *pSics, SConnection *pCon, char *name) - { - CommandList *pObject = NULL; - pObjectDescriptor pDes = NULL; - pIDrivable pInt = NULL; - Dummy *pDum = NULL; - pMotor pMot = NULL; - float fPos; - int iRet; - char pBueffel[132]; +static float findPosition(SicsInterp * pSics, SConnection * pCon, + char *name) +{ + CommandList *pObject = NULL; + pObjectDescriptor pDes = NULL; + pIDrivable pInt = NULL; + Dummy *pDum = NULL; + pMotor pMot = NULL; + float fPos; + int iRet; + char pBueffel[132]; - /* - treat motors separately in order to correct for zero points - Sighh......... - */ - pMot = FindMotor(pSics,name); - if(pMot != NULL) - { - iRet = MotorGetSoftPosition(pMot,pCon,&fPos); - if(iRet) - { - return fPos; - } - else - { - return -999.; - } + /* + treat motors separately in order to correct for zero points + Sighh......... + */ + pMot = FindMotor(pSics, name); + if (pMot != NULL) { + iRet = MotorGetSoftPosition(pMot, pCon, &fPos); + if (iRet) { + return fPos; + } else { + return -999.; } - - pObject = FindCommand(pSics,name); - if(pObject) - { - pDum = (Dummy *)pObject->pData; - if(pDum) - { - pDes = pDum->pDescriptor; - if(pDes) - { - pInt = pDes->GetInterface(pDum,DRIVEID); - if(!pInt) - { - sprintf(pBueffel, - "ERROR: internal error in findPosition for %s", - name); - SCWrite(pCon,pBueffel,eError); - return -999.99; - } - else - { - return pInt->GetValue(pDum,pCon); - } - } - } - } - return -999.99; } -/*--------------------------------------------------------------------------*/ - int DriveWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - Tcl_Interp *tcl_interp; - int iRet,i; - double dTarget; - char pBueffel[512]; - Status eOld; - - assert(pCon); - assert(pSics); - tcl_interp = InterpGetTcl(pSics); - /* check Status */ - eOld = GetStatus(); - - - argtolower(argc,argv); - /* check no of args */ - if(argc < 3) - { - sprintf(pBueffel,"Insufficient number of args. Usage %s name val", - argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* check authorisation */ - if(!SCMatchRights(pCon,usUser)) - { - SCWrite(pCon, - "ERROR: You are not authorized to use the drive command",eError); - return 0; - } - - /* interprete arguments as pairs name value and try to start */ - SetStatus(eDriving); - for(i = 1; i < argc; i+=2) { - if(argv[i+1] == NULL) - { - sprintf(pBueffel,"ERROR: no value found for driving %s", - argv[i]); - SCWrite(pCon,pBueffel,eError); - SetStatus(eOld); - return 0; - } - iRet = Tcl_GetDouble(tcl_interp, argv[i+1], &dTarget); - if (iRet == TCL_ERROR) { - SCWrite(pCon, Tcl_GetStringResult(tcl_interp), eError); - SetStatus(eOld); - return 0; - } else if (!isfinite(dTarget)) { - sprintf(pBueffel,"ERROR: target %s value for %s is not a finite number", - argv[i+1], argv[i]); - SCWrite(pCon,pBueffel,eError); - SetStatus(eOld); - return 0; - } - } - for(i = 1; i < argc; i+=2) { - iRet = Tcl_GetDouble(tcl_interp, argv[i+1], &dTarget); - if (iRet == TCL_ERROR) { - SCWrite(pCon, Tcl_GetStringResult(tcl_interp), eError); - SetStatus(eOld); - return 0; - } - iRet = Start2Run(pCon,pSics,argv[i],dTarget); - if(!iRet) - { - sprintf(pBueffel,"ERROR: cannot run %s to %s",argv[i],argv[i+1]); - SCWrite(pCon,pBueffel,eError); - StopExe(GetExecutor(),"ALL"); - SetStatus(eOld); - return 0; - } - } - - /* wait for completion */ - iRet = Wait4Success(GetExecutor()); - - /* print positions */ - for(i = 1; i < argc; i += 2) - { - sprintf(pBueffel,"New %s position: %9.3f",argv[i], - findPosition(pSics,pCon,argv[i])); - SCWrite(pCon,pBueffel,eValue); + pObject = FindCommand(pSics, name); + if (pObject) { + pDum = (Dummy *) pObject->pData; + if (pDum) { + pDes = pDum->pDescriptor; + if (pDes) { + pInt = pDes->GetInterface(pDum, DRIVEID); + if (!pInt) { + snprintf(pBueffel,131, + "ERROR: internal error in findPosition for %s", name); + SCWrite(pCon, pBueffel, eError); + return -999.99; + } else { + return pInt->GetValue(pDum, pCon); + } } - - /* check the completion status */ - if(!(eOld == eScanning || eOld == eBatch)) - { - eOld = eEager; - } - if(iRet == DEVERROR) - { - sprintf(pBueffel,"Driving finished with problem"); - SCWrite(pCon,pBueffel,eError); - ClearExecutor(GetExecutor()); - SetStatus(eOld); - return 0; - } - else if(iRet == DEVINT) - { - sprintf(pBueffel,"ERROR: Driving Interrupted!"); - SCWrite(pCon,pBueffel,eError); - ClearExecutor(GetExecutor()); - SetStatus(eOld); - return 0; - } - SCWrite(pCon,"Driving finished sucessfully",eStatus); - SetStatus(eOld); - return 1; - } -/*---------------------------------------------------------------------------*/ - int RunWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - Tcl_Interp *tcl_interp; - int iRet, i; - double dTarget; - char pBueffel[512]; - Status eOld; - - assert(pCon); - assert(pSics); - tcl_interp = InterpGetTcl(pSics); - /* check Status */ - eOld = GetStatus(); - - - /* check no of args */ - if(argc < 3) - { - sprintf(pBueffel,"Insufficient number of args. Usage %s name val", - argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* check authorisation */ - if(!SCMatchRights(pCon, usUser)) - { - SCWrite(pCon, - "ERROR: You are not authorized to use the drive command",eError); - return 0; - } - - /* interprete arguments as pairs name value and try to start */ - SetStatus(eDriving); - for(i = 1; i < argc; i+=2) { - if(argv[i+1] == NULL) - { - sprintf(pBueffel,"ERROR: no value found for driving %s", - argv[i]); - SCWrite(pCon,pBueffel,eError); - SetStatus(eOld); - return 0; - } - iRet = Tcl_GetDouble(tcl_interp, argv[i+1], &dTarget); - if (iRet == TCL_ERROR) { - SCWrite(pCon, Tcl_GetStringResult(tcl_interp), eError); - SetStatus(eOld); - return 0; - } else if (!isfinite(dTarget)) { - sprintf(pBueffel,"ERROR: target value %s for %s is not a finite number", - argv[i+1], argv[i]); - SCWrite(pCon,pBueffel,eError); - SetStatus(eOld); - return 0; - } - } - for(i = 1; i < argc; i+=2) { - iRet = Tcl_GetDouble(tcl_interp, argv[i+1], &dTarget); - if (iRet == TCL_ERROR) { - SCWrite(pCon, Tcl_GetStringResult(tcl_interp), eError); - SetStatus(eOld); - return 0; - } - iRet = Start2Run(pCon,pSics,argv[i],dTarget); - if(!iRet) - { - sprintf(pBueffel,"ERROR: cannot run %s to %s",argv[i],argv[i+1]); - SCWrite(pCon,pBueffel,eError); - StopExe(GetExecutor(),"ALL"); - SetStatus(eOld); - return 0; - } - } - return 1; -} -/*---------------------------------------------------------------------------*/ - int MakeDrive(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - int iRet; - char pBueffel[512]; - - assert(pCon); - assert(pSics); - - if(argc > 1) - { - iRet = AddCommand(pSics,argv[1], DriveWrapper,NULL,NULL); - } else { - iRet = AddCommand(pSics,"drive", DriveWrapper,NULL,NULL); - } - if(!iRet) - { - sprintf(pBueffel,"ERROR: duplicate command drive not created"); - SCWrite(pCon,pBueffel,eError); - return 0; - } - if(argc > 2) - { - iRet = AddCommand(pSics,argv[2], RunWrapper,NULL,NULL); - } else { - iRet = AddCommand(pSics,"run", RunWrapper,NULL,NULL); - } - if(!iRet) - { - sprintf(pBueffel,"ERROR: duplicate command run not created"); - SCWrite(pCon,pBueffel,eError); - return 0; - } - return 1; } + } + return -999.99; +} +/*--------------------------------------------------------------------------*/ +int DriveWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + Tcl_Interp *tcl_interp; + int iRet, i; + double dTarget; + char pBueffel[512]; + Status eOld; + char *error = NULL; + + assert(pCon); + assert(pSics); + tcl_interp = InterpGetTcl(pSics); + + /* check Status */ + eOld = GetStatus(); + + + argtolower(argc, argv); + /* check no of args */ + if (argc < 3) { + snprintf(pBueffel, 511,"Insufficient number of args. Usage %s name val", + argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* check authorisation */ + if (!SCMatchRights(pCon, usUser)) { + SCWrite(pCon, + "ERROR: You are not authorized to use the drive command", + eError); + return 0; + } + + /* interprete arguments as pairs name value and try to start */ + SetStatus(eDriving); + for (i = 1; i < argc; i += 2) { + if (argv[i + 1] == NULL) { + snprintf(pBueffel, 511, "ERROR: no value found for driving %s", argv[i]); + SCWrite(pCon, pBueffel, eError); + SetStatus(eOld); + return 0; + } + iRet = Tcl_GetDouble(tcl_interp, argv[i + 1], &dTarget); + if (iRet == TCL_ERROR) { + SCWrite(pCon, Tcl_GetStringResult(tcl_interp), eError); + StopExe(GetExecutor(), "ALL"); + SetStatus(eOld); + return 0; + } + iRet = Start2Run(pCon, pSics, argv[i], RUNDRIVE, dTarget); + if (!iRet) { + error = Tcl_GetStringResult(tcl_interp); + if(error != NULL) { + snprintf(pBueffel, 511,"%s", error); + } else { + snprintf(pBueffel, 511,"ERROR: cannot run %s to %s", argv[i], + argv[i + 1]); + } + SCWrite(pCon, pBueffel, eError); + StopExe(GetExecutor(), "ALL"); + SetStatus(eOld); + return 0; + } + } + + /* wait for completion */ + iRet = Wait4Success(GetExecutor()); + + /* print positions */ + for (i = 1; i < argc; i += 2) { + snprintf(pBueffel,511, "New %s position: %9.3f", argv[i], + findPosition(pSics, pCon, argv[i])); + SCWrite(pCon, pBueffel, eValue); + } + + /* check the completion status */ + if (!(eOld == eScanning || eOld == eBatch)) { + eOld = eEager; + } + if (iRet == DEVERROR) { + sprintf(pBueffel, "Driving finished with problem"); + SCWrite(pCon, pBueffel, eError); + ClearExecutor(GetExecutor()); + SetStatus(eOld); + return 0; + } else if (iRet == DEVINT) { + sprintf(pBueffel, "ERROR: Driving Interrupted!"); + SCWrite(pCon, pBueffel, eError); + ClearExecutor(GetExecutor()); + SetStatus(eOld); + return 0; + } + SCWrite(pCon, "Driving finished sucessfully", eValue); + SetStatus(eOld); + return 1; +} + +/*---------------------------------------------------------------------------*/ +int RunWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + Tcl_Interp *tcl_interp; + int iRet, i; + double dTarget; + char pBueffel[512]; + Status eOld; + + assert(pCon); + assert(pSics); + tcl_interp = InterpGetTcl(pSics); + /* check Status */ + eOld = GetStatus(); + + + /* check no of args */ + if (argc < 3) { + snprintf(pBueffel,511, "Insufficient number of args. Usage %s name val", + argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* check authorisation */ + if (!SCMatchRights(pCon, usUser)) { + SCWrite(pCon, + "ERROR: You are not authorized to use the drive command", + eError); + return 0; + } + + /* interprete arguments as pairs name value and try to start */ + SetStatus(eDriving); + for (i = 1; i < argc; i += 2) { + if (argv[i + 1] == NULL) { + snprintf(pBueffel,511, "ERROR: no value found for driving %s", argv[i]); + SCWrite(pCon, pBueffel, eError); + SetStatus(eOld); + return 0; + } + iRet = Tcl_GetDouble(tcl_interp, argv[i + 1], &dTarget); + if (iRet == TCL_ERROR) { + SCWrite(pCon, Tcl_GetStringResult(tcl_interp), eError); + StopExe(GetExecutor(), "ALL"); + SetStatus(eOld); + return 0; + } + iRet = Start2Run(pCon, pSics, argv[i], RUNRUN, dTarget); + if (!iRet) { + snprintf(pBueffel, 511, "ERROR: cannot run %s to %s", argv[i], + argv[i + 1]); + SCWrite(pCon, pBueffel, eError); + StopExe(GetExecutor(), "ALL"); + SetStatus(eOld); + return 0; + } + } + return 1; +} + +/*---------------------------------------------------------------------------*/ +int MakeDrive(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + int iRet; + char pBueffel[512]; + + assert(pCon); + assert(pSics); + + if (argc > 1) { + iRet = AddCommand(pSics, argv[1], DriveWrapper, NULL, NULL); + } else { + iRet = AddCommand(pSics, "drive", DriveWrapper, NULL, NULL); + } + if (!iRet) { + sprintf(pBueffel, "ERROR: duplicate command drive not created"); + SCWrite(pCon, pBueffel, eError); + return 0; + } + if (argc > 2) { + iRet = AddCommand(pSics, argv[2], RunWrapper, NULL, NULL); + } else { + iRet = AddCommand(pSics, "run", RunWrapper, NULL, NULL); + } + if (!iRet) { + sprintf(pBueffel, "ERROR: duplicate command run not created"); + SCWrite(pCon, pBueffel, eError); + return 0; + } + return 1; +} diff --git a/drive.h b/drive.h index 0b3a690b..06c7d10f 100644 --- a/drive.h +++ b/drive.h @@ -9,29 +9,29 @@ #ifndef SICSDRIVE #define SICSDRIVE #include "conman.h" - - int Drive(SConnection *pCon,SicsInterp *pSics, char *name, float fNew); - - int Start2Run(SConnection *pCon, SicsInterp *pSics, char *name, float - fNew); - - int DriveWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - /* - the wrapper function for the drive command - */ - int RunWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - /* - the wrapper function for the run command - */ - - - int MakeDrive(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - /* - the factory function for the Drive & Run command - */ +int Drive(SConnection * pCon, SicsInterp * pSics, char *name, float fNew); + +int Start2Run(SConnection * pCon, SicsInterp * pSics, char *name, + int level, float fNew); + +int DriveWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); + /* + the wrapper function for the drive command + */ + +int RunWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); + /* + the wrapper function for the run command + */ + + +int MakeDrive(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); + /* + the factory function for the Drive & Run command + */ #endif diff --git a/dynstring.c b/dynstring.c index ea9562c1..83977115 100644 --- a/dynstring.c +++ b/dynstring.c @@ -12,296 +12,303 @@ #include #include "dynstring.h" -#define DYNMAGIC 27031998 +#define DYNMAGIC 27031998 /*--------------------------------------------------------------------------*/ - typedef struct __DynString { - int iMAGIC; - char *pBuffer; - int iTextLen; - int iBufferSize; - int iResize; - } DynString; +typedef struct __DynString { + int iMAGIC; + char *pBuffer; + int iTextLen; + int iBufferSize; + int iResize; +} DynString; /*--------------------------------------------------------------------------*/ - pDynString CreateDynString(int iInitial, int iResize) - { - pDynString pNew = NULL; - - if(iInitial <= 0) - iInitial = 512; - if(iResize <= 0) - iResize = 512; - - /* new memory */ - pNew = (pDynString)malloc(sizeof(DynString)); - if(!pNew) - { - return NULL; - } - memset(pNew,0,sizeof(DynString)); - pNew->pBuffer = (char *)malloc(iInitial*sizeof(char)); - if(!pNew->pBuffer) - { - free(pNew); - return NULL; - } - memset(pNew->pBuffer,0,iInitial*sizeof(char)); - - /* initialise the rest */ - pNew->iMAGIC = DYNMAGIC; - pNew->iBufferSize = iInitial; - pNew->iResize = iResize; - pNew->iTextLen = 0; - - return pNew; - } -/*--------------------------------------------------------------------------*/ - static int Resize(pDynString self, int iRequested) - { - char *pNewBuffer; - int iNewSize; - - if(iRequested < self->iBufferSize) - { - return 1; - } - - /* get new data space */ - iNewSize = iRequested + self->iResize; - pNewBuffer = (char *)malloc(iNewSize *sizeof(char)); - if(!pNewBuffer) - { - return 0; - } - memset(pNewBuffer,0,iNewSize); - - /* copy data */ - memcpy(pNewBuffer,self->pBuffer,self->iTextLen); - - /* swap things around */ - if(self->pBuffer) - { - free(self->pBuffer); - } - self->pBuffer = pNewBuffer; - self->iBufferSize = iNewSize; - return 1; - } -/*--------------------------------------------------------------------------*/ - void DeleteDynString(pDynString self) - { - assert(self); - assert(self->iMAGIC == DYNMAGIC); - - if(self->pBuffer) - free(self->pBuffer); - - free(self); - } -/*--------------------------------------------------------------------------*/ - int DynStringClear(pDynString self) - { - assert(self); - assert(self->iMAGIC == DYNMAGIC); - - self->iTextLen = 0; - memset(self->pBuffer,0,self->iBufferSize); - return 1; - } -/*-------------------------------------------------------------------------*/ - int DynStringCopy(pDynString self, char *pText) - { - int iRequested, iRet; +pDynString CreateDynString(int iInitial, int iResize) +{ + pDynString pNew = NULL; - assert(self); - assert(self->iMAGIC == DYNMAGIC); - - iRequested = strlen(pText); - if(iRequested >= self->iBufferSize) - { - iRet = Resize(self,iRequested); - if(!iRet) - { - return 0; - } - } - else /* safety: remove rubbish */ - { - memset(self->pBuffer,0,self->iBufferSize*sizeof(char)); - } - strcpy(self->pBuffer,pText); - self->iTextLen = iRequested; - return 1; - } -/*--------------------------------------------------------------------------*/ - int DynStringConcat(pDynString self, char *pText) - { - int iRequested, iRet; + if (iInitial <= 0) + iInitial = 512; + if (iResize <= 0) + iResize = 512; - assert(self); - assert(self->iMAGIC == DYNMAGIC); - - iRequested = strlen(pText) + self->iTextLen; - if(iRequested >= self->iBufferSize) - { - iRet = Resize(self,iRequested); - if(!iRet) - { - return 0; - } - } - - strcat(self->pBuffer,pText); - self->iTextLen = iRequested; - return 1; - } -/*--------------------------------------------------------------------------*/ - int DynStringConcatChar(pDynString self, char c) - { - int iRequested, iRet; - - assert(self); - assert(self->iMAGIC == DYNMAGIC); - - iRequested = self->iTextLen + 1; - if(iRequested >= self->iBufferSize) - { - iRet = Resize(self,iRequested); - if(!iRet) - { - return 0; - } - } - - self->pBuffer[self->iTextLen] = c; - self->iTextLen++; - return 1; - } -/*---------------------------------------------------------------------------*/ -#if 0 /* to be removed DFC */ - int DynStringInsert(pDynString self, char *pText, int iPos) - { - int iRequested, iRet, iPush, iRest; - char *pPtr; - - assert(self); - assert(self->iMAGIC == DYNMAGIC); - - /* provide space */ - iPush = strlen(pText); - iRequested = self->iTextLen + iPush; - if(iRequested >= self->iBufferSize) - { - iRet = Resize(self,iRequested); - if(!iRet) - { - return 0; - } - } - - /* we need a temporary buffer to hold the backend of the string */ - iRest = self->iTextLen - iPos; - pPtr = (char *)malloc((iRest+10)*sizeof(char)); - if(!pPtr) - { - return 0; - } - memset(pPtr,0,(iRest+10)*sizeof(char)); - strcpy(pPtr,&self->pBuffer[iPos]); - - /* OK build the result string */ - memset(&self->pBuffer[iPos],0,iRest*sizeof(char)); - strcat(self->pBuffer,pText); - strcat(self->pBuffer,pPtr); - free(pPtr); - self->iTextLen = iRequested; - return 1; - } -/*---------------------------------------------------------------------------*/ -#endif - int DynStringInsertWithLen(pDynString self, char *pText, int iPos, int len) - { - int iRequested, iRet, iPush, iRest; - char *pPtr; - - assert(self); - assert(self->iMAGIC == DYNMAGIC); - - /* provide space */ - iPush = len; - iRequested = self->iTextLen + iPush; - if(iRequested >= self->iBufferSize) - { - iRet = Resize(self,iRequested); - if(!iRet) - { - return 0; - } - } - - /* we need a temporary buffer to hold the backend of the string */ - iRest = self->iTextLen - iPos; - pPtr = (char *)malloc((iRest)*sizeof(char)); - if(!pPtr) - { - return 0; - } - memcpy(pPtr, &self->pBuffer[iPos], (iRest)*sizeof(char)); - - /* OK build the result string */ - memcpy(&self->pBuffer[iPos], pText, len*sizeof(char)); - memcpy(&self->pBuffer[iPos + len],pPtr, (iRest)*sizeof(char)); - free(pPtr); - self->iTextLen = iRequested; - return 1; - } -/*---------------------------------------------------------------------------*/ - int DynStringInsert(pDynString self, char *pText, int iPos) - { - return DynStringInsertWithLen(self, pText, iPos, strlen(pText)); + /* new memory */ + pNew = (pDynString) malloc(sizeof(DynString)); + if (!pNew) { + return NULL; } + memset(pNew, 0, sizeof(DynString)); + pNew->pBuffer = (char *) malloc(iInitial * sizeof(char)); + if (!pNew->pBuffer) { + free(pNew); + return NULL; + } + memset(pNew->pBuffer, 0, iInitial * sizeof(char)); + + /* initialise the rest */ + pNew->iMAGIC = DYNMAGIC; + pNew->iBufferSize = iInitial; + pNew->iResize = iResize; + pNew->iTextLen = 0; + + return pNew; +} + /*--------------------------------------------------------------------------*/ - int DynStringReplaceWithLen(pDynString self, char *pText, int iPos, int len) { - int iRequested, iRet; +static int Resize(pDynString self, int iRequested) +{ + char *pNewBuffer; + int iNewSize; - assert(self); - assert(self->iMAGIC == DYNMAGIC); - - iRequested = len + iPos; - if(iRequested >= self->iBufferSize) - { - iRet = Resize(self,iRequested); - if(!iRet) - { - return 0; - } - } - - memcpy(&self->pBuffer[iPos],pText,(1+len)*sizeof(char)); - self->iTextLen = len; + if (iRequested < self->iBufferSize) { return 1; - } - int DynStringReplace(pDynString self, char *pText, int iPos) - { - return DynStringReplaceWithLen(self, pText, iPos, strlen(pText)); - } + } + + /* get new data space */ + iNewSize = iRequested + self->iResize; + pNewBuffer = (char *) malloc(iNewSize * sizeof(char)); + if (!pNewBuffer) { + return 0; + } + memset(pNewBuffer, 0, iNewSize); + + /* copy data */ + memcpy(pNewBuffer, self->pBuffer, self->iTextLen); + + /* swap things around */ + if (self->pBuffer) { + free(self->pBuffer); + } + self->pBuffer = pNewBuffer; + self->iBufferSize = iNewSize; + return 1; +} + +/*--------------------------------------------------------------------------*/ +void DeleteDynString(pDynString self) +{ + assert(self); + assert(self->iMAGIC == DYNMAGIC); + + if (self->pBuffer) + free(self->pBuffer); + + free(self); +} + +/*--------------------------------------------------------------------------*/ +int DynStringClear(pDynString self) +{ + assert(self); + assert(self->iMAGIC == DYNMAGIC); + + self->iTextLen = 0; + memset(self->pBuffer, 0, self->iBufferSize); + return 1; +} + +/*-------------------------------------------------------------------------*/ +int DynStringCopy(pDynString self, char *pText) +{ + int iRequested, iRet; + + assert(self); + assert(self->iMAGIC == DYNMAGIC); + + if(pText == 0){ + return 0; + } + iRequested = strlen(pText); + if (iRequested >= self->iBufferSize) { + iRet = Resize(self, iRequested); + if (!iRet) { + return 0; + } + } else { /* safety: remove rubbish */ + + memset(self->pBuffer, 0, self->iBufferSize * sizeof(char)); + } + strcpy(self->pBuffer, pText); + self->iTextLen = iRequested; + return 1; +} + +/*--------------------------------------------------------------------------*/ +int DynStringConcat(pDynString self, char *pText) +{ + int iRequested, iRet; + + assert(self); + assert(self->iMAGIC == DYNMAGIC); + + iRequested = strlen(pText) + self->iTextLen; + if (iRequested >= self->iBufferSize) { + iRet = Resize(self, iRequested); + if (!iRet) { + return 0; + } + } + + strcpy(self->pBuffer + self->iTextLen, pText); + self->iTextLen = iRequested; + return 1; +} +/*--------------------------------------------------------------------------*/ +int DynStringConcatLine(pDynString self, char *pText) +{ + DynStringConcat(self,pText); + return DynStringConcatChar(self,'\n'); +} + +/*--------------------------------------------------------------------------*/ +int DynStringConcatChar(pDynString self, char c) +{ + int iRequested, iRet; + + assert(self); + assert(self->iMAGIC == DYNMAGIC); + + iRequested = self->iTextLen + 1; + if (iRequested >= self->iBufferSize) { + iRet = Resize(self, iRequested); + if (!iRet) { + return 0; + } + } + + self->pBuffer[self->iTextLen] = c; + self->iTextLen++; + return 1; +} /*---------------------------------------------------------------------------*/ - char *GetCharArray(pDynString self) - { - assert(self); - assert(self->iMAGIC == DYNMAGIC); +int DynStringConcatBytes(pDynString self, char *data, int datalen) +{ + int iRequested, iRet; - return self->pBuffer; - } + assert(self); + assert(self->iMAGIC == DYNMAGIC); + + iRequested = self->iTextLen + datalen; + if (iRequested >= self->iBufferSize) { + iRet = Resize(self, iRequested); + if (!iRet) { + return 0; + } + } + + memcpy(self->pBuffer + self->iTextLen,data,datalen); + self->iTextLen += datalen; + return 1; + +} /*---------------------------------------------------------------------------*/ - int GetDynStringLength(pDynString self) - { - assert(self); - assert(self->iMAGIC == DYNMAGIC); +int DynStringInsert(pDynString self, char *pText, int iPos) +{ + int iRequested, iRet, iPush, iRest; - return self->iTextLen; - } + assert(self); + assert(self->iMAGIC == DYNMAGIC); + /* provide space */ + iPush = strlen(pText); + iRequested = self->iTextLen + iPush; + if (iRequested >= self->iBufferSize) { + iRet = Resize(self, iRequested); + if (!iRet) { + return 0; + } + } + if (iPos >= self->iTextLen) { + iPos = self->iTextLen; + } else { + if (iPos < 0) { + iPos = 0; + } + memmove(&self->pBuffer[iPos + iPush], &self->pBuffer[iPos], self->iTextLen + 1 - iPos); + } + + memcpy(&self->pBuffer[iPos], pText, iPush); + self->iTextLen = iRequested; + return 1; +} +/*--------------------------------------------------------------------------*/ +int DynStringReplace(pDynString self, char *pText, int iPos) +{ + int iRequested, iRet; + assert(self); + assert(self->iMAGIC == DYNMAGIC); + + iRequested = strlen(pText) + iPos; + if (iRequested >= self->iBufferSize) { + iRet = Resize(self, iRequested); + if (!iRet) { + return 0; + } + } + + memcpy(&self->pBuffer[iPos], pText, strlen(pText) * sizeof(char)); + if (iRequested > self->iTextLen) { + self->iTextLen = iRequested; + } + return 1; +} + +/*---------------------------------------------------------------------------*/ +char *GetCharArray(pDynString self) +{ + assert(self); + assert(self->iMAGIC == DYNMAGIC); + + return self->pBuffer; +} + +/*---------------------------------------------------------------------------*/ +int GetDynStringLength(pDynString self) +{ + assert(self); + assert(self->iMAGIC == DYNMAGIC); + + return self->iTextLen; +} + +/*---------------------------------------------------------------------------*/ +int DynStringBackspace(pDynString self) +{ + assert(self); + assert(self->iMAGIC == DYNMAGIC); + + if (self->iTextLen > 0) { + self->pBuffer[self->iTextLen - 1] = '\0'; + self->iTextLen--; + } + return 1; +} +/*---------------------------------------------------------------------------*/ +int DynStringShorten(pDynString self, int length) +{ + assert(self); + assert(self->iMAGIC == DYNMAGIC); + + if (length >= self->iTextLen || length < 0) { + return 0; + } + self->iTextLen = length; + self->pBuffer[length] = '\0'; + return 1; +} +/*---------------------------------------------------------------------------*/ +char *Dyn2Cstring(pDynString self) { + char *result; + + assert(self); + assert(self->iMAGIC == DYNMAGIC); + + result = self->pBuffer; + + free(self); + + return result; +} diff --git a/dynstring.h b/dynstring.h index 32232bfc..be9d90be 100644 --- a/dynstring.h +++ b/dynstring.h @@ -23,80 +23,90 @@ ----------------------------------------------------------------------------*/ #ifndef DYNAMICSTRING #define DYNAMICSTRING - typedef struct __DynString *pDynString; - +typedef struct __DynString *pDynString; + /*----------------------- live and death ----------------------------------*/ - pDynString CreateDynString(int iInitialLength, int iResizeLength); +pDynString CreateDynString(int iInitialLength, int iResizeLength); /* - Create a new DynString Object. Its initial length will be iInitialLength. - It will be resized in iResizeLength steps. This allows for efficient - storage management. It woul be seriously inefficient to allocate - per added character. - */ - - void DeleteDynString(pDynString self); -/*----------------------- interface to it --------------------------------- */ - - int DynStringCopy(pDynString self, char *pText); - - /* - Copies the text in Text into the DynString starting at 0 and over - writing anything there beforehand. - */ - - int DynStringConcat(pDynString self, char *pText); - /* - Concatenates the string in DynString with the one supplied - in string. - */ - - int DynStringConcatChar(pDynString self, char c); - /* - adds one character at the end of the string - */ - - int DynStringInsert(pDynString self, char *pText, int iPos); - - /* - inserts the text in pText at Position iPos in the DynString. - Everything behind iPos will be pushed outwards in order to create - space for pText. - */ - - int DynStringReplace(pDynString self, char *pText, int iPos); - - /* - Starting at iPos, replace everything after it with ptext. In - contrats to insert this won't push data backwards. - */ - - char *GetCharArray(pDynString self); - - /* - retrieves a pointer to the character array keeping the current - text. NEVER, ever free this pointer, otherwise you are rewarded - with a core dump. The pointer belongs to DynString and will be - deleted when deleting the DynString. - */ - - int GetDynStringLength(pDynString self); - - /* - returns the current length of the dynamic string. - */ - - int DynStringClear(pDynString self); - /* - removes all old dat from the dynstring - */ - - int DynStringReplaceWithLen(pDynString self, char *pText, int iPos, int len); - /* - Useful for making dynstrings containing null chars and other non-Ascii chars + Create a new DynString Object. Its initial length will be iInitialLength. + It will be resized in iResizeLength steps. This allows for efficient + storage management. It woul be seriously inefficient to allocate + per added character. */ - - int DynStringInsertWithLen(pDynString self, char *pText, int iPos, int len); - /* - Useful for making dynstrings containing null chars and other non-Ascii chars + +void DeleteDynString(pDynString self); +/*----------------------- interface to it --------------------------------- */ + +int DynStringCopy(pDynString self, char *pText); + + /* + Copies the text in Text into the DynString starting at 0 and over + writing anything there beforehand. */ -#endif + +int DynStringConcat(pDynString self, char *pText); + /* + Concatenates the string in DynString with the one supplied + in string. + */ +int DynStringConcatLine(pDynString self, char *pText); + /* + Concatenates the string in DynString with the one supplied + in string. And add a newline. + */ + +int DynStringConcatChar(pDynString self, char c); + /* + adds one character at the end of the string + */ +int DynStringConcatBytes(pDynString self, char *data, int datalen); +/* + * adds datalen bytes from data to the buffer + */ +int DynStringInsert(pDynString self, char *pText, int iPos); + + /* + inserts the text in pText at Position iPos in the DynString. + Everything behind iPos will be pushed outwards in order to create + space for pText. + */ + +int DynStringReplace(pDynString self, char *pText, int iPos); + + /* + Starting at iPos, replace everything after it with ptext. In + contrats to insert this won't push data backwards. + */ + +char *GetCharArray(pDynString self); + + /* + retrieves a pointer to the character array keeping the current + text. NEVER, ever free this pointer, otherwise you are rewarded + with a core dump. The pointer belongs to DynString and will be + deleted when deleting the DynString. + */ + +int GetDynStringLength(pDynString self); + + /* + returns the current length of the dynamic string. + */ + +int DynStringClear(pDynString self); + /* + removes all old data from the dynstring + */ +int DynStringBackspace(pDynString self); + /* + removes one character at the end from the dynstring + */ +int DynStringShorten(pDynString self, int length); + /* + shorten the dynstring to the given length + */ +char *Dyn2Cstring(pDynString self); + /* + convert to C string and delete dynstring. The result must be freed when no longer used. + */ +#endif diff --git a/ecbcounter.c b/ecbcounter.c index b5d21d95..e616c4d6 100644 --- a/ecbcounter.c +++ b/ecbcounter.c @@ -19,21 +19,21 @@ /*------------------ our private data structure ------------------------*/ typedef struct { - pECB ecb; /* the ECB system we talk to */ - unsigned char prescaler[8]; /* an array for the prescaler values */ - int tfreq; /* timer frequency */ - unsigned char control; /* marks the control monitor */ - int state; /* current counting state */ -}ECBCounter, *pECBCounter; + pECB ecb; /* the ECB system we talk to */ + unsigned char prescaler[8]; /* an array for the prescaler values */ + int tfreq; /* timer frequency */ + unsigned char control; /* marks the control monitor */ + int state; /* current counting state */ +} ECBCounter, *pECBCounter; /*----------------- private defines ------------------------------------*/ #define STFRD 137 #define STREAD 138 -#define STOPS 136 +#define STOPS 136 #define STCLEA 134 #define PRELOA 139 #define STLOAD 156 -#define STCPRE 133 +#define STCPRE 133 #define STARTS 135 #define SPCSTA 169 @@ -42,7 +42,7 @@ typedef struct { #define COUNT 2 #define NOBEAM 3 /*--------------------------------------------------------------------*/ -#define MAX_COUNT 4294967295.0 +#define MAX_COUNT 4294967295.0 /*------------------ error codes --------------------------------------*/ #define COMMERROR -300 #define TOMANYCOUNTS -301 @@ -51,14 +51,15 @@ typedef struct { #define INVALIDPRESCALER -305 #define BADFREQ -306 /*======================================================================*/ -static int readScaler(pECBCounter pPriv, int scaler, int *count){ +static int readScaler(pECBCounter pPriv, int scaler, int *count) +{ int status; Z80_reg in, out; Ecb_pack data; - - in.c = (unsigned char)scaler; - status = ecbExecute(pPriv->ecb,STREAD,in,&out); - if(status != 1){ + + in.c = (unsigned char) scaler; + status = ecbExecute(pPriv->ecb, STREAD, in, &out); + if (status != 1) { return COMMERROR; } @@ -66,111 +67,122 @@ static int readScaler(pECBCounter pPriv, int scaler, int *count){ data.b.byt2 = out.b; data.b.byt1 = out.d; data.b.byt0 = out.e; - if(scaler == 0){ - *count = data.result/pPriv->tfreq; + if (scaler == 0) { + *count = data.result / pPriv->tfreq; } else { *count = data.result; } return 1; } + /*---------------------------------------------------------------------*/ -static int check4Beam(struct __COUNTER *pCter, int *beam){ +static int check4Beam(struct __COUNTER *pCter, int *beam) +{ Z80_reg in, out; pECBCounter self = NULL; int status; - self = (pECBCounter)pCter->pData; + self = (pECBCounter) pCter->pData; assert(self); in.c = 1; - status = ecbExecute(self->ecb,SPCSTA,in,&out); - if(status != 1){ + status = ecbExecute(self->ecb, SPCSTA, in, &out); + if (status != 1) { pCter->iErrorCode = COMMERROR; return HWFault; } - *beam = (int)out.d; + *beam = (int) out.d; return 1; } + /*----------------------------------------------------------------------*/ -static int stopScalers(pECBCounter self){ +static int stopScalers(pECBCounter self) +{ int status; Z80_reg in, out; - status = ecbExecute(self->ecb,STOPS,in,&out); - if(status != 1){ + status = ecbExecute(self->ecb, STOPS, in, &out); + if (status != 1) { return COMMERROR; } return 1; } + /*======================================================================== These two functions currently rely on the idea that the ECB stops and starts without clearing counters in between. The sequence of things necessary to start it, suggests this. If this is not the case then this will not work. ===========================================================================*/ -static int ECBPause(struct __COUNTER *self){ +static int ECBPause(struct __COUNTER *self) +{ int status; pECBCounter pPriv = NULL; assert(self); - pPriv = (pECBCounter)self->pData; + pPriv = (pECBCounter) self->pData; assert(pPriv); - if((status = stopScalers(pPriv)) <= 0){ + if ((status = stopScalers(pPriv)) <= 0) { self->iErrorCode = status; return HWFault; } return OKOK; } + /*=======================================================================*/ -static int ECBContinue(struct __COUNTER *self){ +static int ECBContinue(struct __COUNTER *self) +{ int status; pECBCounter pPriv = NULL; Z80_reg in, out; assert(self); - pPriv = (pECBCounter)self->pData; + pPriv = (pECBCounter) self->pData; assert(pPriv); - status = ecbExecute(pPriv->ecb,STARTS,in,&out); - if(status != 1){ + status = ecbExecute(pPriv->ecb, STARTS, in, &out); + if (status != 1) { self->iErrorCode = status; return HWFault; } return OKOK; } + /*-----------------------------------------------------------------------*/ -static int ECBGetStatus(struct __COUNTER *self, float *fControl){ - pECBCounter pPriv = (pECBCounter)self->pData; +static int ECBGetStatus(struct __COUNTER *self, float *fControl) +{ + pECBCounter pPriv = (pECBCounter) self->pData; int status, result, scaler; Z80_reg in, out; int count, beam; - + assert(pPriv); /* - This can happen after a stop - */ - if(pPriv->state == IDLE){ + This can happen after a stop + */ + if (pPriv->state == IDLE) { + ECBTransfer(self); return HWIdle; } /* - read status bit - */ - status = ecbExecute(pPriv->ecb,STFRD,in,&out); - if(status != 1){ + read status bit + */ + status = ecbExecute(pPriv->ecb, STFRD, in, &out); + if (status != 1) { self->iErrorCode = COMMERROR; pPriv->state = IDLE; return HWFault; } /* - read beam status - */ - status = check4Beam(self,&beam); - if(status != 1){ + read beam status + */ + status = check4Beam(self, &beam); + if (status != 1) { self->iErrorCode = COMMERROR; return HWFault; } @@ -181,24 +193,25 @@ static int ECBGetStatus(struct __COUNTER *self, float *fControl){ the thing can be in. Complicated by the fact that the status becomes idle (out.d = 0) when the measurement is paused due to the lack of beam. - */ - if(pPriv->state == COUNT && beam == 1){ + */ + if (pPriv->state == COUNT && beam == 1) { ECBPause(self); pPriv->state = NOBEAM; SetStatus(eOutOfBeam); result = HWNoBeam; } - if(pPriv->state == NOBEAM && beam == 0){ + if (pPriv->state == NOBEAM && beam == 0) { ECBContinue(self); pPriv->state = COUNT; SetStatus(eCounting); return HWBusy; } - if(pPriv->state == NOBEAM && beam == 1){ + if (pPriv->state == NOBEAM && beam == 1) { return HWNoBeam; } - if(out.d == 0 && pPriv->state == COUNT){ + if (out.d == 0 && pPriv->state == COUNT) { result = HWIdle; + ECBTransfer(self); pPriv->state = IDLE; } else { result = HWBusy; @@ -206,97 +219,106 @@ static int ECBGetStatus(struct __COUNTER *self, float *fControl){ /* - select which scaler to read - */ - if(self->eMode == eTimer){ + select which scaler to read + */ + if (self->eMode == eTimer) { scaler = 0; - }else { + } else { scaler = pPriv->control; } - readScaler(pPriv,scaler,&count); + readScaler(pPriv, scaler, &count); /* - ignore errors on this one - */ - *fControl = (float)count; + ignore errors on this one + */ + *fControl = (float) count; return result; -} +}exit + + /*=====================================================================*/ -static int clearScalers(pECBCounter self){ +static int clearScalers(pECBCounter self) +{ int status; Z80_reg in, out; - status = ecbExecute(self->ecb,STCLEA,in,&out); - if(status != 1){ + status = ecbExecute(self->ecb, STCLEA, in, &out); + if (status != 1) { return COMMERROR; } return 1; } + /*----------------------------------------------------------------------*/ -static int loadPrescalers(pECBCounter self){ +static int loadPrescalers(pECBCounter self) +{ Z80_reg in, out; int status, i; - for(i = 0; i < 8; i++){ - in.c = (unsigned char)i; + for (i = 0; i < 8; i++) { + in.c = (unsigned char) i; in.d = self->prescaler[i]; - status = ecbExecute(self->ecb,PRELOA,in,&out); - if(status != 1){ + status = ecbExecute(self->ecb, PRELOA, in, &out); + if (status != 1) { return COMMERROR; } } return 1; } + /*----------------------------------------------------------------------*/ -static int loadPreset(pECBCounter self, int preset, unsigned char control){ +static int loadPreset(pECBCounter self, int preset, unsigned char control) +{ Z80_reg in, out; Ecb_pack data; int status, i; data.result = preset; - + in.c = data.b.byt3; in.b = data.b.byt2; in.e = data.b.byt1; in.d = data.b.byt0; - status = ecbExecute(self->ecb,STLOAD,in,&out); - if(status != 1){ + status = ecbExecute(self->ecb, STLOAD, in, &out); + if (status != 1) { return COMMERROR; } in.b = data.b.byt2; in.e = data.b.byt1; in.d = data.b.byt0; - in.c = 4*control; - status = ecbExecute(self->ecb,STCPRE,in,&out); - if(status != 1){ + in.c = 4 * control; + status = ecbExecute(self->ecb, STCPRE, in, &out); + if (status != 1) { return COMMERROR; } return 1; } + /*-----------------------------------------------------------------------*/ -static int ECBStart(struct __COUNTER *self){ +static int ECBStart(struct __COUNTER *self) +{ pECBCounter pPriv = NULL; int preset, status, controlUnit; Z80_reg in, out; assert(self); - pPriv = (pECBCounter)self->pData; + pPriv = (pECBCounter) self->pData; assert(pPriv); /* - check if the preset is permissible - */ - preset = (int)rint(self->fPreset); - if(preset > MAX_COUNT){ + check if the preset is permissible + */ + preset = (int) rint(self->fPreset); + if (preset > MAX_COUNT) { self->iErrorCode = TOMANYCOUNTS; return HWFault; } - if(self->eMode == eTimer){ + if (self->eMode == eTimer) { controlUnit = 0; - preset *= pPriv->tfreq; - if(preset > MAX_COUNT){ + preset *= pPriv->tfreq; + if (preset > MAX_COUNT) { self->iErrorCode = TOMANYCOUNTS; return HWFault; } @@ -304,124 +326,133 @@ static int ECBStart(struct __COUNTER *self){ controlUnit = pPriv->control; } - if((status = stopScalers(pPriv)) <= 0){ + if ((status = stopScalers(pPriv)) <= 0) { self->iErrorCode = status; return HWFault; } - if((status = clearScalers(pPriv)) <= 0){ + if ((status = clearScalers(pPriv)) <= 0) { self->iErrorCode = status; return HWFault; } - if((status = loadPrescalers(pPriv)) <= 0){ + if ((status = loadPrescalers(pPriv)) <= 0) { self->iErrorCode = status; return HWFault; } - if((status = loadPreset(pPriv, preset,(unsigned char)controlUnit)) <= 0){ + if ((status = + loadPreset(pPriv, preset, (unsigned char) controlUnit)) <= 0) { self->iErrorCode = status; return HWFault; } - status = ecbExecute(pPriv->ecb,STARTS,in,&out); - if(status != 1){ + status = ecbExecute(pPriv->ecb, STARTS, in, &out); + if (status != 1) { self->iErrorCode = status; return HWFault; } - + pPriv->state = COUNT; return OKOK; } + /*=======================================================================*/ -static int ECBHalt(struct __COUNTER *self){ +static int ECBHalt(struct __COUNTER *self) +{ int status; pECBCounter pPriv = NULL; assert(self); - pPriv = (pECBCounter)self->pData; + pPriv = (pECBCounter) self->pData; assert(pPriv); pPriv->state = IDLE; - if((status = stopScalers(pPriv)) <= 0){ + if ((status = stopScalers(pPriv)) <= 0) { self->iErrorCode = status; return HWFault; } return OKOK; } + /*=======================================================================*/ -static int ECBTransfer(struct __COUNTER *self){ +static int ECBTransfer(struct __COUNTER *self) +{ int status, count, i; pECBCounter pPriv = NULL; assert(self); - pPriv = (pECBCounter)self->pData; + pPriv = (pECBCounter) self->pData; assert(pPriv); /* - read time - */ - status = readScaler(pPriv,0,&count); - if(status <= 0){ + read time + */ + status = readScaler(pPriv, 0, &count); + if (status <= 0) { self->iErrorCode = COMMERROR; return HWFault; } - self->fTime = (float)count; + self->fTime = (float) count; /* - read other scalers - */ - for(i = 1; i < 8; i++){ - status = readScaler(pPriv,i,&count); - if(status <= 0){ + read other scalers + */ + for (i = 1; i < 8; i++) { + status = readScaler(pPriv, i, &count); + if (status <= 0) { self->iErrorCode = COMMERROR; return HWFault; } - self->lCounts[i-1] = count; + self->lCounts[i - 1] = count; } return OKOK; } + /*======================================================================*/ static int ECBGetError(struct __COUNTER *self, int *iCode, - char *errorText, int errlen){ + char *errorText, int errlen) +{ char pBueffel[132]; *iCode = self->iErrorCode; - switch(self->iErrorCode){ + switch (self->iErrorCode) { case COMMERROR: - strncpy(errorText,"Communication error with ECB",errlen); + strlcpy(errorText, "Communication error with ECB", errlen); break; case TOMANYCOUNTS: - strncpy(errorText,"Preset is to high!",errlen); + strlcpy(errorText, "Preset is to high!", errlen); break; case NOSEND: - strncpy(errorText,"Cannot send naked data to ECB",errlen); + strlcpy(errorText, "Cannot send naked data to ECB", errlen); break; case UNKNOWNPAR: - strncpy(errorText,"parameter unknown",errlen); + strlcpy(errorText, "parameter unknown", errlen); break; case INVALIDCOUNTER: - strncpy(errorText,"Invalid counter number requested, 0-7 allowed", - errlen); + strlcpy(errorText, "Invalid counter number requested, 0-7 allowed", + errlen); break; case INVALIDPRESCALER: - strncpy(errorText,"Invalid prescaler value, allowed 1 or 10", - errlen); + strlcpy(errorText, "Invalid prescaler value, allowed 1 or 10", errlen); break; case BADFREQ: - strncpy(errorText,"Bad timer frequency: 10 or 1000 allowed",errlen); + strlcpy(errorText, "Bad timer frequency: 10 or 1000 allowed", errlen); break; default: - sprintf(pBueffel,"Unknown error code %d", self->iErrorCode); - strncpy(errorText,pBueffel,errlen); + sprintf(pBueffel, "Unknown error code %d", self->iErrorCode); + strlcpy(errorText, pBueffel, errlen); break; } return 1; } + /*=======================================================================*/ -static int ECBFixIt(struct __COUNTER *self, int iCode){ +static int ECBFixIt(struct __COUNTER *self, int iCode) +{ return COTERM; } + /*======================================================================*/ /******************************************************************************* @@ -430,72 +461,71 @@ static int ECBFixIt(struct __COUNTER *self, int iCode){ * of f.ex a motor position. 'divide' specifies how many times the po- * sition is to be divided by two before it is displayed. ******************************************************************************/ -static void -Dot_divide (int device, int data, pECB ecb) +static void Dot_divide(int device, int data, pECB ecb) { int function, dot, divide; Z80_reg x_inreg, out; - if (data == 0) /* If zero, dont send dot/divide) */ + if (data == 0) /* If zero, dont send dot/divide) */ return; dot = 0; - while ((data%10) == 0) - { - dot++; - data /= 10; - } + while ((data % 10) == 0) { + dot++; + data /= 10; + } divide = 0; - while ((data%2) == 0) - { - divide++; - data /= 2; - } - if (data != 1) /* If != 1, not a binary No. */ + while ((data % 2) == 0) { + divide++; + data /= 2; + } + if (data != 1) /* If != 1, not a binary No. */ return; if (dot > 0) dot = 8 - dot; - x_inreg.c = 0; /* Specify input */ + x_inreg.c = 0; /* Specify input */ x_inreg.b = (unsigned char) device; - x_inreg.d = (unsigned char) dot; /* Dot position */ - x_inreg.e = (unsigned char) divide; /* No. of times to divide by 2 */ + x_inreg.d = (unsigned char) dot; /* Dot position */ + x_inreg.e = (unsigned char) divide; /* No. of times to divide by 2 */ - ecbExecute(ecb,170,x_inreg,&out); + ecbExecute(ecb, 170, x_inreg, &out); return; } + /*-----------------------------------------------------------------------*/ -static int ECBSet(struct __COUNTER *self, char *name, - int iCter, float fVal){ +static int ECBSet(struct __COUNTER *self, char *name, + int iCter, float fVal) +{ pECBCounter pPriv = NULL; int iVal; assert(self); - pPriv = (pECBCounter)self->pData; + pPriv = (pECBCounter) self->pData; assert(pPriv); - iVal = (int)rint(fVal); + iVal = (int) rint(fVal); - if(strcmp(name,"prescaler") == 0){ - if(iCter < 0 || iCter > 7){ + if (strcmp(name, "prescaler") == 0) { + if (iCter < 0 || iCter > 7) { self->iErrorCode = INVALIDCOUNTER; return HWFault; } - if(iVal != 1 && iVal != 10){ + if (iVal != 1 && iVal != 10) { self->iErrorCode = INVALIDPRESCALER; return HWFault; } - pPriv->prescaler[iCter] = (unsigned char)iVal; + pPriv->prescaler[iCter] = (unsigned char) iVal; return OKOK; - } else if(strcmp(name,"tfreq") == 0){ - if(fVal == 1000){ + } else if (strcmp(name, "tfreq") == 0) { + if (fVal == 1000) { pPriv->prescaler[0] = 1; pPriv->tfreq = 1000; - Dot_divide(64,1000,pPriv->ecb); + Dot_divide(64, 1000, pPriv->ecb); return OKOK; - } else if(fVal == 10){ + } else if (fVal == 10) { pPriv->tfreq = 10; pPriv->prescaler[0] = 10; - Dot_divide(64,10,pPriv->ecb); + Dot_divide(64, 10, pPriv->ecb); return OKOK; } else { self->iErrorCode = BADFREQ; @@ -506,59 +536,65 @@ static int ECBSet(struct __COUNTER *self, char *name, return HWFault; } } + /*===================================================================*/ -static int ECBGet(struct __COUNTER *self, char *name, - int iCter, float *fVal){ +static int ECBGet(struct __COUNTER *self, char *name, + int iCter, float *fVal) +{ pECBCounter pPriv = NULL; assert(self); - pPriv = (pECBCounter)self->pData; + pPriv = (pECBCounter) self->pData; assert(pPriv); - if(strcmp(name,"prescaler") == 0){ - *fVal = (float)pPriv->prescaler[iCter]; + if (strcmp(name, "prescaler") == 0) { + *fVal = (float) pPriv->prescaler[iCter]; return OKOK; - } else if(strcmp(name,"tfreq") == 0){ - *fVal = (float)pPriv->tfreq; + } else if (strcmp(name, "tfreq") == 0) { + *fVal = (float) pPriv->tfreq; return OKOK; - } else{ + } else { self->iErrorCode = UNKNOWNPAR; return HWFault; } -} +} + /*=====================================================================*/ -static int ECBSend(struct __COUNTER *self, char *text, - char *reply, int replylen){ - strncpy(reply,"ECB does not feast on ASCII strings, refused!", - replylen); +static int ECBSend(struct __COUNTER *self, char *text, + char *reply, int replylen) +{ + strlcpy(reply, "ECB does not feast on ASCII strings, refused!", + replylen); return OKOK; } + /*====================================================================*/ -pCounterDriver MakeECBCounter(char *ecb){ +pCounterDriver MakeECBCounter(char *ecb) +{ pECBCounter pPriv = NULL; pCounterDriver self = NULL; int i; /* - memory for everybody - */ - self = CreateCounterDriver("ecb","ecb"); - pPriv = (pECBCounter)malloc(sizeof(ECBCounter)); - if(self == NULL || pPriv == NULL){ + memory for everybody + */ + self = CreateCounterDriver("ecb", "ecb"); + pPriv = (pECBCounter) malloc(sizeof(ECBCounter)); + if (self == NULL || pPriv == NULL) { return NULL; } - memset(pPriv,0,sizeof(ECBCounter)); + memset(pPriv, 0, sizeof(ECBCounter)); /* - initialize private data structure - */ - pPriv->ecb = (pECB)FindCommandData(pServ->pSics,ecb,"ECB"); - if(pPriv->ecb == NULL){ + initialize private data structure + */ + pPriv->ecb = (pECB) FindCommandData(pServ->pSics, ecb, "ECB"); + if (pPriv->ecb == NULL) { DeleteCounterDriver(self); free(pPriv); return NULL; } - for(i = 0; i < 8; i++){ + for (i = 0; i < 8; i++) { pPriv->prescaler[i] = 1; } pPriv->tfreq = 1000; @@ -566,19 +602,19 @@ pCounterDriver MakeECBCounter(char *ecb){ /* - assign function pointers - */ - self->GetStatus = ECBGetStatus; - self->Start = ECBStart; - self->Pause = ECBPause; - self->Continue = ECBContinue; - self->Halt = ECBHalt; - self->ReadValues = ECBTransfer; - self->GetError = ECBGetError; + assign function pointers + */ + self->GetStatus = ECBGetStatus; + self->Start = ECBStart; + self->Pause = ECBPause; + self->Continue = ECBContinue; + self->Halt = ECBHalt; + self->ReadValues = ECBTransfer; + self->GetError = ECBGetError; self->TryAndFixIt = ECBFixIt; - self->Set = ECBSet; - self->Get = ECBGet; - self->Send = ECBSend; + self->Set = ECBSet; + self->Get = ECBGet; + self->Send = ECBSend; self->KillPrivate = NULL; self->pData = pPriv; diff --git a/ecbcounter.h b/ecbcounter.h index eb12145d..cbfad223 100644 --- a/ecbcounter.h +++ b/ecbcounter.h @@ -12,6 +12,6 @@ #include "countdriv.h" pCounterDriver MakeECBCounter(char *ecb); -void KillECBCounter(CounterDriver *pDriv); +void KillECBCounter(CounterDriver * pDriv); #endif diff --git a/ecode.c b/ecode.c index 50c7d552..d8ceb081 100644 --- a/ecode.c +++ b/ecode.c @@ -7,20 +7,19 @@ #ifndef ERRSTAT #define ERRSTAT - static char *pErrStat[] = { - " ", - "OK", - "HWIdle", - "HWBusy", - "HWFault", - "HWPosFault", - "HWCrash", - "Out of memory", - "No Beam", - "Paused", - NULL - }; - - -#endif +static char *pErrStat[] = { + " ", + "OK", + "HWIdle", + "HWBusy", + "HWFault", + "HWPosFault", + "HWCrash", + "Out of memory", + "No Beam", + "Paused", + NULL +}; + +#endif diff --git a/emon.c b/emon.c index 554c90d6..7cbcc702 100644 --- a/emon.c +++ b/emon.c @@ -6,6 +6,8 @@ Mark Koennecke, Juli 1997 + Reduced polling frequency to any 20 seconds, Mark Koennecke, August 2011 + Copyright: Labor fuer Neutronenstreuung @@ -39,343 +41,335 @@ #include #include #include -#include /* for DString */ +#include +#include /* for DString */ #include "fortify.h" #include "lld.h" #include "sics.h" #include "emon.i" #include "emon.h" #include "event.h" -/*--------------------------------------------------------------------------*/ - pEnvMon CreateEnvMon(void) - { - pEnvMon pNew = NULL; - - pNew = (pEnvMon)malloc(sizeof(EnvMon)); - if(!pNew) - { - return NULL; - } - memset(pNew,0,sizeof(EnvMon)); - - pNew->pDes = CreateDescriptor("Environment Monitor"); - if(!pNew->pDes) - { - free(pNew); - return NULL; - } - pNew->iList = LLDcreate(sizeof(EVEntry)); - if(pNew->iList < 0) - { - DeleteDescriptor(pNew->pDes); - free(pNew); - return NULL; - } - return pNew; - } -/*---------------------------------------------------------------------------*/ - void DeleteEnvMon(void *pData) - { - pEnvMon self; - int iRet; - EVEntry sEntry; - - self = (pEnvMon)pData; - assert(self); - - - /* remove all the names */ - iRet = LLDnodePtr2First(self->iList); - while(iRet != 0) - { - LLDnodeDataTo(self->iList,&sEntry); - if(sEntry.pName) - { - free(sEntry.pName); - sEntry.pName = NULL; - } - iRet = LLDnodePtr2Next(self->iList); - } - /* remove list */ - LLDdelete(self->iList); - - /* remove descriptor */ - if(self->pDes) - { - DeleteDescriptor(self->pDes); - } - free(self); - } -/*---------------------------------------------------------------------------*/ - int EVRegisterController(pEnvMon self, char *pName, void *pData, - SConnection *pCon) - { - EVEntry sEntry; - char pBueffel[512]; - - assert(self); - assert(pData); - assert(pCon); - - sEntry.pDum = (pDummy)pData; - sEntry.pInter = sEntry.pDum->pDescriptor->GetInterface(pData, - ENVIRINTERFACE); - if(sEntry.pInter == NULL) - { - sprintf(pBueffel,"ERROR: cannot register %s, no environment interface", - pName); - SCWrite(pCon,pBueffel,eError); - return 0; - } - sEntry.pName = strdup(pName); - - LLDnodeAppendFrom(self->iList,&sEntry); - return 1; - } -/*------------------------------------------------------------------------*/ - int EVUnregister(pEnvMon self, char *pName) - { - EVEntry sEntry; - int iRet; - assert(self); - - iRet = LLDnodePtr2First(self->iList); - while(iRet != 0) - { - LLDnodeDataTo(self->iList, &sEntry); - if(strcmp(sEntry.pName, pName) == 0) - { - free(sEntry.pName); - LLDnodeDelete(self->iList); - return 1; - } - iRet = LLDnodePtr2Next(self->iList); - } - return 0; - } -/*---------------------------------------------------------------------------*/ - static int EVMonitorSingle(pEnvMon self, EVEntry sEntry) - { - EVMode eMode; - int iRet, iStatus; - - eMode = sEntry.pInter->GetMode(sEntry.pDum); - if(eMode == EVMonitor) - { - iRet = sEntry.pInter->IsInTolerance(sEntry.pDum); - if(iRet == 0) - { - iStatus = sEntry.pInter->HandleError(sEntry.pDum); - return 0; - } - } - return 1; - } +/* + * any how many seconds we check + */ +#define SCANINTERVALL 20 /*--------------------------------------------------------------------------*/ - int EVMonitorControllers(pEnvMon self) - { - int iRet, status; - int iRes = 1; - EVEntry sEntry; - - assert(self); - - iRet = LLDnodePtr2First(self->iList); - while(iRet != 0) - { - LLDnodeDataTo(self->iList,&sEntry); - status = EVMonitorSingle(self, sEntry); - if(status != 1) - { - iRes = 0; - } - iRet = LLDnodePtr2Next(self->iList); - } - return iRes; +pEnvMon CreateEnvMon(void) +{ + pEnvMon pNew = NULL; + + pNew = (pEnvMon) malloc(sizeof(EnvMon)); + if (!pNew) { + return NULL; } + memset(pNew, 0, sizeof(EnvMon)); + + pNew->pDes = CreateDescriptor("Environment Monitor"); + if (!pNew->pDes) { + free(pNew); + return NULL; + } + pNew->iList = LLDcreate(sizeof(EVEntry)); + if (pNew->iList < 0) { + DeleteDescriptor(pNew->pDes); + free(pNew); + return NULL; + } + pNew->nextRun = time(NULL)+SCANINTERVALL; + AddCommand(pServ->pSics, "emon", EVWrapper, DeleteEnvMon, pNew); + return pNew; +} + /*---------------------------------------------------------------------------*/ - int EVList(pEnvMon self, SConnection *pCon) - { - int iRet; - float fVal; - Tcl_DString xString, *pResult; - pIDrivable pDriv; - EVEntry sEntry; - EVMode eMode; - char pNumber[30]; - char *pPtr; - - assert(self); - assert(pCon); - - pResult = &xString; - Tcl_DStringInit(pResult); - Tcl_DStringAppend(pResult,"EMON={",-1); - - iRet = LLDnodePtr2First(self->iList); - while(iRet != 0) - { - LLDnodeDataTo(self->iList,&sEntry); - pDriv = sEntry.pDum->pDescriptor->GetInterface(sEntry.pDum, - DRIVEID); - assert(pDriv); /* a controller must have a drivable and - a environment interface! */ - fVal = pDriv->GetValue(sEntry.pDum,pCon); - sprintf(pNumber,",%f,",fVal); - eMode = sEntry.pInter->GetMode(sEntry.pDum); - Tcl_DStringAppend(pResult,sEntry.pName,-1); - Tcl_DStringAppend(pResult,pNumber,-1); - switch(eMode) - { - case EVIdle: - Tcl_DStringAppend(pResult,"Idle",-1); - break; - case EVDrive: - Tcl_DStringAppend(pResult,"Driving",-1); - break; - case EVMonitor: - Tcl_DStringAppend(pResult,"In Monitor",-1); - break; - case EVError: - Tcl_DStringAppend(pResult,"Out of range",-1); - break; - } - Tcl_DStringAppend(pResult,";\n",-1); - iRet = LLDnodePtr2Next(self->iList); - } - Tcl_DStringAppend(pResult,"}",-1); - pPtr = Tcl_DStringValue(pResult); - SCWrite(pCon,pPtr,eValue); - Tcl_DStringFree(pResult); - return 1; +void DeleteEnvMon(void *pData) +{ + pEnvMon self; + int iRet; + EVEntry sEntry; + + self = (pEnvMon) pData; + assert(self); + + + /* remove all the names */ + iRet = LLDnodePtr2First(self->iList); + while (iRet != 0) { + LLDnodeDataTo(self->iList, &sEntry); + if (sEntry.pName) { + free(sEntry.pName); + sEntry.pName = NULL; + } + iRet = LLDnodePtr2Next(self->iList); } + /* remove list */ + LLDdelete(self->iList); + + /* remove descriptor */ + if (self->pDes) { + DeleteDescriptor(self->pDes); + } + free(self); +} + +/*---------------------------------------------------------------------------*/ +int EVRegisterController(pEnvMon self, char *pName, void *pData, + SConnection * pCon) +{ + EVEntry sEntry; + char pBueffel[512]; + + assert(self); + assert(pData); + assert(pCon); + + sEntry.pDum = (pDummy) pData; + sEntry.pInter = sEntry.pDum->pDescriptor->GetInterface(pData, + ENVIRINTERFACE); + if (sEntry.pInter == NULL) { + snprintf(pBueffel,511, + "ERROR: cannot register %s, no environment interface", pName); + SCWrite(pCon, pBueffel, eError); + return 0; + } + sEntry.pName = strdup(pName); + + LLDnodeAppendFrom(self->iList, &sEntry); + return 1; +} + +/*------------------------------------------------------------------------*/ +int EVUnregister(pEnvMon self, char *pName) +{ + EVEntry sEntry; + int iRet; + + assert(self); + + iRet = LLDnodePtr2First(self->iList); + while (iRet != 0) { + LLDnodeDataTo(self->iList, &sEntry); + if (strcmp(sEntry.pName, pName) == 0) { + free(sEntry.pName); + LLDnodeDelete(self->iList); + return 1; + } + iRet = LLDnodePtr2Next(self->iList); + } + return 0; +} + +/*---------------------------------------------------------------------------*/ +static int EVMonitorSingle(pEnvMon self, EVEntry sEntry) +{ + EVMode eMode; + int iRet, iStatus; + + eMode = sEntry.pInter->GetMode(sEntry.pDum); + if (eMode == EVMonitor) { + iRet = sEntry.pInter->IsInTolerance(sEntry.pDum); + if (iRet == 0) { + iStatus = sEntry.pInter->HandleError(sEntry.pDum); + return 0; + } + } + return 1; +} + +/*--------------------------------------------------------------------------*/ +int EVMonitorControllers(pEnvMon self) +{ + int iRet, status; + int iRes = 1; + EVEntry sEntry; + + assert(self); + + iRet = LLDnodePtr2First(self->iList); + while (iRet != 0) { + LLDnodeDataTo(self->iList, &sEntry); + status = EVMonitorSingle(self, sEntry); + if (status != 1) { + iRes = 0; + } + iRet = LLDnodePtr2Next(self->iList); + } + return iRes; +} + +/*---------------------------------------------------------------------------*/ +int EVList(pEnvMon self, SConnection * pCon) +{ + int iRet; + float fVal; + Tcl_DString xString, *pResult; + pIDrivable pDriv; + EVEntry sEntry; + EVMode eMode; + char pNumber[30]; + char *pPtr; + + assert(self); + assert(pCon); + + pResult = &xString; + Tcl_DStringInit(pResult); + Tcl_DStringAppend(pResult, "EMON={", -1); + + iRet = LLDnodePtr2First(self->iList); + while (iRet != 0) { + LLDnodeDataTo(self->iList, &sEntry); + pDriv = sEntry.pDum->pDescriptor->GetInterface(sEntry.pDum, DRIVEID); + assert(pDriv); /* a controller must have a drivable and + a environment interface! */ + fVal = pDriv->GetValue(sEntry.pDum, pCon); + sprintf(pNumber, ",%f,", fVal); + eMode = sEntry.pInter->GetMode(sEntry.pDum); + Tcl_DStringAppend(pResult, sEntry.pName, -1); + Tcl_DStringAppend(pResult, pNumber, -1); + switch (eMode) { + case EVIdle: + Tcl_DStringAppend(pResult, "Idle", -1); + break; + case EVDrive: + Tcl_DStringAppend(pResult, "Driving", -1); + break; + case EVMonitor: + Tcl_DStringAppend(pResult, "In Monitor", -1); + break; + case EVError: + Tcl_DStringAppend(pResult, "Out of range", -1); + break; + } + Tcl_DStringAppend(pResult, ";\n", -1); + iRet = LLDnodePtr2Next(self->iList); + } + Tcl_DStringAppend(pResult, "}", -1); + pPtr = Tcl_DStringValue(pResult); + SCWrite(pCon, pPtr, eValue); + Tcl_DStringFree(pResult); + return 1; +} + /*-------------------------------------------------------------------------- The Environment Monitor understands a few commands: list : list the current state of affairs register name : registers name as a controller to emon unregister name : removes name from emon ----------------------------------------------------------------------------*/ - int EVWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - pEnvMon self = NULL; - char pBueffel[512]; - int iRet; - CommandList *pCom = NULL; - - self = (pEnvMon)pData; - assert(self); - assert(pCon); - assert(pSics); +---------------------------------------------------------------------------*/ +int EVWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pEnvMon self = NULL; + char pBueffel[512]; + int iRet; + CommandList *pCom = NULL; - argtolower(argc,argv); - if(argc < 2) - { - SCWrite(pCon,"ERROR: Insufficient arguments specified for emon",eError); - return 0; - } - - if(strcmp(argv[1],"list") == 0) /* list command */ - { - EVList(self,pCon); - return 1; - } - else if(strcmp(argv[1],"register") == 0) - { - if(argc < 3) - { - SCWrite(pCon,"ERROR: Insufficient arguments specified for emon register",eError); - return 0; - } - if(!SCMatchRights(pCon,usUser)) - { - SCWrite(pCon,"ERROR: Insufficient privilege to register",eError); - return 0; - } - pCom = FindCommand(pSics,argv[2]); - if(!pCom) - { - sprintf(pBueffel,"ERROR: object %s not found, not registered", - argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - return EVRegisterController(self,argv[2],pCom->pData,pCon); - } - else if(strcmp(argv[1],"unregister") == 0) - { - if(argc < 3) - { - SCWrite(pCon,"ERROR: Insufficient arguments specified for emon unregister",eError); - return 0; - } - if(!SCMatchRights(pCon,usUser)) - { - SCWrite(pCon,"ERROR: Insufficient privilege to unregister",eError); - return 0; - } - iRet = EVUnregister(self,argv[2]); - if(!iRet) - { - sprintf(pBueffel,"WARNING: %s not found in emon",argv[2]); - SCWrite(pCon,pBueffel,eWarning); - } - return 1; - } - else - { - sprintf(pBueffel,"ERROR: %s not recognized as command to emon", - argv[1]); - SCWrite(pCon,pBueffel,eError); - } - return 0; - } -/*---------------------------------------------------------------------------*/ - pEnvMon FindEMON(SicsInterp *pSics) - { - CommandList *pCom = NULL; - - assert(pSics); - - pCom = FindCommand(pSics,"emon"); - assert(pCom); - - return (pEnvMon)pCom->pData; + self = (pEnvMon) pData; + assert(self); + assert(pCon); + assert(pSics); + + argtolower(argc, argv); + if (argc < 2) { + SCWrite(pCon, "ERROR: Insufficient arguments specified for emon", + eError); + return 0; } -/*---------------------------------------------------------------------------*/ - int EnvMonTask(void *pData) - { - pEnvMon self = NULL; - - self = (pEnvMon)pData; - assert(self); - - if(self->iEnd) - { + + if (strcmp(argv[1], "list") == 0) { /* list command */ + EVList(self, pCon); + return 1; + } else if (strcmp(argv[1], "register") == 0) { + if (argc < 3) { + SCWrite(pCon, + "ERROR: Insufficient arguments specified for emon register", + eError); return 0; } - - EVMonitorControllers(self); + if (!SCMatchRights(pCon, usUser)) { + SCWrite(pCon, "ERROR: Insufficient privilege to register", eError); + return 0; + } + pCom = FindCommand(pSics, argv[2]); + if (!pCom) { + snprintf(pBueffel,511, "ERROR: object %s not found, not registered", + argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + return EVRegisterController(self, argv[2], pCom->pData, pCon); + } else if (strcmp(argv[1], "unregister") == 0) { + if (argc < 3) { + SCWrite(pCon, + "ERROR: Insufficient arguments specified for emon unregister", + eError); + return 0; + } + if (!SCMatchRights(pCon, usUser)) { + SCWrite(pCon, "ERROR: Insufficient privilege to unregister", eError); + return 0; + } + iRet = EVUnregister(self, argv[2]); + if (!iRet) { + snprintf(pBueffel,511, "WARNING: %s not found in emon", argv[2]); + SCWrite(pCon, pBueffel, eWarning); + } return 1; + } else { + snprintf(pBueffel, 511, "ERROR: %s not recognized as command to emon", + argv[1]); + SCWrite(pCon, pBueffel, eError); } + return 0; +} + +/*---------------------------------------------------------------------------*/ +pEnvMon FindEMON(SicsInterp * pSics) +{ + CommandList *pCom = NULL; + + assert(pSics); + + pCom = FindCommand(pSics, "emon"); + assert(pCom); + + return (pEnvMon) pCom->pData; +} + +/*---------------------------------------------------------------------------*/ +int EnvMonTask(void *pData) +{ + pEnvMon self = NULL; + + self = (pEnvMon) pData; + assert(self); + + if (self->iEnd) { + return 0; + } + + if(time(NULL) > self->nextRun){ + EVMonitorControllers(self); + self->nextRun = time(NULL) + SCANINTERVALL; + } + return 1; +} + /*------------------------------------------------------------------------*/ - void EnvMonSignal(void *pUser, int iSignal, void *pEventData) - { - pEnvMon self = NULL; - int *iInt; - - self = (pEnvMon)pUser; - assert(self); - iInt = (int *)pEventData; - - if(iSignal == SICSINT) - { - iInt = (int *)pEventData; - if(*iInt == eEndServer) - { - self->iEnd = 1; - } - } +void EnvMonSignal(void *pUser, int iSignal, void *pEventData) +{ + pEnvMon self = NULL; + int *iInt; + + self = (pEnvMon) pUser; + assert(self); + iInt = (int *) pEventData; + + if (iSignal == SICSINT) { + iInt = (int *) pEventData; + if (*iInt == eEndServer) { + self->iEnd = 1; + } } - +} diff --git a/emon.h b/emon.h index 816e7428..d1a747d0 100644 --- a/emon.h +++ b/emon.h @@ -1,5 +1,5 @@ -#line 148 "emonitor.w" +#line 149 "emonitor.w" /*-------------------------------------------------------------------------- E N V I R O N M E N T M O N I T O R @@ -17,7 +17,7 @@ typedef struct __EnvMon *pEnvMon; /*-------------------------------------------------------------------------*/ -#line 85 "emonitor.w" +#line 86 "emonitor.w" pEnvMon CreateEnvMon(void); @@ -39,6 +39,6 @@ int EnvMonTask(void *pEv); void EnvMonSignal(void *pEndv, int iSignal, void *pSigData); -#line 164 "emonitor.w" +#line 165 "emonitor.w" #endif diff --git a/emon.i b/emon.i index 1ff51a27..f1754e46 100644 --- a/emon.i +++ b/emon.i @@ -10,6 +10,7 @@ pObjectDescriptor pDes; int iList; int iEnd; + time_t nextRun; } EnvMon; /*---------------------------------------------------------------------------*/ typedef struct { diff --git a/emonitor.tex b/emonitor.tex index afe04077..91803789 100644 --- a/emonitor.tex +++ b/emonitor.tex @@ -18,15 +18,15 @@ maintained. \end{itemize} Controller objects will be able to share some code among them. Each -environment controller will hold a target value, a permissible tolerance, - a selector variable which defines the type of error handling to perform and - an interrupt code to issue when that form of error handling is chosen. +environemnt controller will hold a target value, a permissable tolerance, + a selctor variable which defines the type of error handling to perform and + an interrupt code to issue when that form of error handling is choosen. Furthermore each environment controller needs to implement the drivable interface (for driving to new values) and the environment interface (for - monitoring the controller). Controller objects will also share the error + monitoring the controller). Controller object will also share the error handling during the monitor phase between them. The scheme is that each controller will have a variable which selects the error handling mechanism. Depending on this -variable an error management routine will be invoked. Current two schemes for +variable an error managment routine will be invoked. Current two schemes for handling errors are supported: \begin{itemize} \item Print a warning but do nothing else. @@ -57,7 +57,7 @@ controllers. It will be called from the main loop to check if each registered environment controller is still within tolerances. If not, emon has to enforce error processing. Else it does nothing. -The environment monitor uses the following data structures: +The environment monitor uses the following datastructures: \begin{flushleft} \small \begin{minipage}{\linewidth} \label{scrap1} $\langle$emondat {\footnotesize ?}$\rangle\equiv$ @@ -68,6 +68,7 @@ $\langle$emondat {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ pObjectDescriptor pDes;@\\ \mbox{}\verb@ int iList;@\\ \mbox{}\verb@ int iEnd;@\\ +\mbox{}\verb@ time_t nextRun;@\\ \mbox{}\verb@ } EnvMon;@\\ \mbox{}\verb@/*---------------------------------------------------------------------------*/@\\ \mbox{}\verb@ typedef struct {@\\ @@ -77,7 +78,7 @@ $\langle$emondat {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ } EVEntry, *pEVEntry; @\\ \mbox{}\verb@@\\ \mbox{}\verb@@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} @@ -90,8 +91,8 @@ As it it will be accessible as SICS object emon needs an object descriptor. The other data member is a list of active controllers. The EVEntry structure contains the data held in the list for each active -controller. It is, disguised as pDum, a pointer to the controller's -data structure, the name of the controller, and the environment interface of +controller. It is, disguised as pDum, a pointer to the controllers +datastructure, the name of the controller, and the environment interface of the controller. The following interface is implemented by the environment monitor: @@ -120,7 +121,7 @@ $\langle$emonint {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ @\\ \mbox{}\verb@ int EnvMonTask(void *pEv);@\\ \mbox{}\verb@ void EnvMonSignal(void *pEndv, int iSignal, void *pSigData);@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} @@ -143,7 +144,7 @@ controller. \item {\bf pName}. The name of the controller object. \item {\bf pData}. A pointer to the data structure belonging to the controller object. -\item {\bf pCon}. A pointer to the client connection to which errors shall be +\item {\bf pCon}. A pointer to the client connection to which erros shall be reported. \end{itemize} @@ -160,7 +161,7 @@ specified. {\bf EVWrapper} is the wrapper function necessary to make the emon available from SICS. The user may interact with the emon through SICS. The user will be enabled to list the currently registered environment -controllers and their current state and to register and unregister +controllers and their current state and to register and unnregister controllers. {\bf EnvMonTask} is the task function associated with the environment @@ -168,7 +169,7 @@ monitor. This is called by the task handling object and eventually invokes EVMonitorControllers for checking on the environment controllers configured into SICS. -{\bf EnvMonSignal} is the signal handler for the environment monitor task. +{\bf EnvMonSignal} is the signale handler for the environment monitor task. \begin{flushleft} \small \begin{minipage}{\linewidth} \label{scrap3} @@ -193,7 +194,7 @@ controllers configured into SICS. \mbox{}\verb@/*-------------------------------------------------------------------------*/@\\ \mbox{}\verb@@$\langle$emonint {\footnotesize ?}$\rangle$\verb@@\\ \mbox{}\verb@#endif@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-2ex} \end{minipage}\\[4ex] @@ -211,7 +212,7 @@ controllers configured into SICS. \mbox{}\verb@ Mark Koennecke, Juli 1997@\\ \mbox{}\verb@---------------------------------------------------------------------------*/@\\ \mbox{}\verb@@$\langle$emondat {\footnotesize ?}$\rangle$\verb@@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-2ex} \end{minipage}\\[4ex] diff --git a/emonitor.w b/emonitor.w index 09af2348..db5f5b10 100644 --- a/emonitor.w +++ b/emonitor.w @@ -18,15 +18,15 @@ maintained. \end{itemize} Controller objects will be able to share some code among them. Each -environment controller will hold a target value, a permissible tolerance, - a selector variable which defines the type of error handling to perform and - an interrupt code to issue when that form of error handling is chosen. +environemnt controller will hold a target value, a permissable tolerance, + a selctor variable which defines the type of error handling to perform and + an interrupt code to issue when that form of error handling is choosen. Furthermore each environment controller needs to implement the drivable interface (for driving to new values) and the environment interface (for monitoring the controller). Controller object will also share the error handling during the monitor phase between them. The scheme is that each controller will have a variable which selects the error handling mechanism. Depending on this -variable an error management routine will be invoked. Current two schemes for +variable an error managment routine will be invoked. Current two schemes for handling errors are supported: \begin{itemize} \item Print a warning but do nothing else. @@ -57,12 +57,13 @@ controllers. It will be called from the main loop to check if each registered environment controller is still within tolerances. If not, emon has to enforce error processing. Else it does nothing. -The environment monitor uses the following data structures: +The environment monitor uses the following datastructures: @d emondat @{ typedef struct __EnvMon { pObjectDescriptor pDes; int iList; int iEnd; + time_t nextRun; } EnvMon; /*---------------------------------------------------------------------------*/ typedef struct { @@ -77,8 +78,8 @@ As it it will be accessible as SICS object emon needs an object descriptor. The other data member is a list of active controllers. The EVEntry structure contains the data held in the list for each active -controller. It is, disguised as pDum, a pointer to the controller's -data structure, the name of the controller, and the environment interface of +controller. It is, disguised as pDum, a pointer to the controllers +datastructure, the name of the controller, and the environment interface of the controller. The following interface is implemented by the environment monitor: @@ -118,7 +119,7 @@ controller. \item {\bf pName}. The name of the controller object. \item {\bf pData}. A pointer to the data structure belonging to the controller object. -\item {\bf pCon}. A pointer to the client connection to which errors shall be +\item {\bf pCon}. A pointer to the client connection to which erros shall be reported. \end{itemize} @@ -135,7 +136,7 @@ specified. {\bf EVWrapper} is the wrapper function necessary to make the emon available from SICS. The user may interact with the emon through SICS. The user will be enabled to list the currently registered environment -controllers and their current state and to register and unregister +controllers and their current state and to register and unnregister controllers. {\bf EnvMonTask} is the task function associated with the environment @@ -143,7 +144,7 @@ monitor. This is called by the task handling object and eventually invokes EVMonitorControllers for checking on the environment controllers configured into SICS. -{\bf EnvMonSignal} is the signal handler for the environment monitor task. +{\bf EnvMonSignal} is the signale handler for the environment monitor task. @o emon.h -d @{ /*-------------------------------------------------------------------------- diff --git a/errormsg.c b/errormsg.c index d50cb3d6..d023c207 100644 --- a/errormsg.c +++ b/errormsg.c @@ -5,9 +5,10 @@ #include "errormsg.h" /* compare two strings for euqality, ignoring text within square brackets */ -int ErrEqual(char *str1, char *str2) { +int ErrEqual(char *str1, char *str2) +{ char *p; - + while (*str1 != '\0' || *str2 != '\0') { if (*str1 != *str2) { return 0; @@ -25,13 +26,15 @@ int ErrEqual(char *str1, char *str2) { return 1; } -ErrMsg *ErrPutMsg(ErrMsg *dump, char *fmt, ...) { +void ErrPutMsg(ErrList *list, char *fmt, ...) +{ ErrMsg *m = NULL; ErrMsg **last = NULL; va_list ap; char buf[256]; char *text = NULL; int l; + static long id = 0; va_start(ap, fmt); l = vsnprintf(buf, sizeof buf, fmt, ap); @@ -41,28 +44,40 @@ ErrMsg *ErrPutMsg(ErrMsg *dump, char *fmt, ...) { } else { /* assuming we have a C99 conforming snprintf and need a larger buffer */ text = calloc(l, 1); + if (!text) return; va_start(ap, fmt); vsnprintf(text, l, fmt, ap); va_end(ap); } - last = &dump; - for (m = dump; m != NULL; m = m->next) { + last = &list->current; + for (m = list->current; m != NULL; m = m->next) { if (ErrEqual(text, m->text)) { - *last = m->next; /* remove found item from list */ + *last = m->next; /* remove found item from list */ break; } last = &m->next; } - if (m == NULL) { /* make a new item */ - if (text == buf) text = strdup(buf); + if (m == NULL) { /* make a new item */ + if (text == buf) + text = strdup(buf); m = calloc(1, sizeof(*m)); m->text = text; m->cnt = 1; + m->dirty = 0; + id++; + m->id = id; } else { - if (text != buf) free(text); + if (text != buf) + free(text); m->cnt++; } - m->next = dump; + m->next = list->current; time(&m->last); - return m; + list->current = m; +} + +char *ErrGetLastMsg(ErrList *list) { + if (list == NULL) return ""; + if (list->current == NULL) return ""; + return list->current->text; } diff --git a/errormsg.h b/errormsg.h index 470ebd5e..5f792147 100644 --- a/errormsg.h +++ b/errormsg.h @@ -11,10 +11,17 @@ typedef struct ErrMsg { struct ErrMsg *next; char *text; /**< the message text */ - int cnt; /**< count */ + long cnt; /**< count */ time_t last; /**< time of last message */ + long dirty; /**< count since last reset */ + char *itemId; /**< an id for the item where the error occured */ + long id; } ErrMsg; +typedef struct { + ErrMsg *current; +} ErrList; + /** \brief Put a formatted message to the error message list * * The error message list contains only one entry for all messages @@ -23,10 +30,17 @@ typedef struct ErrMsg { * when comparing messages. * The new message is always at the head of the list. * - * \param dump the error message list + * \param list the error message list * \param fmt the format for the message * \return the new error message list head */ -ErrMsg *ErrPutMsg(ErrMsg *dump, char *fmt, ...); + +void ErrPutMsg(ErrList *list, char *fmt, ...); + +/** \brief Get the most recent error message + * \param list the error list + * \return the most recent error message + */ +char *ErrGetLastMsg(ErrList *list); #endif diff --git a/eurodriv.h b/eurodriv.h index 132856fa..e220fb76 100644 --- a/eurodriv.h +++ b/eurodriv.h @@ -10,14 +10,14 @@ ---------------------------------------------------------------------------*/ #ifndef EURODRIV #define EURODRIV - pEVDriver CreateEURODriv(int argc, char *argv[]); +pEVDriver CreateEURODriv(int argc, char *argv[]); /* - these are hooks to implement further functionality which, - I'am sure, Joachim Kohlbrecher will request. - */ - int EuroGetParameter(void **pData, char *pPar, int iLen, float *fVal); - int EuroSetParameter(void **pData, char *pPar, int iLen, - char *pFormat, float fVal); - -#endif + these are hooks to implement further functionality which, + I'am sure, Joachim Kohlbrecher will request. + */ +int EuroGetParameter(void **pData, char *pPar, int iLen, float *fVal); +int EuroSetParameter(void **pData, char *pPar, int iLen, + char *pFormat, float fVal); + +#endif diff --git a/evcontroller.c b/evcontroller.c index ba3bdc6c..33fb9abc 100644 --- a/evcontroller.c +++ b/evcontroller.c @@ -68,614 +68,576 @@ #include "site.h" #include "commandlog.h" /*--------------------- Functions needed to implement interfaces -----------*/ - static long EVIDrive(void *pData, SConnection *pCon, float fVal) - { - pEVControl self = NULL; - int iRet, iCode, i, iFix, savedStatus; - char pError[132], pBueffel[256]; - Tcl_Interp *pTcl = NULL; +static long EVIDrive(void *pData, SConnection * pCon, float fVal) +{ + pEVControl self = NULL; + int iRet, iCode, i, iFix, savedStatus; + char pError[132], pBueffel[256]; + Tcl_Interp *pTcl = NULL; - self = (pEVControl)pData; - assert(self); - assert(pCon); - - if (self->runScript != NULL) { - savedStatus = GetStatus(); - SetStatus(eBatch); - pTcl = InterpGetTcl(pServ->pSics); - snprintf(pBueffel, sizeof(pBueffel), "%s %f", self->runScript, fVal); - iRet = Tcl_Eval(pTcl,pBueffel); - SetStatus(savedStatus); - if(iRet != TCL_OK) - { - SCPrintf(pCon, eError, - "ERROR: %s while processing runscript for %s", - pTcl->result,self->pName); - } - } + self = (pEVControl) pData; + assert(self); + assert(pCon); - self->fTarget = fVal; - self->eMode = EVDrive; - self->iStop = 0; - self->start = time(NULL); - self->lastt = 0; - self->iWarned = 0; - self->conn = SCSave(pCon, self->conn); - - /* try at least three times to do it */ - for(i = 0; i < 3; i++) - { - iRet = self->pDriv->SetValue(self->pDriv,fVal); - if(!iRet) - { - self->pDriv->GetError(self->pDriv,&iCode, pError,131); - iFix = self->pDriv->TryFixIt(self->pDriv,iCode); - switch(iFix) - { - case DEVOK: - return 1; - break; - case DEVFAULT: - sprintf(pBueffel,"ERROR: %s",pError); - SCWrite(pCon,pBueffel,eError); - return 0; - case DEVREDO: - sprintf(pBueffel,"WARNING: Fixing problem %s",pError); - SCWrite(pCon,pBueffel,eWarning); - break; - } - } - else - { - return 1; - } - } - SCWrite(pCon,"ERROR: Failed to fix previous problems, Device Error", - eError); - return 0; - } -/*---------------------------------------------------------------------------*/ - static float EVIGet(void *pData, SConnection *pCon) - { - pEVControl self = NULL; - int iRet, iCode, i, iFix; - char pError[132], pBueffel[256]; - float fPos = -999.; - int iPendingCount = 0; - - self = (pEVControl)pData; - assert(self); - assert(pCon); - - /* try at least three times to do it */ - for(i = 0; i < 5; i++) - { - iRet = self->pDriv->GetValue(self->pDriv,&fPos); - if(iRet == 0) - { - self->pDriv->GetError(self->pDriv,&iCode, pError,131); - iFix = self->pDriv->TryFixIt(self->pDriv,iCode); - switch(iFix) - { - case DEVOK: - return fPos; - break; - case DEVFAULT: - sprintf(pBueffel,"ERROR: %s",pError); - SCWrite(pCon,pBueffel,eError); - return -999.; - case DEVREDO: - sprintf(pBueffel,"WARNING: Fixing problem %s",pError); - SCWrite(pCon,pBueffel,eWarning); - break; - } - } - else if(iRet == -1 ) /* pending */ - { - i--; - iPendingCount++; - if(iPendingCount > 300) - { - SCWrite(pCon,"ERROR: cannot get data from socket",eError); - return -999.; - } - } - else - { - return fPos; - } - } - SCWrite(pCon,"ERROR: Failed to fix previous problems, Device Error", - eError); - return -999.; + if (self->runScript != NULL) { + savedStatus = GetStatus(); + SetStatus(eBatch); + pTcl = InterpGetTcl(pServ->pSics); + snprintf(pBueffel, sizeof(pBueffel), "%s %f", self->runScript, fVal); + iRet = Tcl_Eval(pTcl, pBueffel); + SetStatus(savedStatus); + if (iRet != TCL_OK) { + SCPrintf(pCon, eError, + "ERROR: %s while processing runscript for %s", + pTcl->result, self->pName); + } } - static void notifyStatus(pEVControl self, SConnection *pCon, int status) { - if (self->pDrivInt->drivableStatus!=status) { - ((SConnection *)pCon)->conEventType=STATUS; - ((SConnection *)pCon)->conStatus=status; - SCWrite(pCon, "", eEvent); - self->pDrivInt->drivableStatus=status; - } + self->fTarget = fVal; + self->eMode = EVDrive; + self->iStop = 0; + self->start = time(NULL); + self->lastt = 0; + self->iWarned = 0; + if (self->conn != NULL) { + SCDeleteConnection(self->conn); + } + self->conn = SCCopyConnection(pCon); + if (self->conn == NULL) { + SCWrite(pCon, "ERROR: out of memory in EVIDrive", eError); + return 0; } -/*---------------------------------------------------------------------------*/ - static int EVIStatus(void *pData, SConnection *pCon) - { - pEVControl self = NULL; - float fPos, fDelta = .0; - int iRet, iCode, iFix; - char pBueffel[256], pError[132]; - static int callCount; - time_t now, tmo; - float tol; - - self = (pEVControl)pData; - assert(self); - assert(pCon); - - /* go to idle when stopped */ - if(self->iStop) - { - notifyStatus(self, pCon, HWIdle); - return HWIdle; - } - - /* get the current position */ - - iRet = self->pDriv->GetValues(self->pDriv,&self->fTarget,&fPos,&fDelta); - if(iRet == 0) - { - self->pDriv->GetError(self->pDriv,&iCode, pError,131); - iFix = self->pDriv->TryFixIt(self->pDriv,iCode); - switch(iFix) - { - case DEVOK: - return HWBusy; - break; - case DEVFAULT: - sprintf(pBueffel,"ERROR: %s",pError); - SCWrite(pCon,pBueffel,eError); - notifyStatus(self, pCon, HWFault); - return HWFault; - case DEVREDO: - sprintf(pBueffel,"WARNING: Fixing problem %s",pError); - SCWrite(pCon,pBueffel,eWarning); - notifyStatus(self, pCon, HWBusy); - return HWBusy; - break; - } - } - else if(iRet == -1 ) /* pending */ - { - notifyStatus(self, pCon, HWBusy); - return HWBusy; - } - - if(fPos < -990.) - { - sprintf(pBueffel,"ERROR: %s cannot read its current value", - self->pName); - SCWrite(pCon,pBueffel,eError); - self->eMode = EVIdle; - notifyStatus(self, pCon, HWFault); - return HWFault; - } - - if(fDelta < 0.) - { - fDelta = - fDelta; - } - - /* handle callback */ - callCount++; - if(callCount >= 10) - { - sprintf(pBueffel,"%s = %g", self->pName, fPos); - InvokeCallBack(self->pCall, VALUECHANGE,pBueffel); - callCount = 0; - } - - now = time(NULL); - tmo = (int)(ObVal(self->pParam, MAXWAIT)); - /* based on this: logic ! */ - if (tmo>0 && now > self->start+tmo ) /* time out */ - { - sprintf(pBueffel,"ERROR: wait time limit reached on %s", - self->pName); - SCWrite(pCon,pBueffel,eError); - self->eMode = EVMonitor; - notifyStatus(self, pCon, HWIdle); - return HWIdle; - } - tol = ObVal(self->pParam, TOLERANCE); - if (self->lastt > 0) { /* increase tol for hysteresis */ - tol=tol*1.1001; - } - tmo = (int)(ObVal(self->pParam, SETTLE)); - if(fDelta <= tol) /* inside tolerance */ - { - if (self->lastt <= 0) /* lastt negative: -seconds already waited */ - { - self->lastt += now; - if (tmo>0) - { - sprintf(pBueffel,"%s inside tolerance, wait %.2f sec to settle", - self->pName, (self->lastt + tmo - now)*1.0); - SCWrite(pCon,pBueffel,eWarning); - } - notifyStatus(self, pCon, HWBusy); - return HWBusy; - } - if (now > self->lastt + tmo) - { - self->eMode = EVMonitor; - notifyStatus(self, pCon, HWIdle); - return HWIdle; - } - notifyStatus(self, pCon, HWBusy); - return HWBusy; - } - else - { - if (self->lastt > 0) { /* save time already waited */ - if (tmo > 0) { - sprintf(pBueffel,"%s outside tolerance, settling time suspended", - self->pName); - SCWrite(pCon,pBueffel,eWarning); - } - self->lastt -= now; - } - notifyStatus(self, pCon, HWBusy); - return HWBusy; - } - } -/*--------------------------------------------------------------------------*/ - static int EVILimits(void *pData, float fVal, char *pError, int iErrLen) - { - pEVControl self = NULL; - char pBueffel[256]; - - self = (pEVControl)pData; - assert(self); - - /* lower limit */ - if( fVal < ObVal(self->pParam, LOWLIMIT)) - { - sprintf(pBueffel,"ERROR: %g violates lower limit of device",fVal); - strncpy(pError,pBueffel,iErrLen); + /* try at least three times to do it */ + for (i = 0; i < 3; i++) { + iRet = self->pDriv->SetValue(self->pDriv, fVal); + if (!iRet) { + self->pDriv->GetError(self->pDriv, &iCode, pError, 131); + iFix = self->pDriv->TryFixIt(self->pDriv, iCode); + switch (iFix) { + case DEVOK: + return 1; + break; + case DEVFAULT: + sprintf(pBueffel, "ERROR: %s", pError); + SCWrite(pCon, pBueffel, eError); return 0; + case DEVREDO: + sprintf(pBueffel, "WARNING: Fixing problem %s", pError); + SCWrite(pCon, pBueffel, eWarning); + break; } - - /* upper limit */ - if( fVal > ObVal(self->pParam, UPLIMIT)) - { - sprintf(pBueffel,"ERROR: %g violates upper limit of device",fVal); - strncpy(pError,pBueffel,iErrLen); - return 0; - } - - /* OK */ + } else { return 1; + } } -/*---------------------------------------------------------------------------*/ - static int EVIHalt(void *pData) - { - pEVControl self = NULL; - float fPos; - int iRet, iRes; - - self = (pEVControl)pData; - assert(self); + SCWrite(pCon, "ERROR: Failed to fix previous problems, Device Error", + eError); + return 0; +} - iRes = 1; - self->eMode = EVIdle; - self->iStop = 1; - - return iRes; - } +/*---------------------------------------------------------------------------*/ +static float EVIGet(void *pData, SConnection * pCon) +{ + pEVControl self = NULL; + int iRet, iCode, i, iFix; + char pError[132], pBueffel[256]; + float fPos = -999.; + int iPendingCount = 0; + + self = (pEVControl) pData; + assert(self); + assert(pCon); + + /* try at least three times to do it */ + for (i = 0; i < 5; i++) { + iRet = self->pDriv->GetValue(self->pDriv, &fPos); + if (iRet == 0) { + self->pDriv->GetError(self->pDriv, &iCode, pError, 131); + iFix = self->pDriv->TryFixIt(self->pDriv, iCode); + switch (iFix) { + case DEVOK: + return fPos; + break; + case DEVFAULT: + sprintf(pBueffel, "ERROR: %s", pError); + SCWrite(pCon, pBueffel, eError); + return -999.; + case DEVREDO: + sprintf(pBueffel, "WARNING: Fixing problem %s", pError); + SCWrite(pCon, pBueffel, eWarning); + break; + } + } else if (iRet == -1) { /* pending */ + i--; + iPendingCount++; + if (iPendingCount > 300) { + SCWrite(pCon, "ERROR: cannot get data from socket", eError); + return -999.; + } + } else { + return fPos; + } + } + SCWrite(pCon, "ERROR: Failed to fix previous problems, Device Error", + eError); + return -999.; +} + +static void notifyStatus(pEVControl self, SConnection * pCon, int status) +{ + if (self->pDrivInt->drivableStatus != status) { + ((SConnection *) pCon)->conEventType = STATUS; + ((SConnection *) pCon)->conStatus = status; + SCWrite(pCon, "", eEvent); + self->pDrivInt->drivableStatus = status; + } +} + +/*---------------------------------------------------------------------------*/ +static int EVIStatus(void *pData, SConnection * pCon) +{ + pEVControl self = NULL; + float fPos, fDelta = .0; + int iRet, iCode, iFix; + char pBueffel[256], pError[132]; + static int callCount; + time_t now, tmo; + float tol; + + self = (pEVControl) pData; + assert(self); + assert(pCon); + + /* go to idle when stopped */ + if (self->iStop) { + notifyStatus(self, pCon, HWIdle); + return HWIdle; + } + + /* get the current position */ + + iRet = + self->pDriv->GetValues(self->pDriv, &self->fTarget, &fPos, &fDelta); + if (iRet == 0) { + self->pDriv->GetError(self->pDriv, &iCode, pError, 131); + iFix = self->pDriv->TryFixIt(self->pDriv, iCode); + switch (iFix) { + case DEVOK: + return HWBusy; + break; + case DEVFAULT: + sprintf(pBueffel, "ERROR: %s", pError); + SCWrite(pCon, pBueffel, eError); + notifyStatus(self, pCon, HWFault); + return HWFault; + case DEVREDO: + sprintf(pBueffel, "WARNING: Fixing problem %s", pError); + SCWrite(pCon, pBueffel, eWarning); + notifyStatus(self, pCon, HWBusy); + return HWBusy; + break; + } + } else if (iRet == -1) { /* pending */ + notifyStatus(self, pCon, HWBusy); + return HWBusy; + } + + if (fPos < -990.) { + snprintf(pBueffel, 255, "ERROR: %s cannot read its current value", + self->pName); + SCWrite(pCon, pBueffel, eError); + self->eMode = EVIdle; + notifyStatus(self, pCon, HWFault); + return HWFault; + } + + if (fDelta < 0.) { + fDelta = -fDelta; + } + + /* handle callback */ + callCount++; + if (callCount >= 10) { + sprintf(pBueffel, "%s = %g", self->pName, fPos); + InvokeCallBack(self->pCall, VALUECHANGE, pBueffel); + callCount = 0; + } + + now = time(NULL); + tmo = (int) (ObVal(self->pParam, MAXWAIT)); + /* based on this: logic ! */ + if (tmo > 0 && now > self->start + tmo) { /* time out */ + snprintf(pBueffel,255, "ERROR: wait time limit reached on %s", self->pName); + SCWrite(pCon, pBueffel, eError); + self->eMode = EVMonitor; + notifyStatus(self, pCon, HWIdle); + return HWIdle; + } + tol = ObVal(self->pParam, TOLERANCE); + if (self->lastt > 0) { /* increase tol for hysteresis */ + tol = tol * 1.1001; + } + tmo = (int) (ObVal(self->pParam, SETTLE)); + if (fDelta <= tol) { /* inside tolerance */ + if (self->lastt <= 0) { /* lastt negative: -seconds already waited */ + self->lastt += now; + if (tmo > 0) { + snprintf(pBueffel,255, "%s inside tolerance, wait %.2f sec to settle", + self->pName, (self->lastt + tmo - now) * 1.0); + SCWrite(pCon, pBueffel, eLog); + } + notifyStatus(self, pCon, HWBusy); + return HWBusy; + } + if (now > self->lastt + tmo) { + self->eMode = EVMonitor; + notifyStatus(self, pCon, HWIdle); + return HWIdle; + } + notifyStatus(self, pCon, HWBusy); + return HWBusy; + } else { + if (self->lastt > 0) { /* save time already waited */ + if (tmo > 0) { + snprintf(pBueffel,255, "%s outside tolerance, settling time suspended", + self->pName); + SCWrite(pCon, pBueffel, eLog); + } + self->lastt -= now; + } + notifyStatus(self, pCon, HWBusy); + return HWBusy; + } +} + +/*--------------------------------------------------------------------------*/ +static int EVILimits(void *pData, float fVal, char *pError, int iErrLen) +{ + pEVControl self = NULL; + char pBueffel[256]; + + self = (pEVControl) pData; + assert(self); + + /* lower limit */ + if (fVal < ObVal(self->pParam, LOWLIMIT)) { + sprintf(pBueffel, "ERROR: %g violates lower limit of device", fVal); + strlcpy(pError, pBueffel, iErrLen); + return 0; + } + + /* upper limit */ + if (fVal > ObVal(self->pParam, UPLIMIT)) { + sprintf(pBueffel, "ERROR: %g violates upper limit of device", fVal); + strlcpy(pError, pBueffel, iErrLen); + return 0; + } + + /* OK */ + return 1; +} + +/*---------------------------------------------------------------------------*/ +static int EVIHalt(void *pData) +{ + pEVControl self = NULL; + float fPos; + int iRet, iRes; + + self = (pEVControl) pData; + assert(self); + + iRes = 1; + self->eMode = EVIdle; + self->iStop = 1; + + return iRes; +} /*---------------------------- Error Handlers --------------------------------*/ -static void ErrWrite(char *txt, SCStore *conn) +static void ErrWrite(char *txt, SConnection * conn) { - pExeList pExe; - SConnection *pCon = NULL; + pExeList pExe; + SConnection *pCon = NULL; - pExe = GetExecutor(); - pCon = GetExeOwner(pExe); + pExe = GetExecutor(); + pCon = GetExeOwner(pExe); - if (pCon) - { - SCWrite(pCon,txt,eWarning); - } - else - { - pCon = SCStorePush(conn); - SCWrite(pCon, txt, eWarning); - SCStorePop(conn); - } + if (pCon) { + SCWrite(pCon, txt, eLog); + } else { + SCWrite(conn, txt, eLog); + } } + /*-----------------------------------------------------------------------*/ static void ErrReport(pEVControl self) { - float fPos =.0, fDelta =.0; - char pBueffel[256]; - - self->pDriv->GetValues(self->pDriv,&self->fTarget,&fPos,&fDelta); - if(self->iWarned == 0) - { - sprintf(pBueffel,"WARNING: %s is out of range by %g", - self->pName,fDelta); - ErrWrite(pBueffel, self->conn); - self->iWarned = 1; - } - } + float fPos = .0, fDelta = .0; + char pBueffel[256]; + + self->pDriv->GetValues(self->pDriv, &self->fTarget, &fPos, &fDelta); + if (self->iWarned == 0) { + snprintf(pBueffel, 255,"WARNING: %s is out of range by %g", + self->pName, fDelta); + ErrWrite(pBueffel, self->conn); + self->iWarned = 1; + } +} + /*-------------------------------------------------------------------------*/ - static int ErrLazy(void *pData) - { - pEVControl self = NULL; +static int ErrLazy(void *pData) +{ + pEVControl self = NULL; - self = (pEVControl)pData; - assert(self); + self = (pEVControl) pData; + assert(self); + + ErrReport(self); + return 1; +} - ErrReport(self); - return 1; - } /*--------------------------------------------------------------------------*/ - static int ErrPause(void *pData) - { - pEVControl self = NULL; - pExeList pExe; - int iRet; - - self = (pEVControl)pData; - assert(self); +static int ErrPause(void *pData) +{ + pEVControl self = NULL; + pExeList pExe; + int iRet; - ErrReport(self); + self = (pEVControl) pData; + assert(self); + + ErrReport(self); + + pExe = GetExecutor(); + if (IsCounting(pExe)) { + SCWrite(GetExeOwner(pExe), "Pausing till OK", eLogError); + PauseExecution(pExe); + + /* wait till OK */ + iRet = 0; + while (iRet == 0 && IsCounting(pExe)) { + SicsWait(5); + iRet = self->pEnvir->IsInTolerance(self); + } + + /* OK now, continue */ + SetStatus(eEager); + self->iWarned = 0; + ContinueExecution(pExe); + return 1; + } + return 1; +} - pExe = GetExecutor(); - if(IsCounting(pExe)) - { - SCWrite(GetExeOwner(pExe),"Pausing till OK",eError); - PauseExecution(pExe); - - /* wait till OK */ - iRet = 0; - while(iRet == 0 && IsCounting(pExe) ) - { - SicsWait(5); - iRet = self->pEnvir->IsInTolerance(self); - } - - /* OK now, continue */ - SetStatus(eEager); - self->iWarned = 0; - ContinueExecution(pExe); - return 1; - } - return 1; - } /*--------------------------------------------------------------------------*/ - static int ErrScript(void *pData) - { - pEVControl self = NULL; - int iRet; - Tcl_Interp *pTcl = NULL; - pExeList pExe; - char pBueffel[256]; +static int ErrScript(void *pData) +{ + pEVControl self = NULL; + int iRet; + Tcl_Interp *pTcl = NULL; + pExeList pExe; + char pBueffel[256]; - self = (pEVControl)pData; - assert(self); + self = (pEVControl) pData; + assert(self); - ErrReport(self); + ErrReport(self); + + pExe = GetExecutor(); + if (self->errorScript != NULL) { + pTcl = InterpGetTcl(pServ->pSics); + iRet = Tcl_Eval(pTcl, self->errorScript); + if (iRet != TCL_OK) { + snprintf(pBueffel, 255, + "ERROR: %s while processing errorscript for %s", + pTcl->result, self->pName); + ErrWrite(pBueffel, self->conn); + } + /* + assume that everything is fine again after the script + returns + */ + self->eMode = EVMonitor; + self->iWarned = 0; + } else { + snprintf(pBueffel, 255, + "ERROR: script error handling requested for %s, but no script given", + self->pName); + ErrWrite(pBueffel, self->conn); + } + + return 1; +} - pExe = GetExecutor(); - if(self->errorScript != NULL) - { - pTcl = InterpGetTcl(pServ->pSics); - iRet = Tcl_Eval(pTcl,self->errorScript); - if(iRet != TCL_OK) - { - snprintf(pBueffel,255, - "ERROR: %s while processing errorscript for %s", - pTcl->result,self->pName); - ErrWrite(pBueffel, self->conn); - } - /* - assume that everything is fine again after the script - returns - */ - self->eMode = EVMonitor; - self->iWarned = 0; - } - else - { - snprintf(pBueffel,255, - "ERROR: script error handling requested for %s, but no script given", - self->pName); - ErrWrite(pBueffel, self->conn); - } - - return 1; - } /*---------------------------------------------------------------------------*/ - static int ErrInterrupt(void *pData) - { - pEVControl self = NULL; +static int ErrInterrupt(void *pData) +{ + pEVControl self = NULL; - self = (pEVControl)pData; - assert(self); + self = (pEVControl) pData; + assert(self); - ErrReport(self); + ErrReport(self); + + /* interrupt */ + SetInterrupt((int) ObVal(self->pParam, INTERRUPT)); + self->iWarned = 0; + return 1; +} - /* interrupt */ - SetInterrupt((int)ObVal(self->pParam,INTERRUPT)); - self->iWarned = 0; - return 1; - } /*---------------------------------------------------------------------------*/ - static int ErrRun(void *pData) - { - pEVControl self = NULL; - - self = (pEVControl)pData; - assert(self); +static int ErrRun(void *pData) +{ + pEVControl self = NULL; + + self = (pEVControl) pData; + assert(self); + + ErrReport(self); + + ErrWrite("Running to safe value", self->conn); + self->pDriv->SetValue(self->pDriv, ObVal(self->pParam, SAFEVALUE)); + self->eMode = EVIdle; + self->iWarned = 0; + return 1; +} - ErrReport(self); - - ErrWrite("Running to safe value", self->conn); - self->pDriv->SetValue(self->pDriv, ObVal(self->pParam,SAFEVALUE)); - self->eMode = EVIdle; - self->iWarned = 0; - return 1; - } /*---------------------------------------------------------------------------*/ - static int EVIErrHandler(void *pData) - { - pEVControl self = NULL; - int iRet, iHandler, iStatus; - - self = (pEVControl)pData; - assert(self); +static int EVIErrHandler(void *pData) +{ + pEVControl self = NULL; + int iRet, iHandler, iStatus; - /* select an error handler according to the variable set - in Controller - */ - iHandler = (int)ObVal(self->pParam, ERRORHANDLER); - self->eMode = EVError; - switch(iHandler) - { - case 0: /* no op */ - iStatus = ErrLazy(pData); - break; - case 1: /* Pause */ - iStatus = ErrPause(pData); - break; - case 2: /* Interrupt */ - iStatus = ErrInterrupt(pData); - break; - case 3: /* run to a safe place, put him into idle afterwards */ - iStatus = ErrRun(pData); - return iStatus; - break; - case 4: /* invoke a script */ - iStatus = ErrScript(pData); - return iStatus; - break; - default: - return 0; - - } - /* reset mode to monitor again! */ + self = (pEVControl) pData; + assert(self); + + /* select an error handler according to the variable set + in Controller + */ + iHandler = (int) ObVal(self->pParam, ERRORHANDLER); + self->eMode = EVError; + switch (iHandler) { + case 0: /* no op */ + iStatus = ErrLazy(pData); + break; + case 1: /* Pause */ + iStatus = ErrPause(pData); + break; + case 2: /* Interrupt */ + iStatus = ErrInterrupt(pData); + break; + case 3: /* run to a safe place, put him into idle afterwards */ + iStatus = ErrRun(pData); + return iStatus; + break; + case 4: /* invoke a script */ + iStatus = ErrScript(pData); + return iStatus; + break; + default: + return 0; + + } + /* reset mode to monitor again! */ + self->eMode = EVMonitor; + return iStatus; +} + +/*---------------------------------------------------------------------------*/ +static EVMode EVIGetMode(void *pData) +{ + pEVControl self = NULL; + + self = (pEVControl) pData; + assert(self); + + return self->eMode; +} + +/*--------------------------------------------------------------------------*/ +static int EVIIsInTolerance(void *pData) +{ + pEVControl self = NULL; + float fPos, fDelta; + int iRet, iCode, iStat; + char pError[132], pBueffel[512]; + pExeList pExe = NULL; + SConnection *pCon = NULL; + float tol; + + self = (pEVControl) pData; + assert(self); + + + iRet = + self->pDriv->GetValues(self->pDriv, &self->fTarget, &fPos, &fDelta); + if (iRet == 1) { + if (self->iLog) { + VarlogAdd(self->pLog, fPos); + } + if (fDelta < 0.) { + fDelta = -fDelta; + } + tol = ObVal(self->pParam, TOLERANCE); + if (self->iWarned == 0) + tol = tol * 1.1001; + if (fDelta <= tol) { self->eMode = EVMonitor; - return iStatus; - } -/*---------------------------------------------------------------------------*/ - static EVMode EVIGetMode(void *pData) - { - pEVControl self = NULL; - - self = (pEVControl)pData; - assert(self); - - return self->eMode; - } -/*--------------------------------------------------------------------------*/ - static int EVIIsInTolerance(void *pData) - { - pEVControl self = NULL; - float fPos, fDelta; - int iRet, iCode, iStat; - char pError[132], pBueffel[512]; - pExeList pExe = NULL; - SConnection *pCon = NULL; - float tol; - - self = (pEVControl)pData; - assert(self); - - - iRet = self->pDriv->GetValues(self->pDriv,&self->fTarget,&fPos,&fDelta); - if( iRet == 1 ) - { - if(self->iLog) - { - VarlogAdd(self->pLog, fPos); - } - if(fDelta < 0.) - { - fDelta = -fDelta; - } - tol = ObVal(self->pParam,TOLERANCE); - if (self->iWarned == 0) tol=tol*1.1001; - if(fDelta <= tol) - { - self->eMode = EVMonitor; - if(self->iWarned) - { - sprintf(pBueffel,"Environment device %s back in tolerances again", - self->pName); - ErrWrite(pBueffel, self->conn); - self->iWarned = 0; - } - return 1; - } - else - { - return 0; - } - /* deal with callbacks */ - self->callCount++; - if(self->callCount >= 20) - { - sprintf(pBueffel,"%s = %g", self->pName, fPos); - InvokeCallBack(self->pCall,VALUECHANGE, pBueffel); - self->callCount = 0; - } - } - else if(iRet == -1) /* pending */ - { - /* pending means OK to me */ - return 1; - } - else - { - /* break down of connection to a environment device has to be - considered a problem as well - */ - memset(pError,0,132*sizeof(char)); - self->pDriv->GetError(self->pDriv, &iCode,pError,131); - WriteToCommandLog("emon>> ",pError); - iStat = self->pDriv->TryFixIt(self->pDriv, iCode); - if( (iStat == DEVOK) || (iStat == DEVREDO) ) - { - return 1; /* effectively a redo in some time */ - } - else - { - return 0; - } + if (self->iWarned) { + snprintf(pBueffel,255, "Environment device %s back in tolerances again", + self->pName); + ErrWrite(pBueffel, self->conn); + self->iWarned = 0; } + return 1; + } else { return 0; - } + } + /* deal with callbacks */ + self->callCount++; + if (self->callCount >= 20) { + snprintf(pBueffel,255, "%s = %g", self->pName, fPos); + InvokeCallBack(self->pCall, VALUECHANGE, pBueffel); + self->callCount = 0; + } + } else if (iRet == -1) { /* pending */ + /* pending means OK to me */ + return 1; + } else { + /* break down of connection to a environment device has to be + considered a problem as well + */ + memset(pError, 0, 132 * sizeof(char)); + self->pDriv->GetError(self->pDriv, &iCode, pError, 131); + WriteToCommandLog("emon>> ", pError); + iStat = self->pDriv->TryFixIt(self->pDriv, iCode); + if ((iStat == DEVOK) || (iStat == DEVREDO)) { + return 1; /* effectively a redo in some time */ + } else { + return 0; + } + } + return 0; +} + /*-------------------------------------------------------------------------*/ - static void *EVIInterface(void *pData, int iCode) - { - pEVControl self = NULL; - - self = (pEVControl)pData; - assert(self); - - if(iCode == DRIVEID) - { - return self->pDrivInt; - } - else if(iCode == ENVIRINTERFACE) - { - return self->pEnvir; - } - return NULL; - } +static void *EVIInterface(void *pData, int iCode) +{ + pEVControl self = NULL; + + self = (pEVControl) pData; + assert(self); + + if (iCode == DRIVEID) { + return self->pDrivInt; + } else if (iCode == ENVIRINTERFACE) { + return self->pEnvir; + } + return NULL; +} + /*--------------------------------------------------------------------------*/ /* this routine is the standard method of pEVDriver for GetValues. * it may be replaced by a device specific routine, for the case that @@ -683,402 +645,395 @@ static void ErrReport(pEVControl self) * (i.e.control not on sample sensor) * Oct. 2002 M.Zolliker */ - static int StdGetValues(pEVDriver self, float *fTarget, float *fPos, float *fDelta) - { - int iRet; - - assert(self); - iRet=self->GetValue(self, fPos); - if (iRet>0) *fDelta = *fTarget - *fPos; - return iRet; - } +static int StdGetValues(pEVDriver self, float *fTarget, float *fPos, + float *fDelta) +{ + int iRet; + + assert(self); + iRet = self->GetValue(self, fPos); + if (iRet > 0) + *fDelta = *fTarget - *fPos; + return iRet; +} + /*-------- All this done, we can actually implement the controller ---------*/ - pEVControl CreateEVController(pEVDriver pDriv, char *pName, int *iErr) - { - pEVControl pRes = NULL; - int iRet; - - assert(pDriv); - *iErr = 1; - - /* new memory first */ - pRes = (pEVControl)malloc(sizeof(EVControl)); - if(!pRes) - { - return NULL; - } - memset(pRes,0,sizeof(EVControl)); - - /* new Object Descriptor */ - pRes->pDes = CreateDescriptor("Environment_Controller"); - if(!pRes->pDes) - { - free(pRes); - return NULL; - } - pRes->pDes->GetInterface = EVIInterface; - - /* new Drivable interface */ - pRes->pDrivInt = CreateDrivableInterface(); - if(!pRes->pDrivInt) - { - DeleteDescriptor(pRes->pDes); - free(pRes); - return NULL; - } - pRes->pDrivInt->Halt = EVIHalt; - pRes->pDrivInt->CheckLimits = EVILimits; - pRes->pDrivInt->SetValue = EVIDrive; - pRes->pDrivInt->CheckStatus = EVIStatus; - pRes->pDrivInt->GetValue = EVIGet; - - - /* new environment interface */ - pRes->pEnvir = CreateEVInterface(); - if(!pRes->pEnvir) - { - free(pRes->pDrivInt); - DeleteDescriptor(pRes->pDes); - free(pRes); - return NULL; - } - pRes->pEnvir->GetMode = EVIGetMode; - pRes->pEnvir->IsInTolerance = EVIIsInTolerance; - pRes->pEnvir->HandleError = EVIErrHandler; +pEVControl CreateEVController(pEVDriver pDriv, char *pName, int *iErr) +{ + pEVControl pRes = NULL; + int iRet; - /* callback interface */ - pRes->pCall = CreateCallBackInterface(); - if(!pRes->pCall) - { - free(pRes->pDrivInt); - DeleteDescriptor(pRes->pDes); - free(pRes); - return NULL; - } + assert(pDriv); + *iErr = 1; - /* new parameter space */ - pRes->pParam = ObParCreate(9); - if(!pRes->pParam) - { - free(pRes->pDrivInt); - free(pRes->pEnvir); - DeleteDescriptor(pRes->pDes); - free(pRes); - return NULL; - } - ObParInit(pRes->pParam, TOLERANCE, "tolerance", 2.0, usUser); - ObParInit(pRes->pParam, ACCESS, "access", usUser, usMugger); - ObParInit(pRes->pParam, ERRORHANDLER, "errorhandler", 0.0, usUser); - ObParInit(pRes->pParam, INTERRUPT, "interrupt", eContinue, usUser); - ObParInit(pRes->pParam, UPLIMIT, "upperlimit", 300.0, usUser); - ObParInit(pRes->pParam, LOWLIMIT, "lowerlimit", 1.0, usUser); - ObParInit(pRes->pParam, SAFEVALUE, "safevalue", 0., usUser); - ObParInit(pRes->pParam, MAXWAIT, "maxwait", 0., usUser); - ObParInit(pRes->pParam, SETTLE, "settle", 0., usUser); - - /* local initialisations */ - if (pDriv->GetValues==NULL) /* if GetValues is undefined, set to default */ - { - pDriv->GetValues=StdGetValues; - } - iRet = pDriv->Init(pDriv); - - *iErr = iRet; - - /* new var log for logging values */ - pRes->iLog = 1; - if(!VarlogInit(&pRes->pLog)) - { - DeleteEVController(pRes); - return NULL; - } - - pRes->pName = strdup(pName); - pRes->eMode = EVIdle; - pRes->iWarned = 0; - pRes->conn = NULL; - - /* a terminal error gives a -1 in iRet */ - if(iRet < 0) - { - DeleteEVController(pRes); - return NULL; - } - pRes->pDriv = pDriv; /* moved here to avoid double freeing on evfactory del */ - return pRes; - } -/*---------------------------------------------------------------------------*/ - void DeleteEVController(void *pData) - { - pEVControl self = NULL; - - self = (pEVControl)pData; - assert(self); - - if(self->pDes) - { - DeleteDescriptor(self->pDes); - self->pDes = NULL; - } - if(self->pDrivInt) - { - free(self->pDrivInt); - } - if(self->pEnvir) - { - free(self->pEnvir); - } - if(self->pCall) - { - DeleteCallBackInterface(self->pCall); - } - if(self->KillPrivate) - { - self->KillPrivate(self->pPrivate); - } - if(self->pDriv) - { - self->pDriv->Close(self->pDriv); - DeleteEVDriver(self->pDriv); - } - if(self->pName) - { - free(self->pName); - } - if(self->pParam) - { - ObParDelete(self->pParam); - } - if(self->pLog) - { - VarlogDelete(self->pLog); - } - if(self->driverName != NULL) - { - free(self->driverName); - } - if(self->errorScript != NULL) - { - free(self->errorScript); - } - if (self->creationArgs != NULL) - { - free(self->creationArgs); - } - if (self->runScript != NULL) - { - free(self->runScript); - } - if (self->conn != NULL) - { - SCStoreFree(self->conn); - } - free(self); - } -/*--------------------------------------------------------------------------*/ - int EVCDrive(pEVControl self, SConnection *pCon, float fVal) - { - char pBueffel[256], pError[132]; - int iRet; - - assert(self); - assert(pCon); - - /* Check Limits */ - iRet = self->pDrivInt->CheckLimits(self, fVal, pError,131); - if(!iRet) - { - SCWrite(pCon,pError,eError); - return 0; - } - - /* start executing */ - iRet = StartDevice(GetExecutor(), self->pName, self->pDes, - self, pCon, fVal); - if(!iRet) - { - sprintf(pBueffel,"ERROR: Failure to start %s",self->pName); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* Wait for success */ - iRet = Wait4Success(GetExecutor()); - if(iRet == DEVINT) - { - return 0; - } - return 1; - } -/*--------------------------------------------------------------------------*/ - int EVCGetPos(pEVControl self, SConnection *pCon, float *fPos) - { - float fVal; - - assert(self); - assert(pCon); - - fVal = self->pDrivInt->GetValue(self, pCon); - if(fVal < -990) - { - return 0; - } - *fPos = fVal; - return 1; + /* new memory first */ + pRes = (pEVControl) malloc(sizeof(EVControl)); + if (!pRes) { + return NULL; } + memset(pRes, 0, sizeof(EVControl)); + + /* new Object Descriptor */ + pRes->pDes = CreateDescriptor("Environment Controller"); + if (!pRes->pDes) { + free(pRes); + return NULL; + } + pRes->pDes->GetInterface = EVIInterface; + + /* new Drivable interface */ + pRes->pDrivInt = CreateDrivableInterface(); + if (!pRes->pDrivInt) { + DeleteDescriptor(pRes->pDes); + free(pRes); + return NULL; + } + pRes->pDrivInt->Halt = EVIHalt; + pRes->pDrivInt->CheckLimits = EVILimits; + pRes->pDrivInt->SetValue = EVIDrive; + pRes->pDrivInt->CheckStatus = EVIStatus; + pRes->pDrivInt->GetValue = EVIGet; + + + /* new environment interface */ + pRes->pEnvir = CreateEVInterface(); + if (!pRes->pEnvir) { + free(pRes->pDrivInt); + DeleteDescriptor(pRes->pDes); + free(pRes); + return NULL; + } + pRes->pEnvir->GetMode = EVIGetMode; + pRes->pEnvir->IsInTolerance = EVIIsInTolerance; + pRes->pEnvir->HandleError = EVIErrHandler; + + /* callback interface */ + pRes->pCall = CreateCallBackInterface(); + if (!pRes->pCall) { + free(pRes->pDrivInt); + DeleteDescriptor(pRes->pDes); + free(pRes); + return NULL; + } + + /* new parameter space */ + pRes->pParam = ObParCreate(9); + if (!pRes->pParam) { + free(pRes->pDrivInt); + free(pRes->pEnvir); + DeleteDescriptor(pRes->pDes); + free(pRes); + return NULL; + } + ObParInit(pRes->pParam, TOLERANCE, "tolerance", 2.0, usUser); + ObParInit(pRes->pParam, ACCESS, "access", usUser, usMugger); + ObParInit(pRes->pParam, ERRORHANDLER, "errorhandler", 0.0, usUser); + ObParInit(pRes->pParam, INTERRUPT, "interrupt", eContinue, usUser); + ObParInit(pRes->pParam, UPLIMIT, "upperlimit", 300.0, usUser); + ObParInit(pRes->pParam, LOWLIMIT, "lowerlimit", 1.0, usUser); + ObParInit(pRes->pParam, SAFEVALUE, "safevalue", 0., usUser); + ObParInit(pRes->pParam, MAXWAIT, "maxwait", 0., usUser); + ObParInit(pRes->pParam, SETTLE, "settle", 0., usUser); + + /* local initialisations */ + if (pDriv->GetValues == NULL) { /* if GetValues is undefined, set to default */ + pDriv->GetValues = StdGetValues; + } + iRet = pDriv->Init(pDriv); + + *iErr = iRet; + + /* new var log for logging values */ + pRes->iLog = 1; + if (!VarlogInit(&pRes->pLog)) { + DeleteEVController(pRes); + return NULL; + } + + pRes->pName = strdup(pName); + pRes->eMode = EVIdle; + pRes->iWarned = 0; + if (pRes->conn != NULL) { + SCDeleteConnection(pRes->conn); + pRes->conn = NULL; + } + + /* a terminal error gives a -1 in iRet */ + if (iRet < 0) { + DeleteEVController(pRes); + return NULL; + } + pRes->pDriv = pDriv; /* moved here to avoid double freeing on evfactory del */ + return pRes; +} + +/*---------------------------------------------------------------------------*/ +void DeleteEVController(void *pData) +{ + pEVControl self = NULL; + + self = (pEVControl) pData; + assert(self); + + if (self->pDes) { + DeleteDescriptor(self->pDes); + self->pDes = NULL; + } + if (self->pDrivInt) { + free(self->pDrivInt); + } + if (self->pEnvir) { + free(self->pEnvir); + } + if (self->pCall) { + DeleteCallBackInterface(self->pCall); + } + if (self->KillPrivate) { + self->KillPrivate(self->pPrivate); + } + if (self->pDriv) { + self->pDriv->Close(self->pDriv); + DeleteEVDriver(self->pDriv); + } + if (self->pName) { + free(self->pName); + } + if (self->pParam) { + ObParDelete(self->pParam); + } + if (self->pLog) { + VarlogDelete(self->pLog); + } + if (self->driverName != NULL) { + free(self->driverName); + } + if (self->errorScript != NULL) { + free(self->errorScript); + } + if (self->creationArgs != NULL) { + free(self->creationArgs); + } + if (self->runScript != NULL) { + free(self->runScript); + } + if (self->conn != NULL) { + SCDeleteConnection(self->conn); + } + free(self); +} + +/*--------------------------------------------------------------------------*/ +int EVCDrive(pEVControl self, SConnection * pCon, float fVal) +{ + char pBueffel[256], pError[132]; + int iRet; + + assert(self); + assert(pCon); + + /* Check Limits */ + iRet = self->pDrivInt->CheckLimits(self, fVal, pError, 131); + if (!iRet) { + SCWrite(pCon, pError, eError); + return 0; + } + + /* start executing */ + iRet = StartDevice(GetExecutor(), self->pName, self->pDes, + self, pCon, pCon->runLevel, fVal); + if (!iRet) { + snprintf(pBueffel,255, "ERROR: Failure to start %s", self->pName); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* Wait for success */ + iRet = Wait4Success(GetExecutor()); + if (iRet == DEVINT) { + return 0; + } + return 1; +} + +/*--------------------------------------------------------------------------*/ +int EVCGetPos(pEVControl self, SConnection * pCon, float *fPos) +{ + float fVal; + + assert(self); + assert(pCon); + + fVal = self->pDrivInt->GetValue(self, pCon); + if (fVal < -990) { + return 0; + } + *fPos = fVal; + return 1; +} + /*-------------------------------------------------------------------------*/ - pVarLog EVCGetVarLog(pEVControl self) - { - - assert(self); - - return self->pLog; - } +pVarLog EVCGetVarLog(pEVControl self) +{ + + assert(self); + + return self->pLog; +} + /*---------------------------------------------------------------------------*/ - EVMode EVCGetMode(pEVControl self) - { - assert(self); - return self->eMode; - } +EVMode EVCGetMode(pEVControl self) +{ + assert(self); + return self->eMode; +} + /*--------------------------------------------------------------------------*/ - int EVCSetMode(pEVControl self, EVMode eNew) - { - assert(self); - self->eMode = eNew; - return 1; - } +int EVCSetMode(pEVControl self, EVMode eNew) +{ + assert(self); + self->eMode = eNew; + return 1; +} + /*---------------------------------------------------------------------------*/ - int EVCGetPar(pEVControl self, char *name, float *fVal) - { - ObPar *pPar = NULL; - assert(self); +int EVCGetPar(pEVControl self, char *name, float *fVal) +{ + ObPar *pPar = NULL; + assert(self); - - if(strcmp(name,"target") == 0) - { - *fVal = self->fTarget; - return 1; - } - pPar = ObParFind(self->pParam,name); - if(pPar) - { - *fVal = pPar->fVal; - return 1; - } - else - { - return 0; - } - } -/*---------------------------------------------------------------------------*/ - int EVCSetPar(pEVControl self, char *name, float fVal,SConnection *pCon) - { - ObPar *pPar = NULL; - char pBueffel[512]; - int iRet, savedStatus; - - assert(self); - assert(pCon); - - savedStatus = GetStatus(); /* fool status check in ObParSet (avoid "Cannot change parameter while running" message */ - SetStatus(eBatch); - iRet = ObParSet(self->pParam,self->pName,name,fVal,pCon); - SetStatus(savedStatus); - if(!iRet) - { - return iRet; - } - if(self->iTcl) - { - iRet = UpdateTclVariable(self->pDriv,name,fVal); - } - return iRet; - } -/*--------------------------------------------------------------------------*/ - int EVCList(pEVControl self, SConnection *pCon) - { - char pBueffel[256]; - float fPos; - - assert(self); - assert(pCon); - - snprintf(pBueffel,255,"Parameter listing for %s",self->pName); - SCWrite(pCon,pBueffel,eValue); - - snprintf(pBueffel,255,"%s.%s = %g ",self->pName, "tolerance", - ObVal(self->pParam,TOLERANCE)); - SCWrite(pCon,pBueffel, eValue); - snprintf(pBueffel,255,"%s.%s = %g",self->pName, "access", - ObVal(self->pParam,ACCESS)); - SCWrite(pCon,pBueffel, eValue); - snprintf(pBueffel,255,"%s.%s = %g",self->pName, "ErrorHandler", - ObVal(self->pParam,ERRORHANDLER)); - SCWrite(pCon,pBueffel, eValue); - snprintf(pBueffel,255,"%s.%s = %g",self->pName, "interrupt", - ObVal(self->pParam,INTERRUPT)); - SCWrite(pCon,pBueffel, eValue); - snprintf(pBueffel,255,"%s.%s = %g",self->pName, "UpperLimit", - ObVal(self->pParam,UPLIMIT)); - SCWrite(pCon,pBueffel, eValue); - snprintf(pBueffel,255,"%s.%s = %g",self->pName, "LowerLimit", - ObVal(self->pParam,LOWLIMIT)); - SCWrite(pCon,pBueffel, eValue); - snprintf(pBueffel,255,"%s.%s = %g",self->pName, "SafeValue", - ObVal(self->pParam,SAFEVALUE)); - SCWrite(pCon,pBueffel, eValue); - snprintf(pBueffel,255,"%s.%s = %g (sec)",self->pName, "MaxWait", - ObVal(self->pParam,MAXWAIT)); - SCWrite(pCon,pBueffel, eValue); - snprintf(pBueffel,255,"%s.%s = %g (sec)",self->pName, "Settle", - ObVal(self->pParam,SETTLE)); - SCWrite(pCon,pBueffel, eValue); - EVCGetPos(self,pCon,&fPos); - snprintf(pBueffel,255,"%s.%s = %g",self->pName, "CurrentValue", - fPos); - SCWrite(pCon,pBueffel, eValue); - snprintf(pBueffel,255,"%s.%s = %g",self->pName, "TargetValue", - self->fTarget); - SCWrite(pCon,pBueffel, eValue); - snprintf(pBueffel,255,"%s.driver = %s",self->pName, self->driverName); - SCWrite(pCon,pBueffel, eValue); - if(self->errorScript != NULL) - { - snprintf(pBueffel,255,"%s.errorScript = %s", self->pName, - self->errorScript); - } - else - { - snprintf(pBueffel,255,"%s.errorScript = UNDEFINED", self->pName); - } - SCWrite(pCon,pBueffel, eValue); - if(self->runScript != NULL) - { - SCPrintf(pCon, eValue, "%s.runScript = %s", self->pName, self->runScript); - } - else - { - SCPrintf(pCon, eValue, "%s.runScript = none", self->pName); - } - return 1; - } -/*-------------------------------------------------------------------------*/ - static int EVCallBack(int iEvent, void *pEventData, void *pUserData, - commandContext cc) - { - char *pBuf = (char *)pEventData; - SConnection *pCon = (SConnection *)pUserData; - char pBueffel[132]; - - if(iEvent == VALUECHANGE) - { - pCon->conEventType=POSITION; - SCWriteInContext(pCon,pBuf,eEvent,cc); - return 1; - } + if (strcmp(name, "target") == 0) { + *fVal = self->fTarget; return 1; } + + pPar = ObParFind(self->pParam, name); + if (pPar) { + *fVal = pPar->fVal; + return 1; + } else { + return 0; + } +} + +/*---------------------------------------------------------------------------*/ +int EVCSetPar(pEVControl self, char *name, float fVal, SConnection * pCon) +{ + ObPar *pPar = NULL; + int iRet, savedStatus; + + assert(self); + assert(pCon); + + /* find the parameter */ + pPar = ObParFind(self->pParam, name); + if (pPar == NULL) { + SCPrintf(pCon, eError, "ERROR: %s.%s parameter not found", + self->pName, name); + return 0; + } + + /* DO NOT CHECK RUNNING STATE, this is not needed */ + + /* check permission */ + if (!SCMatchRights(pCon, pPar->iCode)) { + SCPrintf(pCon, eError, "ERROR: Insufficient privilege to change %s.%s", + self->pName, name); + return 0; + } + + /* passed all tests: do It! */ + pPar->fVal = fVal; + + iRet = 1; + if (self->iTcl) { + iRet = UpdateTclVariable(self->pDriv, name, fVal); + } + return iRet; +} + +/*--------------------------------------------------------------------------*/ +int EVCList(pEVControl self, SConnection * pCon) +{ + char pBueffel[256]; + float fPos; + + assert(self); + assert(pCon); + + snprintf(pBueffel, 255, "Parameter listing for %s", self->pName); + SCWrite(pCon, pBueffel, eValue); + + snprintf(pBueffel, 255, "%s.%s = %g ", self->pName, "tolerance", + ObVal(self->pParam, TOLERANCE)); + SCWrite(pCon, pBueffel, eValue); + snprintf(pBueffel, 255, "%s.%s = %g", self->pName, "access", + ObVal(self->pParam, ACCESS)); + SCWrite(pCon, pBueffel, eValue); + snprintf(pBueffel, 255, "%s.%s = %g", self->pName, "ErrorHandler", + ObVal(self->pParam, ERRORHANDLER)); + SCWrite(pCon, pBueffel, eValue); + snprintf(pBueffel, 255, "%s.%s = %g", self->pName, "interrupt", + ObVal(self->pParam, INTERRUPT)); + SCWrite(pCon, pBueffel, eValue); + snprintf(pBueffel, 255, "%s.%s = %g", self->pName, "UpperLimit", + ObVal(self->pParam, UPLIMIT)); + SCWrite(pCon, pBueffel, eValue); + snprintf(pBueffel, 255, "%s.%s = %g", self->pName, "LowerLimit", + ObVal(self->pParam, LOWLIMIT)); + SCWrite(pCon, pBueffel, eValue); + snprintf(pBueffel, 255, "%s.%s = %g", self->pName, "SafeValue", + ObVal(self->pParam, SAFEVALUE)); + SCWrite(pCon, pBueffel, eValue); + snprintf(pBueffel, 255, "%s.%s = %g (sec)", self->pName, "MaxWait", + ObVal(self->pParam, MAXWAIT)); + SCWrite(pCon, pBueffel, eValue); + snprintf(pBueffel, 255, "%s.%s = %g (sec)", self->pName, "Settle", + ObVal(self->pParam, SETTLE)); + SCWrite(pCon, pBueffel, eValue); + EVCGetPos(self, pCon, &fPos); + snprintf(pBueffel, 255, "%s.%s = %g", self->pName, "CurrentValue", fPos); + SCWrite(pCon, pBueffel, eValue); + snprintf(pBueffel, 255, "%s.%s = %g", self->pName, "TargetValue", + self->fTarget); + SCWrite(pCon, pBueffel, eValue); + snprintf(pBueffel, 255, "%s.driver = %s", self->pName, self->driverName); + SCWrite(pCon, pBueffel, eValue); + if (self->errorScript != NULL) { + snprintf(pBueffel, 255, "%s.errorScript = %s", self->pName, + self->errorScript); + } else { + snprintf(pBueffel, 255, "%s.errorScript = UNDEFINED", self->pName); + } + SCWrite(pCon, pBueffel, eValue); + if (self->runScript != NULL) { + SCPrintf(pCon, eValue, "%s.runScript = %s", self->pName, + self->runScript); + } else { + SCPrintf(pCon, eValue, "%s.runScript = none", self->pName); + } + return 1; +} + +/*-------------------------------------------------------------------------*/ +static int EVCallBack(int iEvent, void *pEventData, void *pUserData) +{ + char *pBuf = (char *) pEventData; + SConnection *pCon = (SConnection *) pUserData; + char pBueffel[132]; + + if (pCon == NULL || !SCisConnected(pCon)) { + return -1; + } + + if (iEvent == VALUECHANGE && pCon != NULL) { + pCon->conEventType = POSITION; + SCWrite(pCon, pBuf, eEvent); + return 1; + } + return 1; +} + /*--------------------------------------------------------------------------- The wrapper understands the following syntax: EVControl : print current value @@ -1090,252 +1045,219 @@ static void ErrReport(pEVControl self) EVControl send bla bla ..... : sends everything after send to the device ---------------------------------------------------------------------------*/ - int EVControlWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - pEVControl self = NULL; - char pBueffel[256], pReply[512]; - double dVal; - float fPos; - int iRet; - long lID; - - self = (pEVControl)pData; - assert(self); - assert(pSics); - assert(pCon); - - if(argc < 2) /* only value requested */ - { - iRet = EVCGetPos(self,pCon,&fPos); - if(iRet) - { +int EVControlWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pEVControl self = NULL; + char pBueffel[256], pReply[512]; + double dVal; + float fPos; + int iRet; + long lID; + + self = (pEVControl) pData; + assert(self); + assert(pSics); + assert(pCon); + + if (argc < 2) { /* only value requested */ + iRet = EVCGetPos(self, pCon, &fPos); + if (iRet) { /* sprintf(pBueffel,"%s.%s = %g",self->pName,"CurrentValue", fPos); SCWrite(pCon,pBueffel,eValue); */ - SCPrintf(pCon, eValue, "%s = %g", argv[0], fPos); - return 1; - } - return 0; + SCPrintf(pCon, eValue, "%s = %g", argv[0], fPos); + return 1; + } + return 0; + } else { + strtolower(argv[1]); + } + + /* analyse commands */ + if (strcmp(argv[1], "send") == 0) { /* send to controller */ + Arg2Text(argc - 2, &argv[2], pBueffel, 255); + iRet = self->pDriv->Send(self->pDriv, pBueffel, pReply, 511); + SCWrite(pCon, pReply, eValue); + return iRet; + } + /* install automatic notification */ + else if (strcmp(argv[1], "interest") == 0) { + lID = RegisterCallback(self->pCall, + VALUECHANGE, EVCallBack, + SCCopyConnection(pCon), SCDeleteConnection); + SCSendOK(pCon); + return 1; + } else if (strcmp(argv[1], "uninterest") == 0) { + RemoveCallbackCon(self->pCall, pCon); + SCSendOK(pCon); + return 1; + } else if (strcmp(argv[1], "log") == 0) { /* log commands */ + if (argc < 3) { + SCWrite(pCon, "ERROR: insufficient number of commands for varlog", + eError); + return 0; + } + iRet = VarlogWrapper(self->pLog, pCon, argv[2], argv[3], argv[0]); + return iRet; + } else if (argc < 3) { /* either parameter or drive */ + iRet = Tcl_GetDouble(pSics->pTcl, argv[1], &dVal); + if (iRet == TCL_OK) { /* float Value: drive */ + if (!SCMatchRights(pCon, usUser)) { + return 0; } - else - { - strtolower(argv[1]); + iRet = EVCDrive(self, pCon, (float) dVal); + if (iRet) { + SCSendOK(pCon); } - - /* analyse commands */ - if(strcmp(argv[1],"send") == 0) /* send to controller */ - { - Arg2Text(argc-2,&argv[2],pBueffel,255); - iRet = self->pDriv->Send(self->pDriv,pBueffel,pReply, 511); - SCWrite(pCon,pReply,eValue); - return iRet; + return iRet; + } else if (strcmp(argv[1], "list") == 0) { + EVCList(self, pCon); + return 1; + } else if (strcmp(argv[1], "send") == 0) { /* send to controller */ + Arg2Text(argc - 2, &argv[2], pBueffel, 255); + iRet = self->pDriv->Send(self->pDriv, pBueffel, pReply, 511); + SCWrite(pCon, pReply, eValue); + return iRet; + } else if (strcmp(argv[1], "log") == 0) { /* log commands */ + if (argc < 3) { + SCWrite(pCon, "ERROR: insufficient number of commands for varlog", + eError); + return 0; } - /* install automatic notification */ - else if(strcmp(argv[1],"interest") == 0) - { - lID = RegisterCallback(self->pCall, SCGetContext(pCon), - VALUECHANGE, EVCallBack, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); - SCSendOK(pCon); - return 1; + return VarlogWrapper(self->pLog, pCon, argv[2], argv[3], argv[0]); + } else { /* parameter request */ + + strtolower(argv[1]); + /* + catch case of errorScript + */ + if (strcmp(argv[1], "errorscript") == 0) { + if (self->errorScript != NULL) { + snprintf(pBueffel, 255, "%s.errorScript = %s", self->pName, + self->errorScript); + } else { + snprintf(pBueffel, 255, "%s.errorScript = UNDEFINED", + self->pName); + } + SCWrite(pCon, pBueffel, eValue); + return 1; } - else if(strcmp(argv[1],"uninterest") == 0) - { - RemoveCallback2(self->pCall,pCon); - SCSendOK(pCon); - return 1; + /* + catch case of runScript + */ + if (strcmp(argv[1], "runscript") == 0) { + if (self->runScript != NULL) { + SCPrintf(pCon, eValue, "%s.runScript = %s", self->pName, + self->runScript); + } else { + SCPrintf(pCon, eValue, "%s.runScript = none", self->pName); + } + return 1; } - else if(strcmp(argv[1],"log") == 0) /* log commands */ - { - if(argc < 3) - { - SCWrite(pCon,"ERROR: insufficient number of commands for varlog",eError); - return 0; - } - iRet = VarlogWrapper(self->pLog,pCon, - argv[2],argv[3],argv[0]); - return iRet; + /* + catch case for drivername + */ + if (strcmp(argv[1], "driver") == 0) { + snprintf(pBueffel, 255, "%s.driver = %s", self->pName, + self->driverName); + SCWrite(pCon, pBueffel, eValue); + return 1; } - else if( argc < 3) /* either parameter or drive */ - { - iRet = Tcl_GetDouble(pSics->pTcl,argv[1],&dVal); - if(iRet == TCL_OK) /* float Value: drive */ - { - if(!SCMatchRights(pCon,usUser)) - { - return 0; - } - iRet = EVCDrive(self,pCon,(float)dVal); - if(iRet) - { - SCSendOK(pCon); - } - return iRet; - } - else if(strcmp(argv[1],"list") == 0) - { - EVCList(self,pCon); - return 1; - } - else if(strcmp(argv[1],"send") == 0) /* send to controller */ - { - Arg2Text(argc-2,&argv[2],pBueffel,255); - iRet = self->pDriv->Send(self->pDriv,pBueffel,pReply, 511); - SCWrite(pCon,pReply,eValue); - return iRet; - } - else if(strcmp(argv[1],"log") == 0) /* log commands */ - { - if(argc < 3) - { - SCWrite(pCon,"ERROR: insufficient number of commands for varlog",eError); - return 0; - } - return VarlogWrapper(self->pLog,pCon, - argv[2],argv[3],argv[0]); - } - else /* parameter request */ - { - strtolower(argv[1]); - /* - catch case of errorScript - */ - if(strcmp(argv[1],"errorscript") == 0) - { - if(self->errorScript != NULL) - { - snprintf(pBueffel,255,"%s.errorScript = %s",self->pName, - self->errorScript); - } - else - { - snprintf(pBueffel,255,"%s.errorScript = UNDEFINED", - self->pName); - } - SCWrite(pCon,pBueffel,eValue); - return 1; - } - /* - catch case of runScript - */ - if(strcmp(argv[1],"runscript") == 0) - { - if(self->runScript != NULL) - { - SCPrintf(pCon, eValue,"%s.runScript = %s",self->pName, - self->runScript); - } - else - { - SCPrintf(pCon, eValue,"%s.runScript = none",self->pName); - } - return 1; - } - /* - catch case for drivername - */ - if(strcmp(argv[1],"driver") == 0) - { - snprintf(pBueffel,255,"%s.driver = %s", self->pName, - self->driverName); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - iRet = EVCGetPar(self,argv[1],&fPos); - if(!iRet) - { - sprintf(pBueffel,"ERROR: parameter %s NOT found", - argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - else - { - sprintf(pBueffel,"%s.%s = %g",self->pName,argv[1],fPos); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - } + iRet = EVCGetPar(self, argv[1], &fPos); + if (!iRet) { + snprintf(pBueffel,255, "ERROR: parameter %s NOT found", argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } else { + snprintf(pBueffel,255, "%s.%s = %g", self->pName, argv[1], fPos); + SCWrite(pCon, pBueffel, eValue); + return 1; } - else /* try to set parameter */ - { - strtolower(argv[1]); - /* - first catch case of errorScript - */ - if(strcmp(argv[1],"errorscript") == 0) - { - if(self->errorScript != NULL) - { - free(self->errorScript); - } - self->errorScript = Arg2Tcl(argc-2,&argv[2],NULL,0); - SCSendOK(pCon); - SCparChange(pCon); - return 1; - } - /* - catch case of runScript - */ - if(strcmp(argv[1],"runscript") == 0) - { - if(self->runScript != NULL) - { - free(self->runScript); - } - if (strcasecmp(argv[2],"none") == 0) { - self->runScript = NULL; - } else { - self->runScript = Arg2Tcl(argc-2,&argv[2],NULL,0); - } - SCSendOK(pCon); - SCparChange(pCon); - return 1; - } - iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&dVal); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: %s no valid number", argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - iRet = EVCSetPar(self, argv[1],(float)dVal,pCon); - if(iRet) - { - SCSendOK(pCon); - SCparChange(pCon); - } - return iRet; + } + } else { /* try to set parameter */ + + strtolower(argv[1]); + /* + first catch case of errorScript + */ + if (strcmp(argv[1], "errorscript") == 0) { + if (self->errorScript != NULL) { + free(self->errorScript); } - return 0; /* not reached */ - } + self->errorScript = Arg2Tcl(argc - 2, &argv[2], NULL, 0); + SCSendOK(pCon); + SCparChange(pCon); + return 1; + } + /* + catch case of runScript + */ + if (strcmp(argv[1], "runscript") == 0) { + if (self->runScript != NULL) { + free(self->runScript); + } + if (strcasecmp(argv[2], "none") == 0) { + self->runScript = NULL; + } else { + self->runScript = Arg2Tcl(argc - 2, &argv[2], NULL, 0); + } + SCSendOK(pCon); + SCparChange(pCon); + return 1; + } + iRet = Tcl_GetDouble(pSics->pTcl, argv[2], &dVal); + if (iRet != TCL_OK) { + snprintf(pBueffel, 255,"ERROR: %s no valid number", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + iRet = EVCSetPar(self, argv[1], (float) dVal, pCon); + if (iRet) { + SCSendOK(pCon); + SCparChange(pCon); + } + return iRet; + } + return 0; /* not reached */ +} + /*-----------------------------------------------------------------------*/ -static int EVSaveStatus(void *pData, char *name, FILE *fil) +static int EVSaveStatus(void *pData, char *name, FILE * fil) { pEVControl evc = pData; pEVDriver pD = evc->pDriv; - + assert(evc); assert(pD); if (evc->creationArgs && pD->SavePars) { - fprintf(fil, "if {[catch { evfactory replace %s %s }] == 0} {\n", name, evc->creationArgs); + fprintf(fil, "if {[catch { evfactory replace %s %s }] == 0} {\n", name, + evc->creationArgs); if (pD->SavePars(pD, fil) == 1) { - fprintf(fil, " %s %s %g\n",evc->pName, "tolerance", ObVal(evc->pParam,TOLERANCE)); - fprintf(fil, " %s %s %g\n",evc->pName, "access", ObVal(evc->pParam,ACCESS)); - fprintf(fil, " %s %s %g\n",evc->pName, "ErrorHandler", ObVal(evc->pParam,ERRORHANDLER)); - fprintf(fil, " %s %s %g\n",evc->pName, "interrupt", ObVal(evc->pParam,INTERRUPT)); - fprintf(fil, " %s %s %g\n",evc->pName, "UpperLimit", ObVal(evc->pParam,UPLIMIT)); - fprintf(fil, " %s %s %g\n",evc->pName, "LowerLimit", ObVal(evc->pParam,LOWLIMIT)); - fprintf(fil, " %s %s %g\n",evc->pName, "SafeValue", ObVal(evc->pParam,SAFEVALUE)); - fprintf(fil, " %s %s %g\n",evc->pName, "MaxWait", ObVal(evc->pParam,MAXWAIT)); - fprintf(fil, " %s %s %g\n",evc->pName, "Settle", ObVal(evc->pParam,SETTLE)); - if(evc->errorScript != NULL) { - fprintf(fil, " %s errorScript %s\n", evc->pName, evc->errorScript); + fprintf(fil, " %s %s %g\n", evc->pName, "tolerance", + ObVal(evc->pParam, TOLERANCE)); + fprintf(fil, " %s %s %g\n", evc->pName, "access", + ObVal(evc->pParam, ACCESS)); + fprintf(fil, " %s %s %g\n", evc->pName, "ErrorHandler", + ObVal(evc->pParam, ERRORHANDLER)); + fprintf(fil, " %s %s %g\n", evc->pName, "interrupt", + ObVal(evc->pParam, INTERRUPT)); + fprintf(fil, " %s %s %g\n", evc->pName, "UpperLimit", + ObVal(evc->pParam, UPLIMIT)); + fprintf(fil, " %s %s %g\n", evc->pName, "LowerLimit", + ObVal(evc->pParam, LOWLIMIT)); + fprintf(fil, " %s %s %g\n", evc->pName, "SafeValue", + ObVal(evc->pParam, SAFEVALUE)); + fprintf(fil, " %s %s %g\n", evc->pName, "MaxWait", + ObVal(evc->pParam, MAXWAIT)); + fprintf(fil, " %s %s %g\n", evc->pName, "Settle", + ObVal(evc->pParam, SETTLE)); + if (evc->errorScript != NULL) { + fprintf(fil, " %s errorScript %s\n", evc->pName, + evc->errorScript); } - if(evc->runScript != NULL) { + if (evc->runScript != NULL) { fprintf(fil, " %s runScript %s\n", evc->pName, evc->runScript); } } @@ -1343,184 +1265,169 @@ static int EVSaveStatus(void *pData, char *name, FILE *fil) } return 1; } + /*--------------------------------------------------------------------------*/ /* standard method for saving parameters */ -static int EVCSaveStd(void *pData, char *name, FILE *fil) +static int EVCSaveStd(void *pData, char *name, FILE * fil) { return 1; } + /*-----------------------------------------------------------------------*/ -pEVControl MakeEVController(pEVDriver pDriv, SConnection *pCon, +pEVControl MakeEVController(pEVDriver pDriv, SConnection * pCon, ObjectFunc wrapper, int argc, char *argv[]) { pEVControl pNew; int status = 1; char pBueffel[512]; char pError[132]; - + if (pDriv == NULL) { - SCWrite(pCon,"ERROR: failed to create driver",eError); + SCWrite(pCon, "ERROR: failed to create driver", eError); return NULL; } - pNew = CreateEVController(pDriv,argv[0],&status); + pNew = CreateEVController(pDriv, argv[0], &status); if (status != 1) { printf("CEVC error\n"); - SCWrite(pCon,"ERROR: failed to initialize device", eError); - pDriv->GetError(pDriv,&status,pError,sizeof pError -1); + SCWrite(pCon, "ERROR: failed to initialize device", eError); + pDriv->GetError(pDriv, &status, pError, sizeof pError - 1); printf("HW %s\n", pError); - sprintf(pBueffel,"HW reported: %s",pError); - SCWrite(pCon,pBueffel,eError); + sprintf(pBueffel, "HW reported: %s", pError); + SCWrite(pCon, pBueffel, eError); } if (pNew == NULL) { printf("CEVC failed\n"); - SCWrite(pCon,"ERROR: failed to create environment device object", + SCWrite(pCon, "ERROR: failed to create environment device object", eError); DeleteEVDriver(pDriv); return NULL; } if (wrapper == NULL) { - AddCommand(pServ->pSics,argv[0],EVControlWrapper,DeleteEVController,pNew); + AddCommand(pServ->pSics, argv[0], EVControlWrapper, DeleteEVController, + pNew); } else { - AddCommand(pServ->pSics,argv[0],wrapper,DeleteEVController,pNew); + AddCommand(pServ->pSics, argv[0], wrapper, DeleteEVController, pNew); } return pNew; } + /*-----------------------------------------------------------------------*/ -static pEVControl InstallCommonControllers(SicsInterp *pSics, - SConnection *pCon, - int argc, char *argv[], - int *found) +static pEVControl InstallCommonControllers(SicsInterp * pSics, + SConnection * pCon, + int argc, char *argv[], + int *found) { pEVControl pNew = NULL; - pEVDriver pDriv = NULL; - char pBueffel[512],pError[132]; + pEVDriver pDriv = NULL; + char pBueffel[512], pError[132]; int iRet; - int (*Wrapper)(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) = EVControlWrapper; + int (*Wrapper) (SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) = EVControlWrapper; - *found=1; - if(strcmp(argv[3],"sim") == 0) /* SIM driver */ - { + *found = 1; + if (strcmp(argv[3], "sim") == 0) { /* SIM driver */ /* Create a Sim Driver */ - pDriv = CreateSIMEVDriver(argc-4,&argv[4]); - if(!pDriv) - { + pDriv = CreateSIMEVDriver(argc - 4, &argv[4]); + if (!pDriv) { SCWrite(pCon, - "ERROR: failed to create Environment Device driver", - eError); - return NULL; + "ERROR: failed to create Environment Device driver", eError); + return NULL; } - } - else if(strcmp(argv[3],"tcl") == 0) /* Tcl driver */ - { - /* Create a Tcl driver */ - pDriv = CreateTclDriver(argc-4,&argv[4],argv[2], pCon); - if(!pDriv) - { - SCWrite(pCon,"ERROR: failed to create TCL device driver",eError); - return NULL; - } - /* got a driver, initialise everything */ - pNew = CreateEVController(pDriv,argv[2],&iRet); - if(!pNew) - { - SCWrite(pCon,"ERROR creating Environment Controller",eError); - DeleteEVDriver(pDriv); - return NULL; - } - if(!iRet) - { - SCWrite(pCon,"ERROR: problem initialising Environment controller", + } else if (strcmp(argv[3], "tcl") == 0) { /* Tcl driver */ + /* Create a Tcl driver */ + pDriv = CreateTclDriver(argc - 4, &argv[4], argv[2], pCon); + if (!pDriv) { + SCWrite(pCon, "ERROR: failed to create TCL device driver", eError); + return NULL; + } + /* got a driver, initialise everything */ + pNew = CreateEVController(pDriv, argv[2], &iRet); + if (!pNew) { + SCWrite(pCon, "ERROR creating Environment Controller", eError); + DeleteEVDriver(pDriv); + return NULL; + } + if (!iRet) { + SCWrite(pCon, "ERROR: problem initialising Environment controller", eError); - pDriv->GetError(pDriv,&iRet,pError,131); - sprintf(pBueffel,"HW reported: %s",pError); - SCWrite(pCon,pBueffel,eError); - } - Wrapper = TclEnvironmentWrapper; - pNew->iTcl = 1; - /* make ev parameters available to Tcl */ - UpdateTclVariable(pNew->pDriv,"tolerance", - ObVal(pNew->pParam,TOLERANCE)); - UpdateTclVariable(pNew->pDriv,"upperlimit", - ObVal(pNew->pParam,UPLIMIT)); - UpdateTclVariable(pNew->pDriv,"lowerlimit", - ObVal(pNew->pParam,LOWLIMIT)); - } - else if(strcmp(argv[3],"gencon") == 0) /* general controller */ - { + pDriv->GetError(pDriv, &iRet, pError, 131); + sprintf(pBueffel, "HW reported: %s", pError); + SCWrite(pCon, pBueffel, eError); + } + Wrapper = TclEnvironmentWrapper; + pNew->iTcl = 1; + /* make ev parameters available to Tcl */ + UpdateTclVariable(pNew->pDriv, "tolerance", + ObVal(pNew->pParam, TOLERANCE)); + UpdateTclVariable(pNew->pDriv, "upperlimit", + ObVal(pNew->pParam, UPLIMIT)); + UpdateTclVariable(pNew->pDriv, "lowerlimit", + ObVal(pNew->pParam, LOWLIMIT)); + } else if (strcmp(argv[3], "gencon") == 0) { /* general controller */ /* Create a driver */ - pDriv = MakeControllerEnvironmentDriver(argc-4,&argv[4]); - if(!pDriv) - { + pDriv = MakeControllerEnvironmentDriver(argc - 4, &argv[4]); + if (!pDriv) { SCWrite(pCon, - "ERROR: failed to create Controller Environment driver", - eError); + "ERROR: failed to create Controller Environment driver", + eError); return NULL; } } else { /* not recognized */ - *found=0; + *found = 0; return NULL; } - if(pNew == NULL) /* not yet initialized */ - { - pNew = CreateEVController(pDriv,argv[2],&iRet); - if(!pNew) - { - SCWrite(pCon,"ERROR creating Environment Controller",eError); + if (pNew == NULL) { /* not yet initialized */ + pNew = CreateEVController(pDriv, argv[2], &iRet); + if (!pNew) { + SCWrite(pCon, "ERROR creating Environment Controller", eError); DeleteEVDriver(pDriv); return NULL; } - if(!iRet) - { - SCWrite(pCon,"ERROR: problem initialising Environment controller", + if (!iRet) { + SCWrite(pCon, "ERROR: problem initialising Environment controller", eError); - pDriv->GetError(pDriv,&iRet,pError,131); - sprintf(pBueffel,"HW reported: %s",pError); - SCWrite(pCon,pBueffel,eError); + pDriv->GetError(pDriv, &iRet, pError, 131); + sprintf(pBueffel, "HW reported: %s", pError); + SCWrite(pCon, pBueffel, eError); } } /* install command */ - iRet = AddCommand(pSics,argv[2],Wrapper, - DeleteEVController, - pNew); - if(!iRet) - { - sprintf(pBueffel,"ERROR: duplicate command %s not created", - argv[2]); - DeleteEVController((void *)pNew); - SCWrite(pCon,pBueffel,eError); + iRet = AddCommand(pSics, argv[2], Wrapper, DeleteEVController, pNew); + if (!iRet) { + snprintf(pBueffel,511, "ERROR: duplicate command %s not created", argv[2]); + DeleteEVController((void *) pNew); + SCWrite(pCon, pBueffel, eError); return NULL; } return pNew; } -int RemoveEVController(SConnection *pCon, char *name) { +int RemoveEVController(SConnection * pCon, char *name) +{ char pBueffel[512]; int iRet; - - if(!pServ->pExecutor) - { + + if (!pServ->pExecutor) { return 1; } - if(isInRunMode(pServ->pExecutor)) - { - SCWrite(pCon,"ERROR: cannot delete while running",eError); - return 0; + if (isInRunMode(pServ->pExecutor)) { + SCWrite(pCon, "ERROR: cannot delete while running", eError); + return 0; } - EVUnregister(FindEMON(pServ->pSics),name); - iRet = RemoveCommand(pServ->pSics,name); - if(!iRet) - { - sprintf(pBueffel,"ERROR: %s not found, NOT deleted",name); - SCWrite(pCon,pBueffel,eError); + EVUnregister(FindEMON(pServ->pSics), name); + iRet = RemoveCommand(pServ->pSics, name); + if (!iRet) { + snprintf(pBueffel,511, "ERROR: %s not found, NOT deleted", name); + SCWrite(pCon, pBueffel, eError); return 0; } return 1; } + /*------------------------------------------------------------------------- EVControlFactory implements a SICS command which creates and deletes Controllers at run-time. Syntax: @@ -1529,107 +1436,99 @@ int RemoveEVController(SConnection *pCon, char *name) { -- creates a new controller name with a simulation driver ControlFactory del name -- deletes controller name --------------------------------------------------------------------------*/ - int EVControlFactory(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - pEVControl pNew = NULL; - char pBueffel[512],pError[132]; - int iRet, found; - CommandList *pCom = NULL; - pSite site = NULL; - - assert(pSics); - assert(pCon); - - if(argc < 3) - { - SCWrite(pCon,"ERROR: Insufficient number of arguments to EVFactory", - eError); - return 0; - } - - /* check rights */ - if(!SCMatchRights(pCon,usUser)) - { - return 0; - } - - strtolower(argv[1]); - if(strcmp(argv[1],"del") == 0) /* delete */ - { - if (RemoveEVController(pCon, argv[2])) { - SCSendOK(pCon); - return 1; - } else { - return 0; - } - } - else if(strcmp(argv[1],"new") == 0 || strcmp(argv[1], "replace") == 0) - /* make a new one */ - { - /* argv[2] = name */ - /* argv[3] must be type */ - if(argc < 4) - { - SCWrite(pCon,"ERROR: no type specified for Environment Controller", - eError); - return 0; - } - strtolower(argv[2]); - strtolower(argv[3]); - if (FindCommandData(pSics, argv[2], "Environment_Controller")) { - if (strcmp(argv[1], "replace") == 0) { - if (!RemoveEVController(pCon, argv[2])) { - return 0; - } - } else { - sprintf(pBueffel, - "ERROR: environment device %s already installed, delete first", - argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - } - pCom = FindCommand(pSics,argv[2]); - if(pCom) - { - sprintf(pBueffel, "ERROR: command %s already exists", argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - pNew = InstallCommonControllers(pSics,pCon,argc,argv,&found); - if (!found) { - site = getSite(); - if(site != NULL){ - pNew = site->InstallEnvironmentController(pSics,pCon,argc,argv); - } else { - sprintf(pBueffel, - "ERROR: %s not recognized as a valid driver type", - argv[3]); - SCWrite(pCon,pBueffel,eError); - pNew = NULL; - } - } - if(pNew == NULL){ - /* error message is already written */ - return 0; - } - if (pNew->pDriv->SavePars) { - pNew->creationArgs = Arg2Tcl(argc-3, argv+3, NULL, 0); - pNew->pDes->SaveStatus = EVSaveStatus; - } else { - pNew->creationArgs = NULL; - } - - EVRegisterController(FindEMON(pSics),argv[2],pNew, pCon); - pNew->driverName = strdup(argv[3]); - SCSendOK(pCon); - return 1; - } - SCWrite(pCon,"ERROR: command not understood",eError); +-------------------------------------------------------------------------*/ +int EVControlFactory(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pEVControl pNew = NULL; + char pBueffel[512], pError[132]; + int iRet, found; + CommandList *pCom = NULL; + pSite site = NULL; + + assert(pSics); + assert(pCon); + + if (argc < 3) { + SCWrite(pCon, "ERROR: Insufficient number of arguments to EVFactory", + eError); + return 0; + } + + /* check rights */ + if (!SCMatchRights(pCon, usUser)) { + return 0; + } + + strtolower(argv[1]); + if (strcmp(argv[1], "del") == 0) { /* delete */ + if (RemoveEVController(pCon, argv[2])) { + SCSendOK(pCon); + return 1; + } else { return 0; - } - - + } + } else if (strcmp(argv[1], "new") == 0 + || strcmp(argv[1], "replace") == 0) + /* make a new one */ + { + /* argv[2] = name */ + /* argv[3] must be type */ + if (argc < 4) { + SCWrite(pCon, "ERROR: no type specified for Environment Controller", + eError); + return 0; + } + strtolower(argv[2]); + strtolower(argv[3]); + if (FindCommandData(pSics, argv[2], "Environment Controller")) { + if (strcmp(argv[1], "replace") == 0) { + if (!RemoveEVController(pCon, argv[2])) { + return 0; + } + } else { + snprintf(pBueffel, 511, + "ERROR: environment device %s already installed, delete first", + argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + } + pCom = FindCommand(pSics, argv[2]); + if (pCom) { + snprintf(pBueffel,511, "ERROR: command %s already exists", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + pNew = InstallCommonControllers(pSics, pCon, argc, argv, &found); + if (!found) { + site = getSite(); + if (site != NULL) { + pNew = site->InstallEnvironmentController(pSics, pCon, argc, argv); + } else { + snprintf(pBueffel,511, + "ERROR: %s not recognized as a valid driver type", + argv[3]); + SCWrite(pCon, pBueffel, eError); + pNew = NULL; + } + } + if (pNew == NULL) { + /* error message is already written */ + return 0; + } + if (pNew->pDriv->SavePars) { + pNew->creationArgs = Arg2Tcl(argc - 3, argv + 3, NULL, 0); + pNew->pDes->SaveStatus = EVSaveStatus; + } else { + pNew->creationArgs = NULL; + } + EVRegisterController(FindEMON(pSics), argv[2], pNew, pCon); + pNew->driverName = strdup(argv[3]); + SCSendOK(pCon); + return 1; + } + SCWrite(pCon, "ERROR: command not understood", eError); + return 0; +} diff --git a/evcontroller.h b/evcontroller.h index 96fc8d08..560c1244 100644 --- a/evcontroller.h +++ b/evcontroller.h @@ -16,33 +16,33 @@ #line 153 "evcontroller.w" -/*--------------------------- live & death --------------------------------*/ - typedef struct __EVControl *pEVControl; - typedef struct __EVDriver *pEVDriver; +/*--------------------------- live & death --------------------------------*/ +typedef struct __EVControl *pEVControl; +typedef struct __EVDriver *pEVDriver; - pEVControl CreateEVController(pEVDriver pDriv, char *pName, int *iErr); - void DeleteEVController(void *pData); - pEVControl MakeEVController(pEVDriver pDriv, SConnection *pCon, - ObjectFunc wrapper, int argc, char *argv[]); +pEVControl CreateEVController(pEVDriver pDriv, char *pName, int *iErr); +void DeleteEVController(void *pData); +pEVControl MakeEVController(pEVDriver pDriv, SConnection * pCon, + ObjectFunc wrapper, int argc, char *argv[]); /*-------------------------- driving ---------------------------------*/ - int EVCDrive(pEVControl self,SConnection *pCon, float fNew); - int EVCGetPos(pEVControl self, SConnection *pCon,float *fVal); +int EVCDrive(pEVControl self, SConnection * pCon, float fNew); +int EVCGetPos(pEVControl self, SConnection * pCon, float *fVal); /*------------------------ parameters ----------------------------------*/ - EVMode EVCGetMode(pEVControl self); - int EVCSetMode(pEVControl self, EVMode eNew); - int EVCSetPar(pEVControl self, char *name, float fNew, SConnection *pCon); - int EVCGetPar(pEVControl self, char *name, float *fVal); - int EVCList(pEVControl self, SConnection *pCon); +EVMode EVCGetMode(pEVControl self); +int EVCSetMode(pEVControl self, EVMode eNew); +int EVCSetPar(pEVControl self, char *name, float fNew, SConnection * pCon); +int EVCGetPar(pEVControl self, char *name, float *fVal); +int EVCList(pEVControl self, SConnection * pCon); /*------------------------- logging -----------------------------------*/ - pVarLog EVCGetVarLog(pEVControl self); +pVarLog EVCGetVarLog(pEVControl self); /*----------------- Interface to SICS interpreter -----------------------*/ - int EVControlWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - - int EVControlFactory(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - +int EVControlWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); + +int EVControlFactory(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); + #line 245 "evcontroller.w" diff --git a/evcontroller.i b/evcontroller.i index ad57cdbc..cdc30101 100644 --- a/evcontroller.i +++ b/evcontroller.i @@ -41,7 +41,7 @@ int iWarned; int iTcl; int iStop; - SCStore *conn; + SConnection *conn; char *creationArgs; char *runScript; void *pPrivate; diff --git a/evcontroller.tex b/evcontroller.tex index c51b8ee5..b11ecba6 100644 --- a/evcontroller.tex +++ b/evcontroller.tex @@ -52,7 +52,7 @@ $\langle$evdata {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ int iWarned;@\\ \mbox{}\verb@ int iTcl;@\\ \mbox{}\verb@ int iStop;@\\ -\mbox{}\verb@ SCStore *conn;@\\ +\mbox{}\verb@ SConnection *conn;@\\ \mbox{}\verb@ char *creationArgs;@\\ \mbox{}\verb@ char *runScript;@\\ \mbox{}\verb@ void *pPrivate;@\\ diff --git a/evcontroller.w b/evcontroller.w index 0146f28f..b93cbc6d 100644 --- a/evcontroller.w +++ b/evcontroller.w @@ -47,7 +47,7 @@ used by EVControl: int iWarned; int iTcl; int iStop; - SCStore *conn; + SConnection *conn; char *creationArgs; char *runScript; void *pPrivate; diff --git a/evdriver.c b/evdriver.c index 337343e1..d7a1c3ba 100644 --- a/evdriver.c +++ b/evdriver.c @@ -45,28 +45,27 @@ #include "evdriver.h" /*------------------------------------------------------------------------*/ - pEVDriver CreateEVDriver(int argc, char *argv[]) - { - pEVDriver pNew = NULL; - - pNew = (pEVDriver)malloc(sizeof(EVDriver)); - if(!pNew) - { - return NULL; - } - memset(pNew,0,sizeof(EVDriver)); - pNew->GetValues = NULL; /* method will be replaced by default when NULL */ - pNew->SavePars = NULL; /* no save by default */ - return pNew; - } +pEVDriver CreateEVDriver(int argc, char *argv[]) +{ + pEVDriver pNew = NULL; + + pNew = (pEVDriver) malloc(sizeof(EVDriver)); + if (!pNew) { + return NULL; + } + memset(pNew, 0, sizeof(EVDriver)); + pNew->GetValues = NULL; /* method will be replaced by default when NULL */ + pNew->SavePars = NULL; /* no save by default */ + return pNew; +} + /*-------------------------------------------------------------------------*/ - void DeleteEVDriver(pEVDriver self) - { - assert(self); - - if(self->KillPrivate) - { - self->KillPrivate(self->pPrivate); - } - free(self); - } +void DeleteEVDriver(pEVDriver self) +{ + assert(self); + + if (self->KillPrivate) { + self->KillPrivate(self->pPrivate); + } + free(self); +} diff --git a/evdriver.h b/evdriver.h index f6d00d1f..9fbe7492 100644 --- a/evdriver.h +++ b/evdriver.h @@ -3,10 +3,10 @@ #ifndef SICSEVCONTROL -typedef struct __EVDriver *pEVDriver; +typedef struct __EVDriver *pEVDriver; #endif -#include +#include #endif diff --git a/event.c b/event.c index 98ab43be..233dd792 100644 --- a/event.c +++ b/event.c @@ -45,47 +45,45 @@ WATCHIT! see event.h for defines of event codes! The list below MUST match. */ - static char *pEvent[] = { - "VARCHANGE", - "MOTORDRIVE", - "MONITOR", - "ROTORSTART", - "ROTORMOVE", - "SCANEND", - "SCANSTART", - "SCANPOINT", - "WLCHANGE", - "REFLECTIONDONE", - "COUNTSTART", - "COUNTEND", - "FILELOADED", - "MOTEND", - "BATCHSTART", - "BATCHAREA", - "BATCHEND", - "DRIVSTAT", - "STATUS", - "POSITION", - "HDBVAL", - "STATESTART", - "STATEEND", - NULL - }; - +static char *pEvent[] = { + "VARCHANGE", + "MOTORDRIVE", + "MONITOR", + "ROTORSTART", + "ROTORMOVE", + "SCANEND", + "SCANSTART", + "SCANPOINT", + "WLCHANGE", + "REFLECTIONDONE", + "COUNTSTART", + "COUNTEND", + "FILELOADED", + "MOTEND", + "BATCHSTART", + "BATCHAREA", + "BATCHEND", + "DRIVSTAT", + "STATUS", + "POSITION", + "HDBVAL", + "STATESTART", + "STATEEND", + "NEWTARGET", + "DIMCHANGE", + NULL +}; + /*---------------------------------------------------------------------------*/ - int Text2Event(char *pText) - { - int iVal = 0; - - while(pEvent[iVal] != NULL) - { - if(strcmp(pEvent[iVal],pText) == 0) - { - return iVal; - } - iVal++; - } - return -1; +int Text2Event(char *pText) +{ + int iVal = 0; + + while (pEvent[iVal] != NULL) { + if (strcmp(pEvent[iVal], pText) == 0) { + return iVal; + } + iVal++; } - - + return -1; +} diff --git a/event.h b/event.h index 3febe47f..ef9dbabf 100644 --- a/event.h +++ b/event.h @@ -1,5 +1,5 @@ -#line 100 "event.w" +#line 103 "event.w" /*---------------------------------------------------------------------------- E V E N T @@ -18,7 +18,7 @@ int Text2Event(char *pText); -#line 113 "event.w" +#line 116 "event.w" @@ -47,17 +47,20 @@ #define HDBVAL 20 #define STSTART 21 #define STEND 22 -#define STPAUSE 23 -#define STCONTINUE 24 -#define STBUSY 25 -#define STIDLE 26 +#define NEWTARGET 23 +#define DIMCHANGE 24 -#line 115 "event.w" +#line 118 "event.w" +/*----------------- event data structure for the NEWTARGET event ---------*/ +typedef struct { + char *name; + float target; + } NewTarget, *pNewTarget; /*--------------- Signals for the Signalfunction of each task ------------*/ -#line 82 "event.w" +#line 85 "event.w" #define SICSINT 300 #define SICSBROADCAST 301 @@ -66,6 +69,6 @@ #define COMLOG 304 #define CRONLIST 305 -#line 118 "event.w" +#line 126 "event.w" #endif diff --git a/event.tex b/event.tex index c3856e01..34aef4fb 100644 --- a/event.tex +++ b/event.tex @@ -58,6 +58,8 @@ $\langle$VE {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@#define HDBVAL 20@\\ \mbox{}\verb@#define STSTART 21@\\ \mbox{}\verb@#define STEND 22@\\ +\mbox{}\verb@#define NEWTARGET 23@\\ +\mbox{}\verb@#define DIMCHANGE 24@\\ \mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} @@ -96,6 +98,7 @@ operation. \item[POSITION] ANSTO defined code \item[HDBVAL] The Hdb is notified of a value change. The eventData will be the object on which the data changed. + \item[NEWTARGET] is invoked when a new target has been set on a drivable. \end{description} Furthermore event contains system wide signal codes which are interpreted in @@ -157,6 +160,11 @@ data is the string to send. \mbox{}\verb@@\\ \mbox{}\verb@@$\langle$VE {\footnotesize ?}$\rangle$\verb@@\\ \mbox{}\verb@@\\ +\mbox{}\verb@/*----------------- event data structure for the NEWTARGET event ---------*/@\\ +\mbox{}\verb@typedef struct {@\\ +\mbox{}\verb@ char *name;@\\ +\mbox{}\verb@ float target;@\\ +\mbox{}\verb@ } NewTarget, *pNewTarget;@\\ \mbox{}\verb@/*--------------- Signals for the Signalfunction of each task ------------*/@\\ \mbox{}\verb@@$\langle$VSIG {\footnotesize ?}$\rangle$\verb@ @\\ \mbox{}\verb@#endif@\\ diff --git a/event.w b/event.w index fc8e584d..6f4ed0c0 100644 --- a/event.w +++ b/event.w @@ -41,6 +41,8 @@ if the event code is not known, else the apropriate event code. #define HDBVAL 20 #define STSTART 21 #define STEND 22 +#define NEWTARGET 23 +#define DIMCHANGE 24 @} \begin{description} \item[VALUECHANGE] This is a variable changing its value. As event data a pointer to the @@ -71,6 +73,7 @@ operation. \item[POSITION] ANSTO defined code \item[HDBVAL] The Hdb is notified of a value change. The eventData will be the object on which the data changed. + \item[NEWTARGET] is invoked when a new target has been set on a drivable. \end{description} Furthermore event contains system wide signal codes which are interpreted in @@ -114,6 +117,11 @@ data is the string to send. @ +/*----------------- event data structure for the NEWTARGET event ---------*/ +typedef struct { + char *name; + float target; + } NewTarget, *pNewTarget; /*--------------- Signals for the Signalfunction of each task ------------*/ @ #endif diff --git a/exe.w b/exe.w index cd01232c..f68c3625 100644 --- a/exe.w +++ b/exe.w @@ -159,6 +159,7 @@ typedef struct __EXEMAN{ int runList; pExeBuf uploadBuffer; int echo; + SConnection *runCon; }ExeMan, *pExeMan; @} The fields: diff --git a/exebuf.c b/exebuf.c index 45d9dee7..e5ae6c56 100644 --- a/exebuf.c +++ b/exebuf.c @@ -18,149 +18,217 @@ #include "dynstring.h" #include "exebuf.i" #include "status.h" +#include "commandlog.h" + +char *ConID(SConnection *pCon); /* in conman.c */ /*-----------------------------------------------------------------------*/ -pExeBuf exeBufCreate(char *name){ +pExeBuf exeBufCreate(char *name) +{ pExeBuf pNew = NULL; - pNew = (pExeBuf)malloc(sizeof(ExeBuf)); - if(pNew == NULL){ + pNew = (pExeBuf) malloc(sizeof(ExeBuf)); + if (pNew == NULL) { return NULL; } - memset(pNew,0,sizeof(ExeBuf)); + memset(pNew, 0, sizeof(ExeBuf)); pNew->name = strdup(name); - pNew->bufferContent = CreateDynString(1024,1024); - if(!pNew->bufferContent){ + pNew->bufferContent = CreateDynString(1024, 1024); + if (!pNew->bufferContent) { return NULL; } return pNew; } + /*----------------------------------------------------------------------*/ -void exeBufKill(void *data){ - exeBufDelete((pExeBuf)data); +void exeBufKill(void *data) +{ + exeBufDelete((pExeBuf) data); } + /*-----------------------------------------------------------------------*/ -void exeBufDelete(pExeBuf self){ - if(self == NULL){ +void exeBufDelete(pExeBuf self) +{ + if (self == NULL) { return; } - if(self->name != NULL){ + if (self->name != NULL) { free(self->name); self->name = NULL; } - if(self->bufferContent != NULL){ + if (self->bufferContent != NULL) { DeleteDynString(self->bufferContent); self->bufferContent = NULL; } free(self); } + /*----------------------------------------------------------------------*/ -int exeBufAppend(pExeBuf self, char *line){ +int exeBufAppend(pExeBuf self, char *line) +{ int status; assert(self); - status = DynStringConcat(self->bufferContent,line); - if(strrchr(line,(int)'\n') == NULL){ - DynStringConcatChar(self->bufferContent,'\n'); + status = DynStringConcat(self->bufferContent, line); + if (strrchr(line, (int) '\n') == NULL) { + DynStringConcatChar(self->bufferContent, '\n'); } return status; } + /*-----------------------------------------------------------------------*/ -static char *locateName(char *filename){ +static char *locateName(char *filename) +{ char *pPtr; int i; - pPtr = filename + strlen(filename) -1; - for(i = strlen(filename) -1; i > 0; i--,pPtr--){ - if(*pPtr == '/'){ + pPtr = filename + strlen(filename) - 1; + for (i = strlen(filename) - 1; i > 0; i--, pPtr--) { + if (*pPtr == '/') { pPtr++; return pPtr; } } return filename; } + /*-----------------------------------------------------------------------*/ -int exeBufLoad(pExeBuf self, char *filename){ - char line[256]; +int exeBufLoad(pExeBuf self, char *filename) +{ + char line[256], *pPtr; FILE *fd = NULL; - int status; + int status, idx; assert(self); - fd = fopen(filename,"r"); - if(fd == NULL){ + fd = fopen(filename, "r"); + if (fd == NULL) { return 0; } - while(fgets(line,255,fd) != NULL){ + while (fgets(line, 255, fd) != NULL) { /* Do not use exeBufAppend here. Lines longer than 255 would get newline characters within the line */ - status = DynStringConcat(self->bufferContent,line); - if(status != 1){ + status = DynStringConcat(self->bufferContent, line); + if (status != 1) { fclose(fd); return 0; } } fclose(fd); - if(self->name != NULL){ + + /** + * make sure that there is a \n at the end + */ + idx = GetDynStringLength(self->bufferContent); + pPtr = GetCharArray(self->bufferContent); + if(pPtr[idx-1] != '\n'){ + DynStringConcat(self->bufferContent,"\n"); + } + + if (self->name != NULL) { free(self->name); } self->name = strdup(locateName(filename)); return 1; } + /*----------------------------------------------------------------------*/ -int exeBufSave(pExeBuf self, char *filename){ +int exeBufSave(pExeBuf self, char *filename) +{ FILE *fd = NULL; - fd = fopen(filename,"w"); - if(fd == NULL){ + fd = fopen(filename, "w"); + if (fd == NULL) { return 0; } - fputs(GetCharArray(self->bufferContent),fd); + fputs(GetCharArray(self->bufferContent), fd); fclose(fd); self->name = strdup(locateName(filename)); return 1; } + /*================ process batch buffer ==============================*/ -static pDynString findBlockEnd(pExeBuf self){ +static pDynString findBlockEnd(pExeBuf self) +{ pDynString command = NULL; char *buffer = NULL; int i; assert(self); - command = CreateDynString(80,80); - if(command == NULL){ + command = CreateDynString(80, 80); + if (command == NULL) { return NULL; } buffer = GetCharArray(self->bufferContent); - if(self->end != -1){ + if (self->end != -1) { self->start = self->end + 1; } - for(i = self->start; i < strlen(buffer); i++){ - DynStringConcatChar(command,buffer[i]); - if(buffer[i] == '\n'){ + for (i = self->start; i < strlen(buffer); i++) { + DynStringConcatChar(command, buffer[i]); + if (buffer[i] == '\n') { self->lineno++; - if(Tcl_CommandComplete(GetCharArray(command))){ - self->end = i; - return command; + if (Tcl_CommandComplete(GetCharArray(command))) { + self->end = i; + return command; } } } DeleteDynString(command); return NULL; } +/*-----------------attempt at a faster version ------------------------------- + * But this only saves on the ConcatChar side of things...... + * + * */ +static pDynString findBlockEndExp(pExeBuf self) +{ + pDynString command = NULL; + char *buffer = NULL; + char *cStart, *cEnd; + int i, len; + + assert(self); + + command = CreateDynString(80, 80); + if (command == NULL) { + return NULL; + } + buffer = GetCharArray(self->bufferContent); + if (self->end != -1) { + self->start = self->end + 1; + } + cStart = buffer +self->start; + cEnd = strchr(cStart,'\n'); + while(cEnd != NULL){ + len = cEnd - cStart+1; + DynStringConcatBytes(command,cStart, len); + self->lineno++; + if (Tcl_CommandComplete(GetCharArray(command))) { + self->end += len; + return command; + } + cStart = cEnd+1; + cEnd = strchr(cStart,'\n'); + } + + DeleteDynString(command); + return NULL; +} + /*---------------------------------------------------------------------*/ -int exeBufProcess(pExeBuf self, SicsInterp *pSics, - SConnection *pCon, pICallBack pCall, int echo){ +int exeBufProcess(pExeBuf self, SicsInterp * pSics, + SConnection * pCon, pICallBack pCall, int echo) +{ pDynString command = NULL; Tcl_Interp *pTcl = NULL; int status; - + static int weWantLogging = 1; char *cmd; char cmdName[128]; char *ende; int l; - + assert(self); assert(pSics); @@ -169,19 +237,19 @@ int exeBufProcess(pExeBuf self, SicsInterp *pSics, self->lineno = 0; pTcl = InterpGetTcl(pSics); - if(pCall != NULL){ - InvokeCallBack(pCall,BATCHSTART,self->name); + if (pCall != NULL) { + InvokeCallBack(pCall, BATCHSTART, self->name); } - + if (echo) { - SCsetMacro(pCon,0); + SCsetMacro(pCon, 0); } - while((command = findBlockEnd(self)) != NULL){ - if(pCall != NULL){ - InvokeCallBack(pCall,BATCHAREA,NULL); + while ((command = findBlockEnd(self)) != NULL) { + if (pCall != NULL) { + InvokeCallBack(pCall, BATCHAREA, NULL); } cmd = GetCharArray(command); - + if (echo) { /* find first word */ while (*cmd == ' ') { @@ -196,53 +264,61 @@ int exeBufProcess(pExeBuf self, SicsInterp *pSics, strncpy(cmdName, cmd, l); cmdName[l] = '\0'; if (FindCommand(pSics, cmdName) != NULL) { - /* print only SICS commands */ - SCPrintf(pCon, eValue, "%s:%d>> %s",self->name,self->lineno,cmd); + /* print only SICS commands */ + SCPrintf(pCon, eLog, "%s:%d>> %s", self->name, self->lineno, + cmd); + } else { + /* debugging */ + /* SCPrintf(pCon, eValue, "%s:%d>> %s",self->name,self->lineno,cmd); */ } } } - - status = Tcl_Eval(pTcl,cmd); - if(status != TCL_OK){ - if(pCon->sicsError == 0){ - /* - Tcl Error - */ - if(strlen(pTcl->result) >= 2){ - SCWrite(pCon,pTcl->result,eError); + + traceCommand(ConID(pCon),"batch:%s", cmd); + status = Tcl_Eval(pTcl, cmd); + if (status != TCL_OK) { + if (pCon->sicsError == 0) { + /* + Tcl Error + */ + if (strlen(pTcl->result) >= 2) { + SCPrintf(pCon, eError, "ERROR: Tcl reported: %s", + pTcl->result); } - SCWrite(pCon,"ERROR: Tcl error in block:",eError); - SCWrite(pCon,GetCharArray(command),eError); - SCWrite(pCon,"ERROR: end of Tcl error block",eError); } else { - /* - SICS error: has already been reported - */ - pCon->sicsError = 0; + SCWrite(pCon, pTcl->result, eError); + pCon->sicsError = 0; } + SCWrite(pCon, "ERROR: above error was in block:", eError); + SCWrite(pCon, cmd, eError); + SCWrite(pCon, "ERROR: end of Tcl error block", eError); } DeleteDynString(command); - if(SCGetInterrupt(pCon) >= eAbortBatch){ - SCWrite(pCon,"ERROR: batch processing interrupted",eError); - InvokeCallBack(pCall,BATCHEND,self->name); + if (SCGetInterrupt(pCon) >= eAbortBatch) { + SCWrite(pCon, "ERROR: batch processing interrupted", eError); SetStatus(eEager); - return 0; + if (pCall != NULL) { + InvokeCallBack(pCall, BATCHEND, self->name); + } + return 0; } else { - SCSetInterrupt(pCon,eContinue); + SCSetInterrupt(pCon, eContinue); } } - if(pCall != NULL){ - InvokeCallBack(pCall,BATCHEND,self->name); + if (pCall != NULL) { + InvokeCallBack(pCall, BATCHEND, self->name); } return 1; } + /*---------------------------------------------------------------------*/ -int exeBufProcessErrList(pExeBuf self, SicsInterp *pSics, - SConnection *pCon, int errList){ +int exeBufProcessErrList(pExeBuf self, SicsInterp * pSics, + SConnection * pCon, int errList) +{ pDynString command = NULL; Tcl_Interp *pTcl = NULL; int status; - + static int weWantLogging = 1; char *cmd; char cmdName[128]; @@ -250,7 +326,7 @@ int exeBufProcessErrList(pExeBuf self, SicsInterp *pSics, char msg[132]; char *ende; int l; - + assert(self); assert(pSics); @@ -259,60 +335,64 @@ int exeBufProcessErrList(pExeBuf self, SicsInterp *pSics, self->lineno = 0; pTcl = InterpGetTcl(pSics); - while((command = findBlockEnd(self)) != NULL){ + while ((command = findBlockEnd(self)) != NULL) { cmd = GetCharArray(command); - - status = Tcl_Eval(pTcl,cmd); - if(status != TCL_OK){ - LLDstringAppend(errList,cmd); - error = (char *)Tcl_GetStringResult(pTcl); - snprintf(msg, sizeof msg, "#ERR: %s\n", error); - LLDstringAppend(errList,msg); + + status = Tcl_Eval(pTcl, cmd); + if (status != TCL_OK) { + LLDstringAppend(errList, cmd); + error = (char *) Tcl_GetStringResult(pTcl); + snprintf(msg, sizeof msg, "#ERR: %s\n", error); + LLDstringAppend(errList, msg); } DeleteDynString(command); - if(SCGetInterrupt(pCon) >= eAbortBatch){ - SCWrite(pCon,"ERROR: batch processing interrupted",eError); + if (SCGetInterrupt(pCon) >= eAbortBatch) { + SCWrite(pCon, "ERROR: batch processing interrupted", eError); SetStatus(eEager); return 0; } else { - SCSetInterrupt(pCon,eContinue); + SCSetInterrupt(pCon, eContinue); } } return 1; } + /*------------------------------------------------------------------------*/ -void exeBufRange(pExeBuf self, int *start, int *end, int *lineno){ +void exeBufRange(pExeBuf self, int *start, int *end, int *lineno) +{ assert(self); *start = self->start; *end = self->end; *lineno = self->lineno; } + /*------------------------------------------------------------------------*/ -pDynString exeBufText(pExeBuf self, int start, int end){ +pDynString exeBufText(pExeBuf self, int start, int end) +{ pDynString result = NULL; char *pPtr; int i; assert(self); - - result = CreateDynString(256,132); - if(result == NULL){ + + result = CreateDynString(256, 132); + if (result == NULL) { return NULL; } pPtr = GetCharArray(self->bufferContent); - if(end >= strlen(pPtr)){ - end = strlen(pPtr) -1; + if (end >= strlen(pPtr)) { + end = strlen(pPtr) - 1; + } + for (i = start; i < end; i++) { + DynStringConcatChar(result, pPtr[i]); } - for(i = start; i < end; i++){ - DynStringConcatChar(result,pPtr[i]); - } return result; } + /*-----------------------------------------------------------------------*/ -char *exeBufName(pExeBuf self){ +char *exeBufName(pExeBuf self) +{ assert(self); return self->name; } - - diff --git a/exebuf.h b/exebuf.h index bb1edba4..bed450ff 100644 --- a/exebuf.h +++ b/exebuf.h @@ -1,5 +1,5 @@ -#line 226 "exe.w" +#line 227 "exe.w" /** * Buffer handling code for the Exe Buffer batch file processing @@ -16,27 +16,27 @@ #line 44 "exe.w" - typedef struct __EXEBUF *pExeBuf; +typedef struct __EXEBUF *pExeBuf; /** * create an exe buffer * @param The name to use for the exe buffer * @return A new exe buffer or NULL if out of memory */ - pExeBuf exeBufCreate(char *name); +pExeBuf exeBufCreate(char *name); /** * delete an exe buffer * @param data The exe buffer to delete */ - void exeBufKill(void *data); - void exeBufDelete(pExeBuf data); +void exeBufKill(void *data); +void exeBufDelete(pExeBuf data); /** * add a a line to the exe buffer * @param self The exe buffer the line is to be added to * @param line The text to add * @return 1 on success, 0 when out of memory */ - int exeBufAppend(pExeBuf self, char *line); +int exeBufAppend(pExeBuf self, char *line); /** * load an exe buffer from a file * @param self The exe buffer to load @@ -44,14 +44,14 @@ * @return 1 on success, 0 if the file could not be opened or * memory is exhausted. */ - int exeBufLoad(pExeBuf self, char *filename); +int exeBufLoad(pExeBuf self, char *filename); /** * save an exe buffer to a file. * @param self The exe buffer to laod * @param filename The name of the file to laod * @return 1 on success, 0 if the file could not be opened. */ - int exeBufSave(pExeBuf self, char *filename); +int exeBufSave(pExeBuf self, char *filename); /** * process an exe buffer * @param self The exe buffer to process @@ -61,8 +61,8 @@ * @pCall The callback interface to use for automatic notifications * @return 1 on success, 0 on error */ - int exeBufProcess(pExeBuf self, SicsInterp *pSics, - SConnection *pCon, pICallBack pCall, int echo); +int exeBufProcess(pExeBuf self, SicsInterp * pSics, + SConnection * pCon, pICallBack pCall, int echo); /** * Process an exe buffer, but store commands causing errors in a list. * This is used for restoring status files. @@ -74,8 +74,8 @@ * had errors. * @return 1 on success, 0 on error */ - int exeBufProcessErrList(pExeBuf self, SicsInterp *pSics, - SConnection *pCon, int errCommandList); +int exeBufProcessErrList(pExeBuf self, SicsInterp * pSics, + SConnection * pCon, int errCommandList); /** * retrieves the executing range * @param self The exe buffer to query @@ -83,7 +83,7 @@ * @param end The end of the executing range * @param lineno The current line number */ - void exeBufRange(pExeBuf self, int *start, int *end, int *lineno); +void exeBufRange(pExeBuf self, int *start, int *end, int *lineno); /** * retrieves some portion of text * @param self The exe buffer to query @@ -93,16 +93,16 @@ * the clients task to delete this buffer sfter use. Or NULL if out of * memory. */ - pDynString exeBufText(pExeBuf self, int start, int end); +pDynString exeBufText(pExeBuf self, int start, int end); /** * retrieves the name of the batch buffer * @param self The exe buffer to query * @return A pointer to the buffer name. Do not delete! The name * is still owned by the exe beuffer. */ - char *exeBufName(pExeBuf self); +char *exeBufName(pExeBuf self); -#line 239 "exe.w" +#line 240 "exe.w" #endif diff --git a/exebuf.i b/exebuf.i index 32da477f..f69493a0 100644 --- a/exebuf.i +++ b/exebuf.i @@ -1,5 +1,5 @@ -#line 217 "exe.w" +#line 218 "exe.w" /*-------------------------------------------------------------------- Internal header file for the exe buffer module. Do not edit. This is @@ -16,6 +16,6 @@ typedef struct __EXEBUF{ int lineno; } ExeBuf; -#line 222 "exe.w" +#line 223 "exe.w" diff --git a/exeman.c b/exeman.c index d5415592..d5920ac2 100644 --- a/exeman.c +++ b/exeman.c @@ -1,3 +1,4 @@ + /** * Implementation file for the exe buffer buffer manager. * @@ -26,129 +27,133 @@ #include "commandlog.h" #include "protocol.h" /*-------------------------------------------------------------------*/ -static void KillExeMan(void *data){ - pExeMan self = (pExeMan)data; - if(!self){ +static void KillExeMan(void *data) +{ + pExeMan self = (pExeMan) data; + if (!self) { return; } - if(self->pDes){ + if (self->pDes) { DeleteDescriptor(self->pDes); } - if(self->pCall){ + if (self->pCall) { DeleteCallBackInterface(self->pCall); } - if(self->batchPath){ + if (self->batchPath) { free(self->batchPath); } - if(self->sysPath){ + if (self->sysPath) { free(self->sysPath); } - if(self->exeStack){ + if (self->exeStack) { DeleteDynar(self->exeStack); } LLDdelete(self->runList); free(self); } -/*-----------------------------------------------------------------*/ -static int SaveExeMan(void *data, char *name, FILE *fd){ - pExeMan self = (pExeMan)data; - if(!self){ +/*-----------------------------------------------------------------*/ +static int SaveExeMan(void *data, char *name, FILE * fd) +{ + pExeMan self = (pExeMan) data; + + if (!self) { return 0; } - fprintf(fd,"%s batchpath %s\n",name,self->batchPath); - fprintf(fd,"%s syspath %s\n",name,self->sysPath); + fprintf(fd, "%s batchpath %s\n", name, self->batchPath); + fprintf(fd, "%s syspath %s\n", name, self->sysPath); return 1; } -/*-----------------------------------------------------------------*/ -static void *ExeManInterface(void *data, int interfaceID){ - pExeMan self = (pExeMan)data; - if(self == NULL){ +/*-----------------------------------------------------------------*/ +static void *ExeManInterface(void *data, int interfaceID) +{ + pExeMan self = (pExeMan) data; + + if (self == NULL) { return NULL; } - if(interfaceID == CALLBACKINTERFACE){ + if (interfaceID == CALLBACKINTERFACE) { return self->pCall; } return NULL; } + /*------------------------------------------------------------------*/ -int MakeExeManager(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]){ +int MakeExeManager(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ pExeMan pNew = NULL; int status; - pNew = (pExeMan)malloc(sizeof(ExeMan)); - if(!pNew){ - SCWrite(pCon,"ERROR: out of memory creating exe Manager",eError); + pNew = (pExeMan) malloc(sizeof(ExeMan)); + if (!pNew) { + SCWrite(pCon, "ERROR: out of memory creating exe Manager", eError); return 0; } - memset(pNew,0,sizeof(ExeMan)); + memset(pNew, 0, sizeof(ExeMan)); pNew->pDes = CreateDescriptor("ExeManager"); pNew->pCall = CreateCallBackInterface(); pNew->sysPath = strdup("./"); pNew->batchPath = strdup("./"); - pNew->exeStack = CreateDynar(1,10,10,exeBufKill); + pNew->exeStack = CreateDynar(1, 10, 10, exeBufKill); pNew->exeStackPtr = -1; pNew->runList = LLDcreate(sizeof(pExeBuf)); - if(!pNew->pDes || !pNew->pCall || ! pNew->batchPath || - !pNew->exeStack || pNew->runList < 0){ - SCWrite(pCon,"ERROR: out of memory creating exe Manager",eError); + if (!pNew->pDes || !pNew->pCall || !pNew->batchPath || + !pNew->exeStack || pNew->runList < 0) { + SCWrite(pCon, "ERROR: out of memory creating exe Manager", eError); return 0; } pNew->pDes->SaveStatus = SaveExeMan; pNew->pDes->GetInterface = ExeManInterface; - if(argc > 1){ + if (argc > 1) { status = AddCommand(pSics, - argv[1], - ExeManagerWrapper, - KillExeMan, - pNew); + argv[1], ExeManagerWrapper, KillExeMan, pNew); } else { - status = AddCommand(pSics, - "exe", - ExeManagerWrapper, - KillExeMan, - pNew); + status = AddCommand(pSics, "exe", ExeManagerWrapper, KillExeMan, pNew); } - if(status != 1) { - SCWrite(pCon,"ERROR: duplicate exe manager not created",eError); + if (status != 1) { + SCWrite(pCon, "ERROR: duplicate exe manager not created", eError); return 0; } return 1; } + /*======================== buffer execution ==========================*/ -static int fileExists(char *path){ +static int fileExists(char *path) +{ FILE *fd = NULL; int status = 0; - fd = fopen(path,"r"); - if(fd != NULL){ + fd = fopen(path, "r"); + if (fd != NULL) { fclose(fd); status = 1; } return status; } + /*--------------------------------------------------------------------*/ extern char *stptok(char *s, char *t, int len, char *brk); -static pDynString locateBatchBuffer(pExeMan self, char *name){ +static pDynString locateBatchBuffer(pExeMan self, char *name) +{ pDynString result = NULL; char pPath[132], *pPtr = NULL; - result = CreateDynString(256,256); - if(!result){ + result = CreateDynString(256, 256); + if (!result) { return NULL; } /* - do not try to convert absolute paths - */ - if(name[0] == '/'){ - DynStringCopy(result,name); - if(fileExists(GetCharArray(result))){ + do not try to convert absolute paths + */ + if (name[0] == '/') { + DynStringCopy(result, name); + if (fileExists(GetCharArray(result))) { return result; } else { return NULL; @@ -156,589 +161,660 @@ static pDynString locateBatchBuffer(pExeMan self, char *name){ } pPtr = self->batchPath; - while((pPtr = stptok(pPtr,pPath,131,":")) != NULL){ - DynStringCopy(result,pPath); - DynStringConcatChar(result,'/'); - DynStringConcat(result,name); - if(fileExists(GetCharArray(result))){ + while ((pPtr = stptok(pPtr, pPath, 131, ":")) != NULL) { + DynStringCopy(result, pPath); + DynStringConcatChar(result, '/'); + DynStringConcat(result, name); + if (fileExists(GetCharArray(result))) { return result; } } pPtr = self->sysPath; - while((pPtr = stptok(pPtr,pPath,131,":")) != NULL){ - DynStringCopy(result,pPath); - DynStringConcatChar(result,'/'); - DynStringConcat(result,name); - if(fileExists(GetCharArray(result))){ + while ((pPtr = stptok(pPtr, pPath, 131, ":")) != NULL) { + DynStringCopy(result, pPath); + DynStringConcatChar(result, '/'); + DynStringConcat(result, name); + if (fileExists(GetCharArray(result))) { return result; } } DeleteDynString(result); return NULL; } + /*------------------------------------------------------------------- * Generate a full path name for the argument in the first * directory of batch path * -------------------------------------------------------------------*/ -static int makeExePath(pExeMan self, SConnection *pCon, int argc, char *argv[]){ - char buffer[512], *pPtr = NULL, pPath[132]; - - if(argc < 3) { - SCWrite(pCon,"ERROR: require a file name for makepath",eError); - return 0; - } - strcpy(buffer,"exe.makepath = "); - /* - * do nothing to absolute path - */ - if(argv[2][0] == '/'){ - strncat(buffer,argv[2],511-strlen(buffer)); - SCWrite(pCon,buffer,eValue); - return 1; - } - pPtr = self->batchPath; - pPtr = stptok(pPtr,pPath,131,":"); - strncat(buffer,pPath,511-strlen(buffer)); - strncat(buffer,"/",511-strlen(buffer)); - strncat(buffer,argv[2],511-strlen(buffer)); - SCWrite(pCon,buffer,eValue); - +static int makeExePath(pExeMan self, SConnection * pCon, int argc, + char *argv[]) +{ + char buffer[512], *pPtr = NULL, pPath[132]; + + if (argc < 3) { + SCWrite(pCon, "ERROR: require a file name for makepath", eError); + return 0; + } + strcpy(buffer, "exe.makepath = "); + /* + * do nothing to absolute path + */ + if (argv[2][0] == '/') { + strlcat(buffer, argv[2], sizeof buffer); + SCWrite(pCon, buffer, eValue); return 1; + } + pPtr = self->batchPath; + pPtr = stptok(pPtr, pPath, 131, ":"); + strlcat(buffer, pPath, sizeof buffer); + strlcat(buffer, "/", sizeof buffer); + strlcat(buffer, argv[2], sizeof buffer); + SCWrite(pCon, buffer, eValue); + + return 1; } + /*--------------------------------------------------------------------*/ -pDynString findBatchFile(SicsInterp *pSics, char *name){ - pExeMan self = (pExeMan)FindCommandData(pSics,"exe","ExeManager"); - if(self == NULL){ - return NULL; - } - return locateBatchBuffer(self,name); +pDynString findBatchFile(SicsInterp * pSics, char *name) +{ + pExeMan self = (pExeMan) FindCommandData(pSics, "exe", "ExeManager"); + if (self == NULL) { + return NULL; + } + return locateBatchBuffer(self, name); } + /*--------------------------------------------------------------------*/ -static int runBatchBuffer(pExeMan self, SConnection *pCon, - SicsInterp *pSics, char *name){ +static int runBatchBuffer(pExeMan self, SConnection * pCon, + SicsInterp * pSics, char *name) +{ pDynString filePath = NULL; char pBueffel[256]; pExeBuf buffer = NULL; int status; - if(!SCMatchRights(pCon,usUser)) { + if (!SCMatchRights(pCon, usUser)) { return 0; } - filePath = locateBatchBuffer(self,name); - if(filePath == NULL){ - snprintf(pBueffel,255,"ERROR: batch buffer %s not found in path", - name); - SCWrite(pCon,pBueffel,eError); + + if (self->runCon != NULL && self->runCon != pCon) { + SCWrite(pCon, "ERROR: another batch buffer is already runnig", eError); + return 0; + } + + filePath = locateBatchBuffer(self, name); + if (filePath == NULL) { + snprintf(pBueffel, 255, "ERROR: batch buffer %s not found in path", + name); + SCWrite(pCon, pBueffel, eError); return 0; } buffer = exeBufCreate(name); - if(!buffer){ + if (!buffer) { DeleteDynString(filePath); - SCWrite(pCon,"ERROR: out of memory creating batch buffer",eError); + SCWrite(pCon, "ERROR: out of memory creating batch buffer", eError); return 0; } - status = exeBufLoad(buffer,GetCharArray(filePath)); - if(!status){ + status = exeBufLoad(buffer, GetCharArray(filePath)); + if (!status) { DeleteDynString(filePath); - SCWrite(pCon,"ERROR: failed to load batch buffer",eError); + SCWrite(pCon, "ERROR: failed to load batch buffer", eError); return 0; } DeleteDynString(filePath); self->exeStackPtr++; - DynarPut(self->exeStack,self->exeStackPtr,buffer); - status = exeBufProcess(buffer,pSics,pCon,self->pCall,self->echo); + DynarPut(self->exeStack, self->exeStackPtr, buffer); + status = exeBufProcess(buffer, pSics, pCon, self->pCall, self->echo); self->exeStackPtr--; return status; -} +} + /*-------------------------------------------------------------------*/ static char bufferNode[512]; -static int SCHdbWrite(SConnection *self, char *message, int outCode){ - pHdb node = NULL; - char pBueffel[512]; - commandContext cc; - hdbValue v; - pDynString val = NULL; - writeFunc defWrite = NULL; - - - cc = SCGetContext(self); - node = GetHipadabaNode(GetHipadabaRoot(),cc.deviceID); - if(node == NULL || strstr(cc.deviceID,bufferNode) == NULL){ - /* - * this means the deviceId is wrong and the output is for another - * operation. - */ - defWrite = GetProtocolWriteFunc(self); - if(defWrite == NULL){ - defWrite = SCNormalWrite; - } - defWrite(self,message,outCode); - return 1; - } +static int SCHdbWrite(SConnection * self, char *message, int outCode) +{ + pHdb node = NULL; + char pBueffel[512]; + commandContext cc; + hdbValue v; + pDynString val = NULL; + writeFunc defWrite = NULL; - SCFileWrite(self,message,outCode); - if(SCinMacro(self) && (outCode != eError && outCode != eWarning) ){ - return 1; + cc = SCGetContext(self); + node = GetHipadabaNode(GetHipadabaRoot(), cc.deviceID); + if (node == NULL || strstr(cc.deviceID, bufferNode) == NULL) { + /* + * this means the deviceId is wrong and the output is for another + * operation. + */ + defWrite = GetProtocolWriteFunc(self); + if (defWrite == NULL) { + defWrite = SCNormalWrite; } - - v = MakeHdbText(strdup("")); - GetHipadabaPar(node,&v,NULL); - v.dataType = HIPTEXT; - val = CreateDynString(128,128); - if(val == NULL){ - WriteToCommandLog("INTERNAL ERROR>>", - "No memory to append to log in SCHdbWrite"); - return 0; - } - if(v.v.text != NULL){ - DynStringConcat(val,v.v.text); - if(strrchr(v.v.text,(int)'\n') == NULL && strlen(v.v.text) > 1){ - DynStringConcatChar(val,'\n'); - } - } - DynStringConcat(val,message); - if(strrchr(message,(int)'\n') == NULL && strlen(message) > 1){ - DynStringConcatChar(val,'\n'); - } - if(v.v.text != NULL){ - free(v.v.text); - } - v.v.text = GetCharArray(val); - UpdateHipadabaPar(node,v,NULL); - DeleteDynString(val); + defWrite(self, message, outCode); return 1; + } + + SCFileWrite(self, message, outCode); + + if (SCinMacro(self) && (outCode != eError && outCode != eWarning)) { + return 1; + } + + v = MakeHdbText(strdup("")); + GetHipadabaPar(node, &v, NULL); + v.dataType = HIPTEXT; + val = CreateDynString(128, 128); + if (val == NULL) { + WriteToCommandLog("INTERNAL ERROR>>", + "No memory to append to log in SCHdbWrite"); + return 0; + } + if (v.v.text != NULL) { + DynStringConcat(val, v.v.text); + if (strrchr(v.v.text, (int) '\n') == NULL && strlen(v.v.text) > 1) { + DynStringConcatChar(val, '\n'); + } + } + DynStringConcat(val, message); + if (strrchr(message, (int) '\n') == NULL && strlen(message) > 1) { + DynStringConcatChar(val, '\n'); + } + if (v.v.text != NULL) { + free(v.v.text); + } + v.v.text = GetCharArray(val); + UpdateHipadabaPar(node, v, NULL); + DeleteDynString(val); + return 1; } + /*--------------------------------------------------------------------*/ -int exeHdbNode(pHdb exeNode, SConnection *pCon){ +int exeHdbNode(pHdb exeNode, SConnection * pCon) +{ char pBueffel[512], *name = NULL; - pHdb node = NULL, log = NULL; + pHdb node = NULL, log = NULL; pExeBuf buffer = NULL; hdbValue v; int status; - commandContext cc; - writeFunc oldWrite; - + SConnection *conCon = NULL; + /* * clear log buffer */ - log = GetHipadabaNode(exeNode,"log"); - if(log == NULL){ - SCWrite(pCon,"ERROR: Hdb node not found or in wrong format",eError); + log = GetHipadabaNode(exeNode, "log"); + if (log == NULL) { + SCWrite(pCon, "ERROR: Hdb node not found or in wrong format", eError); return 0; } v = MakeHdbText(strdup("")); - UpdateHipadabaPar(log,v,pCon); + UpdateHipadabaPar(log, v, pCon); /* * prepare context */ name = GetHipadabaPath(log); - cc = SCGetContext(pCon); - strncpy(cc.deviceID, name,255); - strncpy(bufferNode,name,511); + conCon = SCCopyConnection(pCon); + if (conCon == NULL) { + SCWrite(pCon, "ERROR: out of memory in exehdbNode", eError); + return 0; + } + strlcpy(conCon->deviceID, name, 255); + strlcpy(bufferNode, name, 511); /* * load commands into buffer - */ - node = GetHipadabaNode(exeNode,"commands"); - if(node == NULL){ - SCWrite(pCon,"ERROR: Hdb node not found or in wrong format",eError); + */ + node = GetHipadabaNode(exeNode, "commands"); + if (node == NULL) { + SCWrite(pCon, "ERROR: Hdb node not found or in wrong format", eError); return 0; } - GetHipadabaPar(node,&v,pCon); - if(v.dataType != HIPTEXT || v.v.text == NULL){ - SCWrite(pCon,"ERROR: Hdb node is of wrong type or contains no data",eError); + GetHipadabaPar(node, &v, pCon); + if (v.dataType != HIPTEXT || v.v.text == NULL) { + SCWrite(pCon, "ERROR: Hdb node is of wrong type or contains no data", + eError); return 0; - + } - + buffer = exeBufCreate(name); - if(!buffer){ - SCWrite(pCon,"ERROR: out of memory creating batch buffer",eError); + if (!buffer) { + SCWrite(pCon, "ERROR: out of memory creating batch buffer", eError); return 0; } - exeBufAppend(buffer,v.v.text); + exeBufAppend(buffer, v.v.text); - strncpy(bufferNode,name,511); - oldWrite = SCGetWriteFunc(pCon); - SCSetWriteFunc(pCon,SCHdbWrite); - SCPushContext2(pCon,cc); - status = exeBufProcess(buffer,pServ->pSics,pCon,NULL,0); - SCSetWriteFunc(pCon,oldWrite); - SCPopContext(pCon); + strlcpy(bufferNode, name, 511); + SCSetWriteFunc(conCon, SCHdbWrite); + status = exeBufProcess(buffer, pServ->pSics, conCon, NULL, 0); + SCDeleteConnection(conCon); exeBufDelete(buffer); free(name); - if(strlen(log->value.v.text) < 2){ - v = MakeHdbText(strdup("OK\n")); - UpdateHipadabaPar(log,v,pCon); - ReleaseHdbValue(&v); + if (strlen(log->value.v.text) < 2) { + v = MakeHdbText(strdup("OK\n")); + UpdateHipadabaPar(log, v, pCon); + ReleaseHdbValue(&v); } return status; } + /*--------------------------------------------------------------------*/ -static int runHdbBuffer(pExeMan self, SConnection *pCon, - SicsInterp *pSics, char *name){ +static int runHdbBuffer(pExeMan self, SConnection * pCon, + SicsInterp * pSics, char *name) +{ char pBueffel[512]; pExeBuf buffer = NULL; pHdb node = NULL; hdbValue v; int status; - commandContext cc; - writeFunc oldWrite; + SConnection *conCon = NULL; - if(!SCMatchRights(pCon,usUser)) { + if (!SCMatchRights(pCon, usUser)) { + return 0; + } + + if (self->runCon != NULL && self->runCon != pCon) { + SCWrite(pCon, "ERROR: another bacth buffer is still running", eError); return 0; } - /* * clear log buffer */ - snprintf(pBueffel,511,"%s/log",name); - node = GetHipadabaNode(GetHipadabaRoot(),pBueffel); - if(node == NULL){ - SCWrite(pCon,"ERROR: Hdb node not found or in wrong format",eError); + snprintf(pBueffel, 511, "%s/log", name); + node = GetHipadabaNode(GetHipadabaRoot(), pBueffel); + if (node == NULL) { + SCWrite(pCon, "ERROR: Hdb node not found or in wrong format", eError); return 0; } v = MakeHdbText(strdup("")); - UpdateHipadabaPar(node,v,pCon); + UpdateHipadabaPar(node, v, pCon); /* * prepare context */ - cc = SCGetContext(pCon); - strcpy(cc.deviceID, pBueffel); + conCon = SCCopyConnection(pCon); + strlcpy(conCon->deviceID, pBueffel,255); /* * load commands into buffer - */ - snprintf(pBueffel,511,"%s/commands",name); - node = GetHipadabaNode(GetHipadabaRoot(),pBueffel); - if(node == NULL){ - SCWrite(pCon,"ERROR: Hdb node not found or in wrong format",eError); + */ + snprintf(pBueffel, 511, "%s/commands", name); + node = GetHipadabaNode(GetHipadabaRoot(), pBueffel); + if (node == NULL) { + SCWrite(pCon, "ERROR: Hdb node not found or in wrong format", eError); return 0; } - GetHipadabaPar(node,&v,pCon); - if(v.dataType != HIPTEXT || v.v.text == NULL){ - SCWrite(pCon,"ERROR: Hdb node is of wrong type or contains no data",eError); + GetHipadabaPar(node, &v, pCon); + if (v.dataType != HIPTEXT || v.v.text == NULL) { + SCWrite(pCon, "ERROR: Hdb node is of wrong type or contains no data", + eError); return 0; - + } - + buffer = exeBufCreate(name); - if(!buffer){ - SCWrite(pCon,"ERROR: out of memory creating batch buffer",eError); + if (!buffer) { + SCWrite(pCon, "ERROR: out of memory creating batch buffer", eError); return 0; } - exeBufAppend(buffer,v.v.text); + exeBufAppend(buffer, v.v.text); - strncpy(bufferNode,name,511); - oldWrite = SCGetWriteFunc(pCon); - SCSetWriteFunc(pCon,SCHdbWrite); - SCPushContext2(pCon,cc); + strlcpy(bufferNode, name, 511); + SCSetWriteFunc(conCon, SCHdbWrite); self->exeStackPtr++; - DynarPut(self->exeStack,self->exeStackPtr,buffer); - status = exeBufProcess(buffer,pSics,pCon,self->pCall,self->echo); + self->runCon = conCon; + DynarPut(self->exeStack, self->exeStackPtr, buffer); + status = exeBufProcess(buffer, pSics, conCon, self->pCall, self->echo); self->exeStackPtr--; - SCSetWriteFunc(pCon,oldWrite); - SCPopContext(pCon); + self->runCon = NULL; + SCDeleteConnection(conCon); return status; -} -/*--------------------------------------------------------------------*/ -int exeHdbBuffer(SConnection *pCon, - SicsInterp *pSics, char *name){ - pExeMan self = (pExeMan)FindCommandData(pSics,"exe","ExeManager"); - if(self != NULL){ - return runHdbBuffer(self,pCon,pSics,name); - } - return 0; } + +/*--------------------------------------------------------------------*/ +int exeHdbBuffer(SConnection * pCon, SicsInterp * pSics, char *name) +{ + pExeMan self = (pExeMan) FindCommandData(pSics, "exe", "ExeManager"); + if (self != NULL) { + return runHdbBuffer(self, pCon, pSics, name); + } + return 0; +} + /*-------------------------------------------------------------------*/ -int runExeBatchBuffer(void *pData, SConnection *pCon, - SicsInterp *pSics, char *name){ - int status, oldEcho; - pExeMan self = (pExeMan)pData; +int runExeBatchBuffer(void *pData, SConnection * pCon, + SicsInterp * pSics, char *name) +{ + int status, oldEcho; + pExeMan self = (pExeMan) pData; oldEcho = self->echo; self->echo = 1; - status = runBatchBuffer(self,pCon,pSics,name); + status = runBatchBuffer(self, pCon, pSics, name); self->echo = oldEcho; return status; } + /*========================== path management ========================*/ -static int handleBatchPath(pExeMan self, SConnection *pCon, int argc, - char *argv[]){ +static int handleBatchPath(pExeMan self, SConnection * pCon, int argc, + char *argv[]) +{ char pBuffer[1024]; - if(strcmp(argv[1],"batchpath") == 0) { - if(argc > 2) { - if(!SCMatchRights(pCon,usUser)){ - return 0; + if (strcasecmp(argv[1], "batchpath") == 0) { + if (argc > 2) { + if (!SCMatchRights(pCon, usUser)) { + return 0; } - if(self->batchPath != NULL){ - free(self->batchPath); + if (self->batchPath != NULL) { + free(self->batchPath); } self->batchPath = strdup(argv[2]); - SCSendOK(pCon); + if(self->batchPath[0] != '/'){ + SCPrintf(pCon,eLog, "WARNING: batchpath %s not an absolute path", argv[2]); + } else { + SCSendOK(pCon); + } SCparChange(pCon); return 1; } else { - snprintf(pBuffer,1023,"%s.batchpath = %s", argv[0],self->batchPath); - SCWrite(pCon,pBuffer,eValue); + snprintf(pBuffer, 1023, "%s.batchpath = %s", argv[0], + self->batchPath); + SCWrite(pCon, pBuffer, eValue); return 1; } } - if(strcmp(argv[1],"syspath") == 0) { - if(argc > 2) { - if(!SCMatchRights(pCon,usMugger)){ - return 0; + if (strcasecmp(argv[1], "syspath") == 0) { + if (argc > 2) { + if (!SCMatchRights(pCon, usMugger)) { + return 0; } - if(self->sysPath != NULL){ - free(self->sysPath); + if (self->sysPath != NULL) { + free(self->sysPath); } self->sysPath = strdup(argv[2]); SCSendOK(pCon); SCparChange(pCon); return 1; } else { - snprintf(pBuffer,1023,"%s.syspath = %s", argv[0],self->sysPath); - SCWrite(pCon,pBuffer,eValue); + snprintf(pBuffer, 1023, "%s.syspath = %s", argv[0], self->sysPath); + SCWrite(pCon, pBuffer, eValue); return 1; } } return -1; } + /*=========================== callbacks ==============================*/ typedef struct { SConnection *pCon; - pExeMan exe; -}exeInfo, *pExeInfo; + pExeMan exe; +} exeInfo, *pExeInfo; /*------------------------------------------------------------------*/ -static void killExeInfo(void *pData){ - pExeInfo self = (pExeInfo)pData; - if(self != NULL){ +static void killExeInfo(void *pData) +{ + pExeInfo self = (pExeInfo) pData; + if (self->pCon != NULL) { + SCDeleteConnection(self->pCon); + } + if (self != NULL) { free(self); } } + /*-----------------------------------------------------------------*/ -static pExeInfo makeExeInfo(SConnection *pCon, pExeMan self){ +static pExeInfo makeExeInfo(SConnection * pCon, pExeMan self) +{ pExeInfo pNew = NULL; pNew = malloc(sizeof(exeInfo)); - if(pNew == NULL){ + if (pNew == NULL) { SCWrite(pCon, - "ERROR: failed to allocate info structure for registering callbacks", - eError); + "ERROR: failed to allocate info structure for registering callbacks", + eError); + return NULL; + } + memset(pNew, 0, sizeof(exeInfo)); + pNew->pCon = SCCopyConnection(pCon); + if (pNew->pCon == NULL) { + SCWrite(pCon, + "ERROR: failed to allocate info structure for registering callbacks", + eError); return NULL; } - pNew->pCon = pCon; pNew->exe = self; return pNew; } -/*------------------------------------------------------------------*/ -static int BufferCallback(int iEvent, void *pEvent, void *pUser, - commandContext cc){ - pExeInfo self = (pExeInfo)pUser; - char *name = (char *)pEvent; - char pBueffel[132]; - if(iEvent == BATCHSTART){ - snprintf(pBueffel,131,"BATCHSTART=%s",name); - SCWriteInContext(self->pCon,pBueffel,eWarning,cc); +/*------------------------------------------------------------------*/ +static int BufferCallback(int iEvent, void *pEvent, void *pUser) +{ + pExeInfo self = (pExeInfo) pUser; + char *name = (char *) pEvent; + char pBueffel[132]; + + if (!SCisConnected(self->pCon)) { + return -1; + } + + if (iEvent == BATCHSTART) { + snprintf(pBueffel, 131, "BATCHSTART=%s", name); + SCWrite(self->pCon, pBueffel, eLog); return 1; } - if(iEvent == BATCHEND){ - snprintf(pBueffel,131,"BATCHEND=%s",name); - SCWriteInContext(self->pCon,pBueffel,eWarning,cc); + if (iEvent == BATCHEND) { + snprintf(pBueffel, 131, "BATCHEND=%s", name); + SCWrite(self->pCon, pBueffel, eLog); return 1; } return 0; } + /*-------------------------------------------------------------------*/ -static int LineCallBack(int iEvent, void *pEvent, void *pUser, - commandContext cc){ - pExeInfo self = (pExeInfo)pUser; +static int LineCallBack(int iEvent, void *pEvent, void *pUser) +{ + pExeInfo self = (pExeInfo) pUser; char pBueffel[256]; int start, end, lineno; void *pPtr = NULL; pExeBuf buf = NULL; assert(self); - if(iEvent == BATCHAREA){ - DynarGet(self->exe->exeStack,self->exe->exeStackPtr,&pPtr); - buf = (pExeBuf)pPtr; + + if (!SCisConnected(self->pCon)) { + return -1; + } + + if (iEvent == BATCHAREA) { + DynarGet(self->exe->exeStack, self->exe->exeStackPtr, &pPtr); + buf = (pExeBuf) pPtr; assert(buf); - exeBufRange(buf,&start,&end,&lineno); - snprintf(pBueffel,255,"%s.range = %d = %d",exeBufName(buf), - start,end); - SCWriteInContext(self->pCon,pBueffel,eWarning,cc); + exeBufRange(buf, &start, &end, &lineno); + snprintf(pBueffel, 255, "%s.range = %d = %d", exeBufName(buf), + start, end); + SCWrite(self->pCon, pBueffel, eLog); return 1; } return 0; } + /*--------------------------------------------------------------------*/ -static void registerCallbacks(SConnection *pCon, SicsInterp *pSics, - pExeMan self){ +static void registerCallbacks(SConnection * pCon, SicsInterp * pSics, + pExeMan self) +{ pExeInfo info = NULL; long lID; - info = makeExeInfo(pCon,self); - if(info == NULL){ + info = makeExeInfo(pCon, self); + if (info == NULL) { return; } - lID = RegisterCallback(self->pCall, SCGetContext(pCon),BATCHSTART, BufferCallback, - info, killExeInfo); - SCRegister(pCon,pSics, self->pCall,lID); - lID = RegisterCallback(self->pCall, SCGetContext(pCon),BATCHEND, BufferCallback, - info, NULL); - SCRegister(pCon,pSics, self->pCall,lID); - lID = RegisterCallback(self->pCall, SCGetContext(pCon),BATCHAREA, LineCallBack, - info, NULL); - SCRegister(pCon,pSics, self->pCall,lID); -} + lID = RegisterCallback(self->pCall, BATCHSTART, BufferCallback, + info, killExeInfo); + lID = RegisterCallback(self->pCall, BATCHEND, BufferCallback, + info, NULL); + lID = RegisterCallback(self->pCall, BATCHAREA, LineCallBack, info, NULL); +} + /*--------------------------------------------------------------------*/ -static void unregisterCallbacks(SConnection *pCon, pExeMan self){ +static void unregisterCallbacks(SConnection * pCon, pExeMan self) +{ long lID; int i; - for(i = 0; i < 3; i++){ - lID = SCgetCallbackID(pCon,self->pCall); - if(lID >= 0){ - RemoveCallback(self->pCall,lID); - SCUnregisterID(pCon,lID); + for (i = 0; i < 3; i++) { + lID = SCgetCallbackID(pCon, self->pCall); + if (lID >= 0) { + RemoveCallback(self->pCall, lID); } } } + /*========================= uploading ===============================*/ -static int startUpload(pExeMan self, SConnection *pCon){ - if(SCGetRights(pCon) > usUser){ - SCWrite(pCon,"ERROR: no permission to upload buffers",eError); +static int startUpload(pExeMan self, SConnection * pCon) +{ + if (SCGetRights(pCon) > usUser) { + SCWrite(pCon, "ERROR: no permission to upload buffers", eError); return 0; } - if(self->uploadBuffer != NULL){ - SCWrite(pCon,"ERRO: another upload is still in progress",eError); + if (self->uploadBuffer != NULL) { + SCWrite(pCon, "ERRO: another upload is still in progress", eError); return 0; } self->uploadBuffer = exeBufCreate("upload"); - if(self->uploadBuffer == NULL){ - SCWrite(pCon,"ERROR: failed to create upload buffer",eError); + if (self->uploadBuffer == NULL) { + SCWrite(pCon, "ERROR: failed to create upload buffer", eError); return 0; } return 1; } + /*-------------------------------------------------------------------*/ -static int clearUpload(pExeMan self, SConnection *pCon){ - if(SCGetRights(pCon) > usUser){ - SCWrite(pCon,"ERROR: no permission to clear buffer upload",eError); +static int clearUpload(pExeMan self, SConnection * pCon) +{ + if (SCGetRights(pCon) > usUser) { + SCWrite(pCon, "ERROR: no permission to clear buffer upload", eError); return 0; } - if(self->uploadBuffer != NULL){ + if (self->uploadBuffer != NULL) { exeBufDelete(self->uploadBuffer); self->uploadBuffer = NULL; } - return 1; -} -/*---------------------------------------------------------------------*/ -static int appendLine(pExeMan self, SConnection *pCon, - int argc, char *argv[]){ - char pLine[1024]; - - if(SCGetRights(pCon) > usUser){ - SCWrite(pCon,"ERROR: no permission to upload buffers",eError); - return 0; - } - if(self->uploadBuffer == NULL){ - SCWrite(pCon,"ERROR: no upload in operation",eError); - return 0; - } - Arg2Text(argc-2,&argv[2],pLine,1023); - exeBufAppend(self->uploadBuffer,pLine); return 1; } + +/*---------------------------------------------------------------------*/ +static int appendLine(pExeMan self, SConnection * pCon, + int argc, char *argv[]) +{ + char pLine[1024]; + + if (SCGetRights(pCon) > usUser) { + SCWrite(pCon, "ERROR: no permission to upload buffers", eError); + return 0; + } + if (self->uploadBuffer == NULL) { + SCWrite(pCon, "ERROR: no upload in operation", eError); + return 0; + } + memset(pLine,0,sizeof(pLine)); + Arg2Text(argc - 2, &argv[2], pLine, 1023); + exeBufAppend(self->uploadBuffer, pLine); + return 1; +} + /*--------------------------------------------------------------------*/ -static int uploadForceSave(pExeMan self, SConnection *pCon, - int argc, char *argv[]){ +static int uploadForceSave(pExeMan self, SConnection * pCon, + int argc, char *argv[]) +{ int status; char pPath[256], *pPtr; - if(SCGetRights(pCon) > usUser){ - SCWrite(pCon,"ERROR: no permission to save buffers",eError); + if (SCGetRights(pCon) > usUser) { + SCWrite(pCon, "ERROR: no permission to save buffers", eError); return 0; } - if(argc < 3) { - SCWrite(pCon,"ERROR: no file given to save upload buffer to",eError); + if (argc < 3) { + SCWrite(pCon, "ERROR: no file given to save upload buffer to", eError); return 0; } - if(self->uploadBuffer == NULL){ - SCWrite(pCon,"ERROR: no upload buffer to save exists",eError); + if (self->uploadBuffer == NULL) { + SCWrite(pCon, "ERROR: no upload buffer to save exists", eError); return 0; } - if(argv[2][0] != '/') { + if (argv[2][0] != '/') { pPtr = self->batchPath; - pPtr = stptok(pPtr,pPath,131,":"); - if(strlen(pPath) + 1 + strlen(argv[2]) <= 256){ - strcat(pPath,"/"); - strcat(pPath,argv[2]); - } else { - strncpy(pPath,argv[2],255); + pPtr = stptok(pPtr, pPath, 131, ":"); + if (strlen(pPath) + 1 + strlen(argv[2]) <= 256) { + strlcat(pPath, "/",255); + strlcat(pPath, argv[2],255); + } else { + strlcpy(pPath, argv[2], 255); } } else { - strncpy(pPath,argv[2],131); + strlcpy(pPath, argv[2], 131); } - status = exeBufSave(self->uploadBuffer,pPath); - if(status == 0){ - SCWrite(pCon,"ERROR: failed to save exe buffer, destroyed...",eError); + status = exeBufSave(self->uploadBuffer, pPath); + if (status == 0) { + SCWrite(pCon, "ERROR: failed to save exe buffer, destroyed...", + eError); } exeBufDelete(self->uploadBuffer); self->uploadBuffer = NULL; return status; } + /*--------------------------------------------------------------------*/ -static int uploadSave(pExeMan self, SConnection *pCon, - int argc, char *argv[]){ +static int uploadSave(pExeMan self, SConnection * pCon, + int argc, char *argv[]) +{ int status; char pPath[256], *pPtr; - if(SCGetRights(pCon) > usUser){ - SCWrite(pCon,"ERROR: no permission to save buffers",eError); + if (SCGetRights(pCon) > usUser) { + SCWrite(pCon, "ERROR: no permission to save buffers", eError); return 0; } - if(argc < 3) { - SCWrite(pCon,"ERROR: no file given to save upload buffer to",eError); + if (argc < 3) { + SCWrite(pCon, "ERROR: no file given to save upload buffer to", eError); return 0; } - if(self->uploadBuffer == NULL){ - SCWrite(pCon,"ERROR: no upload buffer to save exists",eError); + if (self->uploadBuffer == NULL) { + SCWrite(pCon, "ERROR: no upload buffer to save exists", eError); return 0; } - if(argv[2][0] != '/') { + if (argv[2][0] != '/') { pPtr = self->batchPath; - pPtr = stptok(pPtr,pPath,131,":"); - if(strlen(pPath) + 1 + strlen(argv[2]) <= 256){ - strcat(pPath,"/"); - strcat(pPath,argv[2]); - } else { - strncpy(pPath,argv[2],255); + pPtr = stptok(pPtr, pPath, 131, ":"); + if (strlen(pPath) + 1 + strlen(argv[2]) <= 256) { + strcat(pPath, "/"); + strcat(pPath, argv[2]); + } else { + strlcpy(pPath, argv[2], 255); } } else { - strncpy(pPath,argv[2],131); + strlcpy(pPath, argv[2], 131); } - if(fileExists(pPath)) { - SCWrite(pCon,"ERROR: file exists",eError); + if (fileExists(pPath)) { + SCWrite(pCon, "ERROR: file exists", eError); return 0; } - status = exeBufSave(self->uploadBuffer,pPath); - if(status == 0){ - SCWrite(pCon,"ERROR: failed to save exe buffer, destroyed...",eError); + status = exeBufSave(self->uploadBuffer, pPath); + if (status == 0) { + SCWrite(pCon, "ERROR: failed to save exe buffer, destroyed...", + eError); } exeBufDelete(self->uploadBuffer); self->uploadBuffer = NULL; return status; } + /*---------------------------------------------------------------------------------*/ /* See if a string matches a wildcard specification that uses * or ? (like "*.txt"), and return TRUE or FALSE, depending on the result. @@ -750,548 +826,594 @@ static int uploadSave(pExeMan self, SConnection *pCon, #define FALSE 0 #endif /*--------------------------------------------------------------------------------*/ -static int IsWildcardMatch (char *wildcardString, char *stringToCheck, int caseSensitive) +static int IsWildcardMatch(char *wildcardString, char *stringToCheck, + int caseSensitive) { - char wcChar; - char strChar; - // use the starMatchesZero variable to determine whether an asterisk - // matches zero or more characters (TRUE) or one or more characters - // (FALSE) - int starMatchesZero = TRUE; + char wcChar; + char strChar; + // use the starMatchesZero variable to determine whether an asterisk + // matches zero or more characters (TRUE) or one or more characters + // (FALSE) + int starMatchesZero = TRUE; - while ((strChar = *stringToCheck) && (wcChar = *wildcardString)) - { - // we only want to advance the pointers if we successfully assigned - // both of our char variables, so we'll do it here rather than in the - // loop condition itself - *stringToCheck++; - *wildcardString++; + while ((strChar = *stringToCheck) && (wcChar = *wildcardString)) { + // we only want to advance the pointers if we successfully assigned + // both of our char variables, so we'll do it here rather than in the + // loop condition itself + (void)*stringToCheck++; + (void)*wildcardString++; - // if this isn't a case-sensitive match, make both chars uppercase - // (thanks to David John Fielder (Konan) at http://innuendo.ev.ca - // for pointing out an error here in the original code) - if (!caseSensitive) - { - wcChar = toupper(wcChar); - strChar = toupper(strChar); - } + // if this isn't a case-sensitive match, make both chars uppercase + // (thanks to David John Fielder (Konan) at http://innuendo.ev.ca + // for pointing out an error here in the original code) + if (!caseSensitive) { + wcChar = toupper(wcChar); + strChar = toupper(strChar); + } + // check the wcChar against our wildcard list + switch (wcChar) { + // an asterisk matches zero or more characters + case '*': + // do a recursive call against the rest of the string, + // until we've either found a match or the string has + // ended + if (starMatchesZero) + (void)*stringToCheck--; - // check the wcChar against our wildcard list - switch (wcChar) - { - // an asterisk matches zero or more characters - case '*' : - // do a recursive call against the rest of the string, - // until we've either found a match or the string has - // ended - if (starMatchesZero) - *stringToCheck--; + while (*stringToCheck) { + if (IsWildcardMatch + (wildcardString, stringToCheck++, caseSensitive)) + return TRUE; + } - while (*stringToCheck) - { - if (IsWildcardMatch(wildcardString, stringToCheck++, caseSensitive)) - return TRUE; - } + break; - break; + // a question mark matches any single character + case '?': + break; - // a question mark matches any single character - case '?' : - break; + // if we fell through, we want an exact match + default: + if (wcChar != strChar) + return FALSE; + break; + } - // if we fell through, we want an exact match - default : - if (wcChar != strChar) - return FALSE; - break; - } + } - } + // if we have any asterisks left at the end of the wildcard string, we can + // advance past them if starMatchesZero is TRUE (so "blah*" will match "blah") + while ((*wildcardString) && (starMatchesZero)) { + if (*wildcardString == '*') + wildcardString++; + else + break; + } - // if we have any asterisks left at the end of the wildcard string, we can - // advance past them if starMatchesZero is TRUE (so "blah*" will match "blah") - while ((*wildcardString) && (starMatchesZero)) - { - if (*wildcardString == '*') - wildcardString++; - else - break; - } - - // if we got to the end but there's still stuff left in either of our strings, - // return false; otherwise, we have a match - if ((*stringToCheck) || (*wildcardString)) - return FALSE; - else - return TRUE; + // if we got to the end but there's still stuff left in either of our strings, + // return false; otherwise, we have a match + if ((*stringToCheck) || (*wildcardString)) + return FALSE; + else + return TRUE; } + /*----------------------------------------------------------------------------*/ -static int wwmatch(char *pattern, char *name){ - return IsWildcardMatch(pattern,name,1); +static int wwmatch(char *pattern, char *name) +{ + return IsWildcardMatch(pattern, name, 1); } + /*-------------------------------------------------------------------- search the directory pPath for file matching pattern. Successfull files will be appended to result -----------------------------------------------------------------------*/ -static void searchDir(char *pPath, char *pattern, pDynString result){ +static void searchDir(char *pPath, char *pattern, pDynString result) +{ DIR *currentdir = NULL; struct dirent *currentFile = NULL; - + currentdir = opendir(pPath); - if(currentdir == NULL){ + if (currentdir == NULL) { return; } currentFile = readdir(currentdir); - while(currentFile != NULL){ - if(wwmatch(pattern, currentFile->d_name)){ - DynStringConcat(result,currentFile->d_name); - DynStringConcatChar(result,'\n'); + while (currentFile != NULL) { + if (wwmatch(pattern, currentFile->d_name)) { + DynStringConcat(result, currentFile->d_name); + DynStringConcatChar(result, '\n'); } currentFile = readdir(currentdir); } closedir(currentdir); } + /*--------------------------------------------------------------------*/ -static pDynString findDirEntries(pExeMan self, char *pattern){ +static pDynString findDirEntries(pExeMan self, char *pattern) +{ pDynString result = NULL; char pPath[132], *pPtr = NULL; - result = CreateDynString(256,256); - if(!result){ + result = CreateDynString(256, 256); + if (!result) { return NULL; } pPtr = self->batchPath; - while((pPtr = stptok(pPtr,pPath,131,":")) != NULL){ - searchDir(pPath,pattern,result); + while ((pPtr = stptok(pPtr, pPath, 131, ":")) != NULL) { + searchDir(pPath, pattern, result); } pPtr = self->sysPath; - while((pPtr = stptok(pPtr,pPath,131,":")) != NULL){ - searchDir(pPath,pattern,result); + while ((pPtr = stptok(pPtr, pPath, 131, ":")) != NULL) { + searchDir(pPath, pattern, result); } return result; } + /*=========================== info ===================================*/ -static void printExeStack(pExeMan self, SConnection *pCon){ +static void printExeStack(pExeMan self, SConnection * pCon) +{ int i, j; pDynString txt = NULL; pExeBuf buf; void *pPtr = NULL; - txt = CreateDynString(80,80); - if(txt == NULL){ - SCWrite(pCon,"ERROR: failed to allocate memory in printExeStack",eError); + txt = CreateDynString(80, 80); + if (txt == NULL) { + SCWrite(pCon, "ERROR: failed to allocate memory in printExeStack", + eError); return; } - for(i = 0; i <= self->exeStackPtr; i++){ - DynarGet(self->exeStack,i,&pPtr); - buf = (pExeBuf)pPtr; + for (i = 0; i <= self->exeStackPtr; i++) { + DynarGet(self->exeStack, i, &pPtr); + buf = (pExeBuf) pPtr; assert(buf); - for(j = 0; j < i; j++){ - DynStringConcat(txt," "); + for (j = 0; j < i; j++) { + DynStringConcat(txt, " "); } - DynStringConcat(txt,exeBufName(buf)); - DynStringConcatChar(txt,'\n'); + DynStringConcat(txt, exeBufName(buf)); + DynStringConcatChar(txt, '\n'); } - SCWrite(pCon,GetCharArray(txt),eValue); + SCWrite(pCon, GetCharArray(txt), eValue); DeleteDynString(txt); } + /*-----------------------------------------------------------------*/ -static int locateBuffer(pExeMan self, char *name){ +static int locateBuffer(pExeMan self, char *name) +{ int i; pExeBuf buf; void *pPtr = NULL; - for(i = 0; i <= self->exeStackPtr; i++){ - DynarGet(self->exeStack,i,&pPtr); - buf = (pExeBuf)pPtr; - if(strcmp(name,exeBufName(buf)) == 0) { + for (i = 0; i <= self->exeStackPtr; i++) { + DynarGet(self->exeStack, i, &pPtr); + buf = (pExeBuf) pPtr; + if (strcmp(name, exeBufName(buf)) == 0) { return i; } } return -1; } + /*------------------------------------------------------------------*/ -static void printExeRange(pExeMan self, SConnection *pCon, - int argc, char *argv[]){ +static void printExeRange(pExeMan self, SConnection * pCon, + int argc, char *argv[]) +{ int start, end, lineno, bufNo; pExeBuf buf; void *pPtr = NULL; char pBueffel[256]; - if(argc > 3) { - bufNo = locateBuffer(self,argv[3]); + if (argc > 3) { + bufNo = locateBuffer(self, argv[3]); } else { bufNo = self->exeStackPtr; } - if(bufNo < 0){ - SCWrite(pCon,"ERROR: named buffer not found",eError); + if (bufNo < 0) { + SCWrite(pCon, "ERROR: named buffer not found", eError); return; } - DynarGet(self->exeStack,bufNo,&pPtr); - buf = (pExeBuf)pPtr; + DynarGet(self->exeStack, bufNo, &pPtr); + buf = (pExeBuf) pPtr; assert(buf); - exeBufRange(buf,&start,&end,&lineno); - snprintf(pBueffel,255,"%s.range = %d = %d = %d",exeBufName(buf), - start,end,lineno); - SCWrite(pCon,pBueffel,eValue); + exeBufRange(buf, &start, &end, &lineno); + snprintf(pBueffel, 255, "%s.range = %d = %d = %d", exeBufName(buf), + start, end, lineno); + SCWrite(pCon, pBueffel, eValue); } + /*------------------------------------------------------------------*/ -static void printExeText(pExeMan self, SConnection *pCon, - int argc, char *argv[]){ +static void printExeText(pExeMan self, SConnection * pCon, + int argc, char *argv[]) +{ int start, end, lineno, bufNo; pExeBuf buf; void *pPtr = NULL; pDynString txt; - if(argc > 3) { - bufNo = locateBuffer(self,argv[3]); + if (argc > 3) { + bufNo = locateBuffer(self, argv[3]); } else { bufNo = self->exeStackPtr; } - if(bufNo < 0){ - SCWrite(pCon,"ERROR: named buffer not found",eError); + if (bufNo < 0) { + SCWrite(pCon, "ERROR: named buffer not found", eError); return; } - DynarGet(self->exeStack,bufNo,&pPtr); - buf = (pExeBuf)pPtr; + DynarGet(self->exeStack, bufNo, &pPtr); + buf = (pExeBuf) pPtr; assert(buf); - exeBufRange(buf,&start,&end,&lineno); - txt = exeBufText(buf,start,end); - if(txt != NULL){ - SCWrite(pCon,GetCharArray(txt),eValue); + exeBufRange(buf, &start, &end, &lineno); + txt = exeBufText(buf, start, end); + if (txt != NULL) { + SCWrite(pCon, GetCharArray(txt), eValue); DeleteDynString(txt); } else { - SCWrite(pCon,"ERROR: failed to allocate text buffer for operation",eError); + SCWrite(pCon, "ERROR: failed to allocate text buffer for operation", + eError); } } + /*------------------------------------------------------------------*/ -static void printQueue(pExeMan self, SConnection *pCon){ - pExeBuf buf= NULL; +static void printQueue(pExeMan self, SConnection * pCon) +{ + pExeBuf buf = NULL; pDynString text = NULL; int status; - text = CreateDynString(80,80); - if(text == NULL){ - SCWrite(pCon,"ERROR: out of memory",eError); + text = CreateDynString(80, 80); + if (text == NULL) { + SCWrite(pCon, "ERROR: out of memory", eError); return; } - + status = LLDnodePtr2First(self->runList); - while(status != 0) { - LLDnodeDataTo(self->runList,&buf); - if(buf != NULL){ - DynStringConcat(text,exeBufName(buf)); - DynStringConcatChar(text,'\n'); + while (status != 0) { + LLDnodeDataTo(self->runList, &buf); + if (buf != NULL) { + DynStringConcat(text, exeBufName(buf)); + DynStringConcatChar(text, '\n'); } status = LLDnodePtr2Next(self->runList); } - SCWrite(pCon,GetCharArray(text),eValue); + SCWrite(pCon, GetCharArray(text), eValue); DeleteDynString(text); } + /*-------------------------------------------------------------------*/ -static int infoHandler(pExeMan self, SConnection *pCon, - int argc, char *argv[]){ +static int infoHandler(pExeMan self, SConnection * pCon, + int argc, char *argv[]) +{ char pBueffel[256]; pExeBuf buf; void *pPtr = NULL; - - if(self->exeStackPtr < 0){ - SCWrite(pCon,"Idle",eValue); + + if (self->exeStackPtr < 0) { + SCWrite(pCon, "Idle", eValue); return 1; } - if(argc < 3){ - if(self->exeStackPtr >= 0){ - DynarGet(self->exeStack,self->exeStackPtr,&pPtr); - buf = (pExeBuf)pPtr; - if(buf != NULL){ - snprintf(pBueffel,255,"Executing %s",exeBufName(buf)); - SCWrite(pCon,pBueffel,eValue); - return 1; + if (argc < 3) { + if (self->exeStackPtr >= 0) { + DynarGet(self->exeStack, self->exeStackPtr, &pPtr); + buf = (pExeBuf) pPtr; + if (buf != NULL) { + snprintf(pBueffel, 255, "Executing %s", exeBufName(buf)); + SCWrite(pCon, pBueffel, eValue); + return 1; } - } - SCWrite(pCon,"Nothing to execute",eValue); + } + SCWrite(pCon, "Nothing to execute", eValue); return 1; } else { +/* + argv must no be modifed, use strcasecmp instead M.Z. strtolower(argv[2]); - if(strcmp(argv[2],"stack") == 0){ - printExeStack(self,pCon); +*/ + if (strcasecmp(argv[2], "stack") == 0) { + printExeStack(self, pCon); return 1; - } else if(strcmp(argv[2],"range") == 0){ - printExeRange(self,pCon,argc,argv); + } else if (strcasecmp(argv[2], "range") == 0) { + printExeRange(self, pCon, argc, argv); return 1; - } else if(strcmp(argv[2],"text") == 0){ - printExeText(self,pCon,argc,argv); + } else if (strcasecmp(argv[2], "text") == 0) { + printExeText(self, pCon, argc, argv); return 1; } else { - SCWrite(pCon,"ERROR: subcommand to info unknown",eError); - return 0; + SCWrite(pCon, "ERROR: subcommand to info unknown", eError); + return 0; } } } + /*=========================== print ==================================*/ -static int printBuffer(pExeMan self, SConnection *pCon, - int argc, char *argv[]){ +static int printBuffer(pExeMan self, SConnection * pCon, + int argc, char *argv[]) +{ pDynString filePath = NULL; char pLine[512]; pExeBuf buf; void *pPtr = NULL; FILE *fd = NULL; - if(argc < 3){ - if(self->exeStackPtr >= 0) { - DynarGet(self->exeStack,self->exeStackPtr,&pPtr); + if (argc < 3) { + if (self->exeStackPtr >= 0) { + DynarGet(self->exeStack, self->exeStackPtr, &pPtr); buf = (pExeBuf) pPtr; - if(buf != NULL){ - filePath = locateBatchBuffer(self,exeBufName(buf)); + if (buf != NULL) { + filePath = locateBatchBuffer(self, exeBufName(buf)); } } else { - SCWrite(pCon,"ERROR: no default buffer to print, argument required",eError); + SCWrite(pCon, "ERROR: no default buffer to print, argument required", + eError); return 0; } } else { - filePath = locateBatchBuffer(self,argv[2]); + filePath = locateBatchBuffer(self, argv[2]); } - if(filePath == NULL){ - snprintf(pLine,255,"ERROR: batch buffer %s not found in path", - argv[2]); - SCWrite(pCon,pLine,eError); + if (filePath == NULL) { + snprintf(pLine, 255, "ERROR: batch buffer %s not found in path", + argv[2]); + SCWrite(pCon, pLine, eError); return 0; } - fd = fopen(GetCharArray(filePath),"r"); - if(fd == NULL){ - SCWrite(pCon,"ERROR: failed to open file for printing",eError); + fd = fopen(GetCharArray(filePath), "r"); + if (fd == NULL) { + SCWrite(pCon, "ERROR: failed to open file for printing", eError); DeleteDynString(filePath); return 0; } DeleteDynString(filePath); - SCStartBuffering(pCon); - while(fgets(pLine,511,fd) != NULL){ - SCWrite(pCon,pLine,eValue); + filePath = CreateDynString(256,256); + if(filePath == NULL){ + SCWrite(pCon,"ERROR: out of memory printing buffer",eError); + return 0; + } + while (fgets(pLine, 511, fd) != NULL) { + DynStringConcat(filePath, pLine); + DynStringConcatChar(filePath,'\n'); } fclose(fd); - filePath = SCEndBuffering(pCon); - SCWrite(pCon,GetCharArray(filePath),eValue); + SCWrite(pCon, GetCharArray(filePath), eValue); + DeleteDynString(filePath); return 1; } + /*========================== run stack ===============================*/ -static int enqueueBuffer(pExeMan self, SConnection *pCon, - int argc, char *argv[]){ +static int enqueueBuffer(pExeMan self, SConnection * pCon, + int argc, char *argv[]) +{ pExeBuf buf = NULL; int status; pDynString filePath = NULL; - if(SCGetRights(pCon) > usUser){ - SCWrite(pCon,"ERROR: no permission to enque buffers",eError); + if (SCGetRights(pCon) > usUser) { + SCWrite(pCon, "ERROR: no permission to enque buffers", eError); return 0; } - if(argc < 3) { - SCWrite(pCon,"ERROR: no buffer file given to enqueue ",eError); + if (argc < 3) { + SCWrite(pCon, "ERROR: no buffer file given to enqueue ", eError); return 0; } - - filePath = locateBatchBuffer(self,argv[2]); - if(filePath == NULL){ - SCWrite(pCon,"ERROR: failed to locate buffer to enqueue",eError); + + filePath = locateBatchBuffer(self, argv[2]); + if (filePath == NULL) { + SCWrite(pCon, "ERROR: failed to locate buffer to enqueue", eError); return 0; } buf = exeBufCreate("enqueue"); - if(buf == NULL){ - SCWrite(pCon,"ERROR: out of memory",eError); + if (buf == NULL) { + SCWrite(pCon, "ERROR: out of memory", eError); return 0; } - status = exeBufLoad(buf,GetCharArray(filePath)); + status = exeBufLoad(buf, GetCharArray(filePath)); DeleteDynString(filePath); - if(status != 1) { - SCWrite(pCon,"ERROR: failed to load buffer",eError); + if (status != 1) { + SCWrite(pCon, "ERROR: failed to load buffer", eError); return 0; } - LLDnodeAppendFrom(self->runList,&buf); + LLDnodeAppendFrom(self->runList, &buf); return 1; } + /*--------------------------------------------------------------------*/ -static void clearQueue(pExeMan self){ +static void clearQueue(pExeMan self) +{ pExeBuf buf = NULL; int status; status = LLDnodePtr2First(self->runList); - while(status != 0) { - LLDnodeDataTo(self->runList,&buf); - if(buf != NULL){ + while (status != 0) { + LLDnodeDataTo(self->runList, &buf); + if (buf != NULL) { exeBufDelete(buf); } LLDnodeDelete(self->runList); status = LLDnodePtr2Next(self->runList); } /* - A second time round. This is a workaround for some - dodgy behaviour of the list system. - */ + A second time round. This is a workaround for some + dodgy behaviour of the list system. + */ status = LLDnodePtr2First(self->runList); - while(status != 0) { - LLDnodeDataTo(self->runList,&buf); - if(buf != NULL){ + while (status != 0) { + LLDnodeDataTo(self->runList, &buf); + if (buf != NULL) { exeBufDelete(buf); } LLDnodeDelete(self->runList); status = LLDnodePtr2Next(self->runList); } } + /*--------------------------------------------------------------------*/ -static int execQueue(pExeMan self, SConnection *pCon, SicsInterp *pSics){ +static int execQueue(pExeMan self, SConnection * pCon, SicsInterp * pSics) +{ pExeBuf buf = NULL; int status; - if(self->exeStackPtr >= 0){ + if (self->exeStackPtr >= 0 + || (self->runCon != NULL && self->runCon != pCon)) { SCWrite(pCon, - "ERROR: cannot start queue while batch buffers are still running",eError); + "ERROR: cannot start queue while batch buffers are still running", + eError); return 0; } - if(!SCMatchRights(pCon,usUser)){ + if (!SCMatchRights(pCon, usUser)) { return 0; } - - while(LLDnodePtr2First(self->runList) != 0){ - LLDnodeDataTo(self->runList,&buf); + + self->runCon = pCon; + while (LLDnodePtr2First(self->runList) != 0) { + LLDnodeDataTo(self->runList, &buf); LLDnodeDelete(self->runList); self->exeStackPtr++; - if(buf == NULL){ + if (buf == NULL) { SCWrite(pCon, - "ERROR: serious trouble, buffer not in queue, inform programmer",eError); + "ERROR: serious trouble, buffer not in queue, inform programmer", + eError); + self->runCon = NULL; return 0; } - DynarPut(self->exeStack,self->exeStackPtr,buf); - status = exeBufProcess(buf,pSics,pCon,self->pCall,self->echo); + DynarPut(self->exeStack, self->exeStackPtr, buf); + status = exeBufProcess(buf, pSics, pCon, self->pCall, self->echo); self->exeStackPtr--; - if(SCGetInterrupt(pCon) >= eAbortBatch){ - SCWrite(pCon,"ERROR: queue processing interrupted",eError); + if (SCGetInterrupt(pCon) >= eAbortBatch) { + SCWrite(pCon, "ERROR: queue processing interrupted", eError); + self->runCon = NULL; return 0; } } + self->runCon = 0; return 1; } + /*========================== interpreter action =======================*/ -int ExeManagerWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]){ +int ExeManagerWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ pExeMan self = NULL; char pBufferName[256]; int status; pDynString dirList = NULL; pDynString fullPath = NULL; - self = (pExeMan)pData; + self = (pExeMan) pData; assert(self != NULL); - if(argc > 1){ - strncpy(pBufferName,argv[1],255); + if (argc > 1) { + strlcpy(pBufferName, argv[1], 255); +/* + argv must no be modifed, use strcasecmp instead M.Z. strtolower(argv[1]); - status = handleBatchPath(self,pCon,argc,argv); - if(status >= 0){ +*/ + status = handleBatchPath(self, pCon, argc, argv); + if (status >= 0) { return status; } - if(strcmp(argv[1],"interest") == 0){ - registerCallbacks(pCon,pSics,self); + if (strcasecmp(argv[1], "interest") == 0) { + registerCallbacks(pCon, pSics, self); SCSendOK(pCon); return 1; - } else if(strcmp(argv[1],"uninterest") == 0){ - unregisterCallbacks(pCon,self); + } else if (strcasecmp(argv[1], "uninterest") == 0) { + unregisterCallbacks(pCon, self); SCSendOK(pCon); return 1; - }else if(strcmp(argv[1],"upload") == 0){ - status = startUpload(self,pCon); - if(status){ - SCSendOK(pCon); + } else if (strcasecmp(argv[1], "upload") == 0) { + status = startUpload(self, pCon); + if (status) { + SCSendOK(pCon); } return status; - }else if(strcmp(argv[1],"append") == 0){ - status = appendLine(self,pCon,argc,argv); - if(status){ - SCSendOK(pCon); + } else if (strcasecmp(argv[1], "append") == 0) { + status = appendLine(self, pCon, argc, argv); + if (status) { + SCSendOK(pCon); } return status; - }else if(strcmp(argv[1],"save") == 0){ - status = uploadSave(self,pCon,argc,argv); - if(status){ - SCSendOK(pCon); + } else if (strcasecmp(argv[1], "save") == 0) { + status = uploadSave(self, pCon, argc, argv); + if (status) { + SCSendOK(pCon); } return status; - }else if(strcmp(argv[1],"forcesave") == 0){ - status = uploadForceSave(self,pCon,argc,argv); - if(status){ - SCSendOK(pCon); + } else if (strcasecmp(argv[1], "forcesave") == 0) { + status = uploadForceSave(self, pCon, argc, argv); + if (status) { + SCSendOK(pCon); } return status; - }else if(strcmp(argv[1],"clearupload") == 0){ - status = clearUpload(self,pCon); - if(status){ - SCSendOK(pCon); + } else if (strcasecmp(argv[1], "clearupload") == 0) { + status = clearUpload(self, pCon); + if (status) { + SCSendOK(pCon); } return status; - }else if(strcmp(argv[1],"info") == 0){ - status = infoHandler(self,pCon,argc,argv); + } else if (strcasecmp(argv[1], "info") == 0) { + status = infoHandler(self, pCon, argc, argv); return status; - }else if(strcmp(argv[1],"print") == 0){ - status = printBuffer(self,pCon,argc,argv); + } else if (strcasecmp(argv[1], "print") == 0) { + status = printBuffer(self, pCon, argc, argv); return status; - }else if(strcmp(argv[1],"enqueue") == 0){ - status = enqueueBuffer(self,pCon,argc,argv); - if(status){ - SCSendOK(pCon); + } else if (strcasecmp(argv[1], "enqueue") == 0) { + status = enqueueBuffer(self, pCon, argc, argv); + if (status) { + SCSendOK(pCon); } return status; - } else if(strcmp(argv[1],"dir") == 0){ - if(argc <= 2){ - dirList = findDirEntries(self,"*"); + } else if (strcasecmp(argv[1], "dir") == 0) { + if (argc <= 2) { + dirList = findDirEntries(self, "*"); } else { - dirList = findDirEntries(self,argv[2]); + dirList = findDirEntries(self, argv[2]); } - if(dirList != NULL){ - SCWrite(pCon,GetCharArray(dirList),eValue); - DeleteDynString(dirList); + if (dirList != NULL) { + SCWrite(pCon, GetCharArray(dirList), eValue); + DeleteDynString(dirList); } else { - SCWrite(pCon,"Nothing found",eValue); + SCWrite(pCon, "Nothing found", eValue); } return 1; - }else if(strcmp(argv[1],"fullpath") == 0){ - if(argc < 2){ - SCWrite(pCon,"ERROR: not enough arguments to exe fullpath",eError); + } else if (strcasecmp(argv[1], "fullpath") == 0) { + if (argc < 2) { + SCWrite(pCon, "ERROR: not enough arguments to exe fullpath", + eError); return 0; - } - fullPath = locateBatchBuffer(self,argv[2]); - if(fullPath == NULL){ - SCWrite(pCon,"ERROR: buffer NOT found",eError); + } + fullPath = locateBatchBuffer(self, argv[2]); + if (fullPath == NULL) { + SCWrite(pCon, "ERROR: buffer NOT found", eError); return 0; } else { - DynStringInsert(fullPath,"exe.fullpath=",0); - SCWrite(pCon,GetCharArray(fullPath),eValue); + DynStringInsert(fullPath, "exe.fullpath=", 0); + SCWrite(pCon, GetCharArray(fullPath), eValue); DeleteDynString(fullPath); return 1; } return 1; - }else if(strcmp(argv[1],"makepath") == 0){ - return makeExePath(self,pCon,argc,argv); - }else if(strcmp(argv[1],"clear") == 0){ + } else if (strcasecmp(argv[1], "makepath") == 0) { + return makeExePath(self, pCon, argc, argv); + } else if (strcasecmp(argv[1], "clear") == 0) { clearQueue(self); SCSendOK(pCon); return 1; - }else if(strcmp(argv[1],"queue") == 0){ - printQueue(self,pCon); + } else if (strcasecmp(argv[1], "queue") == 0) { + printQueue(self, pCon); SCSendOK(pCon); return 1; - }else if(strcmp(argv[1],"run") == 0){ - status = execQueue(self,pCon,pSics); - if(status){ - SCSendOK(pCon); + } else if (strcasecmp(argv[1], "run") == 0) { + status = execQueue(self, pCon, pSics); + if (status) { + SCSendOK(pCon); } return status; - }else if(strcmp(argv[1],"echo") == 0){ + } else if (strcasecmp(argv[1], "echo") == 0) { if (argc > 2) { self->echo = atoi(argv[2]) != 0; SCSendOK(pCon); @@ -1299,25 +1421,25 @@ int ExeManagerWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, SCPrintf(pCon, eValue, "exe echo = %d", self->echo); } return 1; - }else if(strcmp(argv[1],"runhdb") == 0){ + } else if (strcasecmp(argv[1], "runhdb") == 0) { if (argc < 2) { - SCWrite(pCon,"ERROR: require path to root of queue node",eError); + SCWrite(pCon, "ERROR: require path to root of queue node", eError); SCSendOK(pCon); - } - status = runHdbBuffer(self,pCon,pSics,argv[2]); - if(self->exeStackPtr < 0){ - SCWrite(pCon,"EXE TERMINATED",eWarning); + } + status = runHdbBuffer(self, pCon, pSics, argv[2]); + if (self->exeStackPtr < 0) { + SCWrite(pCon, "EXE TERMINATED", eWarning); } return status; } else { - status = runBatchBuffer(self,pCon,pSics,pBufferName); - if(self->exeStackPtr < 0){ - SCWrite(pCon,"EXE TERMINATED",eWarning); + status = runBatchBuffer(self, pCon, pSics, pBufferName); + if (self->exeStackPtr < 0) { + SCWrite(pCon, "EXE TERMINATED", eWarning); } return status; } } else { - SCWrite(pCon,"ERROR: need argument to manage batch buffers",eError); + SCWrite(pCon, "ERROR: need argument to manage batch buffers", eError); return 0; } return 1; diff --git a/exeman.h b/exeman.h index ddee48dd..fc110a6e 100644 --- a/exeman.h +++ b/exeman.h @@ -9,15 +9,14 @@ #ifndef EXEMAN #define EXEMAN -int MakeExeManager(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); -int ExeManagerWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); -int runExeBatchBuffer(void *pData, SConnection *pCon, SicsInterp *pSics, - char *name); -pDynString findBatchFile(SicsInterp *pSics, char *name); -int exeHdbBuffer(SConnection *pCon, - SicsInterp *pSics, char *name); -int exeHdbNode(pHdb exeNode, SConnection *pCon); +int MakeExeManager(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); +int ExeManagerWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); +int runExeBatchBuffer(void *pData, SConnection * pCon, SicsInterp * pSics, + char *name); +pDynString findBatchFile(SicsInterp * pSics, char *name); +int exeHdbBuffer(SConnection * pCon, SicsInterp * pSics, char *name); +int exeHdbNode(pHdb exeNode, SConnection * pCon); -#endif +#endif diff --git a/exeman.i b/exeman.i index 8b8512fb..aa3eb3d2 100644 --- a/exeman.i +++ b/exeman.i @@ -1,5 +1,5 @@ -#line 195 "exe.w" +#line 196 "exe.w" /*------------------------------------------------------------------- Internal header file for the exe manager module. Do not edit. This @@ -18,7 +18,8 @@ typedef struct __EXEMAN{ int runList; pExeBuf uploadBuffer; int echo; + SConnection *runCon; }ExeMan, *pExeMan; -#line 200 "exe.w" +#line 201 "exe.w" diff --git a/f2c.h b/f2c.h index 2390d41b..ad830f0e 100644 --- a/f2c.h +++ b/f2c.h @@ -15,15 +15,19 @@ typedef float real; /* avoid irritating warnings when math functions are used, M.Z.08.2001 */ #define doublereal double /* typedef double doublereal; */ -typedef struct { real r, i; } complex; -typedef struct { doublereal r, i; } doublecomplex; +typedef struct { + real r, i; +} complex; +typedef struct { + doublereal r, i; +} doublecomplex; typedef long int logical; typedef short int shortlogical; typedef char logical1; typedef char integer1; -#ifdef INTEGER_STAR_8 /* Adjust for integer*8. */ -typedef long long longint; /* system-dependent */ -typedef unsigned long long ulongint; /* system-dependent */ +#ifdef INTEGER_STAR_8 /* Adjust for integer*8. */ +typedef long long longint; /* system-dependent */ +typedef unsigned long long ulongint; /* system-dependent */ #define qbit_clear(a,b) ((a) & ~((ulongint)1 << (b))) #define qbit_set(a,b) ((a) | ((ulongint)1 << (b))) #endif @@ -50,110 +54,110 @@ typedef long int ftnint; #endif /*external read, write*/ -typedef struct -{ flag cierr; - ftnint ciunit; - flag ciend; - char *cifmt; - ftnint cirec; +typedef struct { + flag cierr; + ftnint ciunit; + flag ciend; + char *cifmt; + ftnint cirec; } cilist; /*internal read, write*/ -typedef struct -{ flag icierr; - char *iciunit; - flag iciend; - char *icifmt; - ftnint icirlen; - ftnint icirnum; +typedef struct { + flag icierr; + char *iciunit; + flag iciend; + char *icifmt; + ftnint icirlen; + ftnint icirnum; } icilist; /*open*/ -typedef struct -{ flag oerr; - ftnint ounit; - char *ofnm; - ftnlen ofnmlen; - char *osta; - char *oacc; - char *ofm; - ftnint orl; - char *oblnk; +typedef struct { + flag oerr; + ftnint ounit; + char *ofnm; + ftnlen ofnmlen; + char *osta; + char *oacc; + char *ofm; + ftnint orl; + char *oblnk; } olist; /*close*/ -typedef struct -{ flag cerr; - ftnint cunit; - char *csta; +typedef struct { + flag cerr; + ftnint cunit; + char *csta; } cllist; /*rewind, backspace, endfile*/ -typedef struct -{ flag aerr; - ftnint aunit; +typedef struct { + flag aerr; + ftnint aunit; } alist; /* inquire */ -typedef struct -{ flag inerr; - ftnint inunit; - char *infile; - ftnlen infilen; - ftnint *inex; /*parameters in standard's order*/ - ftnint *inopen; - ftnint *innum; - ftnint *innamed; - char *inname; - ftnlen innamlen; - char *inacc; - ftnlen inacclen; - char *inseq; - ftnlen inseqlen; - char *indir; - ftnlen indirlen; - char *infmt; - ftnlen infmtlen; - char *inform; - ftnint informlen; - char *inunf; - ftnlen inunflen; - ftnint *inrecl; - ftnint *innrec; - char *inblank; - ftnlen inblanklen; +typedef struct { + flag inerr; + ftnint inunit; + char *infile; + ftnlen infilen; + ftnint *inex; /*parameters in standard's order */ + ftnint *inopen; + ftnint *innum; + ftnint *innamed; + char *inname; + ftnlen innamlen; + char *inacc; + ftnlen inacclen; + char *inseq; + ftnlen inseqlen; + char *indir; + ftnlen indirlen; + char *infmt; + ftnlen infmtlen; + char *inform; + ftnint informlen; + char *inunf; + ftnlen inunflen; + ftnint *inrecl; + ftnint *innrec; + char *inblank; + ftnlen inblanklen; } inlist; #define VOID void -union Multitype { /* for multiple entry points */ - integer1 g; - shortint h; - integer i; - /* longint j; */ - real r; - doublereal d; - complex c; - doublecomplex z; - }; +union Multitype { /* for multiple entry points */ + integer1 g; + shortint h; + integer i; + /* longint j; */ + real r; + doublereal d; + complex c; + doublecomplex z; +}; typedef union Multitype Multitype; -/*typedef long int Long;*/ /* No longer used; formerly in Namelist */ + /*typedef long int Long;*//* No longer used; formerly in Namelist */ -struct Vardesc { /* for Namelist */ - char *name; - char *addr; - ftnlen *dims; - int type; - }; +struct Vardesc { /* for Namelist */ + char *name; + char *addr; + ftnlen *dims; + int type; +}; typedef struct Vardesc Vardesc; struct Namelist { - char *name; - Vardesc **vars; - int nvars; - }; + char *name; + Vardesc **vars; + int nvars; +}; typedef struct Namelist Namelist; #define abs(x) ((x) >= 0 ? (x) : -(x)) @@ -170,35 +174,35 @@ typedef struct Namelist Namelist; #define F2C_proc_par_types 1 #ifdef __cplusplus -typedef int /* Unknown procedure type */ (*U_fp)(...); -typedef shortint (*J_fp)(...); -typedef integer (*I_fp)(...); -typedef real (*R_fp)(...); -typedef doublereal (*D_fp)(...), (*E_fp)(...); -typedef /* Complex */ VOID (*C_fp)(...); -typedef /* Double Complex */ VOID (*Z_fp)(...); -typedef logical (*L_fp)(...); -typedef shortlogical (*K_fp)(...); -typedef /* Character */ VOID (*H_fp)(...); -typedef /* Subroutine */ int (*S_fp)(...); +typedef int /* Unknown procedure type */ (*U_fp) (...); +typedef shortint(*J_fp) (...); +typedef integer(*I_fp) (...); +typedef real(*R_fp) (...); +typedef doublereal(*D_fp) (...), (*E_fp) (...); +typedef /* Complex */ VOID(*C_fp) (...); +typedef /* Double Complex */ VOID(*Z_fp) (...); +typedef logical(*L_fp) (...); +typedef shortlogical(*K_fp) (...); +typedef /* Character */ VOID(*H_fp) (...); +typedef /* Subroutine */ int (*S_fp) (...); #else -typedef int /* Unknown procedure type */ (*U_fp)(); -typedef shortint (*J_fp)(); -typedef integer (*I_fp)(); -typedef real (*R_fp)(); -typedef doublereal (*D_fp)(), (*E_fp)(); -typedef /* Complex */ VOID (*C_fp)(); -typedef /* Double Complex */ VOID (*Z_fp)(); -typedef logical (*L_fp)(); -typedef shortlogical (*K_fp)(); -typedef /* Character */ VOID (*H_fp)(); -typedef /* Subroutine */ int (*S_fp)(); +typedef int /* Unknown procedure type */ (*U_fp) (); +typedef shortint(*J_fp) (); +typedef integer(*I_fp) (); +typedef real(*R_fp) (); +typedef doublereal(*D_fp) (), (*E_fp) (); +typedef /* Complex */ VOID(*C_fp) (); +typedef /* Double Complex */ VOID(*Z_fp) (); +typedef logical(*L_fp) (); +typedef shortlogical(*K_fp) (); +typedef /* Character */ VOID(*H_fp) (); +typedef /* Subroutine */ int (*S_fp) (); #endif /* E_fp is for real functions when -R is not specified */ -typedef VOID C_f; /* complex function */ -typedef VOID H_f; /* character function */ -typedef VOID Z_f; /* double complex function */ -typedef doublereal E_f; /* real function with -R not specified */ +typedef VOID C_f; /* complex function */ +typedef VOID H_f; /* character function */ +typedef VOID Z_f; /* double complex function */ +typedef doublereal E_f; /* real function with -R not specified */ /* undef any lower-case symbols that your C compiler predefines, e.g.: */ diff --git a/fitcenter.c b/fitcenter.c index bee1b090..0e4aa9ae 100644 --- a/fitcenter.c +++ b/fitcenter.c @@ -6,6 +6,11 @@ copyright: see copyright.h Mark Koennecke, October 1997 + + Added center of edge finding + + Mark Koennecke, Octover 2011 + -----------------------------------------------------------------------------*/ #include #include @@ -15,547 +20,556 @@ #include "scan.h" #include "fitcenter.h" #define THRESHOLD .1 +/*--------------------------------------------------------------------------*/ +typedef struct __FitCenter { + pObjectDescriptor pDes; + pScanData pScan; + long *lCounts; + float *fAxis; + char pName[132]; + float fCenter; + float fStddev; + long lPeak; + float FWHM; + int iNP; +} FitCenter; +/*-------------------------------------------------------------------------*/ +pFit CreateFitCenter(pScanData pScan) +{ + pFit pNew = NULL; -//Jing: Flag to smooth the scan data -#define SMOOTHSCANDATA + pNew = (pFit) malloc(sizeof(FitCenter)); + if (!pNew) { + return NULL; + } + memset(pNew, 0, sizeof(FitCenter)); -float ggf1[] = {0.006, 0.061, 0.242, 0.383, 0.242, 0.061, 0.006}; // Gaussian Smooth Filter -float ggf2[] = {0.1429, 0.1429, 0.1429, 0.1429, 0.1429, 0.1429, 0.1429}; // Mean Smooth Filter + pNew->pDes = CreateDescriptor("FitCenter"); + if (!pNew->pDes) { + free(pNew); + return NULL; + } + pNew->pScan = pScan; + return pNew; +} +/*-------------------------------------------------------------------------*/ +void DeleteFitCenter(void *pData) +{ + pFit self = NULL; + + self = (pFit) pData; + assert(self); + + if (self->pDes) { + DeleteDescriptor(self->pDes); + } + if (self->lCounts) { + free(self->lCounts); + } + if (self->fAxis) { + free(self->fAxis); + } + free(self); +} /*--------------------------------------------------------------------------*/ - typedef struct __FitCenter { - pObjectDescriptor pDes; - pScanData pScan; - long *lCounts; - float *fAxis; - char pName[132]; - float fCenter; - float fStddev; - long lPeak; - float FWHM; - int iNP; - } FitCenter; +static int Init(pFit self) +{ + pMotor pMot = NULL; + float fZero, fSign; + int i; + + /* collect data first */ + self->iNP = GetScanNP(self->pScan); + if (self->lCounts) { + free(self->lCounts); + self->lCounts = NULL; + } + if (self->fAxis) { + free(self->fAxis); + self->fAxis = NULL; + } + self->lCounts = (long *) malloc(self->iNP * sizeof(long)); + self->fAxis = (float *) malloc(self->iNP * sizeof(float)); + if ((!self->lCounts) || (!self->fAxis)) { + return 0; + } + + GetScanCounts(self->pScan, self->lCounts, self->iNP); + GetScanVar(self->pScan, 0, self->fAxis, self->iNP); + GetScanVarName(self->pScan, 0, self->pName, 131); + + return 1; +} + /*-------------------------------------------------------------------------*/ - pFit CreateFitCenter(pScanData pScan) - { - pFit pNew = NULL; - - pNew = (pFit)malloc(sizeof(FitCenter)); - if(!pNew) - { - return NULL; - } - memset(pNew,0,sizeof(FitCenter)); - - pNew->pDes = CreateDescriptor("FitCenter"); - if(!pNew->pDes) - { - free(pNew); - return NULL; - } - pNew->pScan = pScan; - return pNew; - } +static int FindMax(pFit self) +{ + long lMax = LONG_MIN; + int i, iMax; + + for (i = 0, iMax = 0; i < self->iNP; i++) { + if (self->lCounts[i] > lMax) { + lMax = self->lCounts[i]; + iMax = i; + } + } + + return iMax; +} + /*-------------------------------------------------------------------------*/ - void DeleteFitCenter(void *pData) - { - pFit self = NULL; - - self = (pFit)pData; - assert(self); - - if(self->pDes) - { - DeleteDescriptor(self->pDes); - } - if(self->lCounts) - { - free(self->lCounts); - } - if(self->fAxis) - { - free(self->fAxis); - } - free(self); - } +static int CalculateFitIntern(pFit self) +{ + int i, iLeft, iRight, iRet, iPeak, iLast; + long lHalf; + float fFrac, fDelta, fStep, fLeft, fRight, fNenner, fTest; + float fLFrac, fRFrac, fSum, fCI; + iLeft = 0; -/* Jing: smmoth the scan data */ - void SmoothScanCounts(long *lData, int iDataLen) - { - int ind = (int) (sizeof(ggf1)/sizeof(float) - 1)/2; - long * pData = (long *)malloc(iDataLen * sizeof(long)); + /* find the maximum counts */ + iRet = FindMax(self); + self->lPeak = self->lCounts[iRet]; + /* a default fit is the peak maximum. This + helps optimise to do the right thing if no proper calculation + could be performed + */ + self->fCenter = self->fAxis[iRet]; + iPeak = iRet; - for(int i=0; ilPeak < 3) { + return -3; + } - for(int i=0; i0) - lData[i] += pData[i-j] * ggf1[ind-j]; - if((i+j)lPeak / 2; + iLeft = iPeak; + while ((self->lCounts[iLeft] > lHalf) && (iLeft > 0)) { + iLeft--; + } + if (iLeft == 0) { + iRet = -1; + iLeft++; + } + fNenner = + (float) self->lCounts[iLeft + 1] - (float) self->lCounts[iLeft]; + if (fNenner < 0.) { + fTest = -fNenner; + } else { + fTest = fNenner; + } + if (fTest < .00001) { + return -4; + } + fFrac = ((float) self->lCounts[iLeft + 1] - (float) lHalf) / fNenner; + fLeft = self->fAxis[iLeft] + + fFrac * (self->fAxis[iLeft + 1] - self->fAxis[iLeft]); + fLFrac = fFrac; - free(pData); - } + iRight = iPeak; + while ((self->lCounts[iRight] > lHalf) && (iRight < self->iNP)) { + iRight++; + } + if (iRight >= self->iNP - 1) { + iRet = -2; + iRight = self->iNP - 1; + } + fNenner = + (float) self->lCounts[iRight - 1] - (float) self->lCounts[iRight]; + if (fNenner < 0.) { + fTest = -fNenner; + } else { + fTest = fNenner; + } + if (fTest < .00001) { + return -4; + } + fFrac = ((float) self->lCounts[iRight - 1] - (float) lHalf) / fNenner; + fRight = self->fAxis[iRight] - fFrac * (self->fAxis[1] - self->fAxis[0]); + fRFrac = fFrac; - -/*--------------------------------------------------------------------------*/ - static int Init(pFit self) - { - pMotor pMot = NULL; - float fZero, fSign; - int i; - - /* collect data first */ - self->iNP = GetScanNP(self->pScan); - if(self->lCounts) - { - free(self->lCounts); - self->lCounts = NULL; - } - if(self->fAxis) - { - free(self->fAxis); - self->fAxis = NULL; - } - self->lCounts = (long *)malloc(self->iNP * sizeof(long)); - self->fAxis = (float *)malloc(self->iNP * sizeof(float)); - if( (!self->lCounts) || (!self->fAxis) ) - { - return 0; - } - - GetScanCounts(self->pScan,self->lCounts, self->iNP); - -#ifdef SMOOTHSCANDATA //Jing: Smoothe the scan data with a Gaussian filter - SmoothScanCounts(self->lCounts, self->iNP); -#endif - - GetScanVar(self->pScan,0,self->fAxis,self->iNP); - GetScanVarName(self->pScan,0,self->pName,131); - - return 1; - } -/*-------------------------------------------------------------------------*/ - static int FindMax(pFit self) - { - long lMax = LONG_MIN; - int i, iMax; - - for(i = 0, iMax = 0; i < self->iNP; i++) - { - if(self->lCounts[i] > lMax) - { - lMax = self->lCounts[i]; - iMax = i; - } - } - - return iMax; - } -/*-------------------------------------------------------------------------*/ - static int CalculateFitIntern(pFit self) - { - int i,iLeft, iRight, iRet,iPeak, iLast; - long lHalf; - float fFrac, fDelta, fStep, fLeft, fRight, fNenner, fTest; - float fLFrac, fRFrac, fSum, fCI; - - iLeft = 0; - - /* find the maximum counts */ - iRet = FindMax(self); - self->lPeak = self->lCounts[iRet]; - /* a default fit is the peak maximum. This - helps optimise to do the right thing if no proper calculation - could be performed - */ - self->fCenter = self->fAxis[iRet]; - iPeak = iRet; - - if(self->lPeak < 3) - { - return -3; - } - - /* find FWHM, first from Right then from left */ - iRet =1; - lHalf = self->lPeak/2; - iLeft = iPeak; - while( (self->lCounts[iLeft] > lHalf) && (iLeft > 0) ) - { - iLeft--; - } - if(iLeft == 0) - { - iRet = -1; - iLeft++; - } - fNenner = (float)self->lCounts[iLeft+1] - (float)self->lCounts[iLeft]; - if(fNenner < 0.) - { - fTest = -fNenner; - } - else - { - fTest = fNenner; - } - if(fTest < .00001) - { - return -4; - } - fFrac = ((float)self->lCounts[iLeft+1] - (float)lHalf) / fNenner; - fLeft = self->fAxis[iLeft] + - fFrac * (self->fAxis[iLeft+1] - self->fAxis[iLeft]); - fLFrac = fFrac; - - iRight = iPeak; - while( (self->lCounts[iRight] > lHalf) && (iRight < self->iNP) ) - { - iRight++; - } - if(iRight >= self->iNP - 1) - { - iRet = -2; - iRight = self->iNP - 1; - } - fNenner = (float)self->lCounts[iRight-1] - (float)self->lCounts[iRight]; - if(fNenner < 0.) - { - fTest = -fNenner; - } - else - { - fTest = fNenner; - } - if(fTest < .00001) - { - return -4; - } - fFrac = ((float)self->lCounts[iRight-1] - (float)lHalf) / fNenner; - fRight = self->fAxis[iRight] - - fFrac * (self->fAxis[1] - self->fAxis[0]); - fRFrac = fFrac; - - if(iRight != iLeft) - { - self->FWHM = fRight - fLeft; - } - else - { - self->FWHM = 0.07; - } + if (iRight != iLeft) { + self->FWHM = fRight - fLeft; + } else { + self->FWHM = 0.07; + } /* self->fCenter = fLeft + (fRight - fLeft)/2.; */ - fSum = lHalf*(fLFrac); - fNenner = lHalf; - /* center of gravity calculation between iLeft and iRight */ - for(i = iLeft+1; i < iRight; i++) - { - fSum += self->lCounts[i]*(fLFrac + i - iLeft); - fNenner += self->lCounts[i]; - } - fSum += (iRight - 1 + fRFrac + fLFrac - iLeft )*lHalf; - fNenner += lHalf; - fCI = fSum/fNenner; - /* iLeft is zero, zero point shift by lFrac */ - fCI -= fLFrac; - fTest = fNenner; - fNenner = modff(fCI, &fSum); - self->fCenter = self->fAxis[(int)(fSum)+iLeft] + - fNenner*(self->fAxis[iLeft+1] - self->fAxis[iLeft]); - - /* error calculation */ - fTest = 2*(sqrtf(fTest))/fTest; - /* because we are really summing from iLeft */ - fTest = fCI*fTest; - if(fTest < 0) - fTest = - fTest; - self->fStddev = fTest*(self->fAxis[iLeft+1] - self->fAxis[iLeft]); - - return iRet; - } -/*--------------------------------------------------------------------------*/ - int CalculateFit(pFit self) - { - int iRet; - - - /* initialise */ - iRet = Init(self); - if(!iRet) - { - return iRet; - } - return CalculateFitIntern(self); + fSum = lHalf * (fLFrac); + fNenner = lHalf; + /* center of gravity calculation between iLeft and iRight */ + for (i = iLeft + 1; i < iRight; i++) { + fSum += self->lCounts[i] * (fLFrac + i - iLeft); + fNenner += self->lCounts[i]; } -/*------------------------------------------------------------------------*/ - int CalculateFitFromData(pFit self, float *fAxis, long *lCounts, int iLength) - { - int iRet; - float *fOld; - long *lOld; - int iOld; - - /* save old data. The normal handling is to have a local copy of - data with fit. This is handled differently in this function, where - it is assumed, that the data is owned by the caller. In order not - to upset fit's scheme for data handling data pointers are swapped. - This is more efficient then copying the data around without real - need. - */ - iOld = self->iNP; - fOld = self->fAxis; - lOld = self->lCounts; - - /* put in new */ - self->iNP = iLength; - self->fAxis = fAxis; - self->lCounts = lCounts; - - iRet = CalculateFitIntern(self); - - /* reset data pointers */ - self->iNP = iOld; - self->fAxis = fOld; - self->lCounts = lOld; - - return iRet; - } -/*------------------------------------------------------------------------*/ - void GetFitResults(pFit self, float *fCenter, float *fStdDev, - float *FWHM, float *fMax) - { - assert(self); - *fCenter = self->fCenter; - *FWHM = self->FWHM; - *fMax = (float)self->lPeak; - *fStdDev = self->fStddev; - } -/*--------------------------------------------------------------------------*/ - int DriveCenter(pFit self, SConnection *pCon, SicsInterp *pSics) - { - int iRet; - - assert(self); - assert(pCon); - assert(pSics); - - iRet = StartMotor(pServ->pExecutor, pSics,pCon,self->pName,self->fCenter); - if(!iRet) - { - return 0; - } - - iRet = Wait4Success(pServ->pExecutor); - switch(iRet) - { - case DEVINT: - if(SCGetInterrupt(pCon) == eAbortOperation) - { - SCSetInterrupt(pCon,eContinue); - SCWrite(pCon,"Driving Aborted",eStatus); - } - return 0; - break; - case DEVDONE: - SCWrite(pCon,"Driving to center done",eStatus); - break; - default: - SCWrite(pCon, - "WARNING: driving to center finished with problems", - eWarning); - break; - - } - return 1; + fSum += (iRight - 1 + fRFrac + fLFrac - iLeft) * lHalf; + fNenner += lHalf; + fCI = fSum / fNenner; + /* iLeft is zero, zero point shift by lFrac */ + fCI -= fLFrac; + fTest = fNenner; + fNenner = modff(fCI, &fSum); + self->fCenter = self->fAxis[(int) (fSum) + iLeft] + + fNenner * (self->fAxis[iLeft + 1] - self->fAxis[iLeft]); + + /* error calculation */ + fTest = 2 * (sqrtf(fTest)) / fTest; + /* because we are really summing from iLeft */ + fTest = fCI * fTest; + if (fTest < 0) + fTest = -fTest; + self->fStddev = fTest * (self->fAxis[iLeft + 1] - self->fAxis[iLeft]); + + return iRet; +} +/*-------------------------------------------------------------------------*/ +static int CalculateEdgeIntern(pFit self) +{ + int i, iRet, iPeak, nSlope = 0;; + long lCount; + float fNenner,fSum, fCI; + + + /* find the maximum counts */ + iRet = FindMax(self); + self->lPeak = self->lCounts[iRet]; + /* a default fit is the peak maximum. This + helps optimise to do the right thing if no proper calculation + could be performed + */ + if (self->lPeak < 3) { + return -3; } - + + /* + * calculate the COG between .9*max < counts < .1*max + */ + fSum = 0.; + fNenner = 0.; + for (i = 0; i < self->iNP; i++) { + lCount = self->lCounts[i]; + if(lCount > self->lPeak *.20 && lCount < self->lPeak * .80){ + fSum += lCount * self->fAxis[i]; + fNenner += lCount; + nSlope++; + } + } + if(fNenner > .0001){ + fCI = fSum / fNenner; + } else { + return -3; + } + self->fCenter = fCI; + self->fStddev = 1.0; + + if(nSlope < 3) { + iRet = -7; + } + return iRet; +} + /*--------------------------------------------------------------------------*/ - int FitFactory(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - pFit self = NULL; - pScanData pScan = NULL; - pDummy pDum = NULL; - CommandList *pCom = NULL; - char pBueffel[132]; - int iRet, iRet1; - - if(argc < 2) - { - SCWrite(pCon, - "ERROR: MakeFit expected the name of a scan command as a parameter", - eError); - return 0; - } - - pCom = FindCommand(pSics,argv[1]); - if(!pCom) - { - sprintf(pBueffel,"ERROR: scan command %s not found",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - pDum = (pDummy)pCom->pData; - if(!pDum) - { - sprintf(pBueffel,"ERROR: scan command %s not found",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - if(strcmp(pDum->pDescriptor->name,"ScanObject") != 0) - { - sprintf(pBueffel,"ERROR: %s is no scan command",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - pScan = (pScanData)pDum; - self = CreateFitCenter(pScan); - if(!self) - { - SCWrite(pCon,"ERROR: Failure to allocate Peak & Center command",eError); - return 0; - } - - iRet = AddCommand(pSics,"peak",FitWrapper,DeleteFitCenter,self); - iRet1 = AddCommand(pSics,"center",CenterWrapper,NULL,self); - if(!iRet || !iRet1) - { - sprintf(pBueffel, +int CalculateFit(pFit self) +{ + int iRet; + + + /* initialise */ + iRet = Init(self); + if (!iRet) { + return iRet; + } + return CalculateFitIntern(self); +} + +/*------------------------------------------------------------------------*/ +int CalculateFitFromData(pFit self, float *fAxis, long *lCounts, + int iLength) +{ + int iRet; + float *fOld; + long *lOld; + int iOld; + + /* save old data. The normal handling is to have a local copy of + data with fit. This is handled differently in this function, where + it is assumed, that the data is owned by the caller. In order not + to upset fit's scheme for data handling data pointers are swapped. + This is more efficient then copying the data around without real + need. + */ + iOld = self->iNP; + fOld = self->fAxis; + lOld = self->lCounts; + + /* put in new */ + self->iNP = iLength; + self->fAxis = fAxis; + self->lCounts = lCounts; + + iRet = CalculateFitIntern(self); + + /* reset data pointers */ + self->iNP = iOld; + self->fAxis = fOld; + self->lCounts = lOld; + + return iRet; +} + +/*------------------------------------------------------------------------*/ +void GetFitResults(pFit self, float *fCenter, float *fStdDev, + float *FWHM, float *fMax) +{ + assert(self); + *fCenter = self->fCenter; + *FWHM = self->FWHM; + *fMax = (float) self->lPeak; + *fStdDev = self->fStddev; +} + +/*--------------------------------------------------------------------------*/ +int DriveCenter(pFit self, SConnection * pCon, SicsInterp * pSics) +{ + int iRet; + + assert(self); + assert(pCon); + assert(pSics); + + iRet = + StartMotor(pServ->pExecutor, pSics, pCon, self->pName, + RUNDRIVE, self->fCenter); + if (!iRet) { + return 0; + } + + iRet = Wait4Success(pServ->pExecutor); + switch (iRet) { + case DEVINT: + if (SCGetInterrupt(pCon) == eAbortOperation) { + SCSetInterrupt(pCon, eContinue); + SCWrite(pCon, "Driving Aborted", eError); + } + return 0; + break; + case DEVDONE: + SCWrite(pCon, "Driving to center done", eValue); + break; + default: + SCWrite(pCon, + "WARNING: driving to center finished with problems", eWarning); + break; + + } + return 1; +} + +/*--------------------------------------------------------------------------*/ +int FitFactory(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pFit self = NULL; + pScanData pScan = NULL; + pDummy pDum = NULL; + CommandList *pCom = NULL; + char pBueffel[132]; + int iRet, iRet1, iRet2; + + if (argc < 2) { + SCWrite(pCon, + "ERROR: MakeFit expected the name of a scan command as a parameter", + eError); + return 0; + } + + pCom = FindCommand(pSics, argv[1]); + if (!pCom) { + snprintf(pBueffel,sizeof(pBueffel), "ERROR: scan command %s not found", argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + pDum = (pDummy) pCom->pData; + if (!pDum) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: scan command %s not found", argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + if (strcmp(pDum->pDescriptor->name, "ScanObject") != 0) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s is no scan command", argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + pScan = (pScanData) pDum; + self = CreateFitCenter(pScan); + if (!self) { + SCWrite(pCon, "ERROR: Failure to allocate Peak & Center command", + eError); + return 0; + } + + iRet = AddCommand(pSics, "peak", FitWrapper, DeleteFitCenter, self); + iRet1 = AddCommand(pSics, "center", CenterWrapper, NULL, self); + iRet2 = AddCommand(pSics, "edge", EdgeWrapper, NULL, self); + if (!iRet || !iRet1) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: duplicate commands peak and center not created"); - SCWrite(pCon,pBueffel,eError); - DeleteFitCenter((void *)self); - return 0; - } - return 1; - } + SCWrite(pCon, pBueffel, eError); + DeleteFitCenter((void *) self); + return 0; + } + return 1; +} /*--------------------------------------------------------------------------*/ - int FitWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - pFit self = NULL; - int iRet; - char pBueffel[256]; - pDynString buf = NULL; - pScanData pScan = NULL; - char* cmd = NULL; - - self = (pFit)pData; - assert(self); - if (argc > 1) - { - cmd = argv[1]; - CommandList *pCom = NULL; - pCom = FindCommand(pSics,argv[1]); - if (pCom) - { - pDummy pDum = NULL; - pDum = (pDummy)pCom->pData; - if (pDum) - { - if(strcmp(pDum->pDescriptor->name,"ScanObject") == 0) - { - pScan = (pScanData)pDum; - if (argc > 2) - cmd = argv[2]; - } - } - } - } - if (pScan) - { - pScanData pScanSave; - pScanSave = self->pScan; - self->pScan = pScan; - iRet = CalculateFit(self); - self->pScan = pScanSave; - } - else - { - iRet = CalculateFit(self); - } - switch(iRet) - { - case 0: - SCWrite(pCon,"ERROR: failure to fit your data!",eError); - return 0; - break; - case -1: - SCWrite(pCon,"WARNING: could not find left hand half width",eWarning); - SCWrite(pCon, - "Fit Results most certainly dodgy, SICS suggests measuring a full peak", - eWarning); - break; - case -2: - SCWrite(pCon,"WARNING: could not find right hand half width",eError); - SCWrite(pCon, - "Fit Results most certainly dodgy, SICS suggests measuring a full peak", - eWarning); - break; - case -3: - SCWrite(pCon,"ERROR: No counts found in Fit!",eError); - return 0; - break; - case -4: - SCWrite(pCon,"ERROR: Insufficient counts in peak",eError); - return 0; - break; - } - - /* - This is a little feature to get the peak without rubbish for - the TAS routines - */ - if(cmd) - { - strtolower(cmd); - if(strcmp(cmd,"value") == 0) - { - sprintf(pBueffel,"%f", self->fCenter); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - if(strcmp(cmd,"data") == 0) - { - snprintf(pBueffel,255,"%f,%f,%ld", - self->fCenter, self->FWHM, self->lPeak); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - } - - /* print results */ - SCStartBuffering(pCon); - sprintf(pBueffel,"Estimated Peak Center: %f, StdDev: %f \n", - self->fCenter,self->fStddev); - SCWrite(pCon,pBueffel,eValue); - sprintf(pBueffel,"Maximum peak height: %ld\n", self->lPeak); - SCWrite(pCon,pBueffel,eValue); - sprintf(pBueffel,"Approximate FWHM: %f\n",self->FWHM); - SCWrite(pCon,pBueffel,eValue); - buf = SCEndBuffering(pCon); - if(buf != NULL){ - SCWrite(pCon,GetCharArray(buf),eValue); - } - - return 1; - } +int FitWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pFit self = NULL; + int iRet; + char pBueffel[256]; + pDynString buf = NULL; + + self = (pFit) pData; + assert(self); + + iRet = CalculateFit(self); + switch (iRet) { + case 0: + SCWrite(pCon, "ERROR: failure to fit your data!", eError); + return 0; + break; + case -1: + SCWrite(pCon, "WARNING: could not find left hand half width", + eWarning); + SCWrite(pCon, + "Fit Results most certainly dodgy, SICS suggests measuring a full peak", + eWarning); + break; + case -2: + SCWrite(pCon, "WARNING: could not find right hand half width", eError); + SCWrite(pCon, + "Fit Results most certainly dodgy, SICS suggests measuring a full peak", + eWarning); + break; + case -3: + SCWrite(pCon, "ERROR: No counts found in Fit!", eError); + return 0; + break; + case -4: + SCWrite(pCon, "ERROR: Insufficient counts in peak", eError); + return 0; + break; + } + + /* + This is a little feature to get the peak without rubbish for + the TAS routines + */ + if (argc > 1) { + strtolower(argv[1]); + if (strcmp(argv[1], "value") == 0) { + snprintf(pBueffel,sizeof(pBueffel)-1, "%f", self->fCenter); + SCWrite(pCon, pBueffel, eValue); + return 1; + } + if (strcmp(argv[1], "data") == 0) { + snprintf(pBueffel, 255, "%f,%f,%ld", + self->fCenter, self->FWHM, self->lPeak); + SCWrite(pCon, pBueffel, eValue); + return 1; + } + } + + /* print results */ + buf = CreateDynString(256,256); + if(buf != NULL){ + snprintf(pBueffel,sizeof(pBueffel)-1, "Estimated Peak Center: %f, StdDev: %f \n", + self->fCenter, self->fStddev); + DynStringConcat(buf,pBueffel); + DynStringConcatChar(buf,'\n'); + snprintf(pBueffel,sizeof(pBueffel)-1, "Maximum peak height: %ld\n", self->lPeak); + DynStringConcat(buf,pBueffel); + DynStringConcatChar(buf,'\n'); + snprintf(pBueffel,sizeof(pBueffel)-1, "Approximate FWHM: %f\n", self->FWHM); + DynStringConcat(buf,pBueffel); + DynStringConcatChar(buf,'\n'); + SCWrite(pCon, GetCharArray(buf), eValue); + DeleteDynString(buf); + } else { + SCWrite(pCon,"ERROR: out of memory printing fitcenter results",eError); + return 0; + } + + return 1; +} /*---------------------------------------------------------------------------*/ - int CenterWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - pFit self = NULL; - int iRet; - - self = (pFit)pData; - assert(self); - - return DriveCenter(self,pCon,pSics); +int EdgeWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pFit self = NULL; + int iRet; + char pBueffel[256]; + pDynString buf = NULL; + + self = (pFit) pData; + assert(self); + + Init(self); + iRet = CalculateEdgeIntern(self); + switch (iRet) { + case 0: + SCWrite(pCon, "ERROR: failure to fit your data!", eError); + return 0; + break; + case -3: + SCWrite(pCon, "ERROR: No counts found in Fit!", eError); + return 0; + break; + case -4: + SCWrite(pCon, "ERROR: Insufficient counts in peak", eError); + return 0; + break; + case -7: + SCWrite(pCon, + "WARNING: not enough points in slope, results may be inreliable, remeasure with smaller step width", + eWarning); + break; + } + + /* + This is a little feature to get the peak without rubbish for + the TAS routines + */ + if (argc > 1) { + strtolower(argv[1]); + if (strcmp(argv[1], "value") == 0) { + snprintf(pBueffel,sizeof(pBueffel)-1, "%f", self->fCenter); + SCWrite(pCon, pBueffel, eValue); + return 1; + } } + + /* print results */ + snprintf(pBueffel,sizeof(pBueffel)-1, "Estimated Edge Center: %f\n", + self->fCenter); + SCWrite(pCon, pBueffel, eValue); + + return 1; +} +/*---------------------------------------------------------------------------*/ +int CenterWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pFit self = NULL; + int iRet; + + self = (pFit) pData; + assert(self); + + return DriveCenter(self, pCon, pSics); +} diff --git a/fitcenter.h b/fitcenter.h index bce6fc27..d2b7bec9 100644 --- a/fitcenter.h +++ b/fitcenter.h @@ -8,37 +8,38 @@ copyright: see copyright.h Mark Koennecke, October 1997 + + Added center of edge finding + + Mark Koennecke, Octover 2011 ----------------------------------------------------------------------------*/ #ifndef SICSFITCENTER #define SICSFITCENTER - typedef struct __FitCenter *pFit; +typedef struct __FitCenter *pFit; /*--------------------------------------------------------------------------*/ - pFit CreateFitCenter(pScanData pScan); - void DeleteFitCenter(void *pData); +pFit CreateFitCenter(pScanData pScan); +void DeleteFitCenter(void *pData); /*-------------------------------------------------------------------------*/ - int CalculateFit(pFit self); +int CalculateFit(pFit self); /* - CalcluateFit returns: -1 when left FWHM could not be found - -2 when right FWHM could not be found - 1 on success - */ - int CalculateFitFromData(pFit self, float fAxis[], long lSum[], - int iLen); - void GetFitResults(pFit self, float *fNewCenter, float *fStdDev, - float *FWHM, float *fMax); - int DriveCenter(pFit self, SConnection *pCon, SicsInterp *pSics); + CalcluateFit returns: -1 when left FWHM could not be found + -2 when right FWHM could not be found + 1 on success + */ +int CalculateFitFromData(pFit self, float fAxis[], long lSum[], int iLen); +void GetFitResults(pFit self, float *fNewCenter, float *fStdDev, + float *FWHM, float *fMax); +int DriveCenter(pFit self, SConnection * pCon, SicsInterp * pSics); /*-------------------------------------------------------------------------*/ - int FitFactory(SConnection *pCon,SicsInterp *pSics, void *pData, - int argc, char *argv[]); - int FitWrapper(SConnection *pCon,SicsInterp *pSics, void *pData, - int argc, char *argv[]); - int CenterWrapper(SConnection *pCon,SicsInterp *pSics, void *pData, - int argc, char *argv[]); - - //Jing: smmoth scan data before applying peak-search function - void SmoothScanCounts(long *lData, int iDataLen); - +int FitFactory(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); +int FitWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); +int EdgeWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); +int CenterWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); #endif diff --git a/fomerge.c b/fomerge.c index b6dc9d20..39b88481 100644 --- a/fomerge.c +++ b/fomerge.c @@ -38,14 +38,14 @@ static pFit fitter = NULL; /*================== module static data items ==========================*/ - static HistInt *masterData, *upperData, *mediumData, *lowerData, - *mergedData = NULL; - static int timeBin, nUpper, nLower, nMedium, nMerged; - static float *upperTheta, *lowerTheta, *mediumTheta, *mergedTheta; - static int *mergeUp, *mergeMed, *mergeLow; - int iMerged; +static HistInt *masterData, *upperData, *mediumData, *lowerData, + *mergedData = NULL; +static int timeBin, nUpper, nLower, nMedium, nMerged; +static float *upperTheta, *lowerTheta, *mediumTheta, *mergedTheta; +static int *mergeUp, *mergeMed, *mergeLow; +int iMerged; - int medium, upper, lower; +int medium, upper, lower; /*------------------------------------------------------------------------ The tables with the theta values for the detector banks and the merge table living in mergeUp, mergeMed, mergeLow is initialized from a @@ -55,194 +55,170 @@ static pFit fitter = NULL; -------------------------------------------------------------------------*/ int initializeFM(char *mergefile) { - FILE *fd = NULL; - int i, j, iTest; - char pBuffer[132]; - char *pPtr = NULL; + FILE *fd = NULL; + int i, j, iTest; + char pBuffer[132]; + char *pPtr = NULL; - /* open the file */ - fd = fopen(mergefile,"r"); - if(!fd) - { - fprintf(stdout,"ERROR: merge data file not found!\n"); - return 0; - } + /* open the file */ + fd = fopen(mergefile, "r"); + if (!fd) { + fprintf(stdout, "ERROR: merge data file not found!\n"); + return 0; + } - /* skip first line */ - pPtr = fgets(pBuffer,131,fd); + /* skip first line */ + pPtr = fgets(pBuffer, 131, fd); - /* read the number of merged data points */ - fgets(pBuffer,131,fd); - iTest = sscanf(pBuffer,"%d",&nMerged); - if((iTest != 1) || (nMerged <= 0) ) - { - fprintf(stdout,"ERROR: Invalid or corrupt merge dat file"); - return 0; - } + /* read the number of merged data points */ + fgets(pBuffer, 131, fd); + iTest = sscanf(pBuffer, "%d", &nMerged); + if ((iTest != 1) || (nMerged <= 0)) { + fprintf(stdout, "ERROR: Invalid or corrupt merge dat file"); + return 0; + } - /* allocate space */ - mergedTheta = (float *)malloc(nMerged*sizeof(float)); - mergeUp = (int *)malloc(nMerged*sizeof(int)); - mergeMed = (int *)malloc(nMerged*sizeof(int)); - mergeLow = (int *)malloc(nMerged*sizeof(int)); - if( mergedTheta == NULL || mergeUp == NULL || mergeMed == NULL - || mergeLow == NULL ) - { - fprintf(stdout,"ERROR: out of memory in fomerge\n"); - return 0; - } + /* allocate space */ + mergedTheta = (float *) malloc(nMerged * sizeof(float)); + mergeUp = (int *) malloc(nMerged * sizeof(int)); + mergeMed = (int *) malloc(nMerged * sizeof(int)); + mergeLow = (int *) malloc(nMerged * sizeof(int)); + if (mergedTheta == NULL || mergeUp == NULL || mergeMed == NULL + || mergeLow == NULL) { + fprintf(stdout, "ERROR: out of memory in fomerge\n"); + return 0; + } - /* read the merge table */ - for(i = 0; i < nMerged; i++) - { - fgets(pBuffer,131,fd); - iTest = sscanf(pBuffer,"%d %f %d %d %d",&j, &mergedTheta[i], - &mergeUp[i], &mergeMed[i], &mergeLow[i]); - if(iTest != 5) - { - fprintf(stdout,"ERROR: Invalid or corrupt merge dat file"); + /* read the merge table */ + for (i = 0; i < nMerged; i++) { + fgets(pBuffer, 131, fd); + iTest = sscanf(pBuffer, "%d %f %d %d %d", &j, &mergedTheta[i], + &mergeUp[i], &mergeMed[i], &mergeLow[i]); + if (iTest != 5) { + fprintf(stdout, "ERROR: Invalid or corrupt merge dat file"); return 0; - } - } - - /* read upper bank two theta */ - fgets(pBuffer,131,fd); - fgets(pBuffer,131,fd); - iTest = sscanf(pBuffer,"%d",&nUpper); - if((iTest != 1) || (nUpper <= 0) ) - { - fprintf(stdout,"ERROR: Invalid or corrupt merge data file"); - return 0; - } - upperTheta = (float *)malloc(nUpper*sizeof(float)); - if(upperTheta == NULL) - { - fprintf(stdout,"ERROR: out of memory in fomerge\n"); - return 0; - } - for(i = 0; i < nUpper; i++) - { - fgets(pBuffer,131,fd); - sscanf(pBuffer,"%f",&upperTheta[i]); - } + } + } - /* read middle bank two theta */ - fgets(pBuffer,131,fd); - fgets(pBuffer,131,fd); - iTest = sscanf(pBuffer,"%d",&nMedium); - if((iTest != 1) || (nMedium <= 0) ) - { - fprintf(stdout,"ERROR: Invalid or corrupt merge data file"); - return 0; - } - mediumTheta = (float *)malloc(nMedium*sizeof(float)); - if(mediumTheta == NULL) - { - fprintf(stdout,"ERROR: out of memory in fomerge\n"); - return 0; - } - for(i = 0; i < nMedium; i++) - { - fgets(pBuffer,131,fd); - sscanf(pBuffer,"%f",&mediumTheta[i]); - } + /* read upper bank two theta */ + fgets(pBuffer, 131, fd); + fgets(pBuffer, 131, fd); + iTest = sscanf(pBuffer, "%d", &nUpper); + if ((iTest != 1) || (nUpper <= 0)) { + fprintf(stdout, "ERROR: Invalid or corrupt merge data file"); + return 0; + } + upperTheta = (float *) malloc(nUpper * sizeof(float)); + if (upperTheta == NULL) { + fprintf(stdout, "ERROR: out of memory in fomerge\n"); + return 0; + } + for (i = 0; i < nUpper; i++) { + fgets(pBuffer, 131, fd); + sscanf(pBuffer, "%f", &upperTheta[i]); + } - /* read lower bank two theta */ - fgets(pBuffer,131,fd); - fgets(pBuffer,131,fd); - iTest = sscanf(pBuffer,"%d",&nLower); - if((iTest != 1) || (nLower <= 0) ) - { - fprintf(stdout,"ERROR: Invalid or corrupt merge data file"); - return 0; - } - lowerTheta = (float *)malloc(nLower*sizeof(float)); - if(lowerTheta == NULL) - { - fprintf(stdout,"ERROR: out of memory in fomerge\n"); - return 0; - } - for(i = 0; i < nLower; i++) - { - fgets(pBuffer,131,fd); - sscanf(pBuffer,"%f",&lowerTheta[i]); - } - - /* done */ - timeBin = 0; - iMerged = 0; - medium =1; - upper = lower = 1; + /* read middle bank two theta */ + fgets(pBuffer, 131, fd); + fgets(pBuffer, 131, fd); + iTest = sscanf(pBuffer, "%d", &nMedium); + if ((iTest != 1) || (nMedium <= 0)) { + fprintf(stdout, "ERROR: Invalid or corrupt merge data file"); + return 0; + } + mediumTheta = (float *) malloc(nMedium * sizeof(float)); + if (mediumTheta == NULL) { + fprintf(stdout, "ERROR: out of memory in fomerge\n"); + return 0; + } + for (i = 0; i < nMedium; i++) { + fgets(pBuffer, 131, fd); + sscanf(pBuffer, "%f", &mediumTheta[i]); + } - fclose(fd); - return 1; + /* read lower bank two theta */ + fgets(pBuffer, 131, fd); + fgets(pBuffer, 131, fd); + iTest = sscanf(pBuffer, "%d", &nLower); + if ((iTest != 1) || (nLower <= 0)) { + fprintf(stdout, "ERROR: Invalid or corrupt merge data file"); + return 0; + } + lowerTheta = (float *) malloc(nLower * sizeof(float)); + if (lowerTheta == NULL) { + fprintf(stdout, "ERROR: out of memory in fomerge\n"); + return 0; + } + for (i = 0; i < nLower; i++) { + fgets(pBuffer, 131, fd); + sscanf(pBuffer, "%f", &lowerTheta[i]); + } + + /* done */ + timeBin = 0; + iMerged = 0; + medium = 1; + upper = lower = 1; + + fclose(fd); + return 1; } + /*-------------------------------------------------------------------------- sets the data pointer and finds the starting points for the different banks. This routine contains the knowledge how the detector banks are laid out in the histogram returned from the histogram memory. -------------------------------------------------------------------------*/ -int setFMDataPointer(HistInt *lData, int mytimeBins, int bank) +int setFMDataPointer(HistInt * lData, int mytimeBins, int bank) { HistInt *dataPtr; - if(lData == NULL) - return 0; + if (lData == NULL) + return 0; /* the first set is the medium bank */ masterData = dataPtr = lData; - if (bank==2){ - if(medium) - { + if (bank == 2) { + if (medium) { mediumData = masterData; - } - else - { + } else { mediumData = NULL; } } /* the next set is the upper bank */ - if (bank==1){ - if(upper) - { - upperData = masterData; - } - else - { - upperData = NULL; - } - } + if (bank == 1) { + if (upper) { + upperData = masterData; + } else { + upperData = NULL; + } + } /* the last is the lower bank */ - if (bank==3) { - if(lower) - { - lowerData = masterData; - } - else - { - lowerData = NULL; - } + if (bank == 3) { + if (lower) { + lowerData = masterData; + } else { + lowerData = NULL; + } } /* deal with data allocation for merged data */ - if(mytimeBins != timeBin) - { - if(mergedData != NULL) - { - free(mergedData); + if (mytimeBins != timeBin) { + if (mergedData != NULL) { + free(mergedData); } timeBin = mytimeBins; - mergedData = (HistInt *)malloc(nMerged*timeBin*sizeof(HistInt)); - if(mergedData == NULL) - { - fprintf(stdout,"ERROR: out of memory in fomerge.setFMdataPointer\n"); + mergedData = (HistInt *) malloc(nMerged * timeBin * sizeof(HistInt)); + if (mergedData == NULL) { + fprintf(stdout, + "ERROR: out of memory in fomerge.setFMdataPointer\n"); return 0; } } /* - clear mergedData to 0 - */ - memset(mergedData,0,nMerged*timeBin*sizeof(HistInt)); + clear mergedData to 0 + */ + memset(mergedData, 0, nMerged * timeBin * sizeof(HistInt)); iMerged = 0; return 1; } @@ -254,351 +230,335 @@ void setFMconfiguration(int up, int med, int low) medium = med; lower = low; } + /*-------------------------------------------------------------------------- The algorithm is suboptimal because we have to take care of the case of missing detector banks due to missing or broken electronics or whatever. -*/ +*/ static void mergeData(void) { - int i, j, nDiv; - HistInt *startMerge, *startData; + int i, j, nDiv; + HistInt *startMerge, *startData; - if(!mergedData) - return; + if (!mergedData) + return; - memset(mergedData,0,nMerged*sizeof(HistInt)); - for(i = 0; i < nMerged; i++) - { - startMerge = mergedData + i * timeBin; - nDiv = 0; - /* upper bank contribution */ - if( mergeUp[i] != 0 && upperData != NULL) - { - startData = upperData + (mergeUp[i]-1)*timeBin; - for(j = 0; j < timeBin; j++) - { - startMerge[j] += startData[j]; - } - nDiv++; - } - /* medium bank contribution */ - if( mergeMed[i] != 0 && mediumData != NULL) - { - startData = mediumData + (mergeMed[i]-1)*timeBin; - for(j = 0; j < timeBin; j++) - { - startMerge[j] += startData[j]; - } - nDiv++; - } - /* lower bank contribution */ - if( mergeLow[i] != 0 && lowerData != NULL) - { - startData = lowerData + (mergeLow[i]-1)*timeBin; - for(j = 0; j < timeBin; j++) - { - startMerge[j] += startData[j]; - } - nDiv++; - } - /* do we need to run a division? */ - if(nDiv > 1) - { - for(j = 0; j < timeBin; j++) - { - startMerge[j] /= nDiv; - } - } - } /* end of for */ + memset(mergedData, 0, nMerged * sizeof(HistInt)); + for (i = 0; i < nMerged; i++) { + startMerge = mergedData + i * timeBin; + nDiv = 0; + /* upper bank contribution */ + if (mergeUp[i] != 0 && upperData != NULL) { + startData = upperData + (mergeUp[i] - 1) * timeBin; + for (j = 0; j < timeBin; j++) { + startMerge[j] += startData[j]; + } + nDiv++; + } + /* medium bank contribution */ + if (mergeMed[i] != 0 && mediumData != NULL) { + startData = mediumData + (mergeMed[i] - 1) * timeBin; + for (j = 0; j < timeBin; j++) { + startMerge[j] += startData[j]; + } + nDiv++; + } + /* lower bank contribution */ + if (mergeLow[i] != 0 && lowerData != NULL) { + startData = lowerData + (mergeLow[i] - 1) * timeBin; + for (j = 0; j < timeBin; j++) { + startMerge[j] += startData[j]; + } + nDiv++; + } + /* do we need to run a division? */ + if (nDiv > 1) { + for (j = 0; j < timeBin; j++) { + startMerge[j] /= nDiv; + } + } + } /* end of for */ iMerged = 1; -} +} + /*-----------------------------------------------------------------------*/ void killFM(void) { - if(mergedData != NULL) - free(mergedData); + if (mergedData != NULL) + free(mergedData); - if(lowerTheta != NULL) - free(lowerTheta); + if (lowerTheta != NULL) + free(lowerTheta); - if(mediumTheta != NULL) - free(mediumTheta); + if (mediumTheta != NULL) + free(mediumTheta); - if(upperTheta != NULL) - free(upperTheta); + if (upperTheta != NULL) + free(upperTheta); - if(mergedTheta != NULL) - free(mergedTheta); + if (mergedTheta != NULL) + free(mergedTheta); - if(mergeUp != NULL) - free(mergeUp); + if (mergeUp != NULL) + free(mergeUp); - if(mergeMed != NULL) - free(mergeMed); + if (mergeMed != NULL) + free(mergeMed); - if(mergeLow != NULL) - free(mergeLow); + if (mergeLow != NULL) + free(mergeLow); } + /*-------------------------------------------------------------------------- Below are some not very interesting data access routines ---------------------------------------------------------------------------*/ HistInt *getFMBankPointer(int which) { - switch(which) - { - case UPPER: - return upperData; - break; - case MIDDLE: - return mediumData; - break; - case LOWER: - return lowerData; - break; - case MERGED: - if(!iMerged) - mergeData(); - return mergedData; - break; - default: - assert(0); + switch (which) { + case UPPER: + return upperData; + break; + case MIDDLE: + return mediumData; + break; + case LOWER: + return lowerData; + break; + case MERGED: + if (!iMerged) + mergeData(); + return mergedData; + break; + default: + assert(0); } } + /*-------------------------------------------------------------------------*/ float *getFMBankTheta(int which) { - switch(which) - { - case UPPER: - return upperTheta; - break; - case MIDDLE: - return mediumTheta; - break; - case LOWER: - return lowerTheta; - break; - case MERGED: - return mergedTheta; - break; - default: - assert(0); + switch (which) { + case UPPER: + return upperTheta; + break; + case MIDDLE: + return mediumTheta; + break; + case LOWER: + return lowerTheta; + break; + case MERGED: + return mergedTheta; + break; + default: + assert(0); } } + /*-------------------------------------------------------------------------*/ int getFMdim(int which) { - switch(which) - { - case UPPER: - return nUpper; - break; - case MIDDLE: - return nMedium; - break; - case LOWER: - return nLower; - break; - case MERGED: - return nMerged; - break; - case TIMEBIN: - return timeBin; - break; - default: - assert(0); + switch (which) { + case UPPER: + return nUpper; + break; + case MIDDLE: + return nMedium; + break; + case LOWER: + return nLower; + break; + case MERGED: + return nMerged; + break; + case TIMEBIN: + return timeBin; + break; + default: + assert(0); } } + /*---------------------------------------------------------------------*/ -int InstallFocusMerge(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) +int InstallFocusMerge(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) { int status; char pBueffel[256]; - if(argc < 2) - { - SCWrite(pCon,"ERROR: Insufficient arguments to InstallFocusMerge", - eError); + if (argc < 2) { + SCWrite(pCon, "ERROR: Insufficient arguments to InstallFocusMerge", + eError); return 0; } - + status = initializeFM(argv[1]); - if(!status) - { - snprintf(pBueffel,255,"ERROR: failed to read mergefile %s", - argv[1]); - SCWrite(pCon,pBueffel,eError); + if (!status) { + snprintf(pBueffel, 255, "ERROR: failed to read mergefile %s", argv[1]); + SCWrite(pCon, pBueffel, eError); return 0; } /* Install command */ - AddCommand(pSics,"focusmerge",FocusMergeAction,NULL,NULL); - return 1; + AddCommand(pSics, "focusmerge", FocusMergeAction, NULL, NULL); + return 1; } + /*---------------------------------------------------------------------*/ -static pNXScript checkNXScript(SicsInterp *pSics, char *name) +static pNXScript checkNXScript(SicsInterp * pSics, char *name) { pNXScript result = NULL; - result = FindCommandData(pSics,name,"NXScript"); - if(result == NULL) - { + result = FindCommandData(pSics, name, "NXScript"); + if (result == NULL) { return NULL; } - if(result->fileHandle == NULL || result->dictHandle == NULL) - { + if (result->fileHandle == NULL || result->dictHandle == NULL) { return NULL; } return result; } + /*---------------------------------------------------------------------*/ -static int updateHMFMData(SicsInterp *pSics, SConnection *pCon) +static int updateHMFMData(SicsInterp * pSics, SConnection * pCon) { int status, iTime; const float *fTimeBin = NULL; HistInt *data = NULL; pHistMem pMem = NULL; - pMem = (pHistMem)FindCommandData(pSics,"hm2","HistMem"); - if(pMem == NULL) - { + pMem = (pHistMem) FindCommandData(pSics, "hm2", "HistMem"); + if (pMem == NULL) { return 0; } - fTimeBin = GetHistTimeBin(pMem,&iTime); - setFMDataPointer(GetHistogramPointer(pMem,pCon),iTime,MIDDLE); - - pMem = (pHistMem)FindCommandData(pSics,"hm1","HistMem"); - if(pMem == NULL) - { - return 0; - } - setFMDataPointer(GetHistogramPointer(pMem,pCon),iTime,LOWER); + fTimeBin = GetHistTimeBin(pMem, &iTime); + setFMDataPointer(GetHistogramPointer(pMem, pCon), iTime, MIDDLE); - pMem = (pHistMem)FindCommandData(pSics,"hm3","HistMem"); - if(pMem == NULL) - { + pMem = (pHistMem) FindCommandData(pSics, "hm1", "HistMem"); + if (pMem == NULL) { return 0; } - setFMDataPointer(GetHistogramPointer(pMem,pCon),iTime,UPPER); - setFMconfiguration(1,1,1); + setFMDataPointer(GetHistogramPointer(pMem, pCon), iTime, LOWER); + + pMem = (pHistMem) FindCommandData(pSics, "hm3", "HistMem"); + if (pMem == NULL) { + return 0; + } + setFMDataPointer(GetHistogramPointer(pMem, pCon), iTime, UPPER); + setFMconfiguration(1, 1, 1); return 1; } + /*-------------------------------------------------------------------*/ -static int *calculateDetSum(HistInt *data, int iDet, int iTime) +static int *calculateDetSum(HistInt * data, int iDet, int iTime) { int i, j, iIndex; int *sum = NULL; - sum = (int *)malloc(iDet*sizeof(int)); - if(!sum) - { + sum = (int *) malloc(iDet * sizeof(int)); + if (!sum) { return NULL; } - memset(sum,0,iDet*sizeof(int)); + memset(sum, 0, iDet * sizeof(int)); - for(i = 0; i < iDet; i++) - { - iIndex = i * iTime; - for(j = 0; j < iTime; j++) - { - sum[i] += data[iIndex+j]; - } + for (i = 0; i < iDet; i++) { + iIndex = i * iTime; + for (j = 0; j < iTime; j++) { + sum[i] += data[iIndex + j]; + } } return sum; } + /*-------------------------------------------------------------------*/ -static int *calculateTimeSum(HistInt *data, int iDet, int iTime) +static int *calculateTimeSum(HistInt * data, int iDet, int iTime) { int i, j; int *sum = NULL; - sum = (int *)malloc(iTime*sizeof(int)); - if(!sum) - { + if(data == NULL){ + return NULL; + } + + sum = (int *) malloc(iTime * sizeof(int)); + if (!sum) { return NULL; } - memset(sum,0,iTime*sizeof(int)); + memset(sum, 0, iTime * sizeof(int)); - for(i = 0; i < iTime; i++) - { - for(j = 0; j < iDet; j++) - { - sum[i] += data[j*iTime + i]; - } + for (i = 0; i < iTime; i++) { + for (j = 0; j < iDet; j++) { + sum[i] += data[j * iTime + i]; + } } return sum; } /*--------------------------------------------------------------------*/ -static void checkSum(HistInt *sum, int iDet, char *name, SConnection *pCon){ +static void checkSum(HistInt * sum, int iDet, char *name, + SConnection * pCon) +{ int i, count; char pBueffel[256]; - for(i = 0, count = 0; i < iDet; i++){ - if(sum[i] == 0){ + for (i = 0, count = 0; i < iDet; i++) { + if (sum[i] == 0) { count++; } } - if(count == iDet || count == 0){ + if (count == iDet || count == 0) { return; } - snprintf(pBueffel,255,"WARNING: %d of %d detectors in bank %s are empty", - count, iDet, name); - SCWrite(pCon,pBueffel,eWarning); + snprintf(pBueffel, 255, + "WARNING: %d of %d detectors in bank %s are empty", count, iDet, + name); + SCWrite(pCon, pBueffel, eWarning); } + /*---------------------------------------------------------------------*/ -static int putSum(SicsInterp *pSics, SConnection *pCon, - pNXScript nxscript, char *name, char *alias) +static int putSum(SicsInterp * pSics, SConnection * pCon, + pNXScript nxscript, char *name, char *alias) { HistInt *data = NULL; HistInt *sum = NULL; int iDet, iTime, i, j, iIndex, status; iTime = getFMdim(TIMEBIN); - if(strcmp(name,"upper") == 0) - { + if (strcmp(name, "upper") == 0) { iDet = getFMdim(UPPER); data = getFMBankPointer(UPPER); - } - else if(strcmp(name,"middle") == 0) - { + } else if (strcmp(name, "middle") == 0) { iDet = getFMdim(MIDDLE); data = getFMBankPointer(MIDDLE); - } - else if(strcmp(name,"lower") == 0) - { + } else if (strcmp(name, "lower") == 0) { iDet = getFMdim(LOWER); data = getFMBankPointer(LOWER); - } - else if(strcmp(name,"merged") == 0) - { + } else if (strcmp(name, "merged") == 0) { iDet = getFMdim(MERGED); data = getFMBankPointer(MERGED); - } - else - { - SCWrite(pCon,"ERROR: detector bank to sum not recognised",eError); + } else { + SCWrite(pCon, "ERROR: detector bank to sum not recognised", eError); return NX_ERROR; } - sum = calculateDetSum(data,iDet,iTime); - if(!sum) - { - SCWrite(pCon,"ERROR: out of memory summing bank",eError); + sum = calculateDetSum(data, iDet, iTime); + if (!sum) { + SCWrite(pCon, "ERROR: out of memory summing bank", eError); return NX_ERROR; } - checkSum(sum,iDet, name,pCon); + checkSum(sum, iDet, name, pCon); - status = NXDputalias(nxscript->fileHandle,nxscript->dictHandle, - alias,sum); + status = NXDputalias(nxscript->fileHandle, nxscript->dictHandle, + alias, sum); free(sum); return status; } + /*---------------------------------------------------------------------*/ -static int TOFLambda(SicsInterp *pSics, SConnection *pCon, - int argc, char *argv[]){ +static int TOFLambda(SicsInterp * pSics, SConnection * pCon, + int argc, char *argv[]) +{ int status, iTime, iDet, i; const float *fTimeBin = NULL; int *sum = NULL; @@ -607,72 +567,63 @@ static int TOFLambda(SicsInterp *pSics, SConnection *pCon, float fCenter, fFWHM, fStdDev, fVal; float fMon, fData, distMonoDet, distFermiDet, tdiff, lambda; - pMem = (pHistMem)FindCommandData(pSics,"hm1","HistMem"); - if(pMem == NULL) - { + pMem = (pHistMem) FindCommandData(pSics, "hm1", "HistMem"); + if (pMem == NULL) { SCWrite(pCon, - "ERROR: need lower detector bank for lambda calculation", - eError); + "ERROR: need lower detector bank for lambda calculation", + eError); return 0; } - + /** * locate elastic position in data */ - fTimeBin = GetHistTimeBin(pMem,&iTime); + fTimeBin = GetHistTimeBin(pMem, &iTime); iDet = getFMdim(LOWER); - sum = calculateTimeSum(GetHistogramPointer(pMem,pCon),iDet,iTime); - if(!sum) - { - SCWrite(pCon,"ERROR: out of memory calculating lambda", - eError); + sum = calculateTimeSum(GetHistogramPointer(pMem, pCon), iDet, iTime); + if (!sum) { + SCWrite(pCon, "ERROR: out of memory calculating lambda", eError); return 0; } - if(fitter == NULL) - { + if (fitter == NULL) { fitter = CreateFitCenter(NULL); - if(!fitter) - { - SCWrite(pCon,"ERROR: cannot allocate fitting structure",eError); + if (!fitter) { + SCWrite(pCon, "ERROR: cannot allocate fitting structure", eError); return 0; } } /* - copy sum to make compiler happy - */ - lSum = (long *)malloc(iTime*sizeof(long)); - if(lSum == NULL) - { - SCWrite(pCon,"ERROR: out of memory in TOFLambda",eError); - free(sum); - return 0; + copy sum to make compiler happy + */ + lSum = (long *) malloc(iTime * sizeof(long)); + if (lSum == NULL) { + SCWrite(pCon, "ERROR: out of memory in TOFLambda", eError); + free(sum); + return 0; } - for(i = 0; i < iTime; i++) - { + for (i = 0; i < iTime; i++) { lSum[i] = sum[i]; } - status = CalculateFitFromData(fitter,(float *)fTimeBin,lSum,iTime); - if(status < 0) - { - SCWrite(pCon,"ERROR: no peak in data",eError); - free(sum); - free(lSum); - return 0; + status = CalculateFitFromData(fitter, (float *) fTimeBin, lSum, iTime); + if (status < 0) { + SCWrite(pCon, "ERROR: no peak in data", eError); + free(sum); + free(lSum); + return 0; } - GetFitResults(fitter,&fCenter,&fStdDev,&fFWHM,&fVal); + GetFitResults(fitter, &fCenter, &fStdDev, &fFWHM, &fVal); fData = fCenter; - + /* * locate elastic position in tofmon */ - GetHistogram(pMem, pCon, 0, iTime*iDet, iTime*(iDet+1), - sum, iTime*sizeof(HistInt)); - for(i = 0; i < iTime; i++) - { + GetHistogram(pMem, pCon, 0, iTime * iDet, iTime * (iDet + 1), + sum, iTime * sizeof(HistInt)); + for (i = 0; i < iTime; i++) { lSum[i] = sum[i]; } - status = CalculateFitFromData(fitter,(float *)fTimeBin,lSum,iTime); - GetFitResults(fitter,&fCenter,&fStdDev,&fFWHM,&fVal); + status = CalculateFitFromData(fitter, (float *) fTimeBin, lSum, iTime); + GetFitResults(fitter, &fCenter, &fStdDev, &fFWHM, &fVal); fMon = fCenter; free(sum); free(lSum); @@ -681,15 +632,16 @@ static int TOFLambda(SicsInterp *pSics, SConnection *pCon, * calculate */ distFermiDet = 3000.; - distMonoDet = distFermiDet - 215.7; + distMonoDet = distFermiDet - 215.7; tdiff = fData - fMon; - lambda = tdiff/(252.78*distMonoDet*.001); - SCPrintf(pCon,eValue, "toflambda = %f", lambda); - + lambda = tdiff / (252.78 * distMonoDet * .001); + SCPrintf(pCon, eValue, "toflambda = %f", lambda); + return 1; } + /*---------------------------------------------------------------------*/ -static float calcElastic(SicsInterp *pSics, SConnection *pCon) +static float calcElastic(SicsInterp * pSics, SConnection * pCon) { int status, iTime, iDet, i; const float *fTimeBin = NULL; @@ -698,211 +650,206 @@ static float calcElastic(SicsInterp *pSics, SConnection *pCon) pHistMem pMem = NULL; float fCenter, fFWHM, fStdDev, fVal; - pMem = (pHistMem)FindCommandData(pSics,"hm2","HistMem"); - if(pMem == NULL) - { + pMem = (pHistMem) FindCommandData(pSics, "hm2", "HistMem"); + if (pMem == NULL) { SCWrite(pCon, - "ERROR: need middle detector bank for elastic peak calculation", - eError); + "ERROR: need middle detector bank for elastic peak calculation", + eError); return -1.; } - fTimeBin = GetHistTimeBin(pMem,&iTime); + fTimeBin = GetHistTimeBin(pMem, &iTime); iDet = getFMdim(MIDDLE); - sum = calculateTimeSum(GetHistogramPointer(pMem,pCon),iDet,iTime); - if(!sum) - { - SCWrite(pCon,"ERROR: out of memory calculating elastic peak position", - eError); + sum = calculateTimeSum(GetHistogramPointer(pMem, pCon), iDet, iTime); + if (!sum) { + SCWrite(pCon, "ERROR: out of memory calculating elastic peak position", + eError); return -1; } - if(fitter == NULL) - { + if (fitter == NULL) { fitter = CreateFitCenter(NULL); - if(!fitter) - { - SCWrite(pCon,"ERROR: cannot allocate fitting structure",eError); + if (!fitter) { + SCWrite(pCon, "ERROR: cannot allocate fitting structure", eError); return -1.; } } /* - copy sum to make compiler happy - */ - lSum = (long *)malloc(iTime*sizeof(long)); - if(lSum == NULL) - { - SCWrite(pCon,"ERROR: out of memory in putElastic",eError); + copy sum to make compiler happy + */ + lSum = (long *) malloc(iTime * sizeof(long)); + if (lSum == NULL) { + SCWrite(pCon, "ERROR: out of memory in putElastic", eError); free(sum); return -1.; } - for(i = 0; i < iTime; i++) - { + for (i = 0; i < iTime; i++) { lSum[i] = sum[i]; } - status = CalculateFitFromData(fitter,(float *)fTimeBin,lSum,iTime); + status = CalculateFitFromData(fitter, (float *) fTimeBin, lSum, iTime); free(lSum); - GetFitResults(fitter,&fCenter,&fStdDev,&fFWHM,&fVal); + GetFitResults(fitter, &fCenter, &fStdDev, &fFWHM, &fVal); free(sum); return fCenter; } -/*---------------------------------------------------------------------*/ -#define ABS(x) (x < 0 ? -(x) : (x)) -static int putElastic(SicsInterp *pSics, SConnection *pCon, - pNXScript pNexus, char *alias, float fElastic) +/*---------------------------------------------------------------------*/ +#define ABS(x) (x < 0 ? -(x) : (x)) + +static int putElastic(SicsInterp * pSics, SConnection * pCon, + pNXScript pNexus, char *alias, float fElastic) { - float fCalc; - int status; - - fCalc = calcElastic(pSics,pCon); - if(ABS(fElastic -fCalc) < 20) { - fElastic = fCalc; - } - - status = NXDputalias(pNexus->fileHandle, pNexus->dictHandle,alias, - &fElastic); - return status; + float fCalc; + int status; + + fCalc = calcElastic(pSics, pCon); + if (ABS(fElastic - fCalc) < 20) { + fElastic = fCalc; + } + + status = NXDputalias(pNexus->fileHandle, pNexus->dictHandle, alias, + &fElastic); + return status; } + /*----------------------------------------------------------------------*/ -static int FMputTTH(SConnection *pCon, int argc, char *argv[]){ - pSICSData data = NULL; - int length = -1, i; - float *tthData = NULL; - - if(argc < 4){ - SCWrite(pCon,"ERROR: insufficient no of arguments to FMputTTH", - eError); - return 0; - } - - data = (pSICSData)FindCommandData(pServ->pSics,argv[3],"SICSData"); - if(data == NULL){ - SCWrite(pCon,"ERROR: SICSData object not found", eError); - return 0; - } - if(strcmp(argv[2],"upper") == 0) - { - length = getFMdim(UPPER); - tthData = getFMBankTheta(UPPER); - } - else if(strcmp(argv[2],"middle") == 0) - { - length = getFMdim(MIDDLE); - tthData = getFMBankTheta(MIDDLE); - } - else if(strcmp(argv[2],"lower") == 0) - { - length = getFMdim(LOWER); - tthData = getFMBankTheta(LOWER); - } - else if(strcmp(argv[2],"merged") == 0) - { - length = getFMdim(MERGED); - tthData = getFMBankTheta(MERGED); - } - else - { - SCWrite(pCon,"ERROR: requested two_theta for invalid detector bank", - eError); - return 0; - } - if(length < 0 || tthData == NULL){ - SCWrite(pCon,"ERROR: requested two_theta for invalid detector bank", - eError); - return 0; - } - clearSICSData(data); - for(i = 0; i < length; i++){ - setSICSDataFloat(data,i,tthData[i]); - } - SCSendOK(pCon); - return 1; -} -/*---------------------------------------------------------------------*/ -static int FMcopyMerged(SConnection *pCon, int argc, char *argv[]){ - pSICSData data = NULL; - int i, length; - HistInt *hmData = NULL; - - if(argc < 3){ - SCWrite(pCon,"ERROR: insufficient no of arguments to FMcopyMerged", - eError); - return 0; - } - - data = (pSICSData)FindCommandData(pServ->pSics,argv[2],"SICSData"); - if(data == NULL){ - SCWrite(pCon,"ERROR: SICSData object not found", eError); - return 0; - } - if(!updateHMFMData(pServ->pSics, pCon)){ - SCWrite(pCon,"ERROR: not enough HM's to merge or bad names in fomerge.c", - eError); - return 0; - } - - clearSICSData(data); - length = getFMdim(MERGED)*getFMdim(TIMEBIN); - hmData = getFMBankPointer(MERGED); - if(hmData == NULL){ - SCWrite(pCon,"ERROR: merged data not available", eError); - return 0; - } - for(i = 0; i < length; i++){ - setSICSDataInt(data,i,hmData[i]); - } - SCSendOK(pCon); - return 1; -} -/*---------------------------------------------------------------------*/ -static int FMcopyMergedSum(SConnection *pCon, int argc, char *argv[]){ - pSICSData data = NULL; - int i, length, tbin, j, row; - HistInt *hmData = NULL, *sumData = NULL; - - if(argc < 3){ - SCWrite(pCon,"ERROR: insufficient no of arguments to FMcopyMerged", - eError); - return 0; - } - - data = (pSICSData)FindCommandData(pServ->pSics,argv[2],"SICSData"); - if(data == NULL){ - SCWrite(pCon,"ERROR: SICSData object not found", eError); - return 0; - } - if(!updateHMFMData(pServ->pSics, pCon)){ - SCWrite(pCon,"ERROR: not enough HM's to merge or bad names in fomerge.c", - eError); - return 0; - } - - clearSICSData(data); +static int FMputTTH(SConnection * pCon, int argc, char *argv[]) +{ + pSICSData data = NULL; + int length = -1, i; + float *tthData = NULL; + + if (argc < 4) { + SCWrite(pCon, "ERROR: insufficient no of arguments to FMputTTH", + eError); + return 0; + } + + data = (pSICSData) FindCommandData(pServ->pSics, argv[3], "SICSData"); + if (data == NULL) { + SCWrite(pCon, "ERROR: SICSData object not found", eError); + return 0; + } + if (strcmp(argv[2], "upper") == 0) { + length = getFMdim(UPPER); + tthData = getFMBankTheta(UPPER); + } else if (strcmp(argv[2], "middle") == 0) { + length = getFMdim(MIDDLE); + tthData = getFMBankTheta(MIDDLE); + } else if (strcmp(argv[2], "lower") == 0) { + length = getFMdim(LOWER); + tthData = getFMBankTheta(LOWER); + } else if (strcmp(argv[2], "merged") == 0) { length = getFMdim(MERGED); - tbin = getFMdim(TIMEBIN); - hmData = getFMBankPointer(MERGED); - if(hmData == NULL){ - SCWrite(pCon,"ERROR: merged data not available", eError); - return 0; - } - sumData = malloc(tbin*sizeof(int)); - if(sumData == NULL){ - SCWrite(pCon,"ERROR: out-of-memory in FMcopyMergedSum", eError); - return 0; - } - memset(sumData,0,tbin*sizeof(int)); - for(j = 0; j < length; j++){ - row = j*tbin; - for(i = 0; i < tbin; i++){ - sumData[i] += hmData[row+i]; - } - } - for(i = 0; i < tbin; i++){ - setSICSDataInt(data,i,sumData[i]); - } - free(sumData); - SCSendOK(pCon); - return 1; + tthData = getFMBankTheta(MERGED); + } else { + SCWrite(pCon, "ERROR: requested two_theta for invalid detector bank", + eError); + return 0; + } + if (length < 0 || tthData == NULL) { + SCWrite(pCon, "ERROR: requested two_theta for invalid detector bank", + eError); + return 0; + } + clearSICSData(data); + for (i = 0; i < length; i++) { + setSICSDataFloat(data, i, tthData[i]); + } + SCSendOK(pCon); + return 1; } + +/*---------------------------------------------------------------------*/ +static int FMcopyMerged(SConnection * pCon, int argc, char *argv[]) +{ + pSICSData data = NULL; + int i, length; + HistInt *hmData = NULL; + + if (argc < 3) { + SCWrite(pCon, "ERROR: insufficient no of arguments to FMcopyMerged", + eError); + return 0; + } + + data = (pSICSData) FindCommandData(pServ->pSics, argv[2], "SICSData"); + if (data == NULL) { + SCWrite(pCon, "ERROR: SICSData object not found", eError); + return 0; + } + if (!updateHMFMData(pServ->pSics, pCon)) { + SCWrite(pCon, + "ERROR: not enough HM's to merge or bad names in fomerge.c", + eError); + return 0; + } + + clearSICSData(data); + length = getFMdim(MERGED) * getFMdim(TIMEBIN); + hmData = getFMBankPointer(MERGED); + if (hmData == NULL) { + SCWrite(pCon, "ERROR: merged data not available", eError); + return 0; + } + for (i = 0; i < length; i++) { + setSICSDataInt(data, i, hmData[i]); + } + SCSendOK(pCon); + return 1; +} + +/*---------------------------------------------------------------------*/ +static int FMcopyMergedSum(SConnection * pCon, int argc, char *argv[]) +{ + pSICSData data = NULL; + int i, length, tbin, j, row; + HistInt *hmData = NULL, *sumData = NULL; + + if (argc < 3) { + SCWrite(pCon, "ERROR: insufficient no of arguments to FMcopyMerged", + eError); + return 0; + } + + data = (pSICSData) FindCommandData(pServ->pSics, argv[2], "SICSData"); + if (data == NULL) { + SCWrite(pCon, "ERROR: SICSData object not found", eError); + return 0; + } + if (!updateHMFMData(pServ->pSics, pCon)) { + SCWrite(pCon, + "ERROR: not enough HM's to merge or bad names in fomerge.c", + eError); + return 0; + } + + clearSICSData(data); + length = getFMdim(MERGED); + tbin = getFMdim(TIMEBIN); + hmData = getFMBankPointer(MERGED); + if (hmData == NULL) { + SCWrite(pCon, "ERROR: merged data not available", eError); + return 0; + } + sumData = malloc(tbin * sizeof(int)); + if (sumData == NULL) { + SCWrite(pCon, "ERROR: out-of-memory in FMcopyMergedSum", eError); + return 0; + } + memset(sumData, 0, tbin * sizeof(int)); + for (j = 0; j < length; j++) { + row = j * tbin; + for (i = 0; i < tbin; i++) { + sumData[i] += hmData[row + i]; + } + } + for (i = 0; i < tbin; i++) { + setSICSDataInt(data, i, sumData[i]); + } + free(sumData); + SCSendOK(pCon); + return 1; +} + /*----------------------------------------------------------------------- Usage: focusmerge puttwotheta nxscriptmod bankname alias @@ -919,194 +866,158 @@ nxscriptmod = name of the nxscript module used for writing, must be open alias = The alias under which to write the data item theoelastic = theoretical elastic peak position ------------------------------------------------------------------------*/ -int FocusMergeAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) +int FocusMergeAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) { int status; pNXScript pNexus = NULL; float fElastic; char pNum[20]; - if(argc < 2) - { - SCWrite(pCon,"ERROR: Insufficient arguments to focusmerge", - eError); + if (argc < 2) { + SCWrite(pCon, "ERROR: Insufficient arguments to focusmerge", eError); return 0; } strtolower(argv[1]); - - if(strcmp(argv[1],"puttth") == 0){ - return FMputTTH(pCon,argc,argv); + + if (strcmp(argv[1], "puttth") == 0) { + return FMputTTH(pCon, argc, argv); } - - if(strcmp(argv[1],"copymerged") == 0){ - return FMcopyMerged(pCon,argc,argv); + + if (strcmp(argv[1], "copymerged") == 0) { + return FMcopyMerged(pCon, argc, argv); } - if(strcmp(argv[1],"copymergedsum") == 0){ - return FMcopyMergedSum(pCon,argc,argv); + if (strcmp(argv[1], "copymergedsum") == 0) { + return FMcopyMergedSum(pCon, argc, argv); } - if(strcmp(argv[1],"toflambda") == 0){ - return TOFLambda(pSics, pCon,argc,argv); + if (strcmp(argv[1], "toflambda") == 0) { + return TOFLambda(pSics, pCon, argc, argv); } - if(strcmp(argv[1],"elastic") == 0){ - fElastic = calcElastic(pSics,pCon); - SCPrintf(pCon,eValue,"tofelastic = %f", fElastic); - return 1; + if (strcmp(argv[1], "elastic") == 0) { + fElastic = calcElastic(pSics, pCon); + SCPrintf(pCon, eValue, "tofelastic = %f", fElastic); + return 1; } - - if(strcmp(argv[1],"puttwotheta") == 0) - { - if(argc < 4) - { - SCWrite(pCon,"ERROR: Insufficient arguments to focusmerge puttwotheta", - eError); + + if (strcmp(argv[1], "puttwotheta") == 0) { + if (argc < 4) { + SCWrite(pCon, + "ERROR: Insufficient arguments to focusmerge puttwotheta", + eError); return 0; } pNexus = checkNXScript(pSics, argv[2]); - if(pNexus == NULL) - { - SCWrite(pCon,"ERROR: bad nxscript name or NeXus file not open",eError); + if (pNexus == NULL) { + SCWrite(pCon, "ERROR: bad nxscript name or NeXus file not open", + eError); return 0; } strtolower(argv[3]); - if(strcmp(argv[3],"upper") == 0) - { - status = NXDputalias(pNexus->fileHandle,pNexus->dictHandle, - argv[4],getFMBankTheta(UPPER)); - } - else if(strcmp(argv[3],"middle") == 0) - { - status = NXDputalias(pNexus->fileHandle,pNexus->dictHandle, - argv[4],getFMBankTheta(MIDDLE)); - } - else if(strcmp(argv[3],"lower") == 0) - { - status = NXDputalias(pNexus->fileHandle,pNexus->dictHandle, - argv[4],getFMBankTheta(LOWER)); - } - else if(strcmp(argv[3],"merged") == 0) - { - status = NXDputalias(pNexus->fileHandle,pNexus->dictHandle, - argv[4],getFMBankTheta(MERGED)); - } - else - { - SCWrite(pCon,"ERROR: requested two_theta for invalid detector bank", - eError); + if (strcmp(argv[3], "upper") == 0) { + status = NXDputalias(pNexus->fileHandle, pNexus->dictHandle, + argv[4], getFMBankTheta(UPPER)); + } else if (strcmp(argv[3], "middle") == 0) { + status = NXDputalias(pNexus->fileHandle, pNexus->dictHandle, + argv[4], getFMBankTheta(MIDDLE)); + } else if (strcmp(argv[3], "lower") == 0) { + status = NXDputalias(pNexus->fileHandle, pNexus->dictHandle, + argv[4], getFMBankTheta(LOWER)); + } else if (strcmp(argv[3], "merged") == 0) { + status = NXDputalias(pNexus->fileHandle, pNexus->dictHandle, + argv[4], getFMBankTheta(MERGED)); + } else { + SCWrite(pCon, "ERROR: requested two_theta for invalid detector bank", + eError); return 0; } - if(status == NX_OK) - { + if (status == NX_OK) { SCSendOK(pCon); return 1; - } - else - { - SCWrite(pCon,"ERROR: failed to write two theta array to file",eError); + } else { + SCWrite(pCon, "ERROR: failed to write two theta array to file", + eError); return 0; } - } - else if(strcmp(argv[1],"putmerged") == 0 ) - { - if(argc < 4) - { - SCWrite(pCon,"ERROR: Insufficient arguments to focusmerge", - eError); + } else if (strcmp(argv[1], "putmerged") == 0) { + if (argc < 4) { + SCWrite(pCon, "ERROR: Insufficient arguments to focusmerge", eError); return 0; } pNexus = checkNXScript(pSics, argv[2]); - if(pNexus == NULL) - { - SCWrite(pCon,"ERROR: bad nxscript name or NeXus file not open",eError); + if (pNexus == NULL) { + SCWrite(pCon, "ERROR: bad nxscript name or NeXus file not open", + eError); return 0; } - if(!updateHMFMData(pSics, pCon)) - { - SCWrite(pCon,"ERROR: not enough HM's to merge or bad names in fomerge.c", - eError); + if (!updateHMFMData(pSics, pCon)) { + SCWrite(pCon, + "ERROR: not enough HM's to merge or bad names in fomerge.c", + eError); return 0; } - snprintf(pNum,19,"%d",getFMdim(MERGED)); - NXDupdate(pNexus->dictHandle,"noofdetectors",pNum); - snprintf(pNum,19,"%d",getFMdim(TIMEBIN)); - NXDupdate(pNexus->dictHandle,"timebin",pNum); - status = NXDputalias(pNexus->fileHandle,pNexus->dictHandle, - argv[3],getFMBankPointer(MERGED)); - if(status == NX_OK) - { + snprintf(pNum, 19, "%d", getFMdim(MERGED)); + NXDupdate(pNexus->dictHandle, "noofdetectors", pNum); + snprintf(pNum, 19, "%d", getFMdim(TIMEBIN)); + NXDupdate(pNexus->dictHandle, "timebin", pNum); + status = NXDputalias(pNexus->fileHandle, pNexus->dictHandle, + argv[3], getFMBankPointer(MERGED)); + if (status == NX_OK) { SCSendOK(pCon); return 1; - } - else - { - SCWrite(pCon,"ERROR: failed to write merged data to file",eError); + } else { + SCWrite(pCon, "ERROR: failed to write merged data to file", eError); return 0; } - } - else if(strcmp(argv[1],"putsum") == 0 ) - { - if(argc < 4) - { - SCWrite(pCon,"ERROR: Insufficient arguments to focusmerge putsum", - eError); + } else if (strcmp(argv[1], "putsum") == 0) { + if (argc < 4) { + SCWrite(pCon, "ERROR: Insufficient arguments to focusmerge putsum", + eError); return 0; } pNexus = checkNXScript(pSics, argv[2]); - if(pNexus == NULL) - { - SCWrite(pCon,"ERROR: bad nxscript name or NeXus file not open",eError); + if (pNexus == NULL) { + SCWrite(pCon, "ERROR: bad nxscript name or NeXus file not open", + eError); return 0; } updateHMFMData(pSics, pCon); - status = putSum(pSics,pCon,pNexus,argv[3],argv[4]); - if(status == NX_OK) - { + status = putSum(pSics, pCon, pNexus, argv[3], argv[4]); + if (status == NX_OK) { SCSendOK(pCon); return 1; - } - else - { - SCWrite(pCon,"ERROR: failed to write summed data to file",eError); + } else { + SCWrite(pCon, "ERROR: failed to write summed data to file", eError); return 0; } - } - else if(strcmp(argv[1],"putelastic") == 0 ) - { - if(argc < 4) - { - SCWrite(pCon,"ERROR: Insufficient arguments to focusmerge putelastic", - eError); + } else if (strcmp(argv[1], "putelastic") == 0) { + if (argc < 4) { + SCWrite(pCon, + "ERROR: Insufficient arguments to focusmerge putelastic", + eError); return 0; } pNexus = checkNXScript(pSics, argv[2]); - if(pNexus == NULL) - { - SCWrite(pCon,"ERROR: bad nxscript name or NeXus file not open",eError); + if (pNexus == NULL) { + SCWrite(pCon, "ERROR: bad nxscript name or NeXus file not open", + eError); return 0; } fElastic = atof(argv[4]); - status = putElastic(pSics,pCon,pNexus,argv[3],fElastic); - if(status == NX_OK) - { + status = putElastic(pSics, pCon, pNexus, argv[3], fElastic); + if (status == NX_OK) { SCSendOK(pCon); return 1; - } - else - { - SCWrite(pCon,"ERROR: failed to write elastic peak position",eError); + } else { + SCWrite(pCon, "ERROR: failed to write elastic peak position", + eError); return 0; } - } - else - { - SCWrite(pCon,"ERROR: subcommand to focusmerge not understood",eError); + } else { + SCWrite(pCon, "ERROR: subcommand to focusmerge not understood", + eError); return 0; } return 0; } - - - - diff --git a/fomerge.h b/fomerge.h index 89972939..d133d675 100644 --- a/fomerge.h +++ b/fomerge.h @@ -24,58 +24,57 @@ #define MERGED 4 #define TIMEBIN 5 - int setFMDataPointer(HistInt *lData, int timeBins, int bank); +int setFMDataPointer(HistInt * lData, int timeBins, int bank); /* - sets the data array with the unmerged data. timeBins is the - length of the time binning used. upper, medium and lower are flags - which indicate the presence of the detector bank. - */ + sets the data array with the unmerged data. timeBins is the + length of the time binning used. upper, medium and lower are flags + which indicate the presence of the detector bank. + */ - void setFMconfiguration(int upper, int medium, int lower); +void setFMconfiguration(int upper, int medium, int lower); /* - sets the configuration of the histogram memory - */ + sets the configuration of the histogram memory + */ - HistInt *getFMBankPointer(int which); +HistInt *getFMBankPointer(int which); /* - returns a pointer to the counted data for the detector bank - specified by which. Possible values are given above. - - */ - float *getFMBankTheta(int which); + returns a pointer to the counted data for the detector bank + specified by which. Possible values are given above. + + */ +float *getFMBankTheta(int which); /* - returns a pointer to a float array with the two theta values for - the detector bank specified by which. - */ - - int initializeFM(char *mergefile); + returns a pointer to a float array with the two theta values for + the detector bank specified by which. + */ + +int initializeFM(char *mergefile); /* initializes the two-theta and merging data from the file mergefile. This must have been called before anything else. - */ - - void killFM(void); - /* - frees all merging data structures. - */ + */ - int getFMdim(int which); +void killFM(void); + /* + frees all merging data structures. + */ + +int getFMdim(int which); /* returns the dimension in two theta for the detector banks of the length of the time binning if TIMEBIN has been specified. - */ - - int InstallFocusMerge(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); + */ + +int InstallFocusMerge(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); /* install the standalone FocusMerge module - */ - int FocusMergeAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); + */ +int FocusMergeAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); /* FocusMerge interpreter wrapper function - */ + */ #endif - diff --git a/fortify.c b/fortify.c index 19dac50a..eed4664d 100644 --- a/fortify.c +++ b/fortify.c @@ -17,33 +17,35 @@ * */ #ifdef FORTIFY - + #include #include #include #include #include -#define __FORTIFY_C__ /* So fortify.h knows to not define the fortify macros */ +#define __FORTIFY_C__ /* So fortify.h knows to not define the fortify macros */ #include "fortify.h" -#include "ufortify.h" /* the user's options */ +#include "ufortify.h" /* the user's options */ -struct Header -{ - char *File; /* The sourcefile of the caller */ - unsigned long Line; /* The sourceline of the caller */ - size_t Size; /* The size of the malloc'd block */ - struct Header *Prev, /* List pointers */ - *Next; - int Scope; - int Checksum; /* For validating the Header structure; see ChecksumHeader() */ +struct Header { + char *File; /* The sourcefile of the caller */ + unsigned long Line; /* The sourceline of the caller */ + size_t Size; /* The size of the malloc'd block */ + struct Header *Prev, /* List pointers */ + *Next; + int Scope; + int Checksum; /* For validating the Header structure; see ChecksumHeader() */ }; static int CheckBlock(struct Header *h, char *file, unsigned long line); -static int CheckFortification(unsigned char *ptr, unsigned char value, size_t size); -static void SetFortification(unsigned char *ptr, unsigned char value, size_t size); -static void OutputFortification(unsigned char *ptr, unsigned char value, size_t size); +static int CheckFortification(unsigned char *ptr, unsigned char value, + size_t size); +static void SetFortification(unsigned char *ptr, unsigned char value, + size_t size); +static void OutputFortification(unsigned char *ptr, unsigned char value, + size_t size); static int IsHeaderValid(struct Header *h); static void MakeHeaderValid(struct Header *h); static int ChecksumHeader(struct Header *h); @@ -53,19 +55,19 @@ static void OutputMemory(struct Header *h); static void st_DefaultOutput(char *String) { - printf(String); + printf(String); } -static struct Header *st_Head = 0; /* Head of alloc'd memory list */ -static OutputFuncPtr st_Output = st_DefaultOutput; /* Output function for errors */ -static char st_Buffer[256]; /* Temporary buffer for sprintf's */ -static int st_Disabled = 0; /* If true, Fortify is inactive */ -static int st_MallocFailRate = 0; /* % of the time to fail mallocs */ +static struct Header *st_Head = 0; /* Head of alloc'd memory list */ +static OutputFuncPtr st_Output = st_DefaultOutput; /* Output function for errors */ +static char st_Buffer[256]; /* Temporary buffer for sprintf's */ +static int st_Disabled = 0; /* If true, Fortify is inactive */ +static int st_MallocFailRate = 0; /* % of the time to fail mallocs */ -static char *st_LastVerifiedFile = "unknown"; -static unsigned long st_LastVerifiedLine = 0; -static int st_Scope = 0; -static void OutputLastVerifiedPoint(void); +static char *st_LastVerifiedFile = "unknown"; +static unsigned long st_LastVerifiedLine = 0; +static int st_Scope = 0; +static void OutputLastVerifiedPoint(void); /* * Fortify_malloc() - Allocates a block of memory, with extra bits for @@ -86,135 +88,127 @@ static void OutputLastVerifiedPoint(void); void *FORTIFY_STORAGE Fortify_malloc(size_t size, char *file, unsigned long line) { - unsigned char *ptr; - struct Header *h; + unsigned char *ptr; + struct Header *h; - FORTIFY_LOCK(); - - if(st_Disabled) - { - ptr = malloc(size); - FORTIFY_UNLOCK(); - return(ptr); - } + FORTIFY_LOCK(); + if (st_Disabled) { + ptr = malloc(size); + FORTIFY_UNLOCK(); + return (ptr); + } #ifdef CHECK_ALL_MEMORY_ON_MALLOC - Fortify_CheckAllMemory(file, line); -#endif + Fortify_CheckAllMemory(file, line); +#endif - if(size == 0) - { + if (size == 0) { #ifdef WARN_ON_ZERO_MALLOC - sprintf(st_Buffer, - "\nFortify: %s.%ld\n malloc(0) attempted failed\n", - file, line); - st_Output(st_Buffer); + sprintf(st_Buffer, + "\nFortify: %s.%ld\n malloc(0) attempted failed\n", + file, line); + st_Output(st_Buffer); #endif - FORTIFY_UNLOCK(); - return(0); - } + FORTIFY_UNLOCK(); + return (0); + } - if(st_MallocFailRate > 0) - { - if(rand() % 100 < st_MallocFailRate) - { + if (st_MallocFailRate > 0) { + if (rand() % 100 < st_MallocFailRate) { #ifdef WARN_ON_FALSE_FAIL - sprintf(st_Buffer, - "\nFortify: %s.%ld\n malloc(%ld) \"false\" failed\n", - file, line, (unsigned long)size); - st_Output(st_Buffer); + sprintf(st_Buffer, + "\nFortify: %s.%ld\n malloc(%ld) \"false\" failed\n", + file, line, (unsigned long) size); + st_Output(st_Buffer); #endif - FORTIFY_UNLOCK(); - return(0); - } - } - - /* - * malloc the memory, including the space for the header and fortification - * buffers - */ -#ifdef WARN_ON_SIZE_T_OVERFLOW - { - size_t private_size = sizeof(struct Header) - + FORTIFY_BEFORE_SIZE + size + FORTIFY_AFTER_SIZE; + FORTIFY_UNLOCK(); + return (0); + } + } - if(private_size < size) /* Check to see if the added baggage is larger than size_t */ - { - sprintf(st_Buffer, - "\nFortify: %s.%ld\n malloc(%ld) has overflowed size_t.\n", - file, line, (unsigned long)size); - st_Output(st_Buffer); - FORTIFY_UNLOCK(); - return(0); - } - } -#endif + /* + * malloc the memory, including the space for the header and fortification + * buffers + */ +#ifdef WARN_ON_SIZE_T_OVERFLOW + { + size_t private_size = sizeof(struct Header) + + FORTIFY_BEFORE_SIZE + size + FORTIFY_AFTER_SIZE; - ptr = malloc(sizeof(struct Header) + - FORTIFY_BEFORE_SIZE + size + FORTIFY_AFTER_SIZE); - if(!ptr) - { + if (private_size < size) { /* Check to see if the added baggage is larger than size_t */ + sprintf(st_Buffer, + "\nFortify: %s.%ld\n malloc(%ld) has overflowed size_t.\n", + file, line, (unsigned long) size); + st_Output(st_Buffer); + FORTIFY_UNLOCK(); + return (0); + } + } +#endif + + ptr = malloc(sizeof(struct Header) + + FORTIFY_BEFORE_SIZE + size + FORTIFY_AFTER_SIZE); + if (!ptr) { #ifdef WARN_ON_MALLOC_FAIL - sprintf(st_Buffer, "\nFortify: %s.%ld\n malloc(%ld) failed\n", - file, line, (unsigned long)size); - st_Output(st_Buffer); + sprintf(st_Buffer, "\nFortify: %s.%ld\n malloc(%ld) failed\n", + file, line, (unsigned long) size); + st_Output(st_Buffer); #endif - FORTIFY_UNLOCK(); - return(0); - } + FORTIFY_UNLOCK(); + return (0); + } - /* - * Initialize and validate the header - */ - h = (struct Header *)ptr; + /* + * Initialize and validate the header + */ + h = (struct Header *) ptr; - h->Size = size; - - h->File = file; - h->Line = line; - - h->Next = st_Head; - h->Prev = 0; - - h->Scope = st_Scope; + h->Size = size; - if(st_Head) - { - st_Head->Prev = h; - MakeHeaderValid(st_Head); - } + h->File = file; + h->Line = line; - st_Head = h; - - MakeHeaderValid(h); + h->Next = st_Head; + h->Prev = 0; + + h->Scope = st_Scope; + + if (st_Head) { + st_Head->Prev = h; + MakeHeaderValid(st_Head); + } + + st_Head = h; + + MakeHeaderValid(h); - /* - * Initialize the fortifications - */ - SetFortification(ptr + sizeof(struct Header), - FORTIFY_BEFORE_VALUE, FORTIFY_BEFORE_SIZE); - SetFortification(ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE + size, - FORTIFY_AFTER_VALUE, FORTIFY_AFTER_SIZE); + /* + * Initialize the fortifications + */ + SetFortification(ptr + sizeof(struct Header), + FORTIFY_BEFORE_VALUE, FORTIFY_BEFORE_SIZE); + SetFortification(ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE + + size, FORTIFY_AFTER_VALUE, FORTIFY_AFTER_SIZE); -#ifdef FILL_ON_MALLOC - /* - * Fill the actual user memory - */ - SetFortification(ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE, - FILL_ON_MALLOC_VALUE, size); +#ifdef FILL_ON_MALLOC + /* + * Fill the actual user memory + */ + SetFortification(ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE, + FILL_ON_MALLOC_VALUE, size); #endif - /* - * We return the address of the user's memory, not the start of the block, - * which points to our magic cookies - */ + /* + * We return the address of the user's memory, not the start of the block, + * which points to our magic cookies + */ - FORTIFY_UNLOCK(); + FORTIFY_UNLOCK(); - return(ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE); + return (ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE); } /* @@ -230,83 +224,78 @@ Fortify_malloc(size_t size, char *file, unsigned long line) * + Checks the sentinals of the memory being freed. * + Can check the sentinals of all memory. */ - + void FORTIFY_STORAGE Fortify_free(void *uptr, char *file, unsigned long line) { - unsigned char *ptr = (unsigned char *)uptr - sizeof(struct Header) - FORTIFY_BEFORE_SIZE; - struct Header *h = (struct Header *)ptr; + unsigned char *ptr = + (unsigned char *) uptr - sizeof(struct Header) - FORTIFY_BEFORE_SIZE; + struct Header *h = (struct Header *) ptr; - FORTIFY_LOCK(); - - if(st_Disabled) - { - free(uptr); - FORTIFY_UNLOCK(); - return; - } + FORTIFY_LOCK(); + if (st_Disabled) { + free(uptr); + FORTIFY_UNLOCK(); + return; + } #ifdef CHECK_ALL_MEMORY_ON_FREE - Fortify_CheckAllMemory(file, line); -#endif - -#ifdef PARANOID_FREE - if(!IsOnList(h)) - { - sprintf(st_Buffer, - "\nFortify: %s.%ld\n Invalid pointer, corrupted header, or possible free twice\n", - file, line); - st_Output(st_Buffer); - OutputLastVerifiedPoint(); - goto fail; - } + Fortify_CheckAllMemory(file, line); #endif - if(!CheckBlock(h, file, line)) - goto fail; - - /* - * Remove the block from the list - */ - if(h->Prev) - { - if(!CheckBlock(h->Prev, file, line)) - goto fail; - - h->Prev->Next = h->Next; - MakeHeaderValid(h->Prev); - } - else - st_Head = h->Next; - - if(h->Next) - { - if(!CheckBlock(h->Next, file, line)) - goto fail; +#ifdef PARANOID_FREE + if (!IsOnList(h)) { + sprintf(st_Buffer, + "\nFortify: %s.%ld\n Invalid pointer, corrupted header, or possible free twice\n", + file, line); + st_Output(st_Buffer); + OutputLastVerifiedPoint(); + goto fail; + } +#endif - h->Next->Prev = h->Prev; - MakeHeaderValid(h->Next); - } + if (!CheckBlock(h, file, line)) + goto fail; + /* + * Remove the block from the list + */ + if (h->Prev) { + if (!CheckBlock(h->Prev, file, line)) + goto fail; + + h->Prev->Next = h->Next; + MakeHeaderValid(h->Prev); + } else + st_Head = h->Next; + + if (h->Next) { + if (!CheckBlock(h->Next, file, line)) + goto fail; + + h->Next->Prev = h->Prev; + MakeHeaderValid(h->Next); + } #ifdef FILL_ON_FREE - /* - * Nuke out all memory that is about to be freed - */ - SetFortification(ptr, FILL_ON_FREE_VALUE, - sizeof(struct Header) + FORTIFY_BEFORE_SIZE + h->Size + FORTIFY_AFTER_SIZE); -#endif + /* + * Nuke out all memory that is about to be freed + */ + SetFortification(ptr, FILL_ON_FREE_VALUE, + sizeof(struct Header) + FORTIFY_BEFORE_SIZE + h->Size + + FORTIFY_AFTER_SIZE); +#endif - /* - * And do the actual free - */ - free(ptr); - FORTIFY_UNLOCK(); - return; + /* + * And do the actual free + */ + free(ptr); + FORTIFY_UNLOCK(); + return; fail: - sprintf(st_Buffer, " free(%p) failed\n", uptr); - st_Output(st_Buffer); - FORTIFY_UNLOCK(); + sprintf(st_Buffer, " free(%p) failed\n", uptr); + st_Output(st_Buffer); + FORTIFY_UNLOCK(); } /* @@ -322,57 +311,56 @@ fail: void *FORTIFY_STORAGE Fortify_realloc(void *ptr, size_t new_size, char *file, unsigned long line) { - void *new_ptr; - struct Header *h = (struct Header *) - ((unsigned char *)ptr - sizeof(struct Header) - FORTIFY_BEFORE_SIZE); + void *new_ptr; + struct Header *h = (struct Header *) + ((unsigned char *) ptr - sizeof(struct Header) - + FORTIFY_BEFORE_SIZE); - if(st_Disabled) - { - FORTIFY_LOCK(); - new_ptr = realloc(ptr, new_size); - FORTIFY_UNLOCK(); - return(new_ptr); - } + if (st_Disabled) { + FORTIFY_LOCK(); + new_ptr = realloc(ptr, new_size); + FORTIFY_UNLOCK(); + return (new_ptr); + } - if(!ptr) - return(Fortify_malloc(new_size, file, line)); - - FORTIFY_LOCK(); + if (!ptr) + return (Fortify_malloc(new_size, file, line)); - if(!IsOnList(h)) - { - sprintf(st_Buffer, - "\nFortify: %s.%ld\n Invalid pointer or corrupted header passed to realloc\n", - file, line); - st_Output(st_Buffer); - goto fail; - } + FORTIFY_LOCK(); - if(!CheckBlock(h, file, line)) - goto fail; - - new_ptr = Fortify_malloc(new_size, file, line); - if(!new_ptr) - { - FORTIFY_UNLOCK(); - return(0); - } - - if(h->Size < new_size) - memcpy(new_ptr, ptr, h->Size); - else - memcpy(new_ptr, ptr, new_size); + if (!IsOnList(h)) { + sprintf(st_Buffer, + "\nFortify: %s.%ld\n Invalid pointer or corrupted header passed to realloc\n", + file, line); + st_Output(st_Buffer); + goto fail; + } + + if (!CheckBlock(h, file, line)) + goto fail; + + new_ptr = Fortify_malloc(new_size, file, line); + if (!new_ptr) { + FORTIFY_UNLOCK(); + return (0); + } + + if (h->Size < new_size) + memcpy(new_ptr, ptr, h->Size); + else + memcpy(new_ptr, ptr, new_size); + + Fortify_free(ptr, file, line); + FORTIFY_UNLOCK(); + return (new_ptr); - Fortify_free(ptr, file, line); - FORTIFY_UNLOCK(); - return(new_ptr); - fail: - sprintf(st_Buffer, " realloc(%p, %ld) failed\n", ptr, (unsigned long)new_size); - st_Output(st_Buffer); - FORTIFY_UNLOCK(); - return (NULL); -} + sprintf(st_Buffer, " realloc(%p, %ld) failed\n", ptr, + (unsigned long) new_size); + st_Output(st_Buffer); + FORTIFY_UNLOCK(); + return (NULL); +} /* * Fortifty_calloc() - Uses Fortify_malloc() to implement calloc(). Much @@ -381,14 +369,14 @@ fail: void *FORTIFY_STORAGE Fortify_calloc(size_t num, size_t size, char *file, unsigned long line) { - void *ptr; + void *ptr; - ptr = Fortify_malloc(num * size, file, line); - - if(ptr) - memset(ptr, 0, num * size); + ptr = Fortify_malloc(num * size, file, line); - return(ptr); + if (ptr) + memset(ptr, 0, num * size); + + return (ptr); } /* @@ -402,27 +390,27 @@ Fortify_calloc(size_t num, size_t size, char *file, unsigned long line) int FORTIFY_STORAGE Fortify_CheckPointer(void *uptr, char *file, unsigned long line) { - unsigned char *ptr = (unsigned char *)uptr - sizeof(struct Header) - FORTIFY_BEFORE_SIZE; - int r; - - if(st_Disabled) - return(1); + unsigned char *ptr = + (unsigned char *) uptr - sizeof(struct Header) - FORTIFY_BEFORE_SIZE; + int r; - FORTIFY_LOCK(); + if (st_Disabled) + return (1); - if(!IsOnList((struct Header *)ptr)) - { - sprintf(st_Buffer, - "\nFortify: %s.%ld\n Invalid pointer or corrupted header detected (%p)\n", - file, line, uptr); - st_Output(st_Buffer); - FORTIFY_UNLOCK(); - return(0); - } + FORTIFY_LOCK(); - r = CheckBlock((struct Header *)ptr, file, line); - FORTIFY_UNLOCK(); - return r; + if (!IsOnList((struct Header *) ptr)) { + sprintf(st_Buffer, + "\nFortify: %s.%ld\n Invalid pointer or corrupted header detected (%p)\n", + file, line, uptr); + st_Output(st_Buffer); + FORTIFY_UNLOCK(); + return (0); + } + + r = CheckBlock((struct Header *) ptr, file, line); + FORTIFY_UNLOCK(); + return r; } /* @@ -434,11 +422,11 @@ Fortify_CheckPointer(void *uptr, char *file, unsigned long line) Fortify_OutputFuncPtr FORTIFY_STORAGE Fortify_SetOutputFunc(Fortify_OutputFuncPtr Output) { - OutputFuncPtr Old = st_Output; + OutputFuncPtr Old = st_Output; - st_Output = (OutputFuncPtr)Output; - - return((Fortify_OutputFuncPtr)Old); + st_Output = (OutputFuncPtr) Output; + + return ((Fortify_OutputFuncPtr) Old); } /* @@ -447,111 +435,106 @@ Fortify_SetOutputFunc(Fortify_OutputFuncPtr Output) * available. Useful to "stress-test" an application. Returns the old * value. The fail rate defaults to 0. */ -int FORTIFY_STORAGE -Fortify_SetMallocFailRate(int Percent) +int FORTIFY_STORAGE Fortify_SetMallocFailRate(int Percent) { - int Old = st_MallocFailRate; - - st_MallocFailRate = Percent; - - return(Old); + int Old = st_MallocFailRate; + + st_MallocFailRate = Percent; + + return (Old); } - + /* * Fortify_CheckAllMemory() - Checks the sentinals of all malloc'd memory. * Returns the number of blocks that failed. * * (If Fortify is disabled, this function always returns 0). */ -int FORTIFY_STORAGE -Fortify_CheckAllMemory(char *file, unsigned long line) +int FORTIFY_STORAGE Fortify_CheckAllMemory(char *file, unsigned long line) { - struct Header *curr = st_Head; - int count = 0; + struct Header *curr = st_Head; + int count = 0; - if(st_Disabled) - return(0); + if (st_Disabled) + return (0); - FORTIFY_LOCK(); + FORTIFY_LOCK(); - while(curr) - { - if(!CheckBlock(curr, file, line)) - count++; + while (curr) { + if (!CheckBlock(curr, file, line)) + count++; - curr = curr->Next; - } - - if(file) - { - st_LastVerifiedFile = file; - st_LastVerifiedLine = line; - } + curr = curr->Next; + } - FORTIFY_UNLOCK(); - return(count); + if (file) { + st_LastVerifiedFile = file; + st_LastVerifiedLine = line; + } + + FORTIFY_UNLOCK(); + return (count); } /* Fortify_EnterScope - enters a new Fortify scope level. * returns the new scope level. */ -int FORTIFY_STORAGE -Fortify_EnterScope(char *file, unsigned long line) +int FORTIFY_STORAGE Fortify_EnterScope(char *file, unsigned long line) { - return(++st_Scope); + return (++st_Scope); } /* Fortify_LeaveScope - leaves a Fortify scope level, * also prints a memory dump of all non-freed memory that was allocated * during the scope being exited. */ -int FORTIFY_STORAGE -Fortify_LeaveScope(char *file, unsigned long line) +int FORTIFY_STORAGE Fortify_LeaveScope(char *file, unsigned long line) { - struct Header *curr = st_Head; - int count = 0; - unsigned long size = 0; + struct Header *curr = st_Head; + int count = 0; + unsigned long size = 0; - if(st_Disabled) - return(0); + if (st_Disabled) + return (0); - FORTIFY_LOCK(); + FORTIFY_LOCK(); - st_Scope--; - while(curr) - { - if(curr->Scope > st_Scope) - { - if(count == 0) - { - sprintf(st_Buffer, "\nFortify: Memory Dump at %s.%ld\n", file, line); - st_Output(st_Buffer); - OutputLastVerifiedPoint(); - sprintf(st_Buffer, "%11s %8s %s\n", "Address", "Size", "Allocator"); - st_Output(st_Buffer); - } - - OutputHeader(curr); - count++; - size += curr->Size; - } + st_Scope--; + while (curr) { + if (curr->Scope > st_Scope) { + if (count == 0) { + sprintf(st_Buffer, "\nFortify: Memory Dump at %s.%ld\n", file, + line); + st_Output(st_Buffer); + OutputLastVerifiedPoint(); + sprintf(st_Buffer, "%11s %8s %s\n", "Address", "Size", + "Allocator"); + st_Output(st_Buffer); + } - curr = curr->Next; - } + OutputHeader(curr); + count++; + size += curr->Size; + } - if(count) - { - sprintf(st_Buffer, "%11s %8ld bytes overhead\n", "and", - (unsigned long)(count * (sizeof(struct Header) + FORTIFY_BEFORE_SIZE + FORTIFY_AFTER_SIZE))); - st_Output(st_Buffer); + curr = curr->Next; + } - sprintf(st_Buffer,"%11s %8ld bytes in %d blocks\n", "total", size, count); - st_Output(st_Buffer); - } + if (count) { + sprintf(st_Buffer, "%11s %8ld bytes overhead\n", "and", + (unsigned long) (count * + (sizeof(struct Header) + FORTIFY_BEFORE_SIZE + + FORTIFY_AFTER_SIZE))); + st_Output(st_Buffer); - FORTIFY_UNLOCK(); - return(count); + sprintf(st_Buffer, "%11s %8ld bytes in %d blocks\n", "total", size, + count); + st_Output(st_Buffer); + } + + FORTIFY_UNLOCK(); + return (count); } /* @@ -564,44 +547,44 @@ Fortify_LeaveScope(char *file, unsigned long line) * It returns the number of blocks on the list, unless fortify has been * disabled, in which case it always returns 0. */ -int FORTIFY_STORAGE -Fortify_OutputAllMemory(char *file, unsigned long line) +int FORTIFY_STORAGE Fortify_OutputAllMemory(char *file, unsigned long line) { - struct Header *curr = st_Head; - int count = 0; - unsigned long size = 0; + struct Header *curr = st_Head; + int count = 0; + unsigned long size = 0; - if(st_Disabled) - return(0); + if (st_Disabled) + return (0); - FORTIFY_LOCK(); + FORTIFY_LOCK(); - if(curr) - { - sprintf(st_Buffer, "\nFortify: Memory Dump at %s.%ld\n", file, line); - st_Output(st_Buffer); - OutputLastVerifiedPoint(); - sprintf(st_Buffer, "%11s %8s %s\n", "Address", "Size", "Allocator"); - st_Output(st_Buffer); - - while(curr) - { - OutputHeader(curr); - count++; - size += curr->Size; - curr = curr->Next; - } - - sprintf(st_Buffer, "%11s %8ld bytes overhead\n", "and", - (unsigned long)(count * (sizeof(struct Header) + FORTIFY_BEFORE_SIZE + FORTIFY_AFTER_SIZE))); - st_Output(st_Buffer); + if (curr) { + sprintf(st_Buffer, "\nFortify: Memory Dump at %s.%ld\n", file, line); + st_Output(st_Buffer); + OutputLastVerifiedPoint(); + sprintf(st_Buffer, "%11s %8s %s\n", "Address", "Size", "Allocator"); + st_Output(st_Buffer); - sprintf(st_Buffer,"%11s %8ld bytes in %d blocks\n", "total", size, count); - st_Output(st_Buffer); - } - - FORTIFY_UNLOCK(); - return(count); + while (curr) { + OutputHeader(curr); + count++; + size += curr->Size; + curr = curr->Next; + } + + sprintf(st_Buffer, "%11s %8ld bytes overhead\n", "and", + (unsigned long) (count * + (sizeof(struct Header) + FORTIFY_BEFORE_SIZE + + FORTIFY_AFTER_SIZE))); + st_Output(st_Buffer); + + sprintf(st_Buffer, "%11s %8ld bytes in %d blocks\n", "total", size, + count); + st_Output(st_Buffer); + } + + FORTIFY_UNLOCK(); + return (count); } /* Fortify_DumpAllMemory(Scope) - Outputs the entire list of currently @@ -617,50 +600,51 @@ Fortify_OutputAllMemory(char *file, unsigned long line) int FORTIFY_STORAGE Fortify_DumpAllMemory(int scope, char *file, unsigned long line) { - struct Header *curr = st_Head; - int count = 0; - unsigned long size = 0; + struct Header *curr = st_Head; + int count = 0; + unsigned long size = 0; - if(st_Disabled) - return(0); + if (st_Disabled) + return (0); - FORTIFY_LOCK(); + FORTIFY_LOCK(); - while(curr) - { - if(curr->Scope >= scope) - { - if(count == 0) - { - sprintf(st_Buffer, "\nFortify: Memory Dump at %s.%ld\n", file, line); - st_Output(st_Buffer); - OutputLastVerifiedPoint(); - sprintf(st_Buffer, "%11s %8s %s\n", "Address", "Size", "Allocator"); - st_Output(st_Buffer); - } + while (curr) { + if (curr->Scope >= scope) { + if (count == 0) { + sprintf(st_Buffer, "\nFortify: Memory Dump at %s.%ld\n", file, + line); + st_Output(st_Buffer); + OutputLastVerifiedPoint(); + sprintf(st_Buffer, "%11s %8s %s\n", "Address", "Size", + "Allocator"); + st_Output(st_Buffer); + } - OutputHeader(curr); - OutputMemory(curr); - st_Output("\n"); - count++; - size += curr->Size; - } + OutputHeader(curr); + OutputMemory(curr); + st_Output("\n"); + count++; + size += curr->Size; + } - curr = curr->Next; - } + curr = curr->Next; + } - if(count) - { - sprintf(st_Buffer, "%11s %8ld bytes overhead\n", "and", - (unsigned long)(count * (sizeof(struct Header) + FORTIFY_BEFORE_SIZE + FORTIFY_AFTER_SIZE))); - st_Output(st_Buffer); + if (count) { + sprintf(st_Buffer, "%11s %8ld bytes overhead\n", "and", + (unsigned long) (count * + (sizeof(struct Header) + FORTIFY_BEFORE_SIZE + + FORTIFY_AFTER_SIZE))); + st_Output(st_Buffer); - sprintf(st_Buffer,"%11s %8ld bytes in %d blocks\n", "total", size, count); - st_Output(st_Buffer); - } + sprintf(st_Buffer, "%11s %8ld bytes in %d blocks\n", "total", size, + count); + st_Output(st_Buffer); + } - FORTIFY_UNLOCK(); - return(count); + FORTIFY_UNLOCK(); + return (count); } /* @@ -671,108 +655,106 @@ Fortify_DumpAllMemory(int scope, char *file, unsigned long line) * call this function when there IS memory on the Fortify malloc'd list, * it will issue an error, and fortify will not be disabled. */ -int FORTIFY_STORAGE -Fortify_Disable(char *file, unsigned long line) +int FORTIFY_STORAGE Fortify_Disable(char *file, unsigned long line) { - int result; - FORTIFY_LOCK(); + int result; + FORTIFY_LOCK(); - if(st_Head) - { - sprintf(st_Buffer, "Fortify: %s.%d\n", file, (int)line); - st_Output(st_Buffer); - st_Output(" Fortify_Disable failed\n"); - st_Output(" (because there is memory on the Fortify memory list)\n"); - - Fortify_OutputAllMemory(file, line); - result = 0; - } - else - { - st_Disabled = 1; - result = 1; - } - - FORTIFY_UNLOCK(); - return(result); + if (st_Head) { + sprintf(st_Buffer, "Fortify: %s.%d\n", file, (int) line); + st_Output(st_Buffer); + st_Output(" Fortify_Disable failed\n"); + st_Output + (" (because there is memory on the Fortify memory list)\n"); + + Fortify_OutputAllMemory(file, line); + result = 0; + } else { + st_Disabled = 1; + result = 1; + } + + FORTIFY_UNLOCK(); + return (result); } /* * Check a block's header and fortifications. */ static int CheckBlock(struct Header *h, char *file, unsigned long line) -{ - unsigned char *ptr = (unsigned char *)h; - int result = 1; +{ + unsigned char *ptr = (unsigned char *) h; + int result = 1; - if(!IsHeaderValid(h)) - { - sprintf(st_Buffer, - "\nFortify: %s.%ld\n Invalid pointer or corrupted header detected (%p)\n", - file, line, ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE); - st_Output(st_Buffer); - OutputLastVerifiedPoint(); - return(0); - } + if (!IsHeaderValid(h)) { + sprintf(st_Buffer, + "\nFortify: %s.%ld\n Invalid pointer or corrupted header detected (%p)\n", + file, line, ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE); + st_Output(st_Buffer); + OutputLastVerifiedPoint(); + return (0); + } - if(!CheckFortification(ptr + sizeof(struct Header), - FORTIFY_BEFORE_VALUE, FORTIFY_BEFORE_SIZE)) - { - sprintf(st_Buffer, - "\nFortify: %s.%ld\n Memory overrun detected before block\n", - file, line); - st_Output(st_Buffer); + if (!CheckFortification(ptr + sizeof(struct Header), + FORTIFY_BEFORE_VALUE, FORTIFY_BEFORE_SIZE)) { + sprintf(st_Buffer, + "\nFortify: %s.%ld\n Memory overrun detected before block\n", + file, line); + st_Output(st_Buffer); - sprintf(st_Buffer," (%p,%ld,%s.%ld)\n", - ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE, - (unsigned long)h->Size, h->File, h->Line); - st_Output(st_Buffer); - - OutputFortification(ptr + sizeof(struct Header), - FORTIFY_BEFORE_VALUE, FORTIFY_BEFORE_SIZE); - OutputLastVerifiedPoint(); - result = 0; - } - - if(!CheckFortification(ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE + h->Size, - FORTIFY_AFTER_VALUE, FORTIFY_AFTER_SIZE)) - { - sprintf(st_Buffer, "\nFortify: %s.%ld\n Memory overrun detected after block\n", - file, line); - st_Output(st_Buffer); + sprintf(st_Buffer, " (%p,%ld,%s.%ld)\n", + ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE, + (unsigned long) h->Size, h->File, h->Line); + st_Output(st_Buffer); - sprintf(st_Buffer," (%p,%ld,%s.%ld)\n", - ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE, - (unsigned long)h->Size, h->File, h->Line); - st_Output(st_Buffer); + OutputFortification(ptr + sizeof(struct Header), + FORTIFY_BEFORE_VALUE, FORTIFY_BEFORE_SIZE); + OutputLastVerifiedPoint(); + result = 0; + } - OutputFortification(ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE + h->Size, - FORTIFY_AFTER_VALUE, FORTIFY_AFTER_SIZE); - OutputLastVerifiedPoint(); - result = 0; - } - - return(result); + if (!CheckFortification + (ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE + h->Size, + FORTIFY_AFTER_VALUE, FORTIFY_AFTER_SIZE)) { + sprintf(st_Buffer, + "\nFortify: %s.%ld\n Memory overrun detected after block\n", + file, line); + st_Output(st_Buffer); + + sprintf(st_Buffer, " (%p,%ld,%s.%ld)\n", + ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE, + (unsigned long) h->Size, h->File, h->Line); + st_Output(st_Buffer); + + OutputFortification(ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE + + h->Size, FORTIFY_AFTER_VALUE, FORTIFY_AFTER_SIZE); + OutputLastVerifiedPoint(); + result = 0; + } + + return (result); } /* * Checks if the _size_ bytes from _ptr_ are all set to _value_ */ -static int CheckFortification(unsigned char *ptr, unsigned char value, size_t size) +static int CheckFortification(unsigned char *ptr, unsigned char value, + size_t size) { - while(size--) - if(*ptr++ != value) - return(0); - - return(1); + while (size--) + if (*ptr++ != value) + return (0); + + return (1); } /* * Set the _size_ bytes from _ptr_ to _value_. */ -static void SetFortification(unsigned char *ptr, unsigned char value, size_t size) +static void SetFortification(unsigned char *ptr, unsigned char value, + size_t size) { - memset(ptr, value, size); + memset(ptr, value, size); } /* @@ -782,61 +764,56 @@ static void SetFortification(unsigned char *ptr, unsigned char value, size_t siz static void OutputFortification(unsigned char *ptr, unsigned char value, size_t size) { - unsigned long offset, column; - char ascii[17]; + unsigned long offset, column; + char ascii[17]; - st_Output("Address Offset Data"); + st_Output("Address Offset Data"); - offset = 0; - column = 0; + offset = 0; + column = 0; - while(offset < size) - { - if(column == 0) - { - sprintf(st_Buffer, "\n%8p %8d ", ptr, (int)offset); - st_Output(st_Buffer); - } + while (offset < size) { + if (column == 0) { + sprintf(st_Buffer, "\n%8p %8d ", ptr, (int) offset); + st_Output(st_Buffer); + } - sprintf(st_Buffer, "%02x ", *ptr); - st_Output(st_Buffer); + sprintf(st_Buffer, "%02x ", *ptr); + st_Output(st_Buffer); - ascii[ column ] = isprint( *ptr ) ? (char)(*ptr) : (char)(' '); - ascii[ column + 1 ] = '\0'; + ascii[column] = isprint(*ptr) ? (char) (*ptr) : (char) (' '); + ascii[column + 1] = '\0'; - ptr++; - offset++; - column++; + ptr++; + offset++; + column++; - if(column == 16) - { - st_Output( " \"" ); - st_Output( ascii ); - st_Output( "\"" ); - column = 0; - } - } + if (column == 16) { + st_Output(" \""); + st_Output(ascii); + st_Output("\""); + column = 0; + } + } - if ( column != 0 ) - { - while ( column ++ < 16 ) - { - st_Output( " " ); - } - st_Output( " \"" ); - st_Output( ascii ); - st_Output( "\"" ); - } + if (column != 0) { + while (column++ < 16) { + st_Output(" "); + } + st_Output(" \""); + st_Output(ascii); + st_Output("\""); + } - st_Output("\n"); + st_Output("\n"); } /* * Returns true if the supplied pointer does indeed point to a real Header */ -static int IsHeaderValid(struct Header *h) +static int IsHeaderValid(struct Header *h) { - return(!ChecksumHeader(h)); + return (!ChecksumHeader(h)); } /* @@ -844,8 +821,8 @@ static int IsHeaderValid(struct Header *h) */ static void MakeHeaderValid(struct Header *h) { - h->Checksum = 0; - h->Checksum = -ChecksumHeader(h); + h->Checksum = 0; + h->Checksum = -ChecksumHeader(h); } /* @@ -855,41 +832,40 @@ static void MakeHeaderValid(struct Header *h) */ static int ChecksumHeader(struct Header *h) { - int c, checksum, *p; - - for(c = 0, checksum = 0, p = (int *)h; c < sizeof(struct Header)/sizeof(int); c++) - checksum += *p++; - - return(checksum); -} + int c, checksum, *p; + + for (c = 0, checksum = 0, p = (int *) h; + c < sizeof(struct Header) / sizeof(int); c++) + checksum += *p++; + + return (checksum); +} /* * Examines the malloc'd list to see if the given header is on it. - */ + */ static int IsOnList(struct Header *h) { - struct Header *curr; - - curr = st_Head; - while(curr) - { - if(curr == h) - return(1); - - curr = curr->Next; - } - - return(0); + struct Header *curr; + + curr = st_Head; + while (curr) { + if (curr == h) + return (1); + + curr = curr->Next; + } + + return (0); } /* * Hex and ascii dump the memory */ -static void -OutputMemory(struct Header *h) +static void OutputMemory(struct Header *h) { - OutputFortification((unsigned char*)h + sizeof(struct Header) + FORTIFY_BEFORE_SIZE, - 0, h->Size); + OutputFortification((unsigned char *) h + sizeof(struct Header) + + FORTIFY_BEFORE_SIZE, 0, h->Size); } @@ -898,20 +874,19 @@ OutputMemory(struct Header *h) */ static void OutputHeader(struct Header *h) { - sprintf(st_Buffer, "%11p %8ld %s.%ld (%d)\n", - (unsigned char*)h + sizeof(struct Header) + FORTIFY_BEFORE_SIZE, - (unsigned long)h->Size, - h->File, h->Line, h->Scope); - st_Output(st_Buffer); + sprintf(st_Buffer, "%11p %8ld %s.%ld (%d)\n", + (unsigned char *) h + sizeof(struct Header) + + FORTIFY_BEFORE_SIZE, (unsigned long) h->Size, h->File, h->Line, + h->Scope); + st_Output(st_Buffer); } static void OutputLastVerifiedPoint() { - sprintf(st_Buffer, "\nLast Verified point: %s.%ld\n", - st_LastVerifiedFile, - st_LastVerifiedLine); - st_Output(st_Buffer); + sprintf(st_Buffer, "\nLast Verified point: %s.%ld\n", + st_LastVerifiedFile, st_LastVerifiedLine); + st_Output(st_Buffer); } -#endif /* FORTIFY */ +#endif /* FORTIFY */ diff --git a/fortify.h b/fortify.h index 3983fc57..debbb325 100644 --- a/fortify.h +++ b/fortify.h @@ -24,39 +24,38 @@ extern "C" { #endif -typedef void (*OutputFuncPtr)(char *); + typedef void (*OutputFuncPtr) (char *); -void *Fortify_malloc(size_t size, char *file, unsigned long line); -void *Fortify_realloc(void *ptr, size_t new_size, char *file, unsigned long line); -void *Fortify_calloc(size_t num, size_t size, char *file, unsigned long line); -void Fortify_free(void *uptr, char *file, unsigned long line); -char *Fortify_STRDUP(const char *in, char *file, unsigned long line); + void *Fortify_malloc(size_t size, char *file, unsigned long line); + void *Fortify_realloc(void *ptr, size_t new_size, char *file, + unsigned long line); + void *Fortify_calloc(size_t num, size_t size, char *file, + unsigned long line); + void Fortify_free(void *uptr, char *file, unsigned long line); + char *Fortify_STRDUP(const char *in, char *file, unsigned long line); -int Fortify_OutputAllMemory(char *file, unsigned long line); -int Fortify_CheckAllMemory(char *file, unsigned long line); -int Fortify_CheckPointer(void *uptr, char *file, unsigned long line); -int Fortify_Disable(char *file, unsigned long line); -int Fortify_SetMallocFailRate(int Percent); -int Fortify_EnterScope(char *file, unsigned long line); -int Fortify_LeaveScope(char *file, unsigned long line); -int Fortify_DumpAllMemory(int scope, char *file, unsigned long line); + int Fortify_OutputAllMemory(char *file, unsigned long line); + int Fortify_CheckAllMemory(char *file, unsigned long line); + int Fortify_CheckPointer(void *uptr, char *file, unsigned long line); + int Fortify_Disable(char *file, unsigned long line); + int Fortify_SetMallocFailRate(int Percent); + int Fortify_EnterScope(char *file, unsigned long line); + int Fortify_LeaveScope(char *file, unsigned long line); + int Fortify_DumpAllMemory(int scope, char *file, unsigned long line); -typedef void (*Fortify_OutputFuncPtr)(const char *); -Fortify_OutputFuncPtr Fortify_SetOutputFunc(Fortify_OutputFuncPtr Output); + typedef void (*Fortify_OutputFuncPtr) (const char *); + Fortify_OutputFuncPtr Fortify_SetOutputFunc(Fortify_OutputFuncPtr + Output); #ifdef __cplusplus } #endif - -#ifndef __FORTIFY_C__ /* Only define the macros if we're NOT in fortify.c */ - -#ifdef FORTIFY /* Add file and line information to the fortify calls */ - +#ifndef __FORTIFY_C__ /* Only define the macros if we're NOT in fortify.c */ +#ifdef FORTIFY /* Add file and line information to the fortify calls */ #define malloc(size) Fortify_malloc(size, __FILE__, __LINE__) #define realloc(ptr,new_size) Fortify_realloc(ptr, new_size, __FILE__, __LINE__) #define calloc(num,size) Fortify_calloc(num, size, __FILE__, __LINE__) #define free(ptr) Fortify_free(ptr, __FILE__, __LINE__) - #define Fortify_OutputAllMemory() Fortify_OutputAllMemory(__FILE__, __LINE__) #define Fortify_CheckAllMemory() Fortify_CheckAllMemory(__FILE__, __LINE__) #define Fortify_CheckPointer(ptr) Fortify_CheckPointer(ptr, __FILE__, __LINE__) @@ -65,9 +64,7 @@ Fortify_OutputFuncPtr Fortify_SetOutputFunc(Fortify_OutputFuncPtr Output); #define Fortify_LeaveScope() Fortify_LeaveScope(__FILE__, __LINE__) #define Fortify_DumpAllMemory(s) Fortify_DumpAllMemory(s,__FILE__, __LINE__) #define strdup(s) Fortify_STRDUP(s,__FILE__,__LINE__) - -#else /* FORTIFY Define the special fortify functions away to nothing */ - +#else /* FORTIFY Define the special fortify functions away to nothing */ #define Fortify_OutputAllMemory() 0 #define Fortify_CheckAllMemory() 0 #define Fortify_CheckPointer(ptr) 1 @@ -77,7 +74,6 @@ Fortify_OutputFuncPtr Fortify_SetOutputFunc(Fortify_OutputFuncPtr Output); #define Fortify_EnterScope() 0 #define Fortify_LeaveScope() 0 #define Fortify_DumpAllMemory(s) 0 - -#endif /* FORTIFY */ -#endif /* __FORTIFY_C__ */ -#endif /* __FORTIFY_H__ */ +#endif /* FORTIFY */ +#endif /* __FORTIFY_C__ */ +#endif /* __FORTIFY_H__ */ diff --git a/fourlib.c b/fourlib.c index f954f322..3ce972c2 100644 --- a/fourlib.c +++ b/fourlib.c @@ -31,98 +31,109 @@ #define PI 3.141592653589793 #define RD 57.30 -#define ABS(x) (x < 0 ? -(x) : (x)) +#define ABS(x) (x < 0 ? -(x) : (x)) /*------------------------------------------------------------------------ a safe routine for calculating the atan of y/x ------------------------------------------------------------------------*/ -static double myatan(double y, double x){ - if(ABS(x) < 0.0001){ - if(y > .0){ - return PI/2; - }else { - return -PI/2; +static double myatan(double y, double x) +{ + if (ABS(x) < 0.0001) { + if (y > .0) { + return PI / 2; + } else { + return -PI / 2; } } - if(x > .0){ - return atan(y/x); + if (x > .0) { + return atan(y / x); } else { - if(y > .0){ - return PI + atan(y/x); - } else { - return -PI + atan(y/x); - } - } + if (y > .0) { + return PI + atan(y / x); + } else { + return -PI + atan(y / x); + } + } } + /*-------------------------------------------------------------------------*/ -static double rtan(double y, double x){ +static double rtan(double y, double x) +{ double val; - if( (x == 0.) && (y == 0.) ) { + if ((x == 0.) && (y == 0.)) { return .0; - } - if( x == 0.) { - if(y < 0.){ - return -PI/2.; - } else { - return PI/2.; - } } - if(ABS(y) < ABS(x)) { - val = atan(ABS(y/x)); - if(x < 0.) { - val = PI - val; + if (x == 0.) { + if (y < 0.) { + return -PI / 2.; + } else { + return PI / 2.; + } + } + if (ABS(y) < ABS(x)) { + val = atan(ABS(y / x)); + if (x < 0.) { + val = PI - val; + } + if (y < 0.) { + val = -val; } - if(y < 0.){ - val = -val; - } return val; } else { - val = PI/2. - atan(ABS(x/y)); - if(x < 0.) { + val = PI / 2. - atan(ABS(x / y)); + if (x < 0.) { val = PI - val; - } - if( y < 0.) { - val = - val; - } + } + if (y < 0.) { + val = -val; + } } return val; } + /*---------------------------------------------------------------------- clear3x3 sets a 3x3 matrix to 0 -----------------------------------------------------------------------*/ -static void clear3x3(MATRIX target){ +static void clear3x3(MATRIX target) +{ int i, j; - for(i = 0; i < 3; i++){ - for(j = 0; j < 3; j++){ + for (i = 0; i < 3; i++) { + for (j = 0; j < 3; j++) { target[i][j] = .0; } } } + /*---------------------------------------------------------------------*/ -MATRIX vectorToMatrix(double z[3]){ +MATRIX vectorToMatrix(double z[3]) +{ int i; MATRIX res; - res = mat_creat(3,1,ZERO_MATRIX); - for(i = 0; i < 3; i++){ + res = mat_creat(3, 1, ZERO_MATRIX); + for (i = 0; i < 3; i++) { res[i][0] = z[i]; } return res; } + /*---------------------------------------------------------------------*/ -void matrixToVector(MATRIX zm, double z[3]){ +void matrixToVector(MATRIX zm, double z[3]) +{ int i; - for(i = 0; i < 3; i++){ + for (i = 0; i < 3; i++) { z[i] = zm[i][0]; } } + /*---------------------------------------------------------------------- A Busing & levy PSI matrix ----------------------------------------------------------------------*/ -static void psimat(MATRIX target, double psi){ - double psird = psi/RD; +static void psimat(MATRIX target, double psi) +{ + double psird = psi / RD; clear3x3(target); @@ -132,11 +143,13 @@ static void psimat(MATRIX target, double psi){ target[2][1] = -target[1][2]; target[2][2] = target[1][1]; } + /*---------------------------------------------------------------------- A Busing & levy CHI matrix ----------------------------------------------------------------------*/ -void chimat(MATRIX target, double chi){ - double chird = chi/RD; +void chimat(MATRIX target, double chi) +{ + double chird = chi / RD; clear3x3(target); @@ -146,11 +159,13 @@ void chimat(MATRIX target, double chi){ target[2][0] = -target[0][2]; target[2][2] = target[0][0]; } + /*---------------------------------------------------------------------- A Busing & levy PHI matrix ----------------------------------------------------------------------*/ -void phimat(MATRIX target, double phi){ - double phird = phi/RD; +void phimat(MATRIX target, double phi) +{ + double phird = phi / RD; clear3x3(target); @@ -160,36 +175,40 @@ void phimat(MATRIX target, double phi){ target[1][1] = target[0][0]; target[2][2] = 1.; } + /*------------------- PSD specific code ----------------------------*/ -void det2pol(psdDescription *psd, int x, int y, double *gamma, double *nu) { +void det2pol(psdDescription * psd, int x, int y, double *gamma, double *nu) +{ double xobs, yobs, b, z, d; - assert(ABS(psd->distance ) > .001); + assert(ABS(psd->distance) > .001); - xobs = (x - psd->xZero)*psd->xScale; - yobs = (y - psd->yZero)*psd->yScale; + xobs = (x - psd->xZero) * psd->xScale; + yobs = (y - psd->yZero) * psd->yScale; - b = psd->distance*cos(yobs/psd->distance); - z = psd->distance*sin(yobs/psd->distance); - d = sqrt(xobs*xobs + b*b); - *gamma = psd->gamma + myatan(xobs,b)*RD; - *nu = psd->nu + myatan(z,d)*RD; + b = psd->distance * cos(yobs / psd->distance); + z = psd->distance * sin(yobs / psd->distance); + d = sqrt(xobs * xobs + b * b); + *gamma = psd->gamma + myatan(xobs, b) * RD; + *nu = psd->nu + myatan(z, d) * RD; } + /*----------------------------------------------------------------------*/ -void pol2det(psdDescription *psd, double gamma, double nu, int *x, int *y){ +void pol2det(psdDescription * psd, double gamma, double nu, int *x, int *y) +{ double delga, delnu, td, tn, e, f, g, zobs, xobs; delga = gamma - psd->gamma; - delnu = nu - psd->nu; - td = tan(delga/RD); - tn = tan(delnu/RD); - e = sqrt(1. + td*td); - f = tn*e; - g = psd->distance*(1. + tn*tn +tn*tn*td*td); - zobs = psd->distance*(atan(tn*e) + asin(f/g)); - xobs = td*(psd->distance*cos(zobs/psd->distance)); - *y = (int)rint(psd->yZero + zobs/psd->yScale); - *x = (int)rint(psd->xZero + xobs/psd->xScale); + delnu = nu - psd->nu; + td = tan(delga / RD); + tn = tan(delnu / RD); + e = sqrt(1. + td * td); + f = tn * e; + g = psd->distance * (1. + tn * tn + tn * tn * td * td); + zobs = psd->distance * (atan(tn * e) + asin(f / g)); + xobs = td * (psd->distance * cos(zobs / psd->distance)); + *y = (int) rint(psd->yZero + zobs / psd->yScale); + *x = (int) rint(psd->xZero + xobs / psd->xScale); } /*--------------- bisecting geometry code -----------------------------*/ @@ -197,84 +216,94 @@ void pol2det(psdDescription *psd, double gamma, double nu, int *x, int *y){ /* turn chi and phi in order to get Z1 into the equatorial plane */ -static void turnEquatorial(MATRIX z1, double *chi, double *phi){ - if(ABS(z1[0][0]) < .0001 && ABS(z1[1][0]) < .00001){ +static void turnEquatorial(MATRIX z1, double *chi, double *phi) +{ + if (ABS(z1[0][0]) < .0001 && ABS(z1[1][0]) < .00001) { *phi = .0; *chi = 90.; - if(z1[2][0] < .0){ - *chi = - *chi; + if (z1[2][0] < .0) { + *chi = -*chi; } } else { - *phi = myatan(z1[1][0],z1[0][0])*RD; + *phi = myatan(z1[1][0], z1[0][0]) * RD; *chi = myatan(z1[2][0], - sqrt(z1[0][0]*z1[0][0] + z1[1][0]*z1[1][0]))*RD; + sqrt(z1[0][0] * z1[0][0] + z1[1][0] * z1[1][0])) * RD; } } + /*---------------------------------------------------------------------- calculate d-spacing and theta from z1 -----------------------------------------------------------------------*/ -int calcTheta(double lambda, MATRIX z1, double *d, double *theta){ +int calcTheta(double lambda, MATRIX z1, double *d, double *theta) +{ double dstar, sintheta; - dstar = sqrt(z1[0][0]*z1[0][0] + z1[1][0]*z1[1][0] + z1[2][0]*z1[2][0]); - if(dstar < .0001){ + dstar = + sqrt(z1[0][0] * z1[0][0] + z1[1][0] * z1[1][0] + + z1[2][0] * z1[2][0]); + if (dstar < .0001) { *d = .0; *theta = 0; return 0; } - *d = 1./dstar; - sintheta = lambda * dstar/2.; - if(ABS(sintheta) > 1.0){ + *d = 1. / dstar; + sintheta = lambda * dstar / 2.; + if (ABS(sintheta) > 1.0) { *d = .0; *theta = .0; return 0; } - *theta = asin(sintheta)*RD; + *theta = asin(sintheta) * RD; return 1; } + /*-------------------------------------------------------------------*/ int z1ToBisecting(double lambda, double z1[3], double *stt, double *om, - double *chi, double *phi) { + double *chi, double *phi) +{ MATRIX zz1; int status; zz1 = vectorToMatrix(z1); - status = z1mToBisecting(lambda,zz1,stt,om,chi,phi); + status = z1mToBisecting(lambda, zz1, stt, om, chi, phi); mat_free(zz1); return status; } + /*------------------------------------------------------------------------*/ int z1mToBisecting(double lambda, MATRIX z1, double *stt, double *om, - double *chi, double *phi) { + double *chi, double *phi) +{ double d; int status; - - status = calcTheta(lambda,z1,&d,om); - if(!status){ + + status = calcTheta(lambda, z1, &d, om); + if (!status) { *stt = .0; *om = .0; *chi = .0; *phi = .0; return status; } - turnEquatorial(z1,chi,phi); - *stt = *om*2.; + turnEquatorial(z1, chi, phi); + *stt = *om * 2.; *chi = 180. - *chi; *phi = 180. + *phi; return 1; } + /*---------------------------------------------------------------------*/ -int z1ToAnglesWithOffset(double lambda, MATRIX z1m,double omOffset, - double *stt, double *om, - double *chi, double *phi){ +int z1ToAnglesWithOffset(double lambda, MATRIX z1m, double omOffset, + double *stt, double *om, double *chi, double *phi) +{ int status, i; double d, delOm, sinchi, q, cosp, sinp, dstar; MATRIX z1; - status = calcTheta(lambda,z1m,&d,om); - if(!status){ + status = calcTheta(lambda, z1m, &d, om); + if (!status) { *stt = .0; *om = .0; *chi = .0; @@ -284,158 +313,173 @@ int z1ToAnglesWithOffset(double lambda, MATRIX z1m,double omOffset, *stt = 2. * *om; *om += omOffset; - z1 = mat_copy(z1m); /* routine messes z1m up! */ - dstar = sqrt(z1[0][0]*z1[0][0] + z1[1][0]*z1[1][0] + z1[2][0]*z1[2][0]); - for(i = 0; i < 3; i++){ - z1[i][0] /= dstar; + z1 = mat_copy(z1m); /* routine messes z1m up! */ + dstar = + sqrt(z1[0][0] * z1[0][0] + z1[1][0] * z1[1][0] + + z1[2][0] * z1[2][0]); + for (i = 0; i < 3; i++) { + z1[i][0] /= dstar; } - delOm = -omOffset/RD; - sinchi = z1[2][0]/cos(delOm); - if(ABS(sinchi) > 1.){ + delOm = -omOffset / RD; + sinchi = z1[2][0] / cos(delOm); + if (ABS(sinchi) > 1.) { mat_free(z1); return 0; } *chi = asin(sinchi); *chi = PI - *chi; - if(*chi > PI){ - *chi = *chi - 2* PI; + if (*chi > PI) { + *chi = *chi - 2 * PI; } - - q = cos(delOm)*cos(*chi); - cosp = (sin(delOm)*z1[0][0] + q*z1[1][0])/ - (sin(delOm)*sin(delOm) + q*q); - sinp = (z1[0][0] - sin(delOm)*cosp)/ q; - *phi = rtan(cosp,sinp); + + q = cos(delOm) * cos(*chi); + cosp = (sin(delOm) * z1[0][0] + q * z1[1][0]) / + (sin(delOm) * sin(delOm) + q * q); + sinp = (z1[0][0] - sin(delOm) * cosp) / q; + *phi = rtan(cosp, sinp); *phi *= RD; *chi *= RD; mat_free(z1); - return 1; + return 1; } + /*---------------------------------------------------------------------*/ -int psiForOmegaOffset(MATRIX z1m, double omOffset, - double chi, double phi, double *psi){ - double chibi, sinps, cosps, sinchi, dstar; +int psiForOmegaOffset(MATRIX z1m, double omOffset, + double chi, double phi, double *psi) +{ + double chibi, sinps, cosps, sinchi, dstar; MATRIX z1; - z1 = mat_copy(z1m); /* routine messes z1m up! */ - dstar = sqrt(z1[0][0]*z1[0][0] + z1[1][0]*z1[1][0] + z1[2][0]*z1[2][0]); + z1 = mat_copy(z1m); /* routine messes z1m up! */ + dstar = + sqrt(z1[0][0] * z1[0][0] + z1[1][0] * z1[1][0] + + z1[2][0] * z1[2][0]); z1[2][0] /= dstar; omOffset /= RD; - if(-z1[2][0] == 1.){ + if (-z1[2][0] == 1.) { *psi = phi; } else { chibi = PI - asin(-z1[2][0]); - if(chibi > PI){ - chibi -= 2*PI; + if (chibi > PI) { + chibi -= 2 * PI; } - sinps = tan(chibi)*tan(-omOffset); - sinchi = -z1[2][0]/cos(-omOffset); - if(ABS(sinchi) > 1.){ + sinps = tan(chibi) * tan(-omOffset); + sinchi = -z1[2][0] / cos(-omOffset); + if (ABS(sinchi) > 1.) { mat_free(z1); return 0; } - cosps = (cos(chibi) - sinps*sin(-omOffset)*sinchi)/cos(chi/RD); - *psi = -rtan(sinps,cosps)*RD; + cosps = (cos(chibi) - sinps * sin(-omOffset) * sinchi) / cos(chi / RD); + *psi = -rtan(sinps, cosps) * RD; } mat_free(z1); - return 1; + return 1; } /*----------------------------------------------------------------------*/ void rotatePsi(double om, double chi, double phi, double psi, - double *newom, double *newchi, double *newphi){ + double *newom, double *newchi, double *newphi) +{ MATRIX chim, phim, psim, r0, r0psi; - chim = mat_creat(3,3,ZERO_MATRIX); - chimat(chim,chi); - phim = mat_creat(3,3,ZERO_MATRIX); - phimat(phim,phi); - r0 = mat_mul(chim,phim); - psim = mat_creat(3,3,ZERO_MATRIX); - psimat(psim,psi); - r0psi = mat_mul(psim,r0); - - *newchi = rtan(sqrt(r0psi[2][0]*r0psi[2][0] + r0psi[2][1]*r0psi[2][1]), - r0psi[2][2])*RD; - *newphi = rtan(-r0psi[2][1],-r0psi[2][0])*RD; - *newom = om + rtan(-r0psi[1][2],r0psi[0][2])*RD; + chim = mat_creat(3, 3, ZERO_MATRIX); + chimat(chim, chi); + phim = mat_creat(3, 3, ZERO_MATRIX); + phimat(phim, phi); + r0 = mat_mul(chim, phim); + psim = mat_creat(3, 3, ZERO_MATRIX); + psimat(psim, psi); + r0psi = mat_mul(psim, r0); + + *newchi = + rtan(sqrt(r0psi[2][0] * r0psi[2][0] + r0psi[2][1] * r0psi[2][1]), + r0psi[2][2]) * RD; + *newphi = rtan(-r0psi[2][1], -r0psi[2][0]) * RD; + *newom = om + rtan(-r0psi[1][2], r0psi[0][2]) * RD; mat_free(chim); mat_free(phim); mat_free(psim); mat_free(r0); mat_free(r0psi); } + /*-------------------------------------------------------------------- calculate Z1 = [PHI]TZ3 The T means transposed matrixes for the return calculation! ---------------------------------------------------------------------*/ -static void z1fromz2(double z1[3], MATRIX z2, - double phi){ +static void z1fromz2(double z1[3], MATRIX z2, double phi) +{ MATRIX phim, phimt, zz1; - phim = mat_creat(3,3,ZERO_MATRIX); + phim = mat_creat(3, 3, ZERO_MATRIX); phimat(phim, phi); phimt = mat_tran(phim); - zz1 = mat_mul(phimt,z2); - matrixToVector(zz1,z1); + zz1 = mat_mul(phimt, z2); + matrixToVector(zz1, z1); mat_free(phim); mat_free(phimt); mat_free(zz1); } + /*-------------------------------------------------------------------- calculate Z1 = [PHI]T*[CHI]T*Z3 The T means transposed matrixes for the return calculation! ---------------------------------------------------------------------*/ -static void z1fromz3(double z1[3], MATRIX z3, double chi, - double phi){ +static void z1fromz3(double z1[3], MATRIX z3, double chi, double phi) +{ MATRIX chim, chimt, z2; - chim = mat_creat(3,3,ZERO_MATRIX); + chim = mat_creat(3, 3, ZERO_MATRIX); chimat(chim, chi); chimt = mat_tran(chim); - z2 = mat_mul(chimt,z3); - z1fromz2(z1,z2,phi); + z2 = mat_mul(chimt, z3); + z1fromz2(z1, z2, phi); mat_free(chim); mat_free(chimt); mat_free(z2); } + /*-------------------------------------------------------------------- calculate Z1 = [PHI]T*[CHI]T*[OM]T*Z4 The T means transposed matrixes for the return calculation! ---------------------------------------------------------------------*/ static void z1fromz4(double z1[3], MATRIX z4, double om, double chi, - double phi){ + double phi) +{ MATRIX oma, oma2, z3; - oma = mat_creat(3,3,ZERO_MATRIX); + oma = mat_creat(3, 3, ZERO_MATRIX); phimat(oma, om); oma2 = mat_tran(oma); - z3 = mat_mul(oma2,z4); - z1fromz3(z1,z3,chi,phi); + z3 = mat_mul(oma2, z4); + z1fromz3(z1, z3, chi, phi); mat_free(oma); mat_free(oma2); mat_free(z3); } + /*---------------------------------------------------------------------*/ -void z1FromAngles(double lambda, double stt, double om, - double chi, double phi, double z1[3]){ +void z1FromAngles(double lambda, double stt, double om, + double chi, double phi, double z1[3]) +{ MATRIX z4; double th; - z4 = mat_creat(3,1,ZERO_MATRIX); - th = (stt/2.)/RD; - z4[0][0] = (2. * sin(th)*cos(th))/lambda; - z4[1][0] = (-2. *sin(th)*sin(th))/lambda; + z4 = mat_creat(3, 1, ZERO_MATRIX); + th = (stt / 2.) / RD; + z4[0][0] = (2. * sin(th) * cos(th)) / lambda; + z4[1][0] = (-2. * sin(th) * sin(th)) / lambda; z4[2][0] = .0; - z1fromz4(z1,z4,om,chi,phi); + z1fromz4(z1, z4, om, chi, phi); mat_free(z4); } + /*---------------------------------------------------------------------- Normal Beam geometry specific calculations. This means the reflection is expressed through the three angles omega, gamma (two theta detector) and @@ -443,247 +487,267 @@ void z1FromAngles(double lambda, double stt, double om, bisToNormalBeam was lifted from HKLGEN. -----------------------------------------------------------------------*/ -double sign(double a, double b){ - if(b >= .0){ +double sign(double a, double b) +{ + if (b >= .0) { return ABS(a); } else { return -ABS(a); } } -/*--------------------------------------------------------------------*/ -static void makeNull(double *gamma, double *om, double *nu){ - *gamma = .0; - *om = .0; - *nu = .0; -} -/*---------------------------------------------------------------------*/ -int z1mToNormalBeam(double lambda, MATRIX z1m, double *gamma, double *om, double *nu){ - MATRIX dum, znew; - double d, a, b, sint, theta, omdeg; - int status; - status = calcTheta(lambda,z1m,&d,&theta); - if(!status){ - makeNull(gamma,om,nu); - return status; - } - - /* Everything on omega axis is blind: test for this */ - a = sqrt(z1m[0][0] * z1m[0][0] + z1m[1][0] * z1m[1][0]); - if(ABS(a) < .0001) { - makeNull(gamma,om,nu); - return 0; - } - - sint = sin(theta/RD); - b = 2.*sint*sint/(lambda*a); - if(b >= 1.) { - makeNull(gamma,om,nu); - return 0; - } - a = -atan2(z1m[1][0], -z1m[0][0]); - b = -asin(b); - *om = a + b; - omdeg = *om*RD; - dum = mat_creat(3,3,ZERO_MATRIX); - phimat(dum,omdeg); - znew = mat_mul(dum,z1m); - if(znew[0][0] < 0) { - *om = *om -2.*atan2(-znew[0][0], -znew[1][0]); - omdeg = *om * RD; - } - b = (sign(180.,omdeg)+ omdeg)/360.; - b = sign(1,b)* floor(ABS(b)); - omdeg = omdeg - 360. * b ; - *nu = asin(lambda*z1m[2][0]); - *gamma = acos(cos(2.*(theta/RD)))/cos(*nu); - *om = omdeg; - *nu = *nu * RD; - *gamma = *gamma * RD; - mat_free(dum); - mat_free(znew); - return 1; +/*--------------------------------------------------------------------*/ +static void makeNull(double *gamma, double *om, double *nu) +{ + *gamma = .0; + *om = .0; + *nu = .0; } + +/*---------------------------------------------------------------------*/ +int z1mToNormalBeam(double lambda, MATRIX z1m, double *gamma, double *om, + double *nu) +{ + MATRIX dum, znew; + double d, a, b, sint, theta, omdeg; + int status; + + status = calcTheta(lambda, z1m, &d, &theta); + if (!status) { + makeNull(gamma, om, nu); + return status; + } + + /* Everything on omega axis is blind: test for this */ + a = sqrt(z1m[0][0] * z1m[0][0] + z1m[1][0] * z1m[1][0]); + if (ABS(a) < .0001) { + makeNull(gamma, om, nu); + return 0; + } + + sint = sin(theta / RD); + b = 2. * sint * sint / (lambda * a); + if (b >= 1.) { + makeNull(gamma, om, nu); + return 0; + } + a = -atan2(z1m[1][0], -z1m[0][0]); + b = -asin(b); + *om = a + b; + omdeg = *om * RD; + dum = mat_creat(3, 3, ZERO_MATRIX); + phimat(dum, omdeg); + znew = mat_mul(dum, z1m); + if (znew[0][0] < 0) { + *om = *om - 2. * atan2(-znew[0][0], -znew[1][0]); + omdeg = *om * RD; + } + b = (sign(180., omdeg) + omdeg) / 360.; + b = sign(1, b) * floor(ABS(b)); + omdeg = omdeg - 360. * b; + *nu = asin(lambda * z1m[2][0]); + *gamma = acos(cos(2. * (theta / RD)) / cos(*nu)); + *om = omdeg; + *nu = *nu * RD; + *gamma = *gamma * RD; + mat_free(dum); + mat_free(znew); + return 1; +} + /*----------------------------------------------------------------------*/ int bisToNormalBeam(double twotheta, double omega, double chi, double phi, - double *omeganb, double *gamma, double *nu){ + double *omeganb, double *gamma, double *nu) +{ double tth, fom, fchi, fphi, sint, sinnu, del; - tth = twotheta/RD; - fom = omega/RD; - fchi = chi/RD; - fphi = phi/RD; - + tth = twotheta / RD; + fom = omega / RD; + fchi = chi / RD; + fphi = phi / RD; + /* nu calculation */ - sint = sin(tth/2.); - *nu = 2. * sin(fchi)*sint; - if(*nu > 1.){ + sint = sin(tth / 2.); + *nu = 2. * sin(fchi) * sint; + if (*nu > 1.) { return 0; } *nu = asin(*nu); - *nu = ABS(*nu)*sign(1.,fchi); + *nu = ABS(*nu) * sign(1., fchi); sinnu = sin(*nu); /* gamma calculation */ - *gamma = cos(tth)/cos(*nu); - if(ABS(*gamma) > 1.0){ + *gamma = cos(tth) / cos(*nu); + if (ABS(*gamma) > 1.0) { return 0; } *gamma = acos(*gamma); - *gamma = *gamma * sign(1.,tth); + *gamma = *gamma * sign(1., tth); /* omega normal beam */ - del = asin(sint/cos(fchi)); + del = asin(sint / cos(fchi)); *omeganb = del + fphi; - + *omeganb *= RD; *gamma *= RD; *nu *= RD; - if(ABS(*omeganb) > 180.){ - if(*omeganb < -180.){ + if (ABS(*omeganb) > 180.) { + if (*omeganb < -180.) { *omeganb += 360.; } - if(*omeganb > 180.){ + if (*omeganb > 180.) { *omeganb -= 360.; } } return 1; } + /* --------------------------------------------------------------------*/ static void z4FromNormalBeam(MATRIX z4, double lambda, double gamma, - double nu){ + double nu) +{ double gar, nur; - gar = gamma/RD; - nur = nu/RD; + gar = gamma / RD; + nur = nu / RD; /* - this is basically a conversion from polar coordinates to - x,y,z coordinates. However, sin and cos are exchanged in - comparison to textbook formulas for this conversion. But this - is only a shift of origin - */ - z4[0][0] = (sin(gar) * cos(nur))/lambda; - z4[1][0] = (cos (gar) * cos(nur) -1.)/lambda; - z4[2][0] = (sin(nur))/lambda; + this is basically a conversion from polar coordinates to + x,y,z coordinates. However, sin and cos are exchanged in + comparison to textbook formulas for this conversion. But this + is only a shift of origin + */ + z4[0][0] = (sin(gar) * cos(nur)) / lambda; + z4[1][0] = (cos(gar) * cos(nur) - 1.) / lambda; + z4[2][0] = (sin(nur)) / lambda; } + /*----------------------------------------------------------------------*/ -void z1FromNormalBeam(double lambda, double omega, double gamma, - double nu, double z1[3]){ +void z1FromNormalBeam(double lambda, double omega, double gamma, + double nu, double z1[3]) +{ MATRIX z4, omm, omt, z1m; - z4 = mat_creat(3,1,ZERO_MATRIX); - z4FromNormalBeam(z4,lambda, gamma,nu); - omm = mat_creat(3,3,ZERO_MATRIX); - phimat(omm,omega); + z4 = mat_creat(3, 1, ZERO_MATRIX); + z4FromNormalBeam(z4, lambda, gamma, nu); + omm = mat_creat(3, 3, ZERO_MATRIX); + phimat(omm, omega); omt = mat_tran(omm); - z1m = mat_mul(omt,z4); - matrixToVector(z1m,z1); + z1m = mat_mul(omt, z4); + matrixToVector(z1m, z1); mat_free(z4); mat_free(omm); mat_free(omt); mat_free(z1m); } + /*--------------------------------------------------------------------*/ -double circlify(double val){ - while(val > 360.){ +double circlify(double val) +{ + while (val > 360.) { val -= 360.; } - while(val < 0.){ - val += 360.; + while (val < 0.) { + val += 360.; } return val; } + /*----------------------------------------------------------------------*/ -void z1FromAllAngles(double lambda, double omega , double gamma, - double nu, double chi, double phi, double z1[3]){ +void z1FromAllAngles(double lambda, double omega, double gamma, + double nu, double chi, double phi, double z1[3]) +{ MATRIX z3; - z1FromNormalBeam(lambda, omega, gamma, nu, z1); + z1FromNormalBeam(lambda, omega, gamma, nu, z1); z3 = vectorToMatrix(z1); - z1fromz3(z1,z3,chi,phi); - mat_free(z3); + z1fromz3(z1, z3, chi, phi); + mat_free(z3); } + /*-----------------------------------------------------------------------*/ -int findAllowedBisecting(double lambda, MATRIX z1, float fSet[4], - inRange testFunc, void *userData){ - int status, i, mask[4]; - double stt, om, chi, phi, psi, ompsi, chipsi, phipsi; - float fTest[4]; - - status = z1mToBisecting(lambda,z1, &stt, &om, &chi, &phi); - chi = circlify(chi); - phi = circlify(phi); - fSet[0] = stt; - fSet[1] = om; - fSet[2] = chi; - fSet[3] = phi; - if(status != 1) { - return 0; - } - - if(testFunc(userData, fSet, mask) == 1){ - return 1; - } - - for(psi = .0; psi < 360.; psi += .5){ - rotatePsi(om,chi,phi,psi,&ompsi,&chipsi,&phipsi); - fTest[0] = stt; - fTest[1] = ompsi; - fTest[2] = circlify(chipsi); - fTest[3] = circlify(phipsi); - status = testFunc(userData,fTest,mask); - if(status == 1){ - for(i = 0; i < 4; i++){ - fSet[i] = fTest[i]; - } - return 1; - } - /* - * if chi close to 0, or 180, try to wrap phi onto om - */ - if(ABS(fTest[2] - .0) < .1 || ABS(fTest[2] - 180.) < .1){ - fTest[1] -= fTest[3]; - fTest[3] = .0; - if(fTest[1] < 0.){ - fTest[1] += 360.; - } - if(fTest[1] > 360.0){ - fTest[1] -= 360.; - } - status = testFunc(userData,fTest,mask); - if(status == 1){ - for(i = 0; i < 4; i++){ - fSet[i] = fTest[i]; - } - return 1; - } - } - if(mask[0] == 0) { - /* - * useless: when two theta problem there is no solution - */ - return 0; - } - } +int findAllowedBisecting(double lambda, MATRIX z1, double *fSet, + inRange testFunc, void *userData) +{ + int status, i, mask[4]; + double stt, om, chi, phi, psi, ompsi, chipsi, phipsi; + double fTest[4]; + + status = z1mToBisecting(lambda, z1, &stt, &om, &chi, &phi); + chi = circlify(chi); + phi = circlify(phi); + fSet[0] = stt; + fSet[1] = om; + fSet[2] = chi; + fSet[3] = phi; + if (status != 1) { return 0; -} + } + + if (testFunc(userData, fSet, mask) == 1) { + return 1; + } + + for (psi = .0; psi < 360.; psi += .5) { + rotatePsi(om, chi, phi, psi, &ompsi, &chipsi, &phipsi); + fTest[0] = stt; + fTest[1] = ompsi; + fTest[2] = circlify(chipsi); + fTest[3] = circlify(phipsi); + status = testFunc(userData, fTest, mask); + if (status == 1) { + for (i = 0; i < 4; i++) { + fSet[i] = fTest[i]; + } + return 1; + } + /* + * if chi close to 0, or 180, try to wrap phi onto om + */ + if (ABS(fTest[2] - .0) < .1 || ABS(fTest[2] - 180.) < .1) { + fTest[1] -= fTest[3]; + fTest[3] = .0; + if (fTest[1] < 0.) { + fTest[1] += 360.; + } + if (fTest[1] > 360.0) { + fTest[1] -= 360.; + } + status = testFunc(userData, fTest, mask); + if (status == 1) { + for (i = 0; i < 4; i++) { + fSet[i] = fTest[i]; + } + return 1; + } + } + if (mask[0] == 0) { + /* + * useless: when two theta problem there is no solution + */ + return 0; + } + } + return 0; +} + /*------------------- a test program ------------------------------------*/ #ifdef TESTCODE -int main(int argc, char *argv[]){ +int main(int argc, char *argv[]) +{ psdDescription psd; - double gamma,nu, lambda, stt, om, chi, phi, z1[3], psi; + double gamma, nu, lambda, stt, om, chi, phi, z1[3], psi; double psiom, psichi, psiphi; double sttex, omex, chiex, phiex; int x, y, status, i; - MATRIX UB, UBinv, zz1,zz1b, hkl, hklback; + MATRIX UB, UBinv, zz1, zz1b, hkl, hklback; double gaex, omnbex, nuex, omeganb; /* initializations */ - UB = mat_creat(3,3,ZERO_MATRIX); + UB = mat_creat(3, 3, ZERO_MATRIX); UB[0][0] = 0.016169; UB[0][1] = 0.011969; UB[0][2] = 0.063195; @@ -695,7 +759,7 @@ int main(int argc, char *argv[]){ UB[2][2] = 0.006321; UBinv = mat_inv(UB); lambda = 1.179; - + /* test PSD code */ psd.xScale = .7; @@ -704,206 +768,176 @@ int main(int argc, char *argv[]){ psd.yZero = 64; psd.distance = 450.; psd.gamma = 43.; - psd.nu = 12.3; + psd.nu = 12.3; - det2pol(&psd,200, 111,&gamma, &nu); - pol2det(&psd,gamma,nu, &x, &y); - if(x == 200 && y == 111){ + det2pol(&psd, 200, 111, &gamma, &nu); + pol2det(&psd, gamma, nu, &x, &y); + if (x == 200 && y == 111) { printf("PSD test: OK\n"); } /* test bisecting calculations. The tests were taken from a system known to work - */ + */ status = 1; sttex = 30.58704; - omex = 15.293520; + omex = 15.293520; chiex = 129.053604; phiex = 134.191132; - hkl = mat_creat(3,1,ZERO_MATRIX); + hkl = mat_creat(3, 1, ZERO_MATRIX); hkl[0][0] = -2.; hkl[1][0] = -2.; hkl[2][0] = 4.; - zz1 = mat_mul(UB,hkl); - z1mToBisecting(lambda,zz1,&stt,&om,&chi,&phi); - if(ABS(stt - sttex) > .01 || - ABS(om - omex) > .01 || - ABS(chi - chiex) > .01 || - ABS(phi - phiex) > .01){ + zz1 = mat_mul(UB, hkl); + z1mToBisecting(lambda, zz1, &stt, &om, &chi, &phi); + if (ABS(stt - sttex) > .01 || + ABS(om - omex) > .01 || + ABS(chi - chiex) > .01 || ABS(phi - phiex) > .01) { printf("Bisecting Angles calculation FAILED!!!!!!!!!\n"); - printf("Expected: %12.4f %12.4f %12.4f %12.4f\n", sttex, omex, chiex,phiex); - printf("Got: %12.4f %12.4f %12.4f %12.4f\n", stt,om,chi,phi); + printf("Expected: %12.4f %12.4f %12.4f %12.4f\n", sttex, omex, chiex, + phiex); + printf("Got: %12.4f %12.4f %12.4f %12.4f\n", stt, om, chi, phi); status = 0; } - z1FromAngles(lambda,sttex,omex,chiex,phiex,z1); - for(i = 0; i < 3; i++){ - if(ABS(zz1[i][0] - z1[i]) > .0001){ - printf("Calculation of Z1 from Angles FAILED!!!!\n"); - printf("Expected: %8.4f %8.4f %8.4f\n", zz1[0][0], zz1[1][0], + z1FromAngles(lambda, sttex, omex, chiex, phiex, z1); + for (i = 0; i < 3; i++) { + if (ABS(zz1[i][0] - z1[i]) > .0001) { + printf("Calculation of Z1 from Angles FAILED!!!!\n"); + printf("Expected: %8.4f %8.4f %8.4f\n", zz1[0][0], zz1[1][0], zz1[2][0]); - printf("GOT: %8.4f %8.4f %8.4f\n",z1[0],z1[1],z1[2]); - status = 0; - } + printf("GOT: %8.4f %8.4f %8.4f\n", z1[0], z1[1], z1[2]); + status = 0; + } } - hklback = mat_mul(UBinv,zz1); - for(i = 0; i < 3; i++){ - if(ABS(hklback[i][0] - hkl[i][0]) > .0001){ + hklback = mat_mul(UBinv, zz1); + for (i = 0; i < 3; i++) { + if (ABS(hklback[i][0] - hkl[i][0]) > .0001) { printf("Back Calculation of HKL FAILED!!!!!!!!!\n"); - printf("Expected: %8.4f %8.4f %8.4f\n", hkl[0][0], hkl[1][0], + printf("Expected: %8.4f %8.4f %8.4f\n", hkl[0][0], hkl[1][0], hkl[2][0]); - printf("GOT: %8.4f %8.4f %8.4f\n",hklback[0][0], - hklback[1][0],hklback[2][0]); - status = 0; - } + printf("GOT: %8.4f %8.4f %8.4f\n", hklback[0][0], + hklback[1][0], hklback[2][0]); + status = 0; + } } - if(status == 1){ - printf("Bisecting test: OK\n"); + if (status == 1) { + printf("Bisecting test: OK\n"); } /* try turning in psi */ - rotatePsi(omex,chiex,phiex,30.,&psiom,&psichi,&psiphi); + rotatePsi(omex, chiex, phiex, 30., &psiom, &psichi, &psiphi); omex = 37.374298; chiex = 123.068192; phiex = 170.8209099; - if(ABS(psiom - omex) > .01 || - ABS(psichi - chiex) > .01 || - ABS(psiphi - phiex) > .01){ + if (ABS(psiom - omex) > .01 || + ABS(psichi - chiex) > .01 || ABS(psiphi - phiex) > .01) { printf("Psi Rotation test FAILED!!!!!!!!!\n"); - printf("Expected: %12.4f %12.4f %12.4f\n", omex, chiex,phiex); - printf("Got: %12.4f %12.4f %12.4f\n", psiom,psichi,psiphi); + printf("Expected: %12.4f %12.4f %12.4f\n", omex, chiex, phiex); + printf("Got: %12.4f %12.4f %12.4f\n", psiom, psichi, psiphi); status = 0; } else { printf("Psi rotation test: OK\n"); } /* - try to calculate a psi for a given omega offset - */ - omex = 15.293520; + try to calculate a psi for a given omega offset + */ + omex = 15.293520; chiex = 129.053604; phiex = 134.191132; - if(psiForOmegaOffset(zz1,-5.,chiex, phiex, &psi) != 1){ + if (psiForOmegaOffset(zz1, -5., chiex, phiex, &psi) != 1) { printf("Failed to calculate PSI for a Omega Offset\n"); } else { - rotatePsi(omex,chiex,phiex,psi,&psiom,&psichi,&psiphi); - if(ABS(psiom +5. - omex) > .5){ - printf("Failed to reach desired omega with calculated psi\n"); - printf("Expected: %12.4f Got: %12.4f PSI = %12.4f\n", omex -10., - psiom, psi); + rotatePsi(omex, chiex, phiex, psi, &psiom, &psichi, &psiphi); + if (ABS(psiom + 5. - omex) > .5) { + printf("Failed to reach desired omega with calculated psi\n"); + printf("Expected: %12.4f Got: %12.4f PSI = %12.4f\n", omex - 10., + psiom, psi); } else { printf("Psi for Omega Offset: OK\n"); } } /* - try to calculate angles with a omega offset - */ + try to calculate angles with a omega offset + */ omex = 10.29; chiex = 128.78; phiex = 126.24; sttex = 30.59; z1ToAnglesWithOffset(lambda, zz1, -5., &stt, &om, &chi, &phi); - if(ABS(stt - sttex) > .01 || - ABS(om - omex) > .01 || - ABS(chi - chiex) > .01 || - ABS(phi - phiex) > .01){ + if (ABS(stt - sttex) > .01 || + ABS(om - omex) > .01 || + ABS(chi - chiex) > .01 || ABS(phi - phiex) > .01) { printf("Angles calculation with Omega Offset FAILED!!!!!!!!!\n"); - printf("Expected: %12.4f %12.4f %12.4f %12.4f\n", sttex, omex, chiex,phiex); - printf("Got: %12.4f %12.4f %12.4f %12.4f\n", stt,om,chi,phi); + printf("Expected: %12.4f %12.4f %12.4f %12.4f\n", sttex, omex, chiex, + phiex); + printf("Got: %12.4f %12.4f %12.4f %12.4f\n", stt, om, chi, phi); status = 0; } else { printf("Angles with Omega Offset: OK\n"); } - + /* - test normal beam codes - */ + test normal beam codes + */ omex = 37.374298; gaex = 19.322; - omnbex = -21.057; - nuex = 24.186; - z1mToBisecting(lambda,zz1,&stt,&om,&chi,&phi); + omnbex = -21.057; + nuex = 24.186; + z1mToBisecting(lambda, zz1, &stt, &om, &chi, &phi); chi = 50.949; phi = -45.8088; - if(!bisToNormalBeam(stt,om,chi,phi, - &omeganb, &gamma, &nu)){ + if (!bisToNormalBeam(stt, om, chi, phi, &omeganb, &gamma, &nu)) { printf("Error on normal beam calculation!!\n"); } - if(ABS(omeganb - omnbex) > .01 || - ABS(gamma - gaex) > .01 || - ABS(nu - nuex) > .01){ + if (ABS(omeganb - omnbex) > .01 || + ABS(gamma - gaex) > .01 || ABS(nu - nuex) > .01) { printf("Normal Beam Calculation test FAILED!!!!!!!!!\n"); - printf("Expected: %12.4f %12.4f %12.4f\n", omnbex, gaex,nuex); - printf("Got: %12.4f %12.4f %12.4f\n", omeganb,gamma,nu); + printf("Expected: %12.4f %12.4f %12.4f\n", omnbex, gaex, nuex); + printf("Got: %12.4f %12.4f %12.4f\n", omeganb, gamma, nu); } else { printf("Normal Beam Angle Calculation: OK\n"); } - z1FromNormalBeam(lambda, omnbex, gaex, nuex,z1); + z1FromNormalBeam(lambda, omnbex, gaex, nuex, z1); status = 1; - for(i = 0; i < 3; i++){ - if(ABS(zz1[i][0] - z1[i]) > .0001){ - printf("Calculation of Z1 from Normal Beam Angles FAILED!!!!\n"); - printf("Expected: %8.4f %8.4f %8.4f\n", zz1[0][0], zz1[1][0], + for (i = 0; i < 3; i++) { + if (ABS(zz1[i][0] - z1[i]) > .0001) { + printf("Calculation of Z1 from Normal Beam Angles FAILED!!!!\n"); + printf("Expected: %8.4f %8.4f %8.4f\n", zz1[0][0], zz1[1][0], zz1[2][0]); - printf("GOT: %8.4f %8.4f %8.4f\n",z1[0],z1[1],z1[2]); - break; - status = 0; - } + printf("GOT: %8.4f %8.4f %8.4f\n", z1[0], z1[1], z1[2]); + break; + status = 0; + } } - if(status){ + if (status) { printf("Normal Beam Backwards Calculation: OK\n"); } /* - for interest: try to see how normal beam angles go if we rotate psi - */ + for interest: try to see how normal beam angles go if we rotate psi + */ /* - sttex = 30.58704; - om = 15.293520; - chi = 50.949; - phi = -45.8088; - printf(" PSI Omega Gamma Nu\n"); - for(i = 0; i < 36; i++){ - psi = i*10.; - rotatePsi(om,chi,phi,psi,&psiom,&psichi,&psiphi); - status = bisToNormalBeam(sttex,psiom,psichi,psiphi,&omeganb, &gamma, &nu); - if(status){ - printf("%12.4f%12.4f%12.4f%12.4f\n",psi,omeganb,gamma,nu); - } - } - */ + sttex = 30.58704; + om = 15.293520; + chi = 50.949; + phi = -45.8088; + printf(" PSI Omega Gamma Nu\n"); + for(i = 0; i < 36; i++){ + psi = i*10.; + rotatePsi(om,chi,phi,psi,&psiom,&psichi,&psiphi); + status = bisToNormalBeam(sttex,psiom,psichi,psiphi,&omeganb, &gamma, &nu); + if(status){ + printf("%12.4f%12.4f%12.4f%12.4f\n",psi,omeganb,gamma,nu); + } + } + */ } #endif - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/fourlib.h b/fourlib.h index 34fd23fa..37bcc0b0 100644 --- a/fourlib.h +++ b/fourlib.h @@ -34,29 +34,31 @@ functions for any further work. A lot of information about the detector is required for this transformation which is held in the datastruture as defined below - ----------------------------------------------------------------------*/ + ----------------------------------------------------------------------*/ -typedef struct{ - double xScale; /* scale factor pixel --> mm for x */ - double yScale; /* scale factor pixel --> mm for y */ - double distance; /* distance sample detector in mm */ - double gamma; /* gamma == two theta position of the detector */ - double nu; /* tilt angle of the detector */ - int xZero; /* x pixel coordinate of the zero point of the detector */ - int yZero; /* y pixel coordinate of the zero point of the detector */ +typedef struct { + double xScale; /* scale factor pixel --> mm for x */ + double yScale; /* scale factor pixel --> mm for y */ + double distance; /* distance sample detector in mm */ + double gamma; /* gamma == two theta position of the detector */ + double nu; /* tilt angle of the detector */ + int xZero; /* x pixel coordinate of the zero point of the detector */ + int yZero; /* y pixel coordinate of the zero point of the detector */ } psdDescription; /** * det2pol converts the pixel coordinates x and y on the detector described * by psd to polar coordinates gamma and nu. */ -void det2pol(psdDescription *psd, int x, int y, double *gamma, double *nu); +void det2pol(psdDescription * psd, int x, int y, double *gamma, + double *nu); /** * pol2det converts the polar coordinates gamma and nu to detector coordinates * x and y on the detector described psd */ -void pol2det(psdDescription *psd, double gamma, double nu, int *x, int *y); +void pol2det(psdDescription * psd, double gamma, double nu, int *x, + int *y); /*------------------------------------------------------------------------ calculation of four circle diffractometer angles stt, om, chi and phi @@ -75,26 +77,26 @@ void pol2det(psdDescription *psd, double gamma, double nu, int *x, int *y); * were invalid. The m version acts upon a matrix. */ int z1ToBisecting(double lambda, double z1[3], double *stt, double *om, - double *chi, double *phi); + double *chi, double *phi); int z1mToBisecting(double lambda, MATRIX z1, double *stt, double *om, - double *chi, double *phi); + double *chi, double *phi); /** * calculates diffraction angles to put z1 into a detector with a given * offset in omega against the bisecting position. Useful for tweaking * if omega is restricted. */ -int z1ToAnglesWithOffset(double lambda, MATRIX z1,double omOffset, - double *stt, double *om, +int z1ToAnglesWithOffset(double lambda, MATRIX z1, double omOffset, + double *stt, double *om, double *chi, double *phi); - + /** * calculates a PSI for a given offset in omega from the bisecting * position. This can be useful for tweaking reflections to be * measurable at omega restricted diffractometers. -*/ -int psiForOmegaOffset(MATRIX z1, double omOffset, - double chi, double phi, double *psi); +*/ +int psiForOmegaOffset(MATRIX z1, double omOffset, + double chi, double phi, double *psi); /** * calculate new setting angles for a psi rotation. Input are the angles @@ -110,8 +112,8 @@ void rotatePsi(double om, double chi, double phi, double psi, * a bissecting position, however it is required that the angles describe a * reflection measured in the horizontal plane. */ -void z1FromAngles(double lambda, double stt, double om, - double chi, double phi, double z1[3]); +void z1FromAngles(double lambda, double stt, double om, + double chi, double phi, double z1[3]); /*----------------------------------------------------------------------- Normal beam calculations. Here the diffraction vector is expressed as polar angles gamma and nu and omega. @@ -121,24 +123,25 @@ void z1FromAngles(double lambda, double stt, double om, * circle angles twotheta, omega, chi and phi. */ int bisToNormalBeam(double twotheta, double omega, double chi, double phi, - double *omeganb, double *gamma, double *nu); + double *omeganb, double *gamma, double *nu); /** * calculate normal beam angles from z1 */ -int z1mToNormalBeam(double lambda, MATRIX z1, double *gamma, double *om, double *nu); +int z1mToNormalBeam(double lambda, MATRIX z1, double *gamma, double *om, + double *nu); /** * calculate the vector z1 from the normal beam angles omega, gamma and nu. * chi and phi either do not exist or are 0. */ -void z1FromNormalBeam(double lambda, double omega, double gamma, - double nu, double z1[3]); +void z1FromNormalBeam(double lambda, double omega, double gamma, + double nu, double z1[3]); /** * calculate z1 from four circle angles plus gamma, nu */ -void z1FromAllAngles(double lambda, double omega, double gamma, - double nu, double chi, double phi, double z1[3]); +void z1FromAllAngles(double lambda, double omega, double gamma, + double nu, double chi, double phi, double z1[3]); /*------------------------------------------------------------------------ Utility -------------------------------------------------------------------------*/ @@ -186,17 +189,9 @@ int calcTheta(double lambda, MATRIX z1, double *d, double *theta); * @param userData A user specified pointer to some data which may be needed * in testing the range. * @return 0 on failure, 1 on success. - */ -typedef int (*inRange)(void *userData, float dSet[4], int mask[4]); -int findAllowedBisecting(double lambda, MATRIX z1, float fSet[4], - inRange testFunc, void *userData); - -#endif - - - - - - - + */ +typedef int (*inRange) (void *userData, double dSet[4], int mask[4]); +int findAllowedBisecting(double lambda, MATRIX z1, double fSet[4], + inRange testFunc, void *userData); +#endif diff --git a/fourmess.c b/fourmess.c new file mode 100644 index 00000000..b6cb77b5 --- /dev/null +++ b/fourmess.c @@ -0,0 +1,1215 @@ +/** + * This is a new version of the four circle reflection measurement module. Its task is + * to provide functionality required for measuring a list of reflections. This is done + * with the help of some scripts binding things together. This module provides: + * - a table of scan parameters for measuring reflections at different angles. + * - the functions required to produce the scan data files for single detector + * mode. + * - a list of reflections to measure. + * + * In contrast to the old mesure module, this only provides some help to + * scripts. Thus, through scripts, a more flexible measurement is possible. + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, July 2008 + */ +#include +#include +#include "singlex.h" +#include "sicsobj.h" +#include "fourtable.h" +#include "sicshipadaba.h" +#include "sicsvar.h" +#include +#include "scan.h" +#include "stdscan.h" +#include "evcontroller.h" +#include "integrate.h" +#include "sginfo.h" +#include "matrix/matrix.h" +#include "cell.h" +#include "fourlib.h" +#include "counter.h" +#include "scanvar.h" +#include "scan.i" +#include "sdynar.h" +#include "lld.h" + +extern char *trim(char *); + +extern void SNXFormatTime(char *pBueffel, int iLen); + +#define ABS(x) (x < 0 ? -(x) : (x)) +/*---------------------------------------------------------------------------*/ +typedef struct { + FILE *profFile; /* file with reflection profiles, ccl */ + FILE *hklFile; /* file with integrated intensities */ + pSICSOBJ stepTable; /* table with the scan parameters */ + char *currentFileRoot; + pSICSOBJ messList; + pHdb currentRefl; /* the current reflection being measured */ + int count; + pScanData pScanner; + int masterCount; /* the number of master reflection as craeted by indgen */ +} FourMess, *pFourMess; +/*---------------------------------------------------------------------------*/ +static void KillFourMess(void *data) +{ + pFourMess priv = (pFourMess) data; + if (priv == NULL) { + return; + } + if (priv->profFile != NULL) { + fclose(priv->profFile); + } + if (priv->hklFile != NULL) { + fclose(priv->hklFile); + } + if (priv->currentFileRoot != NULL) { + free(priv->currentFileRoot); + } + if (priv->stepTable >= 0) { + DeleteFourCircleTable(priv->stepTable); + } + free(priv); +} + +/*----------------------------------------------------------------------------*/ +static int FourMessAction(SConnection * pCon, SicsInterp * pSics, + void *data, int argc, char *argv[]) +{ + pFourMess priv = NULL; + pSICSOBJ self = (pSICSOBJ) data; + int err, status; + + assert(self != NULL); + priv = self->pPrivate; + assert(priv != NULL); + + if (argc < 2) { + SCWrite(pCon, "ERROR: insufficient number of arguments to fmess", + eError); + return 0; + } + + if (strcmp(argv[1], "table") == 0) { + return HandleFourCircleCommands(priv->stepTable, pCon, + argc, argv, &err); + } + + status = InvokeSICSOBJ(pCon, pSics, data, argc, argv); + if (status < 0) { + SCPrintf(pCon, eError, "ERROR: %s no subcommand or parameter", + argv[1]); + return 0; + } + return status; +} + +/*-----------------------------------------------------------------------------*/ +static int FourMessClose(pSICSOBJ self, SConnection * pCon, + pHdb commandNode, pHdb par[], int nPar) +{ + pFourMess priv = NULL; + + priv = self->pPrivate; + if (priv->hklFile != NULL) { + fclose(priv->hklFile); + priv->hklFile = NULL; + } + if (priv->profFile != NULL) { + fclose(priv->profFile); + priv->profFile = NULL; + } + return 1; +} + +/*-----------------------------------------------------------------------------*/ +static int FourMessStart(pSICSOBJ self, SConnection * pCon, + pHdb commandNode, pHdb par[], int nPar) +{ + pFourMess priv = NULL; + char pFilename[1024], pRoot[512]; + char pBueffel[1024]; + double lambda; + const double *dUB; + pSicsVariable pVar = NULL; + char *pFile = NULL, *pPtr; + FILE *temp = NULL; + pHdb node; + hdbValue v; + + assert(self); + assert(pCon); + + priv = self->pPrivate; + + if (nPar < 1) { + SCWrite(pCon, "ERROR: need file name parameter to start", eError); + return 0; + } + + /* close open files if so */ + if (priv->hklFile != NULL) { + FourMessClose(self, pCon, commandNode, par, nPar); + } + + /* create filename root */ + GetHipadabaPar(par[0], &v, pCon); + pFile = strdup(v.v.text); + pPtr = strrchr(pFile, (int) '.'); + pPtr++; + *pPtr = '\0'; + if (priv->currentFileRoot != NULL) { + free(priv->currentFileRoot); + } + priv->currentFileRoot = strdup(pFile); + free(pFile); + strlcpy(pRoot, priv->currentFileRoot, 511); + + + /* open the reflection file */ + sprintf(pBueffel, "Writing to %s.ccl, .rfl", pRoot); + SCWrite(pCon, pBueffel, eLog); + strcpy(pFilename, pRoot); + strcat(pFilename, "ccl"); + priv->profFile = fopen(pFilename, "w"); + if (!priv->profFile) { + sprintf(pBueffel, "ERROR: SERIOUS TROUBLE: cannot open %s!", + pFilename); + SCWrite(pCon, pBueffel, eError); + SCSetInterrupt(pCon, eAbortBatch); + return 0; + } + + node = GetHipadabaNode(self->objectNode, "template"); + assert(node != NULL); + GetHipadabaPar(node, &v, pCon); + temp = fopen(v.v.text, "r"); + if (temp == NULL) { + SCWrite(pCon, "ERROR: failed to open header template", eError); + } + if (temp != NULL) { + WriteTemplate(priv->profFile, temp, pFilename, NULL, + pCon, pServ->pSics); + fclose(temp); + } + + /* open hkl-data file */ + strcpy(pFilename, pRoot); + strcat(pFilename, "rfl"); + priv->hklFile = fopen(pFilename, "w"); + if (!priv->hklFile) { + sprintf(pBueffel, "ERROR: SERIOUS TROUBLE: cannot open %s!", + pFilename); + SCWrite(pCon, pBueffel, eError); + SCSetInterrupt(pCon, eAbortBatch); + return 0; + } + fputs(pFilename, priv->hklFile); + fputs("\n", priv->hklFile); + + /* write some header data */ + SNXFormatTime(pBueffel, 1024); + fprintf(priv->hklFile, "filetime = %s\n", pBueffel); + lambda = SXGetLambda(); + fprintf(priv->hklFile, "lambda = %f Angstroem\n", lambda); + dUB = SXGetUB(); + fprintf(priv->hklFile, + "UB = %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f\n", + dUB[0], dUB[1], dUB[2], dUB[3], dUB[4], dUB[5], dUB[6], dUB[7], + dUB[8]); + + /* write sample & user info */ + strcpy(pBueffel, "CCL, Instr=TRICS, "); + pVar = FindVariable(pServ->pSics, "sample"); + if (pVar) { + fprintf(priv->hklFile, "sample = %s\n", pVar->text); + } + pVar = FindVariable(pServ->pSics, "user"); + if (pVar) { + fprintf(priv->hklFile, "user = %s \n", pVar->text); + } + priv->count = 0; + return 1; +} +/*-----------------------------------------------------------------------------*/ +static int FourMessReopen(pSICSOBJ self, SConnection * pCon, + pHdb commandNode, pHdb par[], int nPar) +{ + pFourMess priv = NULL; + char pFilename[1024]; + + priv = self->pPrivate; + if(priv->hklFile != NULL){ + return 1; /* still open! */ + } + + if(priv->currentFileRoot == NULL){ + SCWrite(pCon,"ERROR: nothing to append too", eLogError); + return 0; + } + + strcpy(pFilename, priv->currentFileRoot); + strcat(pFilename, "ccl"); + priv->profFile = fopen(pFilename, "a"); + if(priv->profFile == NULL){ + SCPrintf(pCon,eLogError,"ERROR: failed to reopen %s", pFilename); + return 0; + } + strcpy(pFilename, priv->currentFileRoot); + strcat(pFilename, "rfl"); + priv->hklFile = fopen(pFilename, "a"); + if(priv->hklFile == NULL){ + SCPrintf(pCon,eLogError,"ERROR: failed to reopen %s", pFilename); + return 0; + } + SCPrintf(pCon,eValue,"Reopened %s.ccl,.rfl", priv->currentFileRoot); + + return 1; +} +/*----------------------------------------------------------------------------*/ +static int FourMessScanPar(pSICSOBJ self, SConnection * pCon, + pHdb commandNode, pHdb par[], int nPar) +{ + pFourMess priv = self->pPrivate; + char *scanvar; + double stt, dVal; + int np, preset; + pDynString data; + + assert(priv != NULL); + if (nPar < 1) { + SCWrite(pCon, "ERROR: need two theta parameter to scanpar", eError); + return 0; + } + stt = par[0]->value.v.doubleValue; + + scanvar = GetFourCircleScanVar(priv->stepTable, stt); + dVal = GetFourCircleStep(priv->stepTable, stt); + np = GetFourCircleScanNP(priv->stepTable, stt); + preset = GetFourCirclePreset(priv->stepTable, stt); + if (strcmp(scanvar, "Not found") == 0) { + SCPrintf(pCon, eValue, "%s,%f,%d,%d", "om", dVal, np, preset); + } else { + SCPrintf(pCon, eValue, "%s,%f,%d,%d", scanvar, dVal, np, preset); + } + return 1; +} +/*--------------------------------------------------------------------------*/ +static int FourMessPrepareScan(pScanData self) +{ + pVarEntry pVar = NULL; + void *pDings; + int i, iRet; + float fVal; + char pBueffel[512]; + char pMessage[1024]; + + assert(self); + assert(self->pCon); + + /* check boundaries of scan variables and allocate storage */ + for (i = 0; i < self->iScanVar; i++) { + DynarGet(self->pScanVar, i, &pDings); + pVar = (pVarEntry) pDings; + if (pVar) { + iRet = CheckScanVar(pVar, self->pCon, self->iNP - 1); + if (!iRet) { + return 0; + } + InitScanVar(pVar); + } else { + SCWrite(self->pCon, + "WARNING: Internal error, no scan variable, I try to continue", + eLog); + } + pVar = NULL; + } /* end for */ + + /* configure counter */ + SetCounterMode((pCounter) self->pCounterData, self->iMode); + SetCounterPreset((pCounter) self->pCounterData, self->fPreset); + self->iCounts = 0; + + return 1; +} +/*-----------------------------------------------------------------------------*/ +static int FourMessPrepareCmd(pSICSOBJ self, SConnection * pCon, + pHdb commandNode, pHdb par[], int nPar) +{ + pFourMess priv = self->pPrivate; + + return FourMessPrepareScan(priv->pScanner); +} +/*----------------------------------------------------------------------------*/ +static hdbCallbackReturn SetScannerCB(pHdb node, void *userData, + pHdbMessage mm) +{ + pHdbDataMessage set = NULL; + pFourMess priv = (pFourMess) userData; + SConnection *pCon = NULL; + pScanData old; + + if ((set = GetHdbSetMessage(mm)) != NULL) { + old = priv->pScanner; + priv->pScanner = + FindCommandData(pServ->pSics, set->v->v.text, "ScanObject"); + if (priv->pScanner == NULL) { + priv->pScanner = old; + pCon = set->callData; + if (pCon != NULL) { + SCWrite(pCon, "ERROR: scan object not found", eError); + } + return hdbAbort; + } + } + return hdbContinue; +} + +/*---------------------------------------------------------------------------*/ +static double getProtonAverage(pFourMess self) +{ + int np, i; + long *lData = NULL, lSum = 0; + + np = GetScanNP(self->pScanner); + lData = (long *) malloc((np + 1) * sizeof(long)); + if (lData == NULL || np == 0) { + return 0.; + } + memset(lData, 0, (np + 1) * sizeof(long)); + GetScanMonitor(self->pScanner, 2, lData, np); + for (i = 0; i < np; i++) { + lSum += lData[i]; + } + free(lData); + return (double) lSum / (double) np; +} + +/*---------------------------------------------------------------------------*/ +static int FourMessStoreIntern(pSICSOBJ self, SConnection * pCon, + double fHkl[3], double fPosition[4], char *extra) +{ + pFourMess priv = self->pPrivate; + float fSum, fSigma, fTemp, fStep, fPreset; + int i, iLF, iRet, iNP, ii; + long *lCounts = NULL; + pEVControl pEva = NULL; + pDummy pPtr = NULL; + pIDrivable pDriv = NULL; + char pBueffel[512], pTime[512], pNum[10]; + double prot; + + if (priv->pScanner == NULL) { + SCWrite(pCon, "ERROR: store: scan not configured", eLogError); + return 0; + } + + if (priv->hklFile == NULL) { + SCWrite(pCon, "ERROR: store: no files open", eLogError); + return 0; + } + + /* get necessary data */ + fSum = 0.; + fSigma = 0.; + iRet = ScanIntegrate(priv->pScanner, &fSum, &fSigma); + if (iRet != 1) { + switch (iRet) { + case INTEGLEFT: + sprintf(pBueffel, + "WARNING: integration failed --> no left side to: %f %f %f", + fHkl[0], fHkl[1], fHkl[2]); + break; + case INTEGRIGHT: + sprintf(pBueffel, + "WARNING: integration failed -->no right side to: %f %f %f", + fHkl[0], fHkl[1], fHkl[2]); + break; + case INTEGNOPEAK: + sprintf(pBueffel, + "WARNING: integration failed -->no peak found: %f %f %f", + fHkl[0], fHkl[1], fHkl[2]); + break; + case INTEGFUNNYBACK: + sprintf(pBueffel, + "WARNING: integration problem, asymmetric background: %f %f %f", + fHkl[0], fHkl[1], fHkl[2]); + break; + } + SCWrite(pCon, pBueffel, eLog); + } + iNP = GetScanNP(priv->pScanner); + lCounts = malloc(iNP * sizeof(long)); + if (lCounts == NULL) { + SCWrite(pCon, "ERROR: out of memory in store", eLogError); + return 0; + } + GetScanCounts(priv->pScanner, lCounts, iNP); + + /* write it */ + if (priv->profFile) { + fprintf(priv->profFile, + "%4d %7.3f %7.3f %7.3f %7.2f %7.2f %7.2f %7.2f %7.0f %7.2f\n", + priv->count, fHkl[0], fHkl[1], fHkl[2], fPosition[0], + fPosition[1], fPosition[2], fPosition[3], fSum, fSigma); + } + if (priv->hklFile) { + fprintf(priv->hklFile, + "%5d %6.2f %6.2f %6.2f %7.2f %7.2f %7.2f %7.2f %7.0f %7.2f\n", + priv->count, fHkl[0], fHkl[1], fHkl[2], fPosition[0], + fPosition[1], fPosition[2], fPosition[3], fSum, fSigma); + } + sprintf(pBueffel, + "%5d %6.2f %6.2f %6.2f %7.2f %7.2f %7.2f %7.2f %7.0f %7.2f\n", + priv->count, fHkl[0], fHkl[1], fHkl[2], fPosition[0], + fPosition[1], fPosition[2], fPosition[3], fSum, fSigma); + SCWrite(pCon, pBueffel, eLog); + + /* get temperature */ + fTemp = -777.77; + pEva = (pEVControl) FindCommandData(pServ->pSics, "temperature", + "Environment Controller"); + if (pEva == NULL) { + pPtr = (pDummy) FindCommandData(pServ->pSics, "temperature", + "RemObject"); + if (pPtr != NULL) { + pDriv = pPtr->pDescriptor->GetInterface(pPtr, DRIVEID); + if (pDriv != NULL) { + fTemp = pDriv->GetValue(pPtr, pCon); + } + } + } else { + iRet = EVCGetPos(pEva, pCon, &fTemp); + } + + /* write profile */ + if (priv->profFile) { + /* collect data */ + SNXFormatTime(pBueffel, 512); + GetScanVarStep(priv->pScanner, 0, &fStep); + fPreset = GetScanPreset(priv->pScanner); + prot = getProtonAverage(priv); + if(extra == NULL){ + fprintf(priv->profFile, "%3d %7.4f %9.0f %7.3f %12f %s\n", iNP, fStep, + fPreset, fTemp, prot, pBueffel); + } else { + fprintf(priv->profFile, "%3d %7.4f %9.0f %7.3f %12f %s %s\n", iNP, fStep, + fPreset, fTemp, prot, extra, pBueffel); + } + for (i = 0; i < iNP; i++) { + for (ii = 0; ii < 10 && i < iNP; ii++) { + fprintf(priv->profFile, " %7ld", lCounts[i]); + iLF = 1; + i++; + } + fprintf(priv->profFile, "\n"); + i--; + iLF = 0; + } + if (iLF) { + fprintf(priv->profFile, "\n"); + } + fflush(priv->profFile); + } + + strcpy(pTime, pBueffel); + sprintf(pBueffel, "%3d%8.4f%10.0f%8.3f %s\n", iNP, fStep, + fPreset, fTemp, pTime); + SCWrite(pCon, pBueffel, eLog); + pBueffel[0] = '\0'; + for (i = 0; i < iNP; i++) { + for (ii = 0; ii < 10 && i < iNP; ii++) { + sprintf(pNum, " %6ld", lCounts[i]); + strcat(pBueffel, pNum); + iLF = 1; + i++; + } + SCWrite(pCon, pBueffel, eLog); + pBueffel[0] = '\0'; + i--; + iLF = 0; + } + if (iLF) { + SCWrite(pCon, pBueffel, eLog); + } + free(lCounts); + return 1; + +} + +/*----------------------------------------------------------------------------*/ +static int FourMessStore(pSICSOBJ self, SConnection * pCon, + pHdb commandNode, pHdb par[], int nPar) +{ + double fHkl[3], fPosition[4]; + int i; + + if (nPar < 7) { + SCWrite(pCon, "ERROR: not enough arguments for store", eError); + return 0; + } + + /* load hkl */ + for (i = 0; i < 3; i++) { + fHkl[i] = par[i]->value.v.doubleValue; + } + + /* load positions */ + for (i = 0; i < 4; i++) { + fPosition[i] = par[i + 3]->value.v.doubleValue; + } + + return FourMessStoreIntern(self, pCon, fHkl, fPosition, NULL); +} + +/*----------------------------------------------------------------------------*/ +static int FourMessStoreExtra(pSICSOBJ self, SConnection * pCon, + pHdb commandNode, pHdb par[], int nPar) +{ + double fHkl[3], fPosition[4]; + int i; + + if (nPar < 8) { + SCWrite(pCon, "ERROR: not enough arguments for storeextra", eError); + return 0; + } + + /* load hkl */ + for (i = 0; i < 3; i++) { + fHkl[i] = par[i]->value.v.doubleValue; + } + + /* load positions */ + for (i = 0; i < 4; i++) { + fPosition[i] = par[i + 3]->value.v.doubleValue; + } + + return FourMessStoreIntern(self, pCon, fHkl, fPosition, par[7]->value.v.text); +} + +/*------------------------------------------------------------------*/ +static int weakScan(pSICSOBJ self, SConnection * pCon) +{ + int i, np; + long low = 99999, high = -99999, *lCounts = NULL; + pFourMess priv = self->pPrivate; + hdbValue v; + + /* + the scan is always OK if we do not test for weak conditions or we are in psd mode + */ + SICSHdbGetPar(self, pCon, "weak", &v); + if (v.v.intValue == 0) { + return 0; + } + + np = GetScanNP(priv->pScanner); + lCounts = malloc(np * sizeof(long)); + if (lCounts == NULL) { + SCWrite(pCon, "ERROR: out of memory in weakScan test", eLogError); + return 0; + } + GetScanCounts(priv->pScanner, lCounts, np); + for (i = 0; i < np; i++) { + if (lCounts[i] < low) { + low = lCounts[i]; + } + if (lCounts[i] > high) { + high = lCounts[i]; + } + } + /* + I am using the weakest point here as a rough estimate of + the background + */ + SICSHdbGetPar(self, pCon, "weakthreshold", &v); + if (high - 2 * low > v.v.intValue) { + return 0; + } else { + return 1; + } +} + +/*----------------------------------------------------------------------------*/ +static int FourMessWeak(pSICSOBJ self, SConnection * pCon, + pHdb commandNode, pHdb par[], int nPar) +{ + int weak; + + weak = weakScan(self, pCon); + SCPrintf(pCon, eLog, "weak = %d", weak); + return 1; +} + +/*---------------------------------------------------------------------------- + * Usage of the suppress flag: + * 0 do notthing + * 1 suppress symmetriqually equivalent reflections + * 2 opposite: add only reflections NOT allowed by the spacegroup + * ---------------------------------------------------------------------------*/ +static int GenIndex(pSICSOBJ self, SConnection * pCon, pHdb commandNode, + pHdb par[], int nPar) +{ + double lambda = SXGetLambda(), d, om, hkl[3]; + int h, k, l, minh, mink, minl, suppress; + hdbValue hkllim, sttlim; + T_SgInfo *sginfo = SXGetSpaceGroup(); + pFourMess priv = self->pPrivate; + int count = 0; + MATRIX B, H, Z1; + const double *cell; + lattice direct; + + if (nPar < 1) { + SCWrite(pCon, "ERROR: need a suppression flag for indgen", eError); + return 0; + } + SICSHdbGetPar(self, pCon, "hkllim", &hkllim); + SICSHdbGetPar(self, pCon, "sttlim", &sttlim); + suppress = par[0]->value.v.intValue; + + minh = hkllim.v.intArray[3]; + mink = hkllim.v.intArray[4]; + minl = hkllim.v.intArray[5]; + + SetListMin_hkl(sginfo, hkllim.v.intArray[1], hkllim.v.intArray[2], + &minh, &mink, &minl); + ClearReflectionList(priv->messList); + 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]; + B = mat_creat(3, 3, UNIT_MATRIX); + if (!calculateBMatrix(direct, B)) { + SCWrite(pCon, "ERROR: invalid cell", eError); + return 0; + } + H = mat_creat(3, 1, ZERO_MATRIX); + + + for (h = hkllim.v.intArray[0]; h <= hkllim.v.intArray[3]; h++) { + for (k = hkllim.v.intArray[1]; k <= hkllim.v.intArray[4]; k++) { + for (l = hkllim.v.intArray[2]; l <= hkllim.v.intArray[5]; l++) { + /* SCPrintf(pCon,eLog, "Testing %d, %d, %d", h,k,l); */ + /* first test: extinct */ + + if(suppress != 2){ + if (IsSysAbsent_hkl(sginfo, h, k, l, NULL) != 0) { + /* SCPrintf(pCon,eLog, "%d, %d, %d rejected for sys absent", h, k, l); */ + continue; + } + } else { + if (!IsSysAbsent_hkl(sginfo, h, k, l, NULL) != 0) { + /* SCPrintf(pCon,eLog, "%d, %d, %d rejected for not sys absent", h, k, l); */ + continue; + } + } + /* second test: a symmetrically equivalent already seen */ + if ((suppress > 0) && IsSuppressed_hkl(sginfo, minh, mink, minl, + hkllim.v.intArray[1], + hkllim.v.intArray[2], h, k, + l) != 0) { + /* SCPrintf(pCon,eLog, "%d, %d, %d rejected for symmetrical eqiv", h, k, l); */ + continue; + } + /* third test: within stt limits */ + H[0][0] = (double) h; + H[1][0] = (double) k; + H[2][0] = (double) l; + Z1 = mat_mul(B, H); + calcTheta(lambda, Z1, &d, &om); + om *= 2.; + mat_free(Z1); + if (om > sttlim.v.floatArray[0] && om < sttlim.v.floatArray[1]) { + hkl[0] = (double) h; + hkl[1] = (double) k; + hkl[2] = (double) l; + AddRefIdx(priv->messList, hkl); + count++; + } + if(SCGetInterrupt(pCon) != eContinue){ + SCWrite(pCon,"ERROR: reflection generation aborted", eError); + return 0; + } + } + } + } + mat_free(B); + mat_free(H); + priv->masterCount = count; + SCPrintf(pCon, eValue, "%d reflections generated", count); + return 1; +} + +/*-----------------------------------------------------------------------------*/ +static int GenInconsumerate(pSICSOBJ self, SConnection * pCon, + pHdb commandNode, pHdb par[], int nPar) +{ + double hkl[3], qvec[3]; + pFourMess priv = self->pPrivate; + int i, j; + + if (nPar < 3) { + SCWrite(pCon, + "ERROR: need q displacement vector with three compononts", + eError); + return 0; + } + qvec[0] = par[0]->value.v.doubleValue; + qvec[1] = par[1]->value.v.doubleValue; + qvec[2] = par[2]->value.v.doubleValue; + + for (i = 0; i < priv->masterCount; i++) { + GetRefIndex(priv->messList, i, hkl); + if(ABS(hkl[0])+ABS(hkl[1])+ABS(hkl[2]) < .3){ + /* + * Stop generation for 0,0,0, + */ + continue; + } + for (j = 0; j < 3; j++) { + hkl[j] += qvec[j]; + } + AddRefIdx(priv->messList, hkl); + GetRefIndex(priv->messList, i, hkl); + for (j = 0; j < 3; j++) { + hkl[j] -= qvec[j]; + } + AddRefIdx(priv->messList, hkl); + if(SCGetInterrupt(pCon) != eContinue){ + SCWrite(pCon,"ERROR: generating incommensurate reflections aborted", eError); + return 0; + } + } + SCPrintf(pCon, eValue, + "%d additional inconsumerate reflections generated", + priv->masterCount*2); + return 1; +} + +/*----------------------------------------------------------------------------*/ +static int hklCompare(const void *h1, const void *h2) +{ + const double *hkl1 = h1, *hkl2 = h2; + + if (hkl1[3] < hkl2[3]) { + return -1; + } else if (hkl1[3] == hkl2[3]) { + return 0; + } else { + return 1; + } +} + +/*---------------------------------------------------------------------------- + * This sorts on two theta only. + -----------------------------------------------------------------------------*/ +static int SortRef(pSICSOBJ self, SConnection * pCon, pHdb commandNode, + pHdb par[], int nPar) +{ + double *sortlist, d, lambda, om, hkl[4], ang[4]; + const double *cell; + double *hklc; + int nRefl, i, j; + MATRIX B, H, Z1; + lattice direct; + pFourMess priv = self->pPrivate; + + lambda = SXGetLambda(); + 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]; + B = mat_creat(3, 3, UNIT_MATRIX); + if (!calculateBMatrix(direct, B)) { + SCWrite(pCon, "ERROR: invalid cell", eError); + return 0; + } + H = mat_creat(3, 1, ZERO_MATRIX); + + nRefl = ReflectionListCount(priv->messList); + sortlist = malloc(nRefl * 4 * sizeof(double)); + if (sortlist == NULL) { + SCWrite(pCon, "ERROR: out of memory in SortRef", eError); + return 0; + } + /* + * I am using hkl[3] for storing the theta value to sort for! */ + for (i = 0; i < nRefl; i++) { + GetRefIndex(priv->messList, i, hkl); + for (j = 0; j < 3; j++) { + H[j][0] = hkl[j]; + } + Z1 = mat_mul(B, H); + calcTheta(lambda, Z1, &d, &om); + mat_free(Z1); + hkl[3] = om; + memcpy(sortlist + i * 4, hkl, 4 * sizeof(double)); + } + + qsort(sortlist, nRefl, 4 * sizeof(double), hklCompare); + + ClearReflectionList(priv->messList); + for (i = 0; i < nRefl; i++) { + ang[1] = sortlist[i * 4 + 3]; + ang[0] = 2. * ang[1]; + ang[2] = .0; + ang[3] = .0; + /* AddRefIdxAng(priv->messList, sortlist+i*4,ang); */ + AddRefIdx(priv->messList, sortlist + i * 4); + } + free(sortlist); + mat_free(B); + mat_free(H); + SCSendOK(pCon); + return 1; +} +/*---------------------------------------------------------------------------- + * Sorting reflection is actually a variant of the traveling salesman + * problem. Optimal solutions for this are computationally expensive. + * Optimise for the shortest path between reflections. Not all motors + * are equal though. Om and phi move quick whereas stt and chi go slow. + * As a compromise, what I try here is sorting by a weighted addition of + * stt and chi. + ----------------------------------------------------------------------------*/ +static int SortRefNew(pSICSOBJ self, SConnection * pCon, pHdb commandNode, + pHdb par[], int nPar) +{ + double *sortlist, d, lambda, om, hkl[4], ang[5]; + const double *cell; + double *hklc; + int nRefl, i, j, status, count; + SingleXModes mode; + pFourMess priv = self->pPrivate; + pSingleDiff diffi = NULL; + + diffi = SXGetDiffractometer(); + mode = SXGetMode(); + if(diffi == NULL){ + SCWrite(pCon,"ERROR: not initialized, no diffractometer", eError); + return 0; + } + + nRefl = ReflectionListCount(priv->messList); + sortlist = malloc(nRefl * 4 * sizeof(double)); + if (sortlist == NULL) { + SCWrite(pCon, "ERROR: out of memory in SortRef", eError); + return 0; + } + + /* + * I am using hkl[3] for storing the sort value to sort for! */ + for (i = 0, count = 0; i < nRefl; i++) { + GetRefIndex(priv->messList, i, hkl); + status = diffi->calculateSettings(diffi,hkl,ang); + if(status == 1){ + if(mode == Bisecting){ + hkl[3] = ang[0] + 0.5* ang[2]; + if(ang[2] < 0){ + SCWrite(pCon,"WARNING: chi < 0!", eWarning); + } + } else if(mode == NB){ + /* + * sort for nu in the first place. In order to cope with negativity, add + * 10. + */ + hkl[3] = ang[2]+10 + 0.1 * ang[0]; + } else if(mode == BiNB){ + /* + * sort for nu in the first place. In order to cope with negativity, add + * 10. + */ + hkl[3] = ang[4]+10 + 0.1 * ang[0]; + } else { + hkl[3] = ang[0]; + } + memcpy(sortlist + count * 4, hkl, 4 * sizeof(double)); + count++; + } + } + + qsort(sortlist, count, 4 * sizeof(double), hklCompare); + + ClearReflectionList(priv->messList); + for (i = 0; i < count; i++) { + hklc = sortlist+i*4; + hklc[3] = .0; /* otherwise this will be interpreted as psi! */ + status = diffi->calculateSettings(diffi,hklc,ang); + AddRefIdxAng(priv->messList, sortlist+i*4,ang); + /* AddRefIdx(priv->messList, sortlist + i * 4); */ + } + free(sortlist); + SCSendOK(pCon); + return 1; +} +/*---------------------------------------------------------------------------- + * Write a reflection list in the TSPLIB format for running a traveling + * salesman algorithm against it. +----------------------------------------------------------------------------- */ +static int WriteTSP(pSICSOBJ self, SConnection * pCon, pHdb commandNode, + pHdb par[], int nPar) +{ + double hkl[4], ang[4]; + int nRefl, i, j, status, count; + SingleXModes mode; + pFourMess priv = self->pPrivate; + pSingleDiff diffi = NULL; + FILE *fd = NULL; + + if(nPar < 1) { + SCWrite(pCon,"ERROR: need a filename parameter", eError); + return 0; + } + fd = fopen(trim(par[0]->value.v.text),"w"); + if(fd == NULL){ + SCPrintf(pCon,eError,"ERROR: failed to open %s for writing", par[0]->value.v.text); + return 0; + } + + diffi = SXGetDiffractometer(); + mode = SXGetMode(); + if(diffi == NULL){ + SCWrite(pCon,"ERROR: not initialized, no diffractometer", eError); + return 0; + } + + nRefl = ReflectionListCount(priv->messList); + /* + * smear header... + */ + fprintf(fd,"NAME : %s\n", par[0]->value.v.text); + fprintf(fd,"TYPE : TSP\n"); + fprintf(fd,"DIMENSION : %d\n", nRefl); + fprintf(fd,"EDGE_WEIGHT_TYPE : EUC_3D\n"); + fprintf(fd,"NODE_COORD_SECTION\n"); + + + for (i = 0, count = 0; i < nRefl; i++) { + GetRefIndex(priv->messList, i, hkl); + status = diffi->calculateSettings(diffi,hkl,ang); + if(status == 1){ + if(mode == Bisecting){ + fprintf(fd,"%d %e %e %e\n",i+1,ang[0]*3*100,ang[2]*2*100,ang[3]*100); + } else if(mode == NB){ + fprintf(fd,"%d %e %e %e\n",i,ang[2]*4*100,ang[0]*3*100,ang[1]*100); + } else { + fprintf(fd,"%d %e %e %e\n",i,ang[0]*3*100,ang[2]*2*100,ang[3]*2*100); + } + } + } + fclose(fd); + + SCSendOK(pCon); + return 1; +} +/*---------------------------------------------------------------------------- + * read a tour file as generated by LKH or other TSP solvers and + * reorder the reflection list accordingly. + -----------------------------------------------------------------------------*/ +static int ReadTour(pSICSOBJ self, SConnection * pCon, pHdb commandNode, + pHdb par[], int nPar) +{ + FILE *fd = NULL; + char buffer[132]; + double hkl[4], ang[5]; + int idx, tour; + pFourMess priv = self->pPrivate; + pSingleDiff diffi = NULL; + + + if(nPar < 1) { + SCWrite(pCon,"ERROR: need name of a tour file to read", eError); + return 0; + } + fd = fopen(par[0]->value.v.text,"r"); + if(fd == NULL){ + SCPrintf(pCon,eError,"ERROR: failed to open tour file %s for reading", + par[0]->value.v.text); + return 0; + } + tour = LLDcreate(sizeof(hkl)); + diffi = SXGetDiffractometer(); + assert(diffi != NULL); + + /* skip header */ + while(fgets(buffer,sizeof(buffer),fd) != NULL){ + if(strstr(buffer,"TOUR_SECTION") != NULL){ + break; + } + } + while(fscanf(fd,"%d",&idx) == 1){ + if(idx < 0){ + break; + } + GetRefIndex(priv->messList,idx-1,hkl); + LLDnodeAppendFrom(tour,hkl); + } + fclose(fd); + + idx = LLDnodePtr2First(tour); + ClearReflectionList(priv->messList); + while(idx == 1){ + LLDnodeDataTo(tour,hkl); + hkl[3] = 0; + diffi->calculateSettings(diffi,hkl,ang); + AddRefIdxAng(priv->messList, hkl,ang); + idx = LLDnodePtr2Next(tour); + } + LLDdelete(tour); + SCSendOK(pCon); + return 1; +} +/*----------------------------------------------------------------------------*/ +static int FourMessSave(void *data, char *name, FILE * fd) +{ + pSICSOBJ self = data; + pFourMess priv = self->pPrivate; + + SaveSICSOBJ(data, name, fd); + priv->stepTable->pDes->SaveStatus(priv->stepTable,"fmess table", fd); + return 1; +} + +/*----------------------------------------------------------------------------*/ +void InstallFourMess(SConnection * pCon, SicsInterp * pSics) +{ + pFourMess priv = NULL; + pSICSOBJ pNew = NULL; + pHdb cmd = NULL; + int hkl[] = { -10, -10, 10, 10, 10, 10 }; + double sttlim[] = { 5.0, 180 }; + + pNew = MakeSICSOBJ("fmess", "FourMess"); + priv = calloc(1, sizeof(FourMess)); + if (pNew == NULL || priv == NULL) { + SCWrite(pCon, "ERROR: out of memory creating fourmess", eError); + } + pNew->pDes->SaveStatus = FourMessSave; + pNew->pPrivate = priv; + pNew->KillPrivate = KillFourMess; + + priv->stepTable = MakeFourCircleTable(); + AddCommand(pSics, "fmesstable", InterInvokeSICSOBJ, NULL, priv->stepTable); + + priv->messList = CreateReflectionList(pCon, pSics, "messref"); + if (priv->stepTable < 0 || priv->messList == NULL) { + SCWrite(pCon, "ERROR: out of memory creating fourmess", eError); + } + + cmd = AddSICSHdbPar(pNew->objectNode, "weak", usUser, MakeHdbInt(0)); + SetHdbProperty(cmd, "__save", "true"); + cmd = AddSICSHdbPar(pNew->objectNode, "weakthreshold", usUser, + MakeHdbInt(20)); + SetHdbProperty(cmd, "__save", "true"); + + cmd = AddSICSHdbPar(pNew->objectNode, "fast", usUser, MakeHdbInt(0)); + SetHdbProperty(cmd, "__save", "true"); + + cmd = + AddSICSHdbPar(pNew->objectNode, "mode", usUser, + MakeHdbText("Monitor")); + + cmd = + AddSICSHdbPar(pNew->objectNode, "hkllim", usUser, + MakeHdbIntArray(6, hkl)); + SetHdbProperty(cmd, "__save", "true"); + cmd = + AddSICSHdbPar(pNew->objectNode, "sttlim", usUser, + MakeHdbFloatArray(2, sttlim)); + SetHdbProperty(cmd, "__save", "true"); + + cmd = + AddSICSHdbPar(pNew->objectNode, "start", usUser, + MakeSICSFunc(FourMessStart)); + cmd = AddSICSHdbPar(cmd, "filename", usUser, MakeHdbText("Unknown")); + cmd = + AddSICSHdbPar(pNew->objectNode, "close", usUser, + MakeSICSFunc(FourMessClose)); + cmd = + AddSICSHdbPar(pNew->objectNode, "reopen", usUser, + MakeSICSFunc(FourMessReopen)); + + cmd = + AddSICSHdbPar(pNew->objectNode, "prepare", usUser, + MakeSICSFunc(FourMessPrepareCmd)); + + cmd = + AddSICSHdbPar(pNew->objectNode, "scanpar", usUser, + MakeSICSFunc(FourMessScanPar)); + cmd = AddSICSHdbPar(cmd, "twotheta", usUser, MakeHdbFloat(.0)); + + cmd = + AddSICSHdbPar(pNew->objectNode, "store", usUser, + MakeSICSFunc(FourMessStore)); + AddSICSHdbPar(cmd, "h", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "k", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "l", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "stt", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "om", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "chi", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "phi", usUser, MakeHdbFloat(.0)); + + cmd = + AddSICSHdbPar(pNew->objectNode, "storeextra", usUser, + MakeSICSFunc(FourMessStoreExtra)); + AddSICSHdbPar(cmd, "h", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "k", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "l", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "stt", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "om", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "chi", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "phi", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "extra", usUser, MakeHdbText("")); + + cmd = + AddSICSHdbPar(pNew->objectNode, "weak", usUser, + MakeSICSFunc(FourMessWeak)); + + cmd = + AddSICSHdbPar(pNew->objectNode, "indgen", usUser, + MakeSICSFunc(GenIndex)); + AddSICSHdbPar(cmd, "sup", usUser, MakeHdbInt(1)); + + cmd = + AddSICSHdbPar(pNew->objectNode, "genw", usUser, + MakeSICSFunc(GenInconsumerate)); + AddSICSHdbPar(cmd, "hw", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "kw", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "lw", usUser, MakeHdbFloat(.0)); + + cmd = + AddSICSHdbPar(pNew->objectNode, "indsort", usUser, + MakeSICSFunc(SortRef)); + cmd = + AddSICSHdbPar(pNew->objectNode, "writetsp", usUser, + MakeSICSFunc(WriteTSP)); + AddSICSHdbPar(cmd, "filename", usUser, MakeHdbText("Unknown")); + + cmd = + AddSICSHdbPar(pNew->objectNode, "readtour", usUser, + MakeSICSFunc(ReadTour)); + AddSICSHdbPar(cmd, "filename", usUser, MakeHdbText("Unknown")); + + cmd = + AddSICSHdbPar(pNew->objectNode, "template", usMugger, + MakeHdbText("Unknown")); + cmd = + AddSICSHdbPar(pNew->objectNode, "scanobj", usMugger, + MakeHdbText("xxxscan")); + PrependHipadabaCallback(cmd, + MakeHipadabaCallback(SetScannerCB, priv, NULL)); + + priv->pScanner = FindCommandData(pSics, "xxxscan", "ScanObject"); + /* AddHipadabaChild(pNew->objectNode, priv->stepTable->objectNode,pCon); */ + + AddCommand(pSics, "fmess", FourMessAction, KillSICSOBJ, pNew); +} diff --git a/fourmess.h b/fourmess.h new file mode 100644 index 00000000..357cbc17 --- /dev/null +++ b/fourmess.h @@ -0,0 +1,24 @@ +/** + * This is a new version of the four circle reflection measurement module. Its task is + * to provide functionality required for measuring a list of reflections. This is done + * with the help of some scripts bind things together. This module provides: + * - a table of scan parameters for measuring reflections at different angles. + * - the functions required to produce the scan data files for single detector + * mode. + * - a list of reflections to measure. + * + * In contrast to the old mesure module, this module is more flexible and + * allows for reflection list processing in all modes and for all detectors. + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, July 2008 + */ + +#ifndef _FOURMESS +#define _FOURMESS +#include + +void InstallFourMess(SConnection * pCon, SicsInterp * pSics); + +#endif diff --git a/fourtable.c b/fourtable.c index 38941613..4236e5b5 100644 --- a/fourtable.c +++ b/fourtable.c @@ -6,309 +6,195 @@ copyright: see copyright.h Mark Koennecke, February 2005 + + Massively reworked to make use of the new hdbtable object. + + Mark Koennecke, March 2009 ---------------------------------------------------------------------------*/ #include #include #include "sics.h" -#include "fortify.h" -#include "lld.h" -#include -#include "splitter.h" +#include "hdbtable.h" +#include #include "fourtable.h" -/*====================== table entry ===================================*/ -typedef struct { - double twoThetaEnd; - char scanVar[30]; - double step; - int np; - float preset; -}FourTableEntry, *pFourTableEntry; /*==================== functions =======================================*/ -int MakeFourCircleTable(){ - return LLDcreate(sizeof(FourTableEntry)); +pSICSOBJ MakeFourCircleTable() +{ + pSICSOBJ table = NULL; + pHdb node = NULL; + + table = MakeHdbTable("fmesstable","FourMess"); + node = GetHipadabaNode(table->objectNode,"template"); + assert(node != NULL); + AddSICSHdbPar(node, "endTTH", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(node, "scanvar", usUser, MakeHdbText("")); + AddSICSHdbPar(node, "step", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(node, "np", usUser, MakeHdbInt(0)); + AddSICSHdbPar(node, "preset", usUser, MakeHdbFloat(.0)); + ReadTableTemplate(table, NULL); + return table; } /*-----------------------------------------------------------------------*/ -void DeleteFourCircleTable(int handle){ - LLDdelete(handle); -} -/*------------------------------------------------------------------------*/ -static void printList(int handle, SConnection *pCon){ - FourTableEntry entry; - char pBueffel[132]; - int status, printed = 0; - Tcl_DString list; - - Tcl_DStringInit(&list); - status = LLDnodePtr2First(handle); - while(status == 1) { - LLDnodeDataTo(handle,&entry); - snprintf(pBueffel,131,"%8.3f %10s %8.3f %d %8.3f\n", entry.twoThetaEnd, - entry.scanVar,entry.step, entry.np,entry.preset); - Tcl_DStringAppend(&list,pBueffel,-1); - printed = 1; - status = LLDnodePtr2Next(handle); - } - if(printed == 0){ - Tcl_DStringAppend(&list,"table is empty",-1); - } - SCWrite(pCon,Tcl_DStringValue(&list), eValue); - Tcl_DStringFree(&list); +void DeleteFourCircleTable(pSICSOBJ data) +{ + KillSICSOBJ(data); } /*--------------------------------------------------------------------- Make sure that the entry is added in a sorted way according to two_theta - ----------------------------------------------------------------------*/ -static void insertEntry(int list, FourTableEntry newEntry){ - int status, count = 0, pos; - FourTableEntry test; - - /* - locate the last entry bigger then us - */ - status = LLDnodePtr2First(list); - while(status == 1){ - LLDnodeDataTo(list,&test); - count++; - if(test.twoThetaEnd == newEntry.twoThetaEnd){ - LLDnodeDataFrom(list,&newEntry); - return; - } - if(test.twoThetaEnd > newEntry.twoThetaEnd){ - break; - } - status = LLDnodePtr2Next(list); - } - /* - special case: empty list - */ - if(count == 0){ - LLDnodeAppendFrom(list,&newEntry); - return; - } - /* - special case: append after last - */ - LLDnodePtr2Last(list); - LLDnodeDataTo(list,&test); - if(newEntry.twoThetaEnd > test.twoThetaEnd){ - LLDnodeAppendFrom(list,&newEntry); - return; - } - - status = LLDnodePtr2First(list); - pos = 0; - while(status == 1){ - LLDnodeDataTo(list,&test); - pos++; - if(pos == count){ - LLDnodeInsertFrom(list,&newEntry); - return; - } - status = LLDnodePtr2Next(list); - } +----------------------------------------------------------------------*/ +static int rowCompare(const void *r1, const void *r2) +{ + pHdb *row1, *row2; + pHdb tth1, tth2; + + row1 = (pHdb *)r1; + row2 = (pHdb *)r2; + tth1 = GetHipadabaNode(*row1,"endTTH"); + tth2 = GetHipadabaNode(*row2,"endTTH"); + assert(tth1 != NULL && tth2 != NULL); + if(tth1->value.v.doubleValue < tth2->value.v.doubleValue){ + return -1; + } else if(tth1->value.v.doubleValue > tth2->value.v.doubleValue){ + return 1; + } else { + return 0; + } } -/*-----------------------------------------------------------------------*/ -static int addToList(int handle, SConnection *pCon, int argc, char *argv[]){ - FourTableEntry entry; - char pBueffel[132]; - - if(argc < 7){ - SCWrite(pCon,"ERROR: not enough arguments to table add",eError); - return 0; - } - - if(isNumeric(argv[3])){ - entry.twoThetaEnd = atof(argv[3]); - } else { - snprintf(pBueffel,131,"ERROR: expected numeric argument, received %s", argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - strncpy(entry.scanVar,argv[4],29); - strtolower(entry.scanVar); - if(strcmp(entry.scanVar,"om") != 0 && strcmp(entry.scanVar,"o2t") != 0){ - SCWrite(pCon,"ERROR: Invalied scan variable specified, only om, o2t allowed",eError); - return 0; - } - if(isNumeric(argv[5])){ - entry.step = atof(argv[5]); - } else { - snprintf(pBueffel,131,"ERROR: expected numeric argument, received %s", argv[4]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - if(isNumeric(argv[6])){ - entry.np = atoi(argv[6]); - } else { - snprintf(pBueffel,131,"ERROR: expected numeric argument, received %s", argv[6]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - entry.preset = -1.0; - if(argc > 7){ - if(isNumeric(argv[7])){ - entry.preset = atof(argv[7]); - } - } - insertEntry(handle,entry); - return 1; -} -/*-----------------------------------------------------------------------*/ -static void delEntry(int handle, int index){ - int count = 0, status; - - status = LLDnodePtr2First(handle); - while(status == 1) { - if(count == index){ - LLDnodeDelete(handle); - break; - } else { - count++; - status = LLDnodePtr2Next(handle); - } - } +/*--------------------------------------------------------------------*/ +static void sortFourTable(pSICSOBJ self) +{ + pHdb data, *dataArray, child; + int count, i; + char number[10]; + + data = GetHipadabaNode(self->objectNode,"data"); + assert(data != NULL); + count = CountHdbChildren(data); + if(count <= 1){ + return; + } + + dataArray = malloc(count*sizeof(pHdb)); + if(dataArray == NULL){ + return; + } + child = data->child; + count = 0; + while(child != NULL){ + dataArray[count] = child; + count++; + child = child->next; + } + + qsort(dataArray, count, sizeof(pHdb), rowCompare); + + data->child = NULL; + for(i = 0; i < count; i++){ + snprintf(number,10,"%4.4d", i); + child = dataArray[i]; + if(child->name != NULL){ + free(child->name); + } + child->name = strdup(number); + AddHipadabaChild(data,child, NULL); + } + free(dataArray); } /*------------------------------------------------------------------------*/ -int HandleFourCircleCommands(int *table, SConnection *pCon, - int argc, char *argv[], int *err){ - int handle; - - *err = 1; - handle = *table; - - /* - test if this is for us - */ - if(argc >= 3){ +int HandleFourCircleCommands(pSICSOBJ self, SConnection * pCon, + int argc, char *argv[], int *err) +{ + int status; + /* + test if this is for us + */ + if (argc >= 3) { strtolower(argv[1]); - if(strcmp(argv[1],"table") != 0){ + if (strcmp(argv[1], "table") != 0) { return 0; } } else { return 0; } - /* - what are we supposed to do? - */ - strtolower(argv[2]); - if(strcmp(argv[2],"clear") == 0){ - if(!SCMatchRights(pCon,usUser)){ - *err = 0; - return 1; - } - LLDdelete(handle); - handle = LLDcreate(sizeof(FourTableEntry)); - *table = handle; - SCparChange(pCon); - SCSendOK(pCon); - } else if (strcmp(argv[2],"list") == 0){ - printList(handle,pCon); - } else if(strcmp(argv[2],"add") == 0){ - if(!SCMatchRights(pCon,usUser)){ - *err = 0; - return 1; - } - *err = addToList(handle,pCon,argc,argv); - if(*err != 0) - { - SCparChange(pCon); - SCSendOK(pCon); - } - } else if(strcmp(argv[2],"del") == 0){ - if(!SCMatchRights(pCon,usUser)){ - *err = 0; - return 1; - } - if(argc < 4){ - SCWrite(pCon,"ERROR: insufficnet number of arguments to table del",eError); - *err = 0; - } else { - if(isNumeric(argv[3])){ - delEntry(handle, atoi(argv[3])); - SCparChange(pCon); - SCSendOK(pCon); - } else { - SCWrite(pCon,"ERROR: bad argument: expected numeric argument to table del",eError); - *err = 0; - } - } - } else { - SCWrite(pCon,"ERROR: subcommand to table not known",eError); - *err = 0; + status = InvokeSICSOBJ(pCon,pServ->pSics,self,argc-1,&argv[1]); + if(strcmp(argv[2],"addrow") == 0){ + sortFourTable(self); } - - return 1; + return status; } /*-----------------------------------------------------------------------*/ -static FourTableEntry findEntry(int handle, double two_theta){ - int status; - FourTableEntry entry; - - status = LLDnodePtr2First(handle); - while(status == 1) { - LLDnodeDataTo(handle,&entry); - if(entry.twoThetaEnd > two_theta){ - return entry; - } - status = LLDnodePtr2Next(handle); - } - strcpy(entry.scanVar,"NOT FOUND"); - return entry; +static pHdb findEntry(pSICSOBJ self, double two_theta) +{ + pHdb data, row, tth; + + data = GetHipadabaNode(self->objectNode,"data"); + assert(data != NULL); + row = data->child; + while(row != NULL){ + tth = GetHipadabaNode(row,"endTTH"); + if(tth != NULL){ + if(tth->value.v.doubleValue > two_theta){ + return row; + } + } + row = row->next; + } + return NULL; } /*------------------------------------------------------------------------*/ -char *GetFourCircleScanVar(int handle, double two_theta){ - FourTableEntry entry; - - entry = findEntry(handle,two_theta); - return strdup(entry.scanVar); +char *GetFourCircleScanVar(pSICSOBJ handle, double two_theta) +{ + pHdb row, val; + + row = findEntry(handle, two_theta); + if(row != NULL){ + val = GetHipadabaNode(row,"scanvar"); + if(val != NULL){ + return strdup(val->value.v.text); + } + } + return strdup("Not found"); } /*------------------------------------------------------------------------*/ -double GetFourCircleStep(int handle, double two_theta){ - FourTableEntry entry; - - entry = findEntry(handle,two_theta); - if(strcmp(entry.scanVar,"NOT FOUND") == 0){ - return -999.99; - } else { - return entry.step; - } +double GetFourCircleStep(pSICSOBJ handle, double two_theta) +{ + pHdb row, val; + + row = findEntry(handle, two_theta); + if(row != NULL){ + val = GetHipadabaNode(row,"step"); + if(val != NULL){ + return val->value.v.doubleValue; + } + } + return -999.99; } /*------------------------------------------------------------------------*/ -float GetFourCirclePreset(int handle, double two_theta){ - FourTableEntry entry; - - entry = findEntry(handle,two_theta); - if(strcmp(entry.scanVar,"NOT FOUND") == 0){ - return -999.99; - } else { - return entry.preset; - } +float GetFourCirclePreset(pSICSOBJ handle, double two_theta) +{ + pHdb row, val; + + row = findEntry(handle, two_theta); + if(row != NULL){ + val = GetHipadabaNode(row,"preset"); + if(val != NULL){ + return val->value.v.doubleValue; + } + } + return -999.99; } /*------------------------------------------------------------------------*/ -int GetFourCircleScanNP(int handle, double two_theta){ - FourTableEntry entry; - - entry = findEntry(handle,two_theta); - if(strcmp(entry.scanVar,"NOT FOUND") == 0){ - return -999; - } else { - return entry.np; - } +int GetFourCircleScanNP(pSICSOBJ handle, double two_theta) +{ + pHdb row, val; + + row = findEntry(handle, two_theta); + if(row != NULL){ + val = GetHipadabaNode(row,"np"); + if(val != NULL){ + return val->value.v.intValue; + } + } + return 1; } -/*------------------------------------------------------------------------*/ -int SaveFourCircleTable(int handle, char *objName, FILE *fd){ - FourTableEntry entry; - int status; - - fprintf(fd,"%s table clear\n",objName); - status = LLDnodePtr2Last(handle); - while(status != 0) { - LLDnodeDataTo(handle,&entry); - fprintf(fd,"%s table add %f %s %f %d %f\n",objName, - entry.twoThetaEnd,entry.scanVar, - entry.step,entry.np,entry.preset); - status = LLDnodePtr2Prev(handle); - } - return 1; -} - diff --git a/fourtable.h b/fourtable.h index 0348975d..35a02f43 100644 --- a/fourtable.h +++ b/fourtable.h @@ -10,15 +10,15 @@ ---------------------------------------------------------------------------*/ #ifndef FOURTABLE #define FOURTABLE +#include - int MakeFourCircleTable(); - void DeleteFourCircleTable(int handle); - int HandleFourCircleCommands(int *handle, SConnection *pCon, - int argc, char *argv[], int *err); - char *GetFourCircleScanVar(int handle, double two_theta); - double GetFourCircleStep(int handle, double two_theta); - int SaveFourCircleTable(int handle, char *objName, FILE *fd); - float GetFourCirclePreset(int handle, double twoTheta); - int GetFourCircleScanNP(int handle, double twoTheta); +pSICSOBJ MakeFourCircleTable(); +void DeleteFourCircleTable(pSICSOBJ self); +int HandleFourCircleCommands(pSICSOBJ self, SConnection * pCon, + int argc, char *argv[], int *err); +char *GetFourCircleScanVar(pSICSOBJ self, double two_theta); +double GetFourCircleStep(pSICSOBJ self, double two_theta); +float GetFourCirclePreset(pSICSOBJ self, double twoTheta); +int GetFourCircleScanNP(pSICSOBJ self, double twoTheta); #endif diff --git a/frame.c b/frame.c index 20ef7293..bef62cba 100644 --- a/frame.c +++ b/frame.c @@ -19,224 +19,261 @@ #include "HistMem.h" #include "HistMem.i" #include "HistDriv.i" -#include "hardsup/sinqhm.h" -#include "sinqhmdriv.i" +#include "psi/hardsup/sinqhm.h" +#include "psi/sinqhmdriv.i" #include "nxdict.h" #include "frame.h" + +extern int isSINQHTTP(pHistDriver self); /*======================================================================*/ -static int readHMFrame(SConnection *pCon, pHistMem pHM, int nFrame){ - HistInt *buffer = NULL; +static int readHMFrame(SConnection * pCon, pHistMem pHM, + int nFrame, int sansflag) +{ + HistInt *buffer = NULL, *subbuf = NULL; int iDim[MAXDIM], rank, length, status, i, noTimeBins; pSINQHM pHist; SinqHMDriv *pTata; const float *timeBin; - + char histCommand[132]; + /* - find dimensions and allocate data - */ - GetHistDim(pHM,iDim,&rank); - timeBin = GetHistTimeBin(pHM,&noTimeBins); + find dimensions and allocate data + */ + GetHistDim(pHM, iDim, &rank); + timeBin = GetHistTimeBin(pHM, &noTimeBins); - if(rank < 2){ - SCWrite(pCon,"ERROR: no PSD data present, cannot send frame",eError); + if (rank < 2) { + SCWrite(pCon, "ERROR: no PSD data present, cannot send frame", eError); return 0; } - length = iDim[0]*iDim[1]; - buffer = (HistInt *)malloc((length + 2)*sizeof(HistInt)); - if(!buffer){ - SCWrite(pCon,"ERROR: out of memory in readHMFrame",eError); + length = iDim[0] * iDim[1]; + buffer = (HistInt *) malloc((length + 2) * sizeof(HistInt)); + if (!buffer) { + SCWrite(pCon, "ERROR: out of memory in readHMFrame", eError); return 0; } - memset(buffer,0,(length+2)*sizeof(HistInt)); + memset(buffer, 0, (length + 2) * sizeof(HistInt)); /* - first two values are dimensions - */ + first two values are dimensions + */ buffer[0] = htonl(iDim[0]); buffer[1] = htonl(iDim[1]); - if(isSINQHMDriv(pHM->pDriv) && noTimeBins > 2) { + if (nFrame < 0) { + nFrame = 0; + } + if (nFrame >= noTimeBins) { + nFrame = noTimeBins - 1; + } + if (isSINQHMDriv(pHM->pDriv) && noTimeBins > 2) { /* - read from HM. The 5 is PROJECT__FRAME in Sinqhm_def.h - Again: be friendly: fix out of range frames - */ - if(nFrame < 0){ - nFrame = 0; - } - if(nFrame >= noTimeBins){ - nFrame = noTimeBins-1; - } - pTata = (SinqHMDriv *)pHM->pDriv->pPriv; - pHist = (pSINQHM)pTata->pMaster; + read from HM. The 5 is PROJECT__FRAME in Sinqhm_def.h + Again: be friendly: fix out of range frames + */ + pTata = (SinqHMDriv *) pHM->pDriv->pPriv; + pHist = (pSINQHM) pTata->pMaster; status = SINQHMProject(pHist, 0x0005, 0, nFrame, - 0, iDim[1], buffer+2,length*sizeof(HistInt)); - if(status != 1){ - SCWrite(pCon,"ERROR: SINQHM refused to deliver frame",eError); + 0, iDim[1], buffer + 2, + length * sizeof(HistInt)); + if (status != 1) { + SCWrite(pCon, "ERROR: SINQHM refused to deliver frame", eError); free(buffer); return 0; } + } else if(isSINQHTTP(pHM->pDriv) && noTimeBins > 2){ + if(sansflag){ + snprintf(histCommand,132,"sample:0:%d:%d:%d", iDim[0]*iDim[1], nFrame, nFrame+1); + } else { + snprintf(histCommand,132,"sample:0:%d:0:%d:%d:%d", iDim[0], iDim[1], nFrame, nFrame+1); + } + if(pHM->pDriv->SubSample != NULL){ + subbuf = pHM->pDriv->SubSample(pHM->pDriv, pCon,0,histCommand); + if(subbuf == NULL){ + SCWrite(pCon,"ERROR: subsampling failed ", eError); + return 0; + } + memcpy(buffer+2,subbuf, length *sizeof(HistInt)); + free(subbuf); + } } else { /* - be friendly, just read the 2D data which is there - */ - status = GetHistogram(pHM,pCon,0,0,length,buffer+2,length*sizeof(HistInt)); - if(!status){ + be friendly, just read the 2D data which is there + */ + status = + GetHistogram(pHM, pCon, 0, 0, length, buffer + 2, + length * sizeof(HistInt)); + if (!status) { free(buffer); return status; } } /* - enforce network byte order - */ - for(i = 0; i < length; i++){ - buffer[i+2] = htonl(buffer[i+2]); + enforce network byte order + */ + for (i = 0; i < length; i++) { + buffer[i + 2] = htonl(buffer[i + 2]); } - SCWriteUUencoded(pCon,"framedata", buffer,(length+2)*sizeof(HistInt)); + SCWriteUUencoded(pCon, "framedata", buffer, + (length + 2) * sizeof(HistInt)); free(buffer); return 1; } + /*=======================================================================*/ -static int readFileFrame(SConnection *pCon, - char *file, char *dictFile, - char *alias, int nFrame){ +static int readFileFrame(SConnection * pCon, + char *file, char *dictFile, + char *alias, int nFrame) +{ int status, iDim[NX_MAXRANK], rank = 0, type = 0; int iStart[3], iSize[3], length, i; int *buffer = NULL; NXhandle fileHandle; - NXdict dictHandle; + NXdict dictHandle; char error[512]; - status = NXopen(file,NXACC_READ,&fileHandle); - if(status != NX_OK){ - sprintf(error,"ERROR: failed to open %s", file); - SCWrite(pCon,error,eError); + status = NXopen(file, NXACC_READ, &fileHandle); + if (status != NX_OK) { + snprintf(error,sizeof(error)-1, "ERROR: failed to open %s", file); + SCWrite(pCon, error, eError); return 0; } status = NXDinitfromfile(dictFile, &dictHandle); - if(status != NX_OK){ - sprintf(error,"ERROR: failed to open dictionary %s", dictFile); + if (status != NX_OK) { + snprintf(error,sizeof(error)-1, "ERROR: failed to open dictionary %s", dictFile); NXclose(&fileHandle); - SCWrite(pCon,error,eError); + SCWrite(pCon, error, eError); return 0; } - - status = NXDopenalias(fileHandle,dictHandle,alias); - if(status != NX_OK){ - sprintf(error,"ERROR: failed to open alias %s", alias); + + status = NXDopenalias(fileHandle, dictHandle, alias); + if (status != NX_OK) { + snprintf(error,sizeof(error)-1, "ERROR: failed to open alias %s", alias); NXclose(&fileHandle); - NXDclose(dictHandle,NULL); - SCWrite(pCon,error,eError); + NXDclose(dictHandle, NULL); + SCWrite(pCon, error, eError); return 0; } - - status = NXgetinfo(fileHandle,&rank,iDim,&type); - if(type != NX_INT32 && type != NX_UINT32)type = -1; - if(status != NX_OK || rank < 2 || type < 0 ){ - sprintf(error,"ERROR: Dataset does not match!"); + + status = NXgetinfo(fileHandle, &rank, iDim, &type); + if (type != NX_INT32 && type != NX_UINT32) + type = -1; + if (status != NX_OK || rank < 2 || type < 0) { + snprintf(error,sizeof(error)-1, "ERROR: Dataset does not match!"); NXclose(&fileHandle); - NXDclose(dictHandle,NULL); - SCWrite(pCon,error,eError); + NXDclose(dictHandle, NULL); + SCWrite(pCon, error, eError); return 0; } /* - allocate space - */ - length = iDim[0]*iDim[1]; - buffer = (int *)malloc((length+2)*sizeof(int)); - if(!buffer){ + allocate space + */ + length = iDim[0] * iDim[1]; + buffer = (int *) malloc((length + 2) * sizeof(int)); + if (!buffer) { NXclose(&fileHandle); - NXDclose(dictHandle,NULL); - SCWrite(pCon,"ERROR: out of memory in readFrameFromFile",eError); + NXDclose(dictHandle, NULL); + SCWrite(pCon, "ERROR: out of memory in readFrameFromFile", eError); return 0; } - memset(buffer,0,(length+2)*sizeof(int)); + memset(buffer, 0, (length + 2) * sizeof(int)); /* - first two values: dimensions - */ + first two values: dimensions + */ buffer[0] = htonl(iDim[0]); buffer[1] = htonl(iDim[1]); - if(rank == 2){ + if (rank == 2) { /* - be friendly - */ - status = NXgetdata(fileHandle,buffer+2); + be friendly + */ + status = NXgetdata(fileHandle, buffer + 2); } else { iStart[0] = iStart[1] = 0; iStart[2] = nFrame; iSize[0] = iDim[0]; iSize[1] = iDim[1]; iSize[2] = 1; - status = NXgetslab(fileHandle,buffer+2,iStart,iSize); + status = NXgetslab(fileHandle, buffer + 2, iStart, iSize); } - if(status != NX_OK){ + if (status != NX_OK) { NXclose(&fileHandle); - NXDclose(dictHandle,NULL); + NXDclose(dictHandle, NULL); free(buffer); - SCWrite(pCon,"ERROR: failed to read data",eError); + SCWrite(pCon, "ERROR: failed to read data", eError); return 0; } /* - enforce network byte order - */ - for(i = 0; i < length; i++){ - buffer[2+i] = htonl(buffer[2+i]); + enforce network byte order + */ + for (i = 0; i < length; i++) { + buffer[2 + i] = htonl(buffer[2 + i]); } - SCWriteUUencoded(pCon,"framedata",buffer,(length+2)*sizeof(int)); + SCWriteUUencoded(pCon, "framedata", buffer, (length + 2) * sizeof(int)); NXclose(&fileHandle); - NXDclose(dictHandle,NULL); + NXDclose(dictHandle, NULL); free(buffer); return 1; } + /*=======================================================================*/ -int PSDFrameAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]){ +int PSDFrameAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ pHistMem pHM; int nFrame; + int sansflag; /* this is unique and special for the SANS at PSI */ - if(argc < 2){ - SCWrite(pCon,"ERROR: Insufficient number of arguments to PSDFrame", - eError); + if (argc < 2) { + SCWrite(pCon, "ERROR: Insufficient number of arguments to PSDFrame", + eError); return 0; } strtolower(argv[1]); - if(strcmp(argv[1],"hm") == 0){ - if(argc < 4){ - SCWrite(pCon,"ERROR: Insufficient number of arguments to PSDFrame", - eError); + if (strcmp(argv[1], "hm") == 0) { + if (argc < 4) { + SCWrite(pCon, "ERROR: Insufficient number of arguments to PSDFrame", + eError); return 0; } - pHM = (pHistMem)FindCommandData(pSics,argv[2],"HistMem"); - if(pHM == NULL){ - SCWrite(pCon,"ERROR: Did not find histogram memory",eError); + pHM = (pHistMem) FindCommandData(pSics, argv[2], "HistMem"); + if (pHM == NULL) { + SCWrite(pCon, "ERROR: Did not find histogram memory", eError); return 0; } - nFrame = atoi(argv[3]); - return readHMFrame(pCon,pHM,nFrame); - } else if(strcmp(argv[1],"file") == 0){ - if(argc < 6 ){ - SCWrite(pCon,"ERROR: Insufficient number of arguments to PSDframe file", - eError); + nFrame = atoi(argv[3]); + if(argc > 3 && (strcmp(argv[4],"sans") == 0) ){ + sansflag = 1; + } else { + sansflag = 0; + } + return readHMFrame(pCon, pHM, nFrame, sansflag); + } else if (strcmp(argv[1], "file") == 0) { + if (argc < 6) { + SCWrite(pCon, + "ERROR: Insufficient number of arguments to PSDframe file", + eError); return 0; } nFrame = atoi(argv[5]); - return readFileFrame(pCon,argv[2],argv[3],argv[4],nFrame); + return readFileFrame(pCon, argv[2], argv[3], argv[4], nFrame); } else { - SCWrite(pCon,"ERROR: subcommand to PSDframe not recognised",eError); + SCWrite(pCon, "ERROR: subcommand to PSDframe not recognised", eError); return 0; } } -/*======================================================================*/ -int MakeFrameFunc(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]){ - return AddCommand(pSics,"PSDframe",PSDFrameAction,NULL,NULL); -} +/*======================================================================*/ +int MakeFrameFunc(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + return AddCommand(pSics, "PSDframe", PSDFrameAction, NULL, NULL); +} diff --git a/frame.h b/frame.h index af5a1efd..6788f09e 100644 --- a/frame.h +++ b/frame.h @@ -12,11 +12,11 @@ #ifndef SICSFRAME #define SICSFRAME -int MakeFrameFunc(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); +int MakeFrameFunc(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); -int PSDFrameAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); +int PSDFrameAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); #endif diff --git a/fupa.c b/fupa.c index c77980a1..6d4221cf 100644 --- a/fupa.c +++ b/fupa.c @@ -47,127 +47,102 @@ #include "splitter.h" #include "fupa.h" - int EvaluateFuPa(pFuncTemplate pTemplate, int iFunc, int argc, char *argv[], - FuPaResult *pRes) - { - TokenList *pList = NULL; - TokenList *pCurrent; - int i; - int iRet = -1; - - pList = SplitArguments(argc,argv); - if(!pList) - { - strcpy(pRes->pError,"ERROR: cannot parse argument list"); - return iRet; - } +int EvaluateFuPa(pFuncTemplate pTemplate, int iFunc, int argc, + char *argv[], FuPaResult * pRes) +{ + TokenList *pList = NULL; + TokenList *pCurrent; + int i; + int iRet = -1; - /* first one must be name, try locate that one first */ - pCurrent = pList; - for(i = 0; i < iFunc; i++) - { - if(strcmp(pCurrent->text,pTemplate[i].name) == 0) - { - iRet = i; - break; - } - } - if(iRet == -1) - { - sprintf(pRes->pError,"ERROR: function %s not available",pCurrent->text); - goto end; - } + pList = SplitArguments(argc, argv); + if (!pList) { + strcpy(pRes->pError, "ERROR: cannot parse argument list"); + return iRet; + } - /* now try to find arguments */ - pRes->iArgs = pTemplate[iRet].iArgs; - for(i = 0; i < pRes->iArgs; i++) - { - pCurrent = pCurrent->pNext; - /* check presence */ - if(!pCurrent) - { - if(pTemplate[iRet].pArgs[i] == FUPAOPT) - { - pRes->Arg[i].iVal = 0; - goto end; - } - else - { - sprintf(pRes->pError,"ERROR: Insufficient number of arguments to %s", - pTemplate[iRet].name); - iRet = -1; - goto end; - } - } - /* check type, optional first */ - if(pTemplate[iRet].pArgs[i] == FUPAOPT) - { - pRes->Arg[i].iVal = 1; - strcpy(pRes->Arg[i].text,pCurrent->text); - if(pCurrent->Type == eInt) - { - pRes->Arg[i].fVal = pCurrent->iVal; - } - else if(pCurrent->Type == eFloat) - { - pRes->Arg[i].fVal = pCurrent->fVal; - } - goto end; - } - - /* now text */ - if(pTemplate[iRet].pArgs[i] == FUPATEXT) /* text is simple */ - { - strcpy(pRes->Arg[i].text,pCurrent->text); - continue; - } - - /* check integer */ - if(pTemplate[iRet].pArgs[i] == FUPAINT) - { - if(pCurrent->Type == eInt) - { - pRes->Arg[i].iVal = pCurrent->iVal; - continue; - } - else if(pCurrent->Type == eFloat) - { - pRes->Arg[i].iVal = (int)pCurrent->fVal; - continue; - } - else - { - sprintf(pRes->pError,"ERROR: expected integer parameter, got %s", - pCurrent->text); - iRet = -1; - goto end; - } - } + /* first one must be name, try locate that one first */ + pCurrent = pList; + for (i = 0; i < iFunc; i++) { + if (strcmp(pCurrent->text, pTemplate[i].name) == 0) { + iRet = i; + break; + } + } + if (iRet == -1) { + snprintf(pRes->pError,sizeof(pRes->pError)-1, "ERROR: function %s not available", + pCurrent->text); + goto end; + } - /* check float */ - if(pTemplate[iRet].pArgs[i] == FUPAFLOAT) - { - if(pCurrent->Type == eInt) - { - pRes->Arg[i].fVal = (float)pCurrent->iVal; - continue; - } - else if(pCurrent->Type == eFloat) - { - pRes->Arg[i].fVal = pCurrent->fVal; - continue; - } - else - { - sprintf(pRes->pError,"ERROR: expected float parameter, got %s", - pCurrent->text); - iRet = -1; - goto end; - } - } - } + /* now try to find arguments */ + pRes->iArgs = pTemplate[iRet].iArgs; + for (i = 0; i < pRes->iArgs; i++) { + pCurrent = pCurrent->pNext; + /* check presence */ + if (!pCurrent) { + if (pTemplate[iRet].pArgs[i] == FUPAOPT) { + pRes->Arg[i].iVal = 0; + goto end; + } else { + snprintf(pRes->pError,sizeof(pRes->pError)-1, + "ERROR: Insufficient number of arguments to %s", + pTemplate[iRet].name); + iRet = -1; + goto end; + } + } + /* check type, optional first */ + if (pTemplate[iRet].pArgs[i] == FUPAOPT) { + pRes->Arg[i].iVal = 1; + strcpy(pRes->Arg[i].text, pCurrent->text); + if (pCurrent->Type == eInt) { + pRes->Arg[i].fVal = pCurrent->iVal; + } else if (pCurrent->Type == eFloat) { + pRes->Arg[i].fVal = pCurrent->fVal; + } + goto end; + } + + /* now text */ + if (pTemplate[iRet].pArgs[i] == FUPATEXT) { /* text is simple */ + strcpy(pRes->Arg[i].text, pCurrent->text); + continue; + } + + /* check integer */ + if (pTemplate[iRet].pArgs[i] == FUPAINT) { + if (pCurrent->Type == eInt) { + pRes->Arg[i].iVal = pCurrent->iVal; + continue; + } else if (pCurrent->Type == eFloat) { + pRes->Arg[i].iVal = (int) pCurrent->fVal; + continue; + } else { + snprintf(pRes->pError,sizeof(pRes->pError)-1, "ERROR: expected integer parameter, got %s", + pCurrent->text); + iRet = -1; + goto end; + } + } + + /* check float */ + if (pTemplate[iRet].pArgs[i] == FUPAFLOAT) { + if (pCurrent->Type == eInt) { + pRes->Arg[i].fVal = (float) pCurrent->iVal; + continue; + } else if (pCurrent->Type == eFloat) { + pRes->Arg[i].fVal = pCurrent->fVal; + continue; + } else { + snprintf(pRes->pError,sizeof(pRes->pError)-1, "ERROR: expected float parameter, got %s", + pCurrent->text); + iRet = -1; + goto end; + } + } + } end: - DeleteTokenList(pList); - return iRet; - } - + DeleteTokenList(pList); + return iRet; +} diff --git a/fupa.h b/fupa.h index adcb0434..0d77f41b 100644 --- a/fupa.h +++ b/fupa.h @@ -28,31 +28,30 @@ #define FUPATEXT 0 #define FUPAINT 1 #define FUPAFLOAT 2 -#define FUPAOPT 3 /* optional argument, in this case text contains it - and iVal indicates its presence - */ - - typedef struct { - char *name; - int iArgs; - int pArgs[MAXARG]; - } FuncTemplate, *pFuncTemplate; - - typedef struct { - char text[80]; - int iVal; - float fVal; - } FuPaArg; - - typedef struct { - char pError[132]; - int iArgs; - FuPaArg Arg[MAXARG]; - } FuPaResult; - - int EvaluateFuPa(pFuncTemplate pTemplate,int iFunc, int argc, char *argv[], - FuPaResult *pRes); - - -#endif +#define FUPAOPT 3 /* optional argument, in this case text contains it + and iVal indicates its presence + */ +typedef struct { + char *name; + int iArgs; + int pArgs[MAXARG]; +} FuncTemplate, *pFuncTemplate; + +typedef struct { + char text[80]; + int iVal; + float fVal; +} FuPaArg; + +typedef struct { + char pError[132]; + int iArgs; + FuPaArg Arg[MAXARG]; +} FuPaResult; + +int EvaluateFuPa(pFuncTemplate pTemplate, int iFunc, int argc, + char *argv[], FuPaResult * pRes); + + +#endif diff --git a/genbinprot.c b/genbinprot.c new file mode 100644 index 00000000..e6d34157 --- /dev/null +++ b/genbinprot.c @@ -0,0 +1,155 @@ +/* + * genbinprot.c + * + * This is a generic binary protocol handler for scriptcontext. It expects a + * command of the form: + * + * writepointer:writecount:readpointer:readcount + * + * And will writecount bytes from the data area writepointer and + * read readcount bytes into the memory area under readpointer. + * If writecount is 0, the nothing will be written. This can + * be used to read a binary message in parts. Both writepointer and + * readpointer are memory addresses in hexadecimal. + * + * This is a workaround for the essential weakness of devser not being + * able to work with binary protocols. + * + * Created on: Jul 7, 2010 + * Author: koennecke + */ +#include +#include +#include +#include +#include +#include + +/*-----------------------------------------------------------------*/ +typedef struct { + char *writePointer; + unsigned int toWrite; + char *readPointer; + unsigned int readCount; + unsigned int toRead; +}GenBin, *pGenBin; +/*------------------------------------------------------------------*/ +static void initGenBin(Ascon *a) +{ + pGenBin self = (pGenBin)a->private; + char *pPtr = NULL, pToken[60]; + long lval; + + pPtr = GetCharArray(a->wrBuffer); + + pPtr = stptok(pPtr,pToken,60,":"); + sscanf(pToken,"%lx",&lval); + self->writePointer = (char *)lval; + + pPtr = stptok(pPtr,pToken,60,":"); + sscanf(pToken,"%d",&self->toWrite); + + pPtr = stptok(pPtr,pToken,60,":"); + sscanf(pToken,"%lx",&lval); + self->readPointer = (char *)lval; + + pPtr = stptok(pPtr,pToken,60,":"); + sscanf(pToken,"%d",&self->toRead); + + a->wrPos = 0; + self->readCount = 0; +} +/*------------------------------------------------------------------*/ +static int GenBinHandler(Ascon *a) +{ + pGenBin self = (pGenBin)a->private; + unsigned int toWrite; + int ret; + char chr; + + switch(a->state){ + case AsconWriteStart: + AsconReadGarbage(a->fd); + initGenBin(a); + a->state = AsconWriting; + break; + case AsconWriting: + toWrite = self->toWrite - a->wrPos; + if(toWrite == 0){ + a->state = AsconWriteDone; + } else { + ret = AsconWriteChars(a->fd, self->writePointer+a->wrPos, toWrite); + if (ret < 0) { + if (errno != EINTR && errno != EAGAIN) { + AsconError(a, "send failed:", errno); + } + } else { + a->wrPos += ret; + if(a->wrPos >= self->toWrite){ + a->state = AsconWriteDone; + } + } + } + break; + case AsconReading: + if(self->readCount >= self->toRead){ + a->state = AsconReadDone; + DynStringCopy(a->rdBuffer,"OK"); + } else { + ret = AsconReadChar(a->fd, &chr); + if (ret < 0) { + /* EINTR means we must retry */ + if (errno != EINTR && errno != EAGAIN) { + AsconError(a, "AsconReadChar failed:", errno); + } + return 1; + } else if (ret > 0) { + a->start = DoubleTime(); + self->readPointer[self->readCount] = chr; + self->readCount++; + } else if (ret == 0) { + if (a->timeout > 0) { + if (DoubleTime() - a->start > a->timeout) { + AsconError(a, "read timeout", 0); + a->state = AsconTimeout; + } + } + return 0; + } + } + break; + default: + return AsconStdHandler(a); + } + return 1; +} +/*------------------------------------------------------------------------*/ +static int GenBinInit(Ascon * a, SConnection * con, int argc, char *argv[]) +{ + pGenBin priv = NULL; + + priv = calloc(sizeof(GenBin), 1); + a->fd = -1; + a->state = AsconConnectStart; + a->reconnectInterval = 10; + a->hostport = strdup(argv[1]); + if (argc > 2) { + a->timeout = atof(argv[2]); + } else { + a->timeout = 2.0; /* sec */ + } + a->private = priv; + a->killPrivate = free; + return 1; +} +/*------------------------------------------------------------------------*/ +void AddGenBinProtocoll() +{ + AsconProtocol *prot = NULL; + + prot = calloc(sizeof(AsconProtocol), 1); + prot->name = strdup("genbin"); + prot->init = GenBinInit; + prot->handler = GenBinHandler; + AsconInsertProtocol(prot); +} diff --git a/genericcontroller.c b/genericcontroller.c deleted file mode 100644 index 75586942..00000000 --- a/genericcontroller.c +++ /dev/null @@ -1,622 +0,0 @@ -/** - * This is a generic controller for devices in SICS. It is configurable via Tcl - * scripts. - * - * copyright: see file COPYRIGHT - * - * Mark Koennecke, November 2007 - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -/*--------------------------------------------------------------------------*/ -static hdbCallbackReturn GenConSetCallback(pHdb node, void *userData, - pHdbMessage message){ - pSICSOBJ self = (pSICSOBJ)userData; - SConnection *pCon = NULL; - pGenController priv = NULL; - char command[1024]; - char value[80]; - int status, privilege; - pDynString data; - pHdbDataMessage mm = NULL; - - assert(self != NULL); - - if((mm = GetHdbSetMessage(message)) == NULL){ - return hdbContinue; - } - - priv = (pGenController)self->pPrivate; - pCon = mm->callData; - - /* - * check rights - */ - memset(value,0,80); - if(GetHdbProperty(node,"priv",value,80) && pCon != NULL){ - privilege = usInternal; - if(strcmp(value,"manager") == 0){ - privilege = usMugger; - } - if(strcmp(value,"user") == 0){ - privilege = usUser; - } - if(!SCMatchRights(pCon,privilege)){ - return hdbAbort; - } - } - - /* - * check writeCommand - */ - memset(value,0,80); - GetHdbProperty(node,"writeCommand",value,80); - if(strlen(value) < 2){ - if(pCon != NULL){ - SCWrite(pCon,"ERROR: parameter is read-only",eError); - return hdbAbort; - } - return hdbAbort; - } - - /* - * check status - */ - memset(value,0,80); - GetHdbProperty(node,"status",value,80); - if(strstr(value,"idle") == NULL){ - return hdbAbort; - } - SetHdbProperty(node,"status","setting"); - data = formatValue(*(mm->v), node); - if(data != NULL){ - SetHdbProperty(node,"target",GetCharArray(data)); - DeleteDynString(data); - } - - /* - * issue command - */ - if(priv->enqueueNodeHead != NULL){ - priv->enqueueNodeHead(self,pCon,node); - } else { - if(pCon != NULL){ - SCWrite(pCon,"ERROR: generic controller NOT configured", - eError); - } - return hdbAbort; - } - - return hdbContinue; -} -/*--------------------------------------------------------------------------*/ -static hdbCallbackReturn GenConGetCallback(pHdb node, void *userData, - pHdbMessage message){ - pSICSOBJ self = (pSICSOBJ)userData; - SConnection *pCon = NULL; - pGenController priv = NULL; - char command[1024]; - char value[256]; - int status, privilege; - pHdbDataMessage mm = NULL; - - assert(self != NULL); - - if((mm = GetHdbGetMessage(message)) == NULL){ - return hdbContinue; - } - pCon = mm->callData; - - priv = (pGenController)self->pPrivate; - - /* - * check status - */ - memset(value,0,80); - GetHdbProperty(node,"status",value,80); - if(strstr(value,"idle") == NULL){ - return hdbContinue; - } - SetHdbProperty(node,"status","getting"); - - /* - * check readCommand - */ - memset(value,0,256); - GetHdbProperty(node,"readCommand",value,255); - if(strlen(value) < 2){ - return hdbAbort; - } else { - if(priv->enqueueNode != NULL){ - priv->enqueueNode(self,pCon, node); - } else { - if(pCon != NULL){ - SCWrite(pCon,"ERROR: generic controller connection NOT configured", - eError); - } - return hdbAbort; - } - } - - /* - * Upper Level GetHipadabaPar will automatically return the - * node value. Which should have been updated through an update - * during the execution of enqueueNode - */ - - return hdbContinue; -} -/*---------------------------------------------------------------------------*/ -static pHdb MakeGenConPar(pSICSOBJ self, char *name, int type, int length){ - pHdb result = NULL; - pHdbCallback kalle = NULL; - - result = MakeHipadabaNode(name,type,length); - if(result == NULL){ - return NULL; - } - - kalle = MakeHipadabaCallback(GenConSetCallback, - self, - NULL); - if(kalle == NULL){ - return NULL; - } - AppendHipadabaCallback(result,kalle); - - kalle = MakeHipadabaCallback(GenConGetCallback, - self, - NULL); - - if(kalle == NULL){ - return NULL; - } - AppendHipadabaCallback(result,kalle); - - SetHdbProperty(result,"priv","manager"); - SetHdbProperty(result,"readCommand",""); - SetHdbProperty(result,"writeCommand",""); - SetHdbProperty(result,"replyCommand",""); - SetHdbProperty(result,"status","idle"); - - return result; -} -/*---------------------------------------------------------------------------*/ -static int MakeGenPar(pSICSOBJ self, SConnection *pCon, - char *argv[], int argc){ - char buffer[2048]; - int type, length = 1; - pHdb node = NULL , parent; - char *pPtr = NULL; - - if(argc < 5){ - snprintf(buffer,2048,"ERROR: insufficient arguments to %s makepar", - argv[0]); - SCWrite(pCon,buffer, eError); - return 0; - } - type = convertHdbType(argv[4]); - if(argc > 5){ - length = atoi(argv[5]); - } - strncpy(buffer,argv[3],2047); - pPtr = strrchr(buffer,'/'); - if(pPtr == NULL){ - node = MakeGenConPar(self, argv[3], type, length); - parent = self->objectNode; - } else { - *pPtr = '\0'; - pPtr++; - node = MakeGenConPar(self, pPtr, type, length); - parent = GetHipadabaNode(self->objectNode,buffer); - } - if(node == NULL || parent == NULL){ - SCWrite(pCon,"ERROR: failed to create node or parent not found", - eError); - return 0; - } - AddHipadabaChild(parent, node, pCon); - SCSendOK(pCon); - return 1; -} -/*=============================== ========================================== - * This stuff is for the Tcl - AsynQueue implementation of GenericController - * ==========================================================================*/ - typedef struct { - pHdb node; - pSICSOBJ obj; - SConnection *pCon; - pGenController priv; - pAsyncUnit assi; - pAsyncTxn trans; - commandContext comCon; - char replyCommand[2048]; - } GenContext, *pGenContext; - /*-------------------------------------------------------------------------- - * This is called by AsyncQueue when a reply has been received. - * -------------------------------------------------------------------------*/ - static int GenConTxnHandler(pAsyncTxn pTxn){ - pGenContext genCon = NULL; - char reply[10240]; - - genCon = (pGenContext)pTxn->cntx; - assert(genCon != NULL); - - memset(reply,0,10240*sizeof(char)); - switch(pTxn->txn_state){ - case ATX_NULL: - case ATX_ACTIVE: - return 1; - break; - case ATX_TIMEOUT: - strcpy(reply,"TIMEOUT"); - break; - case ATX_DISCO: - strcpy(reply,"DISCONNECTED"); - break; - case ATX_COMPLETE: - strncpy(reply,pTxn->inp_buf,10240); - break; - } - - if(genCon->pCon != NULL){ - SCPushContext2(genCon->pCon, genCon->comCon); - } - genCon->priv->replyCallback(genCon->obj, genCon->pCon, - genCon->node, genCon->replyCommand, reply, strlen(reply)); - if(genCon->pCon != NULL){ - SCPopContext(genCon->pCon); - } - free(genCon); - - return 1; - } -/*--------------------------------------------------------------------------*/ -static char *formatCommand(pHdb node, SConnection *pCon){ - pDynString com = NULL; - char value[512]; - Tcl_Interp *pTcl = NULL; - int status; - - com = CreateDynString(256,128); - if(com == NULL){ - return NULL; - } - - memset(value,0,512); - GetHdbProperty(node,"status",value,512); - if(strstr(value,"set") != NULL){ - memset(value,0,512); - GetHdbProperty(node,"writeCommand",value,512); - DynStringConcat(com,value); - DynStringConcatChar(com,' '); - memset(value,0,512); - GetHdbProperty(node,"target",value,512); - DynStringConcat(com,value); - } else { - memset(value,0,512); - GetHdbProperty(node,"readCommand",value,512); - DynStringConcat(com,value); - } - pTcl = InterpGetTcl(pServ->pSics); - if(pCon != NULL){ - MacroPush(pCon); - } - status = Tcl_Eval(pTcl, GetCharArray(com)); - if(pCon != NULL){ - MacroPop(); - } - DeleteDynString(com); - if(status != TCL_OK){ - SetHdbProperty(node,"result", (char *)Tcl_GetStringResult(pTcl)); - return NULL; - } - return strdup(Tcl_GetStringResult(pTcl)); -} -/*--------------------------------------------------------------------------*/ -static pGenContext PrepareToEnque(pSICSOBJ self, SConnection *pCon, pHdb node){ - pGenContext result = NULL; - char *command = NULL; - pGenController priv = NULL; - - priv = (pGenController)self->pPrivate; - assert(priv != NULL); - - command = formatCommand(node, pCon); - if(command == NULL){ - return NULL; - } - - result = malloc(sizeof(GenContext)); - if(result == NULL){ - return NULL; - } - memset(result,0,sizeof(GenContext)); - if(!GetHdbProperty(node,"replyCommand",result->replyCommand,2048)){ - if(pCon != NULL){ - SCWrite(pCon,"ERROR: no replyCommand found",eError); - } - free(result); - return NULL; - } - - result->assi = AsyncUnitFromQueue((pAsyncQueue)priv->comContext); - if(result->assi == NULL){ - return NULL; - } - result->trans = AsyncUnitPrepareTxn(result->assi, - command,strlen(command), - GenConTxnHandler, - result, - 2048); - if(result->trans == NULL){ - return NULL; - } - result->node = node; - result->priv = priv; - result->obj = self; - result->pCon = pCon; - priv->comError = GCOK; - result->comCon = SCGetContext(pCon); - free(command); - - return result; -} -/*---------------------------------------------------------------------------*/ -static int AsyncEnqueueNode(pSICSOBJ self, SConnection *pCon, pHdb node){ - pGenContext genCon = NULL; - - genCon = PrepareToEnque(self, pCon, node); - if(genCon == NULL){ - return 0; - } - return AsyncUnitEnqueueTxn(genCon->assi, genCon->trans); -} -/*---------------------------------------------------------------------------*/ -static int AsyncEnqueueNodeHead(pSICSOBJ self, SConnection *pCon, pHdb node){ - pGenContext genCon = NULL; - - genCon = PrepareToEnque(self, pCon, node); - if(genCon == NULL){ - return 0; - } - return AsyncUnitEnqueueHead(genCon->assi, genCon->trans); -} -/*---------------------------------------------------------------------------*/ -static int AsyncReply(pSICSOBJ self, SConnection *pCon, pHdb node, - char *replyCommand, char *reply, int replylen){ - pDynString com = NULL; - Tcl_Interp *pTcl; - int status; - - SetHdbProperty(node,"result",reply); - - com = CreateDynString(256,128); - if(com == NULL){ - return 0; - } - DynStringConcat(com, replyCommand); - DynStringConcat(com," \""); - DynStringConcat(com, reply); - DynStringConcat(com,"\"\0"); - if(pCon != NULL){ - MacroPush(pCon); - } - pTcl = InterpGetTcl(pServ->pSics); - status = Tcl_Eval(pTcl,GetCharArray(com)); - if(pCon != NULL){ - MacroPop(); - } - DeleteDynString(com); - if(status != TCL_OK){ - SetHdbProperty(node,"lastError",(char *)Tcl_GetStringResult(pTcl)); - } - return status; -} -/*============= GenController Object Functions ==============================*/ -static int ConnectAsync(pSICSOBJ self, SConnection *pCon, - char *argv[], int argc){ - pGenController priv = NULL; - pAsyncQueue assi = NULL; - char buffer[2048]; - pAsyncUnit uni = NULL; - - priv = (pGenController)self->pPrivate; - assert(priv != NULL); - - if(argc < 4){ - snprintf(buffer,2048,"ERROR: insufficient arguments to %s asynconnect", - argv[0]); - SCWrite(pCon,buffer, eError); - return 0; - } - - assi = (pAsyncQueue)FindCommandData(pServ->pSics, argv[3],"AsyncQueue"); - if(assi == NULL){ - snprintf(buffer,2048,"ERROR: %s not found or no AsyncQueue", argv[3]); - SCWrite(pCon,buffer,eError); - return 0; - } - - priv->comContext = assi; - priv->killComContext = NULL; /* not ours, cleaned up by AsyncQueue module */ - priv->enqueueNode = AsyncEnqueueNode; - priv->enqueueNodeHead = AsyncEnqueueNodeHead; - priv->replyCallback = AsyncReply; - priv->comError = GCOK; - - /* - * This unit is solely for the purpose of receiving event notifications - */ - uni = AsyncUnitFromQueue(assi); - - SCSendOK(pCon); - return 1; -} -/*---------------------------------------------------------------------------*/ -int GenControllerConfigure(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]){ - pSICSOBJ controller = NULL; - pGenController self = NULL; - char buffer[2048]; - - if(argc < 3){ - snprintf(buffer,2048,"ERROR: insufficient arguments to %s", argv[0]); - SCWrite(pCon,buffer,eError); - return 0; - } - - controller = (pSICSOBJ)FindCommandData(pSics,argv[2], "GenericController"); - if(controller == NULL){ - snprintf(buffer,2048,"ERROR: controller %s not found", argv[2]); - SCWrite(pCon,buffer,eError); - return 0; - } - - strtolower(argv[1]); - if(strcmp(argv[1],"makepar") == 0){ - return MakeGenPar(controller,pCon,argv,argc); - } else if(strcmp(argv[1],"asynconnect") == 0){ - return ConnectAsync(controller, pCon, argv, argc); - } else { - SCWrite(pCon,"ERROR: argument to GenControllerConfigure not found", - eError); - return 0; - } - - return 1; -} -/*---------------------------------------------------------------------------*/ -static void killGeneric(void *data){ - pGenController self = (pGenController)data; - - if(self == NULL){ - return; - } - if(self->comContext != NULL && self->killComContext != NULL){ - self->killComContext(self->comContext); - } - free(self); -} -/*---------------------------------------------------------------------------*/ -static int EnqueFunc(pSICSOBJ self, SConnection *pCon, pHdb commandNode, - pHdb par[], int nPar){ - pGenController priv = NULL; - pHdb node = NULL; - char buffer[512]; - - priv = (pGenController)self->pPrivate; - assert(priv != NULL); - assert(nPar >= 1); - - node = GetHipadabaNode(self->objectNode,par[0]->value.v.text); - if(node == NULL){ - snprintf(buffer,511,"ERROR: node %s to enqueue not found", - par[0]->value.v.text); - SCWrite(pCon,buffer,eError); - return 0; - } - - if(priv->enqueueNode != NULL){ - priv->enqueueNode(self, pCon, node); - } else { - SCWrite(pCon,"ERROR: GenController NOT configured",eError); - return 0; - } - return 1; -} -/*---------------------------------------------------------------------------*/ -static int EnqueHeadFunc(pSICSOBJ self, SConnection *pCon, Hdb commandNode, - pHdb par[], int nPar){ - pGenController priv = NULL; - pHdb node = NULL; - char buffer[512]; - - priv = (pGenController)self->pPrivate; - assert(priv != NULL); - assert(nPar >= 1); - - node = GetHipadabaNode(self->objectNode,par[0]->value.v.text); - if(node == NULL){ - snprintf(buffer,511,"ERROR: node %s to enqueue not found", - par[0]->value.v.text); - SCWrite(pCon,buffer,eError); - return 0; - } - - if(priv->enqueueNodeHead != NULL){ - priv->enqueueNodeHead(self, pCon, node); - } else { - SCWrite(pCon,"ERROR: GenController NOT configured",eError); - return 0; - } - return 1; -} -/*---------------------------------------------------------------------------*/ -int GenControllerFactory(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]){ - pSICSOBJ pNew = NULL; - pGenController priv = NULL; - hdbValue funcValue, textValue; - pHdb node = NULL; - char line[132]; - int status; - - if(argc < 2){ - SCWrite(pCon, - "ERROR: insufficient number of arguments to GenControllerFactrory", - eError); - return 0; - } - priv = malloc(sizeof(GenController)); - if(priv == NULL){ - SCWrite(pCon,"ERROR: out of memory in GenControllerFactory", - eError); - return 0; - } - memset(priv,0,sizeof(GenController)); - - pNew = MakeSICSOBJ(argv[1],"GenericController"); - if(pNew == NULL){ - SCWrite(pCon,"ERROR: out of memory in GenControllerFactory", - eError); - return 0; - } - pNew->pPrivate = priv; - pNew->KillPrivate = killGeneric; - - textValue = MakeHdbText("Undefined"); - funcValue = MakeHdbFunc((voidFunc *)EnqueFunc); - node = MakeSICSHdbPar("enqueue",usUser, funcValue); - AddSICSHdbPar(node,"node",usUser,textValue); - AppendHipadabaCallback(node,MakeSICSFuncCallback(pNew)); - AddHipadabaChild(pNew->objectNode,node,NULL); - - funcValue = MakeHdbFunc((voidFunc *)EnqueHeadFunc); - node = MakeSICSHdbPar("enqueuehead",usUser, funcValue); - AddSICSHdbPar(node,"node",usUser,textValue); - AppendHipadabaCallback(node,MakeSICSFuncCallback(pNew)); - AddHipadabaChild(pNew->objectNode,node,NULL); - - status = AddCommand(pSics, - argv[1], - InvokeSICSOBJ, - KillSICSOBJ, - pNew); - if(status != 1){ - KillSICSOBJ(pNew); - SCPrintf(pCon,eError,"ERROR: failed create duplicate command %s", argv[1]); - return 0; - } - SCSendOK(pCon); - - return 1; -} - diff --git a/genericcontroller.h b/genericcontroller.h deleted file mode 100644 index 2ba805a7..00000000 --- a/genericcontroller.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * This is a generic controller for devices in SICS. In its default configuration it - * will be configurable via Tcl scripts and used AsynqQueue for communication. But - * it is suitably generic to support other mechanisms as well. - * - * copyright: see file COPYRIGHT - * - * Mark Koennecke, November 2007 - */ -#ifndef GENERICCONTROLLER_H_ -#define GENERICCONTROLLER_H_ -#include -#include - -#define GCTIMEOUT 5001 -#define GCDISCONNECT 5002 -#define GCOK 5000 -#define GCRECONNECT 5003 -#define GCRETRY 5004 - -typedef struct { - int (*enqueueNode)(pSICSOBJ self, SConnection *pCon, pHdb node); - int (*enqueueNodeHead)(pSICSOBJ self, SConnection *pCon, pHdb node); - int (*replyCallback)(pSICSOBJ self, SConnection *pCon, pHdb node, - char *replyCommand, char *reply, int replylen); - void *comContext; - void (*killComContext)(void *data); - int comError; -}GenController, *pGenController; -/*---------------------------------------------------------------------------*/ -int GenControllerFactory(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]); -/*---------------------------------------------------------------------------*/ -int GenControllerConfigure(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]); - -#endif /*GENERICCONTROLLER_H_*/ diff --git a/geninter.c b/geninter.c index 0567494b..8e0037b9 100644 --- a/geninter.c +++ b/geninter.c @@ -12,8 +12,9 @@ #include /*---------------------------------------------------------------------------*/ -int GenDrivableFactory(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]){ - - return 1; +int GenDrivableFactory(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]) +{ + + return 1; } diff --git a/geninter.h b/geninter.h index 05a469cd..d6dc01f3 100644 --- a/geninter.h +++ b/geninter.h @@ -12,8 +12,8 @@ * make a drivable parameter: * Usage: * MakeGenDrivable name par-node control-node - */ -int GenDrivableFactory(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]); + */ +int GenDrivableFactory(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]); -#endif /*GENINTER_H_*/ +#endif /*GENINTER_H_ */ diff --git a/gpibcontroller.c b/gpibcontroller.c index cff8c1f2..fb79a82c 100644 --- a/gpibcontroller.c +++ b/gpibcontroller.c @@ -15,24 +15,33 @@ #include "gpibcontroller.h" #include "gpibcontroller.i" /*----------------------------------------------------------------------*/ -int GPIBattach(pGPIB self, int boardNo, int address, - int secondaryAddress, int tmo, int eot, int eos){ - return self->attach(boardNo,address,secondaryAddress,tmo,eot,eos); +int GPIBattach(pGPIB self, int boardNo, int address, + int secondaryAddress, int tmo, int eot, int eos) +{ + return self->attach(boardNo, address, secondaryAddress, tmo, eot, eos); } + /*---------------------------------------------------------------------*/ -int GPIBdetach(pGPIB self, int devID){ +int GPIBdetach(pGPIB self, int devID) +{ return self->detach(devID); } + /*----------------------------------------------------------------------*/ -int GPIBsend(pGPIB self, int devID, void *buffer, int bytesToWrite){ - return self->send(devID, buffer,bytesToWrite); +int GPIBsend(pGPIB self, int devID, void *buffer, int bytesToWrite) +{ + return self->send(devID, buffer, bytesToWrite); } + /*--------------------------------------------------------------------*/ -int GPIBread(pGPIB self, int devID, void *buffer, int bytesToRead){ - return self->read(devID, buffer,bytesToRead); +int GPIBread(pGPIB self, int devID, void *buffer, int bytesToRead) +{ + return self->read(devID, buffer, bytesToRead); } + /*--------------------------------------------------------------------*/ -char *GPIBreadTillTerm(pGPIB self, int devID, int terminator){ +char *GPIBreadTillTerm(pGPIB self, int devID, int terminator) +{ char buchstabe[2]; Tcl_DString buffer; char *result = NULL; @@ -40,71 +49,91 @@ char *GPIBreadTillTerm(pGPIB self, int devID, int terminator){ Tcl_DStringInit(&buffer); buchstabe[1] = '\0'; - GPIBread(self,devID,buchstabe,1); - while(buchstabe[0] != (unsigned char)terminator){ - Tcl_DStringAppend(&buffer,buchstabe,-1); - status = GPIBread(self,devID,buchstabe,1); - if(status != 1){ - Tcl_DStringAppend(&buffer,"GPIB Read Error",-1); + GPIBread(self, devID, buchstabe, 1); + while (buchstabe[0] != (unsigned char) terminator) { + Tcl_DStringAppend(&buffer, buchstabe, -1); + status = GPIBread(self, devID, buchstabe, 1); + if (status != 1) { + Tcl_DStringAppend(&buffer, "GPIB Read Error", -1); break; } - } + } result = strdup(Tcl_DStringValue(&buffer)); Tcl_DStringFree(&buffer); return result; } + /*--------------------------------------------------------------------*/ -void GPIBclear(pGPIB self, int devID){ +void GPIBclear(pGPIB self, int devID) +{ self->clear(devID); } + /*--------------------------------------------------------------------*/ -void GPIBerrorDescription(pGPIB self, int code, char *buffer, int maxBuf){ - self->getErrorDescription(code, buffer,maxBuf); +void GPIBerrorDescription(pGPIB self, int code, char *buffer, int maxBuf) +{ + self->getErrorDescription(code, buffer, maxBuf); } + /*------------------------------------------------------------------- These are void implementations of the functions for simulation purposes ----------------------------------------------------------------------*/ static int SIMattach(int boardNo, int address, int secondaryAddress, - int tmo, int eoi, int eot){ + int tmo, int eoi, int eot) +{ return 1; } + /*----------------------------------------------------------------------*/ -static int SIMdetach(int devID){ +static int SIMdetach(int devID) +{ return 1; } + /*---------------------------------------------------------------------*/ -static int SIMsend(int devID, void *buffer, int bytesToWrite){ +static int SIMsend(int devID, void *buffer, int bytesToWrite) +{ return 1; } + /*--------------------------------------------------------------------*/ -static int SIMread(int devID, void *buffer, int bytesToRead){ +static int SIMread(int devID, void *buffer, int bytesToRead) +{ return 1; } + /*--------------------------------------------------------------------*/ -static int SIMclear(int devID){ +static int SIMclear(int devID) +{ return 1; } + /*---------------------------------------------------------------------*/ -static void SIMerror(int code, char *buffer, int maxBuf){ - strncpy(buffer,"Unknown simulated error",maxBuf); +static void SIMerror(int code, char *buffer, int maxBuf) +{ + strlcpy(buffer, "Unknown simulated error", maxBuf); } + /*---------------------------------------------------------------------*/ -void GPIBKill(void *pData){ +void GPIBKill(void *pData) +{ pGPIB self = NULL; - if(pData != NULL){ - self = (pGPIB)pData; - if(self->pDes){ + if (pData != NULL) { + self = (pGPIB) pData; + if (self->pDes) { DeleteDescriptor(self->pDes); } free(pData); } } + /*---------------------------------------------------------------------*/ -int GPIBAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]){ - pGPIB self = (pGPIB)pData; - int boardID, devID, tmo, count, eoi, eot, address, +int GPIBAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pGPIB self = (pGPIB) pData; + int boardID, devID, tmo, count, eoi, eot, address, secondaryAddress, status, terminator, value; char pBuffer[1024]; char *result = NULL; @@ -112,225 +141,226 @@ int GPIBAction(SConnection *pCon, SicsInterp *pSics, void *pData, assert(self != NULL); /* - Only managers will be allowed to wrestle directly with GPIB - controllers. - */ - if(!SCinMacro(pCon)){ - if(!SCMatchRights(pCon,usMugger)){ + Only managers will be allowed to wrestle directly with GPIB + controllers. + */ + if (!SCinMacro(pCon)) { + if (!SCMatchRights(pCon, usMugger)) { return 0; } } - if(argc > 1){ + if (argc > 1) { strtolower(argv[1]); - if(strcmp(argv[1],"attach") == 0){ + if (strcmp(argv[1], "attach") == 0) { /* the attach command */ - if(argc < 8){ - SCWrite(pCon,"ERROR: insufficient number of arguments to attach", - eError); - return 0; + if (argc < 8) { + SCWrite(pCon, "ERROR: insufficient number of arguments to attach", + eError); + return 0; } count = 0; - count += Tcl_GetInt(pSics->pTcl,argv[2],&boardID); - count += Tcl_GetInt(pSics->pTcl,argv[3],&address); - count += Tcl_GetInt(pSics->pTcl,argv[4],&secondaryAddress); - count += Tcl_GetInt(pSics->pTcl,argv[5],&tmo); - count += Tcl_GetInt(pSics->pTcl,argv[6],&eot); - count += Tcl_GetInt(pSics->pTcl,argv[7],&eoi); - if(count != 6*TCL_OK){ - SCWrite(pCon,"ERROR: failed to convert arguments to integer", - eError); - return 0; + count += Tcl_GetInt(pSics->pTcl, argv[2], &boardID); + count += Tcl_GetInt(pSics->pTcl, argv[3], &address); + count += Tcl_GetInt(pSics->pTcl, argv[4], &secondaryAddress); + count += Tcl_GetInt(pSics->pTcl, argv[5], &tmo); + count += Tcl_GetInt(pSics->pTcl, argv[6], &eot); + count += Tcl_GetInt(pSics->pTcl, argv[7], &eoi); + if (count != 6 * TCL_OK) { + SCWrite(pCon, "ERROR: failed to convert arguments to integer", + eError); + return 0; } - status = GPIBattach(self,boardID, address, secondaryAddress, - tmo,eot,eoi); - if(status > 0){ - sprintf(pBuffer,"%d",status); - SCWrite(pCon,pBuffer,eValue); - return 1; + status = GPIBattach(self, boardID, address, secondaryAddress, + tmo, eot, eoi); + if (status > 0) { + snprintf(pBuffer,sizeof(pBuffer)-1, "%d", status); + SCWrite(pCon, pBuffer, eValue); + return 1; } else { - sprintf(pBuffer,"ERROR: error %d on attach", status); - SCWrite(pCon,pBuffer,eError); - return 0; + snprintf(pBuffer,sizeof(pBuffer)-1, "ERROR: error %d on attach", status); + SCWrite(pCon, pBuffer, eError); + return 0; } - } else if(strcmp(argv[1],"detach") == 0){ + } else if (strcmp(argv[1], "detach") == 0) { /* - detach command - */ - if(argc < 2){ - SCWrite(pCon,"ERROR: insufficient number of arguments to dettach", - eError); - return 0; + detach command + */ + if (argc < 2) { + SCWrite(pCon, "ERROR: insufficient number of arguments to dettach", + eError); + return 0; } - if(Tcl_GetInt(pSics->pTcl,argv[2],&devID) != TCL_OK){ - SCWrite(pCon,"ERROR: failed to convert arguments to integer", - eError); - return 0; + if (Tcl_GetInt(pSics->pTcl, argv[2], &devID) != TCL_OK) { + SCWrite(pCon, "ERROR: failed to convert arguments to integer", + eError); + return 0; } - status = GPIBdetach(self,devID); - if(status > 0){ - SCSendOK(pCon); - return 1; + status = GPIBdetach(self, devID); + if (status > 0) { + SCSendOK(pCon); + return 1; } else { - sprintf(pBuffer,"ERROR: error %d on dettach", status); - SCWrite(pCon,pBuffer,eError); - return 0; + snprintf(pBuffer,sizeof(pBuffer)-1, "ERROR: error %d on dettach", status); + SCWrite(pCon, pBuffer, eError); + return 0; } - } else if(strcmp(argv[1],"clear") == 0){ + } else if (strcmp(argv[1], "clear") == 0) { /* - clear command - */ - if(argc < 2){ - SCWrite(pCon,"ERROR: insufficient number of arguments to clear", - eError); - return 0; + clear command + */ + if (argc < 2) { + SCWrite(pCon, "ERROR: insufficient number of arguments to clear", + eError); + return 0; } - if(Tcl_GetInt(pSics->pTcl,argv[2],&devID) != TCL_OK){ - SCWrite(pCon,"ERROR: failed to convert arguments to integer", - eError); - return 0; + if (Tcl_GetInt(pSics->pTcl, argv[2], &devID) != TCL_OK) { + SCWrite(pCon, "ERROR: failed to convert arguments to integer", + eError); + return 0; } - GPIBclear(self,devID); + GPIBclear(self, devID); SCSendOK(pCon); return 1; - } else if(strcmp(argv[1],"send") == 0){ + } else if (strcmp(argv[1], "send") == 0) { /* - send command - */ - if(argc < 4){ - SCWrite(pCon,"ERROR: insufficient number of arguments to send", - eError); - return 0; + send command + */ + if (argc < 4) { + SCWrite(pCon, "ERROR: insufficient number of arguments to send", + eError); + return 0; } - if(Tcl_GetInt(pSics->pTcl,argv[2],&devID) != TCL_OK){ - SCWrite(pCon,"ERROR: failed to convert arguments to integer", - eError); - return 0; + if (Tcl_GetInt(pSics->pTcl, argv[2], &devID) != TCL_OK) { + SCWrite(pCon, "ERROR: failed to convert arguments to integer", + eError); + return 0; } - Arg2Text(argc-3,argv+3,pBuffer,1023); - status = GPIBsend(self,devID,pBuffer, (int)strlen(pBuffer)); - if(status > 0){ - SCSendOK(pCon); - return 1; + Arg2Text(argc - 3, argv + 3, pBuffer, 1023); + status = GPIBsend(self, devID, pBuffer, (int) strlen(pBuffer)); + if (status > 0) { + SCSendOK(pCon); + return 1; } else { - sprintf(pBuffer,"ERROR: error %d on send", status); - SCWrite(pCon,pBuffer,eError); - return 0; + snprintf(pBuffer,sizeof(pBuffer)-1, "ERROR: error %d on send", status); + SCWrite(pCon, pBuffer, eError); + return 0; } - } else if(strcmp(argv[1],"sendwithterm") == 0){ + } else if (strcmp(argv[1], "sendwithterm") == 0) { /* - send command - */ - if(argc < 5){ - SCWrite(pCon,"ERROR: insufficient number of arguments to sendwithterm", - eError); - return 0; + send command + */ + if (argc < 5) { + SCWrite(pCon, + "ERROR: insufficient number of arguments to sendwithterm", + eError); + return 0; } - if(Tcl_GetInt(pSics->pTcl,argv[2],&devID) != TCL_OK){ - SCWrite(pCon,"ERROR: failed to convert arguments to integer", - eError); - return 0; + if (Tcl_GetInt(pSics->pTcl, argv[2], &devID) != TCL_OK) { + SCWrite(pCon, "ERROR: failed to convert arguments to integer", + eError); + return 0; } - if(Tcl_GetInt(pSics->pTcl,argv[4],&terminator) != TCL_OK){ - SCWrite(pCon,"ERROR: failed to convert arguments to integer", - eError); - return 0; + if (Tcl_GetInt(pSics->pTcl, argv[4], &terminator) != TCL_OK) { + SCWrite(pCon, "ERROR: failed to convert arguments to integer", + eError); + return 0; } - strncpy(pBuffer,argv[3], 1024); - pBuffer[strlen(pBuffer)] = (char)terminator; - status = GPIBsend(self,devID,pBuffer, (int)strlen(pBuffer)); - if(status > 0){ - SCSendOK(pCon); - return 1; + strlcpy(pBuffer, argv[3], 1024); + pBuffer[strlen(pBuffer)] = (char) terminator; + status = GPIBsend(self, devID, pBuffer, (int) strlen(pBuffer)); + if (status > 0) { + SCSendOK(pCon); + return 1; } else { - sprintf(pBuffer,"ERROR: error %d on send", status); - SCWrite(pCon,pBuffer,eError); - return 0; + snprintf(pBuffer,sizeof(pBuffer)-1, "ERROR: error %d on send", status); + SCWrite(pCon, pBuffer, eError); + return 0; } - } else if(strcmp(argv[1],"read") == 0){ + } else if (strcmp(argv[1], "read") == 0) { /* - read command - */ - if(argc < 2){ - SCWrite(pCon,"ERROR: insufficient number of arguments to read", - eError); - return 0; + read command + */ + if (argc < 2) { + SCWrite(pCon, "ERROR: insufficient number of arguments to read", + eError); + return 0; } - if(Tcl_GetInt(pSics->pTcl,argv[2],&devID) != TCL_OK){ - SCWrite(pCon,"ERROR: failed to convert arguments to integer", - eError); - return 0; + if (Tcl_GetInt(pSics->pTcl, argv[2], &devID) != TCL_OK) { + SCWrite(pCon, "ERROR: failed to convert arguments to integer", + eError); + return 0; } - status = GPIBread(self,devID,pBuffer, 1023); - if(status > 0){ - SCWrite(pCon,pBuffer,eValue); - return 1; + status = GPIBread(self, devID, pBuffer, 1023); + if (status > 0) { + SCWrite(pCon, pBuffer, eValue); + return 1; } else { - sprintf(pBuffer,"ERROR: error %d on read", status); - SCWrite(pCon,pBuffer,eError); - return 0; + snprintf(pBuffer,sizeof(pBuffer)-1, "ERROR: error %d on read", status); + SCWrite(pCon, pBuffer, eError); + return 0; } - } else if(strcmp(argv[1],"readnum") == 0){ + } else if (strcmp(argv[1], "readnum") == 0) { /* - readnum command - */ - if(argc < 2){ - SCWrite(pCon,"ERROR: insufficient number of arguments to read", - eError); - return 0; + readnum command + */ + if (argc < 2) { + SCWrite(pCon, "ERROR: insufficient number of arguments to read", + eError); + return 0; } - if(Tcl_GetInt(pSics->pTcl,argv[2],&devID) != TCL_OK){ - SCWrite(pCon,"ERROR: failed to convert arguments to integer", - eError); - return 0; + if (Tcl_GetInt(pSics->pTcl, argv[2], &devID) != TCL_OK) { + SCWrite(pCon, "ERROR: failed to convert arguments to integer", + eError); + return 0; } - status = GPIBread(self,devID,&value, 4); - if(status > 0){ - sprintf(pBuffer,"gpib %d = %d",devID,value); - SCWrite(pCon,pBuffer,eValue); - return 1; + status = GPIBread(self, devID, &value, 4); + if (status > 0) { + snprintf(pBuffer,sizeof(pBuffer)-1, "gpib %d = %d", devID, value); + SCWrite(pCon, pBuffer, eValue); + return 1; } else { /* - sprintf(pBuffer,"ERROR: error %d on read", status); - SCWrite(pCon,pBuffer,eError); - */ - return 0; + snprintf(pBuffer,sizeof(pBuffer)-1,"ERROR: error %d on read", status); + SCWrite(pCon,pBuffer,eError); + */ + return 0; } - } else if(strcmp(argv[1],"readtillterm") == 0){ + } else if (strcmp(argv[1], "readtillterm") == 0) { /* - read command - */ - if(argc < 3){ - SCWrite(pCon,"ERROR: insufficient number of arguments to read", - eError); - return 0; + read command + */ + if (argc < 3) { + SCWrite(pCon, "ERROR: insufficient number of arguments to read", + eError); + return 0; } - if(Tcl_GetInt(pSics->pTcl,argv[2],&devID) != TCL_OK){ - SCWrite(pCon,"ERROR: failed to convert arguments to integer", - eError); - return 0; + if (Tcl_GetInt(pSics->pTcl, argv[2], &devID) != TCL_OK) { + SCWrite(pCon, "ERROR: failed to convert arguments to integer", + eError); + return 0; } - if(Tcl_GetInt(pSics->pTcl,argv[3],&terminator) != TCL_OK){ - SCWrite(pCon,"ERROR: failed to convert arguments to integer", - eError); - return 0; + if (Tcl_GetInt(pSics->pTcl, argv[3], &terminator) != TCL_OK) { + SCWrite(pCon, "ERROR: failed to convert arguments to integer", + eError); + return 0; } - result = GPIBreadTillTerm(self,devID,terminator); - if(result != NULL){ - SCWrite(pCon,result,eValue); - free(result); - return 1; + result = GPIBreadTillTerm(self, devID, terminator); + if (result != NULL) { + SCWrite(pCon, result, eValue); + free(result); + return 1; } else { - SCWrite(pCon,"ERROR: failed to read at GPIB",eError); - return 0; + SCWrite(pCon, "ERROR: failed to read at GPIB", eError); + return 0; } } else { - SCWrite(pCon,"ERROR: command not recognized",eError); + SCWrite(pCon, "ERROR: command not recognized", eError); return 0; } } else { - SCWrite(pCon,"ERROR: no command given to GPIB",eError); + SCWrite(pCon, "ERROR: no command given to GPIB", eError); return 0; } } @@ -340,45 +370,41 @@ int GPIBAction(SConnection *pCon, SicsInterp *pSics, void *pData, extern void NIassign(pGPIB self); #endif -int MakeGPIB(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]){ +int MakeGPIB(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ pGPIB self = NULL; - if(argc < 3){ - SCWrite(pCon,"ERROR: insufficient number of arguments to MakeGPIB", - eError); + if (argc < 3) { + SCWrite(pCon, "ERROR: insufficient number of arguments to MakeGPIB", + eError); return 0; } - self = (pGPIB)malloc(sizeof(GPIB)); - if(self == NULL){ - SCWrite(pCon,"ERROR: cannot allocate memory in MakeGPIB",eError); + self = (pGPIB) malloc(sizeof(GPIB)); + if (self == NULL) { + SCWrite(pCon, "ERROR: cannot allocate memory in MakeGPIB", eError); return 0; } - memset(self,0,sizeof(GPIB)); + memset(self, 0, sizeof(GPIB)); self->pDes = CreateDescriptor("GPIB"); strtolower(argv[2]); - if(strcmp(argv[2],"sim") == 0){ + if (strcmp(argv[2], "sim") == 0) { self->attach = SIMattach; self->detach = SIMdetach; - self->send = SIMsend; + self->send = SIMsend; self->read = SIMread; self->clear = SIMclear; self->getErrorDescription = SIMerror; #ifdef HAVENI - } else if(strcmp(argv[2],"ni") == 0){ + } else if (strcmp(argv[2], "ni") == 0) { NIassign(self); #endif } else { - SCWrite(pCon,"ERROR: GPIB driver not recognised",eError); + SCWrite(pCon, "ERROR: GPIB driver not recognised", eError); return 0; } - return AddCommand(pSics,argv[1],GPIBAction,GPIBKill,self); + return AddCommand(pSics, argv[1], GPIBAction, GPIBKill, self); } - - - - - diff --git a/gpibcontroller.h b/gpibcontroller.h index 62f19b5e..3a799eb9 100644 --- a/gpibcontroller.h +++ b/gpibcontroller.h @@ -21,28 +21,26 @@ #define GPIBENOL 2 - typedef struct __GPIB *pGPIB; +typedef struct __GPIB *pGPIB; - int GPIBattach(pGPIB self, int boardNo, - int address, int secondaryAddress, - int tmo, int eot, int eos); - int GPIBdetach(pGPIB self, int devID); - int GPIBsend(pGPIB self, int devID, void *buffer, int bytesToWrite); - int GPIBread(pGPIB self, int devID, void *buffer, int bytesToRead); - char *GPIBreadTillTerm(pGPIB self, int devID, int terminator); - void GPIBclear(pGPIB self, int devID); - void GPIBerrorDescription(pGPIB self, int code, - char *buffer, int maxBuffer); +int GPIBattach(pGPIB self, int boardNo, + int address, int secondaryAddress, + int tmo, int eot, int eos); +int GPIBdetach(pGPIB self, int devID); +int GPIBsend(pGPIB self, int devID, void *buffer, int bytesToWrite); +int GPIBread(pGPIB self, int devID, void *buffer, int bytesToRead); +char *GPIBreadTillTerm(pGPIB self, int devID, int terminator); +void GPIBclear(pGPIB self, int devID); +void GPIBerrorDescription(pGPIB self, int code, + char *buffer, int maxBuffer); - int MakeGPIB(SConnection *pCon, SicsInterp *pSics, - void *pData, - int argc, char *argv[]); - int GPIBAction(SConnection *pCon, SicsInterp *pSics, - void *pData, - int argc, char *argv[]); - +int MakeGPIB(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]); +int GPIBAction(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]); + #endif diff --git a/hdbcommand.c b/hdbcommand.c deleted file mode 100644 index 5308322c..00000000 --- a/hdbcommand.c +++ /dev/null @@ -1,291 +0,0 @@ -/** - * This module implements a generalized scheme for executing functions. - * Functions are described by a special data structure containing the - * parameters as a Hipadaba list and and an execute function which implements - * the actual operation. This is augmented by list mechanisms in order to - * allow for a list of functions. This shall facilitate a couple of things: - * - when functions are defined in such a structured form, general invocation - * functions can be devised for handling the interpreter interface. - * - The set of functions of an object can be configured and extended at - * runtime. - * - A common usage case: execute a function with the same arguments, can be - * easily catered for. - * All this is not new and was pioneered in the language self or other - * dynamic object systems. - * - * copyright: see file COPYRIGHT - * - * Mark Koennecke, September 2006 - */ -#include -#include -#include -#include -#include -/*-------------------------------------------------------------------------*/ -static int debug = 1; -/* ============================= live and death ============================*/ -pHdbCommand CreateHdbCommand(char *name, int (*execute)(pHdb parameters)){ - pHdbCommand result = NULL; - - assert(name != NULL); - assert(execute != NULL); - - result = malloc(sizeof(hdbCommand)); - if(result == NULL){ - return NULL; - } - memset(result,0,sizeof(hdbCommand)); - result->name = strdup(name); - if(result->name == NULL){ - free(result); - return NULL; - } - result->execute = execute; - return result; -} -/*--------------------------------------------------------------------------*/ -void AppendHdbCommandToList(pHdbCommand commandList, pHdbCommand command){ - pHdbCommand current = NULL; - - assert(commandList != NULL); - assert(command != NULL); - - current = commandList; - while(current->next != NULL){ - current = (pHdbCommand)current->next; - } - command->previous = (struct __hdbCommand *)current; - current->next = (struct __hdbCommand *)command; - command->next = NULL; -} -/*--------------------------------------------------------------------------*/ -void AppendCommandParameter(pHdbCommand command, pHdb par){ - assert(command != NULL); - assert(par != NULL); - - AddHipadabaChild(command->parameters,par,NULL); -} -/*--------------------------------------------------------------------------*/ -void KillHdbCommandList(pHdbCommand commandList){ - pHdbCommand next = NULL, current = NULL; - - assert(commandList != NULL); - - current = commandList; - next = (pHdbCommand)current->next; - while(current != NULL){ - if(current->name != NULL){ - free(current->name); - } - if(current->parameters != NULL){ - DeleteHipadabaNode(current->parameters,NULL); - } - free(current); - current = next; - if(current != NULL){ - next = (pHdbCommand)current->next; - } else { - next = NULL; - } - } -} -/*======================= Invocation =======================================*/ -static pHdbCommand locateCommand(pHdbCommand commandList, char *name){ - pHdbCommand current = NULL; - - current = commandList; - while(current != NULL){ - if(strcmp(current->name,name) == 0) { - return current; - } - current = (pHdbCommand)current->next; - } - return NULL; -} -/*---------------------------------------------------------------------------*/ -int HdbCommandInvoke(pHdbCommand commandList, char *name, ...){ - va_list ap; - pHdbCommand toInvoke = NULL; - pHdb currentPar = NULL; - char *txt = NULL; - hdbValue *v = NULL; - - va_start(ap,name); - toInvoke = locateCommand(commandList,name); - if(toInvoke == NULL){ - return HDBCOMNOCOM; - } - - currentPar = toInvoke->parameters; - while(currentPar != NULL){ - /* - * I cannot call a function for this as ap would be undefined after - * a call to a function here - */ - switch(currentPar->value.dataType){ - case HIPNONE: - break; - case HIPINT: - currentPar->value.v.intValue = va_arg(ap,int); - if(debug == 1){ - printf("Read %d for parameter %s\n", - currentPar->value.v.intValue, currentPar->name); - } - break; - case HIPFLOAT: - currentPar->value.v.doubleValue = va_arg(ap,double); - if(debug == 1){ - printf("Read %lf for parameter %s\n", - currentPar->value.v.doubleValue, currentPar->name); - } - break; - case HIPTEXT: - txt = va_arg(ap,char *); - if(currentPar->value.v.text != NULL){ - free(currentPar->value.v.text); - } - currentPar->value.v.text = strdup(txt); - if(debug == 1){ - printf("Read %s for parameter %s\n", - currentPar->value.v.text, currentPar->name); - } - break; - case HIPOBJ: - currentPar->value.v.obj = va_arg(ap,void *); - break; - case HIPINTAR: - case HIPINTVARAR: - case HIPFLOATAR: - case HIPFLOATVARAR: - v = (hdbValue *)va_arg(ap,void *); - copyHdbValue(v,¤tPar->value); - break; - default: - assert(0); - break; - - } - currentPar = currentPar->next; - } - va_end(ap); - return toInvoke->execute(toInvoke->parameters); -} -/*-------------------------------------------------------------------------*/ -static void *(*objMap)(char *name) = NULL; -/*-------------------------------------------------------------------------*/ -void SetHdbComObjMapper(void *(*mapObj)(char *name)){ - objMap = mapObj; -} -/*-------------------------------------------------------------------------*/ -static int readParArguments(pHdb parNode, int argc, char *argv[]){ - int i, intVal; - double doVal; - - switch(parNode->value.dataType){ - case HIPNONE: - return 0; - break; - case HIPINT: - if(argc < 1){ - return HDBCOMNOARGS; - } - if(sscanf(argv[0],"%d",&parNode->value.v.intValue) != 1){ - return HDBCOMBADARG; - } - return 1; - break; - case HIPFLOAT: - if(argc < 1){ - return HDBCOMNOARGS; - } - if(sscanf(argv[0],"%lf",&parNode->value.v.doubleValue) != 1){ - return HDBCOMBADARG; - } - return 1; - break; - case HIPOBJ: - if(objMap != NULL){ - parNode->value.v.obj = objMap(argv[0]); - if(parNode->value.v.obj == NULL){ - return HDBCOMBADOBJ; - } else { - return 1; - } - } - return 0; - break; - case HIPTEXT: - if(argc < 1){ - return HDBCOMNOARGS; - } - if(parNode->value.v.text != NULL){ - free(parNode->value.v.text); - } - parNode->value.v.text = strdup(argv[0]); - return 1; - break; - case HIPINTAR: - if(parNode->value.arrayLength > argc){ - return HDBCOMNOARGS; - } - for(i = 0; i < parNode->value.arrayLength; i++){ - if(sscanf(argv[i],"%d",&intVal) != 1){ - return HDBCOMBADARG; - } - parNode->value.v.intArray[i] = intVal; - } - return parNode->value.arrayLength; - break; - case HIPFLOATAR: - if(parNode->value.arrayLength > argc){ - return HDBCOMNOARGS; - } - for(i = 0; i < parNode->value.arrayLength; i++){ - if(sscanf(argv[i],"%lf",&doVal) != 1){ - return HDBCOMBADARG; - } - parNode->value.v.floatArray[i] = doVal; - } - return parNode->value.arrayLength; - break; - default: - /* - * I cannot process such variables - */ - return HDBCOMINVARG; - break; - } - return 0; -} -/*--------------------------------------------------------------------------*/ -int HdbCommandTextInvoke(pHdbCommand commandList, int argc, char *argv[]){ - pHdbCommand toInvoke = NULL; - pHdb currentPar = NULL; - int argPointer, status; - - assert(commandList != NULL); - - if(argc < 1){ - return HDBCOMNOARGS; - } - - toInvoke = locateCommand(commandList,argv[0]); - if(toInvoke == NULL){ - return HDBCOMNOCOM; - } - - currentPar = toInvoke->parameters; - argPointer = 1; - while(currentPar != NULL){ - status = readParArguments(currentPar,argc-argPointer, - &argv[argPointer]); - if(status < 0){ - return status; - } else { - argPointer += status; - } - currentPar = currentPar->next; - } - return toInvoke->execute(toInvoke->parameters); -} diff --git a/hdbcommand.h b/hdbcommand.h deleted file mode 100644 index b1b8285f..00000000 --- a/hdbcommand.h +++ /dev/null @@ -1,96 +0,0 @@ -/** - * This module implements a generalized scheme for executing functions. - * Functions are described by a special data structure containing the - * parameters as a Hipadaba list and and an execute function which implements - * the actual operation. This is augmented by list mechanisms in order to - * allow for a list of functions. This shall facilitate a couple of things: - * - when functions are defined in such a structured form, general invocation - * functions can be devised for handling the interpreter interface. - * - The set of functions of an object can be configured and extended at - * runtime. - * - A common usage case: execute a function with the same arguments, can be - * easily catered for. - * All this is not new and was pioneered in the language self or other - * dynamic object systems. - * - * copyright: see file COPYRIGHT - * - * Mark Koennecke, September 2006 - */ -#ifndef HDBCOMMAND_H_ -#define HDBCOMMAND_H_ -#include -#include -/*--------------- error codes ----------------------------------------------*/ -#define HDCOMNOMEM -7801 -#define HDBCOMNOCOM -7802 -#define HDBCOMNOARGS -7803 -#define HDBCOMBADARG -7804 -#define HDBCOMINVARG -7805 -#define HDBCOMBADOBJ -7806 -/*---------------------------------------------------------------------------*/ -typedef struct __hdbCommmand { - char *name; - pHdb parameters; - int (*execute)(pHdb parameters); - struct __hdbCommand *next; - struct __hdbCommand *previous; -}hdbCommand, *pHdbCommand; -/*======================= live and death ===================================*/ -/** - * create a hdbCommand with an empty parameter list - * @param name The name of teh command - * @param execute The execute function for this command - * @return a fresh hdbCommand or NULL when out of memory - * */ -pHdbCommand CreateHdbCommand(char *name, int (*execute)(pHdb parameters)); -/** - * append a hdbCommand to a command list - * @param commandList The list to append the command to - * @param command The command to append - * @return 1 on success, a negative error code else. - */ -void AppendHdbCommandToList(pHdbCommand commandList, pHdbCommand command); -/** - * append a parameter to the parameter list - * @param command The command to append the parameter too - * @param par The parameter to append - */ -void AppendCommandParameter(pHdbCommand command, pHdb par); -/** - * delete a command list recursively - * @param commandList The command list to delete - */ -void KillHdbCommandList(pHdbCommand commandList); -/*===================== invocation ========================================*/ -/** - * invoke a hdbCommand name. This does a lot: it locates the command, - * it assigne the parameter values and finally calls the execute function. - * @param commandList The command list in which to search for the command - * @param name The name of the command - * @param ... arguments to the command. ints, double, text and objects (pointers) - * are accepted as is.Arrays have to be passed in a pointers to a - * hdbValue structure. Otherwise there is not eonough information to safely - * copy array data. - * @return Negative error codes on invocation error, else the return - * value of the execute function. - */ -int HdbCommandInvoke(pHdbCommand commandList, char *name, ...); -/** - * invoke a hdbCommand name. This does a lot: it locates the command, - * it assigne the parameter values and finally calls the execute function. - * The name of the command must be in argv[0] - * @param commandList The command list in which to search for the command - * @param argc The number of arguments - * @param argv[] An array of strings holding the argument data - * @return Negative error codes on invocation error, else the return - * value of the execute function. - */ -int HdbCommandTextInvoke(pHdbCommand commandList, int argc, char *argv[]); -/** - * set a mapper which returns a void pointer for a name in order to resolve - * object references - * @param mapfunc - */ -void SetHdbComObjMapper(void *(*mapObj)(char *name)); -#endif /*HDBCOMMAND_H_*/ diff --git a/hdbqueue.c b/hdbqueue.c deleted file mode 100644 index 88757825..00000000 --- a/hdbqueue.c +++ /dev/null @@ -1,497 +0,0 @@ -/** - * This is the new Hipadaba based queuing system in support of the MountainGum - * user interface. - * - * copyright: see file COPYRIGHT - * - * Mark Koennecke, July 2007 - */ -#include -#include -#include -#include "sicsobj.h" -#include "hdbqueue.h" -#include "sicshipadaba.h" -#include "dynstring.h" -#include "exeman.h" -#include "macro.h" -/*--------------------------------------------------------------------------*/ -typedef struct { - int iStop; - int isRunning; - SConnection *pCon; -}HdbQueue, *pHdbQueue; -/*--------------------------------------------------------------------------*/ -static pHdbCallback CopyCallbackChain(pHdbCallback source){ - pHdbCallback current = NULL; - pHdbCallback result = NULL; - pHdbCallback head = NULL; - pHdbCallback tail = NULL; - - current = source; - while(current != NULL){ - result = MakeHipadabaCallback(current->userCallback, - current->userData, - NULL, - current->id, - current->internalID); - if(head == NULL){ - head = result; - tail = result; - } else { - tail->next = result; - result->previous = tail; - tail = result; - } - current = current->next; - } - return head; -} -/*---------------------------------------------------------------------------*/ -static pHdb MakeNewEntry(char *name, pHdbCallback update){ - pHdb entry = NULL, child = NULL; - hdbValue v; - - v = MakeHdbText("Undefined"); - entry = MakeHipadabaNode(name,HIPNONE, 1); - entry->updateCallbacks = CopyCallbackChain(update); - child = MakeSICSHdbPar("description",usUser,v); - child->updateCallbacks = CopyCallbackChain(update); - AddHipadabaChild(entry,child,NULL); - child = MakeSICSHdbPar("commands",usUser,v); - child->updateCallbacks = CopyCallbackChain(update); - AddHipadabaChild(entry,child,NULL); - child = MakeSICSHdbPar("log",usUser,v); - child->updateCallbacks = CopyCallbackChain(update); - AddHipadabaChild(entry,child,NULL); - - return entry; -} -/*---------------------------------------------------------------------------*/ -static int EnqueFunc(pSICSOBJ self, SConnection *pCon, Hdb commandNode, - pHdb par[], int nPar){ - pHdb entry = NULL; - pHdb work = NULL; - char name[80]; - hdbValue v; - - if(nPar < 1){ - SCWrite(pCon,"ERROR: internal: not enough parameters to EnqueFunc",eError); - return 0; - } - - /* - * new entry - */ - memset(&v,0,sizeof(hdbValue)); - work = GetHipadabaNode(self->objectNode,"control/maxEntry"); - assert(work != NULL); - snprintf(name,80,"%3.3d", work->value.v.intValue); - entry = MakeNewEntry(name, work->updateCallbacks); - if(entry == NULL){ - SCWrite(pCon,"ERROR: out of memory in EnqueFunc",eError); - return 0; - } - /* - * Update maxEntry - */ - cloneHdbValue(&work->value,&v); - v.v.intValue++; - UpdateHipadabaPar(work,v,pCon); - - work = GetHipadabaNode(self->objectNode,"queue"); - assert(work != NULL); - AddHipadabaChild(work, entry, pCon); - - /* - * save description - */ - work = GetHipadabaNode(entry,"description"); - assert(work != NULL); - UpdateHipadabaPar(work,par[0]->value,pCon); - - - return 1; -} -/*---------------------------------------------------------------------------*/ -static int AddCmdData(pSICSOBJ self, SConnection *pCon, Hdb comNode, - pHdb par[], int nPar){ - pHdb work = NULL; - pHdb commandNode = NULL; - char name[80]; - pDynString txt = NULL; - - if(nPar < 1){ - SCWrite(pCon,"ERROR: internal: not enough parameters to AddCmdData",eError); - return 0; - } - - work = GetHipadabaNode(self->objectNode,"control/maxEntry"); - assert(work != NULL); - snprintf(name,80,"queue/%3.3d/commands", work->value.v.intValue-1); - commandNode = GetHipadabaNode(self->objectNode,name); - if(commandNode == NULL){ - SCWrite(pCon,"ERROR: Internal error in AddCommand",eError); - return 0; - } - txt = CreateDynString(80,80); - if(strstr(commandNode->value.v.text,"Undefined") == NULL){ - DynStringCopy(txt,commandNode->value.v.text); - } - DynStringConcat(txt,par[0]->value.v.text); - DynStringConcat(txt,"\n"); - free(commandNode->value.v.text); - commandNode->value.v.text = strdup(GetCharArray(txt)); - NotifyHipadabaPar(commandNode,pCon); - DeleteDynString(txt); - return 1; -} -/*--------------------------------------------------------------------------*/ -static void sequentialNames(pHdb obj,SConnection *pCon){ - pHdb work = NULL; - pHdb current = NULL; - int count = 0; - char name[80]; - - work = GetHipadabaNode(obj,"queue"); - assert(work != NULL); - current = work->child; - while(current != NULL){ - snprintf(name,80,"%3.3d",count); - if(current->name != NULL){ - free(current->name); - } - current->name = strdup(name); - count++; - current = current->next; - } - InvokeCallbackChain(work->treeChangeCallbacks,work,pCon,work->value); - - work = GetHipadabaNode(obj,"control/maxEntry"); - assert(work != NULL); - work->value.v.intValue = count; - NotifyHipadabaPar(work,pCon); -} -/*---------------------------------------------------------------------------*/ -static int Dequeue(pSICSOBJ self, SConnection *pCon, pHdb commandNode, - pHdb par[], int nPar){ - pHdb work = NULL; - char name[80]; - pHdbQueue priv = (pHdbQueue)self->pPrivate; - - if(priv->isRunning == 1){ - SCWrite(pCon,"ERROR: cannot dequeue while running",eError); - return 0; - } - - - if(nPar < 1){ - SCWrite(pCon,"ERROR: internal: not enough parameters to Dequeue",eError); - return 0; - } - - snprintf(name,80,"queue/%3.3d", par[0]->value.v.intValue); - work = GetHipadabaNode(self->objectNode,name); - if(work != NULL){ - DeleteHipadabaNode(work,pCon); - sequentialNames(self->objectNode, pCon); - return 1; - } - - return 0; -} -/*---------------------------------------------------------------------------*/ -static int Clean(pSICSOBJ self, SConnection *pCon,Hdb commandNode, - pHdb par[], int nPar){ - int i; - pHdb current = NULL, queue = NULL; - pHdb currentEntry = NULL, tmp = NULL; - pHdbQueue priv = (pHdbQueue)self->pPrivate; - - if(priv->isRunning == 1){ - SCWrite(pCon,"ERROR: cannot clean while running",eError); - return 0; - } - currentEntry = GetHipadabaNode(self->objectNode,"control/currentEntry"); - queue = GetHipadabaNode(self->objectNode,"queue"); - current = queue->child; - for(i = 0; i < currentEntry->value.v.intValue; i++){ - if(current != NULL){ - tmp = current->next; - DeleteNodeData(current); - current = tmp; - } - } - queue->child = tmp; - currentEntry->value.v.intValue = 0; - sequentialNames(self->objectNode, pCon); - NotifyHipadabaPar(currentEntry,pCon); - return 1; -} -/*---------------------------------------------------------------------------*/ -static int CleanAll(pSICSOBJ self, SConnection *pCon, pHdb commandNode, - pHdb par[], int nPar){ - int i; - pHdb current = NULL, queue = NULL; - pHdb currentEntry = NULL, tmp; - pHdbQueue priv = (pHdbQueue)self->pPrivate; - - if(priv->isRunning == 1){ - SCWrite(pCon,"ERROR: cannot clear queue while executing",eError); - return 0; - } - currentEntry = GetHipadabaNode(self->objectNode,"control/currentEntry"); - queue = GetHipadabaNode(self->objectNode,"queue"); - current = queue->child; - while(current != NULL){ - tmp = current->next; - DeleteNodeData(current); - current = tmp; - } - queue->child = NULL; - currentEntry->value.v.intValue = 0; - sequentialNames(self->objectNode, pCon); - NotifyHipadabaPar(currentEntry,pCon); - return 1; -} -/*----------------------------------------------------------------------------*/ -static int QueueTask(void *pData){ - pSICSOBJ self = (pSICSOBJ)pData; - int status, pos; - pHdb work = NULL; - pHdb exeNode = NULL; - pHdb max = NULL; - char name[80]; - pHdbQueue priv = (pHdbQueue)self->pPrivate; - - if(priv->iStop == 1){ - priv->isRunning = 0; - return 0; - } - - work = GetHipadabaNode(self->objectNode,"control/currentEntry"); - max = GetHipadabaNode(self->objectNode,"control/maxEntry"); - assert(work != NULL && max != NULL); - pos = work->value.v.intValue; - snprintf(name,80,"queue/%3.3d", pos); - - exeNode = GetHipadabaNode(self->objectNode,name); - if(exeNode != NULL){ - MacroPush(priv->pCon); - exeHdbNode(exeNode, priv->pCon); - MacroPop(); - } - if(priv->iStop == 1 || SCGetInterrupt(priv->pCon) != eContinue){ - priv->isRunning = 0; - return 0; - } - - pos++; - work->value.v.intValue = pos; - NotifyHipadabaPar(work,priv->pCon); - if(pos >= max->value.v.intValue){ - priv->isRunning = 0; - return 0; - } - - return 1; -} -/*---------------------------------------------------------------------------*/ -static int Start(pSICSOBJ self, SConnection *pCon, pHdb commandNode, - pHdb par[], int nPar){ - pHdbQueue priv = (pHdbQueue)self->pPrivate; - - priv->iStop = 0; - priv->pCon = pCon; - - if(priv->isRunning == 1){ - SCWrite(pCon,"ERROR: Hdbqueue is already running",eError); - return 0; - } - priv->isRunning = 1; - - TaskRegister(pServ->pTasker, - QueueTask, - NULL, - NULL, - self, - 10); - return 1; -} -/*---------------------------------------------------------------------------*/ -static int Restart(pSICSOBJ self, SConnection *pCon, pHdb commandNode, - pHdb par[], int nPar){ - pHdbQueue priv = (pHdbQueue)self->pPrivate; - pHdb maxCurrent = NULL; - - maxCurrent = GetHipadabaNode(self->objectNode,"control/currentEntry"); - if(maxCurrent != NULL){ - maxCurrent->value.v.intValue = 0; - NotifyHipadabaPar(maxCurrent,pCon); - } - - return Start(self,pCon,commandNode,par,nPar); -} -/*---------------------------------------------------------------------------*/ -static int Stop(pSICSOBJ self, SConnection *pCon, pHdb commandNode, - pHdb par[], int nPar){ - pHdbQueue priv = (pHdbQueue)self->pPrivate; - - priv->iStop = 1; - return 1; -} -/*----------------------------------------------------------------------------*/ -static int Move(pSICSOBJ self, SConnection *pCon, pHdb commandNode, - pHdb par[], int nPar){ - pHdb moveNode = NULL; - pHdb insertNode = NULL; - pHdb prevNode = NULL, queueNode = NULL; - pHdb tmp; - char name[80]; - pHdbQueue priv = (pHdbQueue)self->pPrivate; - - if(priv->isRunning == 1){ - SCWrite(pCon,"ERROR: cannot move while running",eError); - return 0; - } - - if(nPar < 2){ - SCWrite(pCon,"ERROR: internal: not enough parameters to Move",eError); - return 1; - } - - if(par[1]->value.v.intValue == par[0]->value.v.intValue + 1){ - /* - * already in right sequence, nothing to do - */ - return 1; - } - - snprintf(name,80,"queue/%3.3d", par[1]->value.v.intValue); - moveNode = GetHipadabaNode(self->objectNode,name); - - snprintf(name,80,"queue/%3.3d", par[0]->value.v.intValue); - insertNode = GetHipadabaNode(self->objectNode,name); - if(moveNode == NULL || insertNode == NULL){ - SCWrite(pCon,"ERROR: move not possible, participating nodes not found", - eError); - return 0; - } - queueNode = GetHipadabaNode(self->objectNode,"queue"); - - if(moveNode == queueNode->child){ - queueNode->child = queueNode->child->next; - moveNode->next = insertNode->next; - insertNode->next = moveNode; - } else { - prevNode = queueNode->child; - while(prevNode != NULL && prevNode->next != moveNode){ - prevNode = prevNode->next; - } - if(insertNode == queueNode->child ){ - /* - * insert at top - */ - tmp = queueNode->child; - queueNode->child = moveNode; - prevNode->next = moveNode->next; - moveNode->next = tmp; - } else { - tmp = insertNode->next; - insertNode->next = moveNode; - prevNode->next = moveNode->next; - moveNode->next = tmp; - } - } - sequentialNames(self->objectNode, pCon); - - return 1; -} -/*---------------------------------------------------------------------------*/ -static void Configure(pSICSOBJ self){ - pHdb n = NULL, par = NULL; - hdbValue intValue, textValue, funcValue; - pHdb obj = self->objectNode; - - intValue = MakeHdbInt(0); - textValue = MakeHdbText("Undefined"); - - n = MakeHipadabaNode("control",HIPNONE,1); - AddHipadabaChild(obj,n,NULL); - AddSICSHdbPar(n,"maxEntry",usInternal,intValue); - AddSICSHdbPar(n,"currentEntry",usInternal,intValue); - - - n = MakeHipadabaNode("queue",HIPNONE,1); - AddHipadabaChild(obj,n, NULL); - - funcValue = MakeSICSFunc(EnqueFunc); - n = MakeSICSHdbPar("enqueue",usUser, funcValue); - AddSICSHdbPar(n,"description",usUser,textValue); - AddHipadabaChild(obj,n,NULL); - AppendHipadabaCallback(n,HCBSET,MakeSICSFuncCallback(self)); - - funcValue = MakeSICSFunc(AddCmdData); - n = MakeSICSHdbPar("addcommand",usUser, funcValue); - AddSICSHdbPar(n,"command",usUser,textValue); - AddHipadabaChild(obj,n,NULL); - AppendHipadabaCallback(n,HCBSET,MakeSICSFuncCallback(self)); - - - funcValue = MakeSICSFunc(Dequeue); - n = MakeSICSHdbPar("dequeue",usUser,funcValue); - AddHipadabaChild(obj,n,NULL); - AddSICSHdbPar(n,"index",usUser,intValue); - AppendHipadabaCallback(n,HCBSET,MakeSICSFuncCallback(self)); - - - funcValue = MakeSICSFunc(Clean); - n = MakeSICSHdbPar("clean",usUser, funcValue); - AddHipadabaChild(obj,n,NULL); - AppendHipadabaCallback(n,HCBSET,MakeSICSFuncCallback(self)); - - funcValue = MakeSICSFunc(CleanAll); - n = MakeSICSHdbPar("cleanall",usUser, funcValue); - AddHipadabaChild(obj,n,NULL); - AppendHipadabaCallback(n,HCBSET,MakeSICSFuncCallback(self)); - - funcValue = MakeSICSFunc(Start); - n = MakeSICSHdbPar("start",usUser, funcValue); - AddHipadabaChild(obj,n,NULL); - AppendHipadabaCallback(n,HCBSET,MakeSICSFuncCallback(self)); - - funcValue = MakeSICSFunc(Restart); - n = MakeSICSHdbPar("restart",usUser, funcValue); - AddHipadabaChild(obj,n,NULL); - AppendHipadabaCallback(n,HCBSET,MakeSICSFuncCallback(self)); - - funcValue = MakeSICSFunc(Stop); - n = MakeSICSHdbPar("stop",usUser, funcValue); - AddHipadabaChild(obj,n,NULL); - AppendHipadabaCallback(n,HCBSET,MakeSICSFuncCallback(self)); - - funcValue = MakeSICSFunc(Move); - n = MakeSICSHdbPar("move",usUser,funcValue); - AddHipadabaChild(obj,n,NULL); - AddSICSHdbPar(n,"moveindex",usUser,intValue); - AddSICSHdbPar(n,"insertindex",usUser,intValue); - AppendHipadabaCallback(n,HCBSET,MakeSICSFuncCallback(self)); - -} -/*---------------------------------------------------------------------------*/ -int MakeHDBQueue(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]){ - pSICSOBJ self = NULL; - pHdbQueue priv = NULL; - - priv = (pHdbQueue)malloc(sizeof(HdbQueue)); - self = SetupSICSOBJ(pCon,pSics, pData,argc, argv); - if(self == NULL || priv == NULL){ - return 0; - } - Configure(self); - memset(priv,0,sizeof(HdbQueue)); - self->pPrivate = priv; - self->KillPrivate = free; - return 1; -} diff --git a/hdbqueue.h b/hdbqueue.h deleted file mode 100644 index a1663da8..00000000 --- a/hdbqueue.h +++ /dev/null @@ -1,15 +0,0 @@ -/** - * This is the new Hipadab based queuing system in support of the MountainGum - * user interface. - * - * copyright: see file COPYRIGHT - * - * Mark Koennecke, July 2007 - */ -#ifndef HDBQUEUE_H_ -#define HDBQUEUE_H_ - -int MakeHDBQueue(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - -#endif /*HDBQUEUE_H_*/ diff --git a/hdbtable.c b/hdbtable.c new file mode 100644 index 00000000..abdc7efc --- /dev/null +++ b/hdbtable.c @@ -0,0 +1,500 @@ +/** + * Hdbtable is a more generic implementation for a table based on a Hipadaba + * tree structure. This table will be used at various instances in SICS. The general + * approach is that there is a child node called template whose children will be + * the nodes describing each column. Another entry called data will hold the + * rows of the table. Each row is a clone of the template. The result is + * an inefficient mapping of a table into a tree. But then, for smaller tables this + * is good enough and fits nicely into the Hipadaba and gumtree schemes. This file + * provides a couple of commands to deal with such tables. A user of this module will + * have to add content to the template first. And then run readtemplate in order + * to activate the new structure. + * + * I use a descriptor key called rowcount for the row ID management rather then + * the private data structure. This leaves clients of this module to use the + * private data structure at will. + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, March 2009 + */ +#include +#include "sicshipadaba.h" +#include +/*------------------------------------------------------------------------*/ +int SaveHdbTable(void *data, char *name, FILE * fd) +{ + pSICSOBJ self = (pSICSOBJ) data; + pHdb datanode, row, child; + pDynString val; + + datanode = GetHipadabaNode(self->objectNode,"data"); + assert(datanode != NULL); + row = datanode->child; + fprintf(fd,"%s clear\n", name); + while(row != NULL){ + fprintf(fd,"%s addrow ", name); + child = row->child; + while(child != NULL){ + val = formatValue(child->value, child); + if(val != NULL){ + fprintf(fd," %s", GetCharArray(val)); + DeleteDynString(val); + } + child = child->next; + } + fprintf(fd,"\n"); + row = row->next; + } + return 1; +} +/*------------------------------------------------------------------------*/ +static int ClearTblCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode, + pHdb par[], int nPar) +{ + pHdb node, child, tmp; + + node = GetHipadabaNode(self->objectNode,"data"); + if(node != NULL){ + if(CountHdbChildren(node) < 1){ + return 1; + } + child = node->child; + while(child != NULL){ + tmp = child; + child = child->next; + DeleteNodeData(tmp); + } + } + node->child = NULL; + SendTreeChangeMessage(node,pCon); + SetDescriptorKey(self->pDes,"rowcount","0"); + if(pCon != NULL){ + SCparChange(pCon); + } + return 1; +} +/*----------------------------------------------------------------------*/ +static int AddTblRowCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode, + pHdb par[], int nPar) +{ + int count; + char *ct, number[10]; + pHdb row, val, child, template; + + ct = GetDescriptorKey(self->pDes,"rowcount"); + count = atoi(ct); + snprintf(number,10,"%4.4d", count); + row = MakeHipadabaNode(number,HIPNONE,1); + if(row == NULL){ + SCWrite(pCon,"ERROR: out of memory in AddTblRow", eError); + return 0; + } + count++; + snprintf(number,10,"%d",count); + SetDescriptorKey(self->pDes,"rowcount",number); + SetHdbProperty(row,"__save","true"); + + template = GetHipadabaNode(self->objectNode,"template"); + assert(template != NULL); + child = template->child; + count = 0; + while(child != NULL){ + val = MakeSICSHdbPar(child->name,usUser, + makeHdbValue(child->value.dataType, child->value.arrayLength)); + if(count < nPar){ + UpdateHipadabaPar(val,par[count]->value,pCon); + } + AddHipadabaChild(row,val, pCon); + SetHdbProperty(val,"__save","true"); + count++; + child = child->next; + } + child = GetHipadabaNode(self->objectNode,"data"); + assert(child != NULL); + AddHipadabaChild(child,row, pCon); + SendTreeChangeMessage(child,pCon); + if(pCon != NULL){ + SCparChange(pCon); + } + return 1; +} +/*----------------------------------------------------------------------*/ +static int RepTblRowCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode, + pHdb par[], int nPar) +{ + int count; + char path[132]; + pHdb row, val, child; + + if(nPar < 1) { + SCPrintf(pCon,eError,"ERROR: no parameters found to reprow"); + return 0; + } + snprintf(path,131,"data/%s", par[0]->value.v.text); + row = GetHipadabaNode(self->objectNode,path); + if(row == NULL){ + SCPrintf(pCon,eError,"ERROR: row with ID %s not found", par[0]->value.v.text); + return 0; + } + + child = row->child; + count = 1; + while(child != NULL && count < nPar){ + if(count < nPar){ + UpdateHipadabaPar(child,par[count]->value,pCon); + } + count++; + child = child->next; + } + if(pCon != NULL){ + SCparChange(pCon); + } + return 1; +} +/*---------------------------------------------------------------------- + * ReadTemplateCmd does something interesting: it rewrites the parameter + * lists of both addrow and reprow according to the template + * ---------------------------------------------------------------------*/ +int ReadTableTemplate(pSICSOBJ self, SConnection *con) +{ + pHdb node, template, child, cmd; + SConnection *pCon = con; + + if(pCon == NULL){ + pCon = pServ->dummyCon; + } + + template = GetHipadabaNode(self->objectNode,"template"); + assert(template != NULL); + + /* mogrify addrow */ + node = GetHipadabaNode(self->objectNode,"addrow"); + if(node != NULL){ + DeleteHipadabaNode(node,pCon); + } + + cmd = AddSICSHdbPar(self->objectNode, "addrow", usUser, + MakeSICSFunc(AddTblRowCmd)); + if(cmd == NULL){ + SCWrite(pCon,"ERROR: out of memory in ReadTemplateCmd",eError ); + return 0; + } + SetHdbProperty(cmd,"type","command"); + SetHdbProperty(cmd,"priv","user"); + child = template->child; + while(child != NULL){ + node = MakeSICSHdbPar(child->name, usUser, + makeHdbValue(child->value.dataType, child->value.arrayLength)); + if(node == NULL){ + SCWrite(pCon,"ERROR: out of memory in ReadTemplateCmd",eError ); + return 0; + } + AddHipadabaChild(cmd,node,pCon); + child = child->next; + } + + /* mogrify reprow */ + node = GetHipadabaNode(self->objectNode,"reprow"); + if(node != NULL){ + DeleteHipadabaNode(node,pCon); + } + cmd = AddSICSHdbPar(self->objectNode, "reprow", usUser, + MakeSICSFunc(RepTblRowCmd)); + if(cmd == NULL){ + SCWrite(pCon,"ERROR: out of memory in ReadTemplateCmd",eError ); + return 0; + } + SetHdbProperty(cmd,"type","command"); + SetHdbProperty(cmd,"priv","user"); + node = MakeSICSHdbPar("id",usUser, makeHdbValue(HIPTEXT,1)); + AddHipadabaChild(cmd,node, pCon); + + child = template->child; + while(child != NULL){ + node = MakeSICSHdbPar(child->name, usUser, + makeHdbValue(child->value.dataType, child->value.arrayLength)); + if(node == NULL){ + SCWrite(pCon,"ERROR: out of memory in ReadTemplateCmd",eError ); + return 0; + } + AddHipadabaChild(cmd,node,pCon); + child = child->next; + } + return 1; +} +/*----------------------------------------------------------------------*/ +static int ReadTemplateCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode, + pHdb par[], int nPar) +{ + return ReadTableTemplate(self,pCon); +} +/*----------------------------------------------------------------------*/ +static int DelRowCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode, + pHdb par[], int nPar) +{ + pHdb row = NULL, data; + char path[132]; + + if(nPar < 1){ + SCWrite(pCon,"ERROR: need ID of row to kill",eError); + return 0; + } + snprintf(path,132,"data/%s",par[0]->value.v.text); + row = GetHipadabaNode(self->objectNode,path); + if(row == NULL){ + SCPrintf(pCon,eError,"ERROR: row with ID %s not found", par[0]->value.v.text); + return 0; + } + data = row->mama; + DeleteHipadabaNode(row,pCon); + if(pCon != NULL){ + SCparChange(pCon); + } + SendTreeChangeMessage(data,pCon); + SCSendOK(pCon); + return 1; +} +/*----------------------------------------------------------------------*/ +static int GetRowCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode, + pHdb par[], int nPar) +{ + pHdb row = NULL, child; + char path[132]; + pDynString result, val; + + if(nPar < 1){ + SCWrite(pCon,"ERROR: need ID of row to read",eError); + return 0; + } + snprintf(path,132,"data/%s",par[0]->value.v.text); + row = GetHipadabaNode(self->objectNode,path); + if(row == NULL){ + SCPrintf(pCon,eError,"ERROR: row with ID %s not found", par[0]->value.v.text); + return 0; + } + result = CreateDynString(128,128); + if(result == NULL){ + SCWrite(pCon,"ERROR: out of memory in GetRowCmd", eError); + return 0; + } + child = row->child; + while(child != NULL){ + val = formatValue(child->value, child); + if(val != NULL){ + DynStringConcat(result,GetCharArray(val)); + if(child->next != NULL){ + DynStringConcatChar(result,','); + } + DeleteDynString(val); + } + child = child->next; + } + SCWrite(pCon,GetCharArray(result),eValue); + DeleteDynString(result); + return 1; +} +/*----------------------------------------------------------------------*/ +static int GetRowNoCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode, + pHdb par[], int nPar) +{ + pHdb row = NULL, child, data; + int i, nodeNo; + char path[132]; + pDynString result, val; + + if(nPar < 1){ + SCWrite(pCon,"ERROR: need index of row to read",eError); + return 0; + } + nodeNo = par[0]->value.v.intValue; + + data = GetHipadabaNode(self->objectNode,"data"); + assert(data != NULL); + row = data->child; + for(i = 0; i < nodeNo; i++){ + row = row->next; + if(row == NULL){ + SCPrintf(pCon,eError,"ERROR: row %d not found", nodeNo); + return 0; + } + } + + result = CreateDynString(128,128); + if(result == NULL){ + SCWrite(pCon,"ERROR: out of memory in GetRowCmd", eError); + return 0; + } + child = row->child; + while(child != NULL){ + val = formatValue(child->value, child); + if(val != NULL){ + DynStringConcat(result,GetCharArray(val)); + if(child->next != NULL){ + DynStringConcatChar(result,','); + } + DeleteDynString(val); + } + child = child->next; + } + SCWrite(pCon,GetCharArray(result),eValue); + DeleteDynString(result); + return 1; +} +/*----------------------------------------------------------------------*/ +static int ListTblCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode, + pHdb par[], int nPar) +{ + pHdb node, row, child, data, template; + char buffer[20]; + pDynString list = NULL, val; + + list = CreateDynString(25,256); + if(list == NULL){ + SCWrite(pCon,"ERROR: out of memory in LisTblCmd", eError); + return 0; + } + + /* + * create the list header + */ + DynStringConcat(list," ID"); + template = GetHipadabaNode(self->objectNode,"template"); + assert(template != NULL); + child = template->child; + while(child != NULL){ + snprintf(buffer,20," %8s", child->name); + DynStringConcat(list,buffer); + child = child->next; + } + DynStringConcatChar(list,'\n'); + + data = GetHipadabaNode(self->objectNode,"data"); + assert(data != NULL); + + /* + * list the data + */ + row = data->child; + while(row != NULL){ + snprintf(buffer,20," %8s", row->name); + DynStringConcat(list,buffer); + child = row->child; + while(child != NULL){ + val = formatValue(child->value,child); + snprintf(buffer,20," %8s", GetCharArray(val)); + DynStringConcat(list,buffer); + DeleteDynString(val); + child = child->next; + } + DynStringConcatChar(list,'\n'); + row = row->next; + } + + SCWrite(pCon,GetCharArray(list),eValue); + DeleteDynString(list); + return 1; +} +/*----------------------------------------------------------------------*/ +pSICSOBJ MakeHdbTable(char *name, char *hdbclass) +{ + pSICSOBJ result = NULL; + pHdb node, cmd; + + result = MakeSICSOBJv(name,hdbclass,HIPNONE,usSpy); + if(result == NULL){ + return NULL; + } + SetDescriptorKey(result->pDes,"rowcount","0"); + SetHdbProperty(result->objectNode,"viewer","mountaingumui.TableViewer"); + result->pDes->SaveStatus = SaveHdbTable; + + node = MakeSICSHdbPar("template",usMugger,MakeHdbText("x,y")); + if(node == NULL){ + return NULL; + } + SetHdbProperty(node,"__save","true"); + + AddHipadabaChild(result->objectNode,node,NULL); + node = MakeHipadabaNode("data",HIPNONE,1); + if(node == NULL){ + return NULL; + } + SetHdbProperty(node,"__save","true"); + AddHipadabaChild(result->objectNode,node,NULL); + + cmd = AddSICSHdbPar(result->objectNode, "clear", usUser, + MakeSICSFunc(ClearTblCmd)); + SetHdbProperty(cmd,"type","command"); + SetHdbProperty(cmd,"priv","user"); + + cmd = AddSICSHdbPar(result->objectNode, "print", usUser, + MakeSICSFunc(ListTblCmd)); + SetHdbProperty(cmd,"type","command"); + SetHdbProperty(cmd,"priv","user"); + + cmd = AddSICSHdbPar(result->objectNode, "addrow", usUser, + MakeSICSFunc(AddTblRowCmd)); + SetHdbProperty(cmd,"type","command"); + SetHdbProperty(cmd,"priv","user"); + + cmd = AddSICSHdbPar(result->objectNode, "reprow", usUser, + MakeSICSFunc(RepTblRowCmd)); + SetHdbProperty(cmd,"type","command"); + SetHdbProperty(cmd,"priv","user"); + + cmd = AddSICSHdbPar(result->objectNode, "readtemplate", usUser, + MakeSICSFunc(ReadTemplateCmd)); + + cmd = AddSICSHdbPar(result->objectNode, "del", usUser, + MakeSICSFunc(DelRowCmd)); + node = MakeHipadabaNode("id",HIPTEXT,1); + SetHdbProperty(cmd,"type","command"); + SetHdbProperty(cmd,"priv","user"); + SetHdbProperty(node,"priv","user"); + AddHipadabaChild(cmd,node, NULL); + + cmd = AddSICSHdbPar(result->objectNode, "get", usUser, + MakeSICSFunc(GetRowCmd)); + SetHdbProperty(cmd,"type","command"); + SetHdbProperty(cmd,"priv","user"); + node = MakeHipadabaNode("id",HIPTEXT,1); + SetHdbProperty(node,"priv","user"); + AddHipadabaChild(cmd,node, NULL); + + cmd = AddSICSHdbPar(result->objectNode, "getno", usUser, + MakeSICSFunc(GetRowNoCmd)); + SetHdbProperty(cmd,"type","command"); + SetHdbProperty(cmd,"priv","user"); + node = MakeHipadabaNode("id",HIPINT,1); + SetHdbProperty(node,"priv","user"); + AddHipadabaChild(cmd,node, NULL); + + return result; +} +/*---------------------------------------------------------------------------*/ +int HdbTableFactory(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]) +{ + pSICSOBJ pNew = NULL; + int status; + + if(argc < 2) { + SCWrite(pCon,"ERROR: need name of table to create", eError); + return 0; + } + + pNew = MakeHdbTable(argv[1],"HdbTable"); + if(pNew == NULL){ + SCWrite(pCon,"ERROR: out of memory in MakeHdbTable", eError); + return 0; + } + + status = AddCommand(pSics, argv[1], InterInvokeSICSOBJ, DefaultKill, pNew); + if (status != 1) { + SCWrite(pCon, "ERROR: duplicate HdbTable command not created", eError); + return 0; + } + + return 1; +} diff --git a/hdbtable.h b/hdbtable.h new file mode 100644 index 00000000..b958c89b --- /dev/null +++ b/hdbtable.h @@ -0,0 +1,18 @@ +/** + * Hdbtable is a more generic implementation for a table based on a Hipadaba + * tree structure. This table will be used at various instances in SICS. + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, March 2009 + */ +#ifndef HDBTABLE_H_ +#define HDBTABLE_H_ +#include + +pSICSOBJ MakeHdbTable(char *name, char *hdbclass); +int ReadTableTemplate(pSICSOBJ self, SConnection *con); +int HdbTableFactory(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); +int SaveHdbTable(void *data, char *name, FILE * fd); + +#endif /*HDBTABLE_H_*/ diff --git a/help.c b/help.c index 0a16d434..1164e095 100644 --- a/help.c +++ b/help.c @@ -18,133 +18,147 @@ extern char *stptok(const char *s, char *tok, size_t toklen, char *brk); #define PATHSEP ":" #define DIRSEP "/" static char *helpDirs = NULL; -static char *defaultFile="master.txt"; +static char *defaultFile = "master.txt"; /*----------------------------------------------------------------------*/ -void KillHelp(void *pData){ +void KillHelp(void *pData) +{ KillDummy(pData); - if(helpDirs != NULL){ + if (helpDirs != NULL) { free(helpDirs); helpDirs = NULL; } } + /*-----------------------------------------------------------------------*/ -static FILE *findHelpFile(char *name){ +static FILE *findHelpFile(char *name) +{ FILE *fd = NULL; char pBueffel[256]; char dir[132]; char *pPtr; - if(helpDirs == NULL){ + if (helpDirs == NULL) { return NULL; } pPtr = helpDirs; - while( (pPtr = stptok(pPtr,dir,131,PATHSEP)) != NULL){ - strcpy(pBueffel,dir); - strcat(pBueffel,DIRSEP); - strncat(pBueffel,name,(254-strlen(pBueffel))); - fd = fopen(pBueffel,"r"); - if(fd != NULL){ + while ((pPtr = stptok(pPtr, dir, 131, PATHSEP)) != NULL) { + strlcpy(pBueffel, dir, sizeof pBueffel); + strlcat(pBueffel, DIRSEP, sizeof pBueffel); + strlcat(pBueffel, name, sizeof pBueffel); + fd = fopen(pBueffel, "r"); + if (fd != NULL) { return fd; } } - + /* - this means: not found! - */ + this means: not found! + */ return NULL; } + /*----------------------------------------------------------------------*/ -static void printHelpFile(SConnection *pCon, FILE *fd){ +static void printHelpFile(SConnection * pCon, FILE * fd) +{ char line[132]; - while(fgets(line,131,fd) != NULL){ - SCWrite(pCon,line,eValue); + while (fgets(line, 131, fd) != NULL) { + SCWrite(pCon, line, eValue); } } + /*----------------------------------------------------------------------*/ -static void configureHelp(SConnection *pCon, - char *option, char *parameter){ +static void configureHelp(SConnection * pCon, + char *option, char *parameter) +{ char *pPtr = NULL; int length; strtolower(option); - if(strcmp(option,"adddir") == 0){ - if(parameter == NULL){ - SCWrite(pCon,helpDirs,eValue); + if (strcmp(option, "adddir") == 0) { + if (parameter == NULL) { + SCWrite(pCon, helpDirs, eValue); return; } else { pPtr = helpDirs; - if(pPtr != NULL){ - length = strlen(pPtr) + strlen(PATHSEP) + strlen(parameter) + 2; - helpDirs = (char *)malloc(length*sizeof(char)); - memset(helpDirs,0,length*sizeof(char)); - strcpy(helpDirs,pPtr); - strcat(helpDirs,PATHSEP); - strcat(helpDirs,parameter); - free(pPtr); + if (pPtr != NULL) { + length = strlen(pPtr) + strlen(PATHSEP) + strlen(parameter) + 2; + helpDirs = (char *) malloc(length * sizeof(char)); + memset(helpDirs, 0, length * sizeof(char)); + strcpy(helpDirs, pPtr); + strcat(helpDirs, PATHSEP); + strcat(helpDirs, parameter); + free(pPtr); } else { - helpDirs=strdup(parameter); + helpDirs = strdup(parameter); } } - } else if(strcmp(option,"defaultfile") == 0){ - if(parameter == NULL){ - SCWrite(pCon,defaultFile,eValue); + } else if (strcmp(option, "defaultfile") == 0) { + if (parameter == NULL) { + SCWrite(pCon, defaultFile, eValue); return; } else { - if(defaultFile != NULL){ - free(defaultFile); + if (defaultFile != NULL) { + free(defaultFile); } defaultFile = strdup(parameter); } } else { - SCWrite(pCon,"Unknown option to configure",eWarning); - SCWrite(pCon,"Known options: defaultfile, adddir",eWarning); + SCWrite(pCon, "Unknown option to configure", eWarning); + SCWrite(pCon, "Known options: defaultfile, adddir", eWarning); } } + /*-----------------------------------------------------------------------*/ -int SicsHelp(SConnection *pCon,SicsInterp *pSics, void *pData, - int argc, char *argv[]){ +int SicsHelp(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ char helpFile[256]; FILE *fd = NULL; - strncpy(helpFile,defaultFile,255); + strlcpy(helpFile, defaultFile, 255); - if(argc > 1){ + if (argc > 1) { strtolower(argv[1]); /* - check for configure - */ - if(strcmp(argv[1],"configure") == 0){ - if(argc < 3){ - SCWrite(pCon,"ERROR: need an option to configure",eError); - return 0; + check for configure + */ + if (strcmp(argv[1], "configure") == 0) { + if (argc < 3) { + SCWrite(pCon, "ERROR: need an option to configure", eError); + return 0; } - if(argc > 3){ - configureHelp(pCon,argv[2],argv[3]); + if (argc > 3) { + configureHelp(pCon, argv[2], argv[3]); } else { - configureHelp(pCon,argv[2],NULL); + configureHelp(pCon, argv[2], NULL); } SCSendOK(pCon); return 1; } /* - the parameter is a help file name - */ - strncpy(helpFile,argv[1],255); - strncat(helpFile,".txt",255); + the parameter is a help file name + */ + strlcpy(helpFile, argv[1], 255); + strlcat(helpFile, ".txt", 255); } /* - print the helpFile - */ + print the helpFile + */ fd = findHelpFile(helpFile); - if(fd == NULL){ - SCWrite(pCon,"ERROR: failed to locate helpFile:",eError); - SCWrite(pCon,helpFile,eError); + if (fd == NULL) { + SCWrite(pCon, "ERROR: failed to locate helpFile:", eError); + SCWrite(pCon, helpFile, eError); return 0; } - printHelpFile(pCon,fd); + printHelpFile(pCon, fd); fclose(fd); return 1; } +/*-----------------------------------------------------------------------*/ +void HelpInit(void) +{ + AddCommand(pServ->pSics, "help", SicsHelp, KillHelp, NULL); +} diff --git a/help.h b/help.h index 179dd700..94c15837 100644 --- a/help.h +++ b/help.h @@ -9,9 +9,8 @@ #ifndef SICSHELP #define SICSHELP - int SicsHelp(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); +int SicsHelp(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); - void KillHelp(void *pData); +void KillHelp(void *pData); #endif - diff --git a/hipadaba.c b/hipadaba.c index 953adea8..b0bf067d 100644 --- a/hipadaba.c +++ b/hipadaba.c @@ -12,959 +12,1140 @@ #include #include "hipadaba.h" -#define ABS(x) (x < 0 ? -(x) : (x)) +#define ABS(x) (x < 0 ? -(x) : (x)) #define HDBMAGICK 77119900 /*================== Message Stuff ========================================*/ -static char set[] = {"set"}; -static char get[] = {"get"}; -static char update[] = {"update"}; -static char treeChange[] = {"treeChange"}; -static char dataSearch[] = {"dataSearch"}; -static char killNode[] = {"killNode"}; +static char set[] = { "set" }; +static char get[] = { "get" }; +static char update[] = { "update" }; +static char treeChange[] = { "treeChange" }; +static char dataSearch[] = { "dataSearch" }; +static char killNode[] = { "killNode" }; + /*------------------------------------------------------------------------*/ -pHdbDataMessage GetHdbSetMessage(pHdbMessage toTest){ - if(toTest->type == set){ - return (pHdbDataMessage)toTest; - } - return NULL; +pHdbDataMessage GetHdbSetMessage(pHdbMessage toTest) +{ + if (toTest->type == set) { + return (pHdbDataMessage) toTest; + } + return NULL; } + /*------------------------------------------------------------------------*/ -pHdbDataMessage GetHdbGetMessage(pHdbMessage toTest){ - if(toTest->type == get){ - return (pHdbDataMessage)toTest; - } - return NULL; +pHdbDataMessage GetHdbGetMessage(pHdbMessage toTest) +{ + if (toTest->type == get) { + return (pHdbDataMessage) toTest; + } + return NULL; } + /*------------------------------------------------------------------------*/ -pHdbDataMessage GetHdbUpdateMessage(pHdbMessage toTest){ - if(toTest->type == update){ - return (pHdbDataMessage)toTest; - } - return NULL; +pHdbDataMessage GetHdbUpdateMessage(pHdbMessage toTest) +{ + if (toTest->type == update) { + return (pHdbDataMessage) toTest; + } + return NULL; } + /*-------------------------------------------------------------------------*/ -pHdbTreeChangeMessage GetHdbTreeChangeMessage(pHdbMessage toTest){ - if(toTest->type == treeChange){ - return (pHdbTreeChangeMessage)toTest; - } - return NULL; +pHdbTreeChangeMessage GetHdbTreeChangeMessage(pHdbMessage toTest) +{ + if (toTest->type == treeChange) { + return (pHdbTreeChangeMessage) toTest; + } + return NULL; } + /*-------------------------------------------------------------------------*/ -pHdbDataSearch GetHdbDataSearchMessage(pHdbMessage toTest){ - if(toTest->type == dataSearch){ - return (pHdbDataSearch)toTest; - } - return NULL; +pHdbDataSearch GetHdbDataSearchMessage(pHdbMessage toTest) +{ + if (toTest->type == dataSearch) { + return (pHdbDataSearch) toTest; + } + return NULL; } + /*-------------------------------------------------------------------------*/ -pHdbMessage GetHdbKillNodeMessage(pHdbMessage toTest){ - if(toTest->type == killNode){ - return toTest; - } - return NULL; +pHdbMessage GetHdbKillNodeMessage(pHdbMessage toTest) +{ + if (toTest->type == killNode) { + return toTest; + } + return NULL; } + /*================== internal functions ===================================*/ -void DeleteCallbackChain(pHdb node){ - pHdbCallback current = NULL, thisEntry; - hdbMessage killNodeMsg; - - killNodeMsg.type = killNode; - InvokeCallbackChain(node, &killNodeMsg); - - current = node->callBackChain; - while(current != NULL){ - if(current->killFunc != NULL){ - current->killFunc(current->userData); - } - thisEntry = current; - current = (pHdbCallback)current->next; - free(thisEntry); +void DeleteCallbackChain(pHdb node) +{ + pHdbCallback current = NULL, thisEntry; + hdbMessage killNodeMsg; + + killNodeMsg.type = killNode; + InvokeCallbackChain(node, &killNodeMsg); + + current = node->callBackChain; + node->callBackChain = NULL; + while (current != NULL) { + if (current->killFunc != NULL) { + current->killFunc(current->userData); } + thisEntry = current; + current = (pHdbCallback) current->next; + free(thisEntry); + } } + /*----------------------------------------------------------------------*/ -void RecurseCallbackChains(pHdb node, pHdbMessage message){ - pHdb current = NULL; +void RecurseCallbackChains(pHdb node, pHdbMessage message) +{ + pHdb current = NULL; - InvokeCallbackChain(node,message); - current = node->child; - while(current != NULL){ - RecurseCallbackChains(current,message); - current = current->next; - } + InvokeCallbackChain(node, message); + current = node->child; + while (current != NULL) { + RecurseCallbackChains(current, message); + current = current->next; + } } + /*-----------------------------------------------------------------------*/ -void DeleteNodeData(pHdb node){ - pHdb tmp = NULL; - - if(node == NULL){ - return; - } +void DeleteNodeData(pHdb node) +{ + pHdb tmp = NULL, next = NULL; - DeleteCallbackChain(node); - if(node->properties != NULL){ - DeleteStringDict(node->properties); - } - - if(node->name != NULL){ - free(node->name); - } - if(node->path != NULL){ - free(node->path); - } - ReleaseHdbValue(&node->value); - node->magic = 000000; + if (node == NULL) { + return; + } - while(node->child != NULL){ - tmp = node->child; - node->child = node->child->next; - DeleteNodeData(tmp); - } - free(node); + DeleteCallbackChain(node); + if (node->properties != NULL) { + DeleteStringDict(node->properties); + } + + if (node->name != NULL) { + free(node->name); + } + ReleaseHdbValue(&node->value); + node->magic = 000000; + + while (node->child != NULL) { + tmp = node->child; + next = node->child->next; + DeleteNodeData(tmp); + node->child = next; + } + free(node); } + /*------------------------------------------------------------------------*/ -static pHdbCallback CleanCallbackChain(pHdbCallback head){ - pHdbCallback current = head; - pHdbCallback next; - pHdbCallback *ptr2last = &head; - - while(current != NULL){ - if(current->killFlag == 1){ - next = current->next; - /* - * unlink - */ - *ptr2last = next; - /* - * delete - */ - if(current->killFunc != NULL){ - current->killFunc(current->userData); - } - free(current); - /* - * move on - */ - current = next; - } else { - ptr2last = ¤t->next; - current = current->next; - } - } - - return head; +static pHdbCallback CleanCallbackChain(pHdbCallback head) +{ + pHdbCallback current = head; + pHdbCallback next; + pHdbCallback *ptr2last = &head; + + while (current != NULL) { + if (current->killFlag == 1) { + next = current->next; + /* + * unlink + */ + *ptr2last = next; + /* + * delete + */ + if (current->killFunc != NULL) { + current->killFunc(current->userData); + } + free(current); + /* + * move on + */ + current = next; + } else { + ptr2last = ¤t->next; + current = current->next; + } + } + + return head; } + /*-------------------------------------------------------------------------*/ -int InvokeCallbackChain(pHdb node, pHdbMessage message){ - pHdbCallback current = node->callBackChain; - hdbCallbackReturn status; - int killFlag = 0; - - while(current != NULL){ - status = current->userCallback(node, current->userData,message); - switch(status){ - case hdbAbort: - return 0; - break; - case hdbKill: - current->killFlag = 1; - killFlag = 1; - break; - case hdbContinue: - break; - } - current = current->next; +int InvokeCallbackChain(pHdb node, pHdbMessage message) +{ + pHdbCallback current = node->callBackChain; + hdbCallbackReturn status; + int killFlag = 0; + + while (current != NULL) { + status = current->userCallback(node, current->userData, message); + switch (status) { + case hdbAbort: + return 0; + break; + case hdbKill: + current->killFlag = 1; + killFlag = 1; + break; + case hdbContinue: + break; } - if(killFlag == 1){ - node->callBackChain = CleanCallbackChain(node->callBackChain); - } - return 1; + current = current->next; + } + if (killFlag == 1) { + node->callBackChain = CleanCallbackChain(node->callBackChain); + } + return 1; } + /*-----------------------------------------------------------------------*/ -static void SendTreeChangeMessage(pHdb node, void *callData){ - hdbTreeChangeMessage treeChangeMes; - treeChangeMes.type = treeChange; - treeChangeMes.callData = callData; - InvokeCallbackChain(node, (pHdbMessage)&treeChangeMes); +void SendTreeChangeMessage(pHdb node, void *callData) +{ + hdbTreeChangeMessage treeChangeMes; + treeChangeMes.type = treeChange; + treeChangeMes.callData = callData; + InvokeCallbackChain(node, (pHdbMessage) & treeChangeMes); } + /*------------------------------------------------------------------------*/ -void RemoveHdbNodeFromParent(pHdb node, void *callData){ - pHdb parent = NULL; - pHdb current = NULL; - hdbTreeChangeMessage treeChangeMes; - - parent = node->mama; - if(parent != NULL){ - if(parent->child == node){ - parent->child = node->next; - } else { - current = parent->child; - while(current->next != node){ - current = current->next; - } - current->next = current->next->next; - } - SendTreeChangeMessage(parent,callData); - node->mama = NULL; - } -} -/*----------------------------------------------------------------------*/ -int CountHdbChildren(pHdb node){ - int count = 0; - pHdb current = NULL; - current = node->child; - while(current != NULL){ +void RemoveHdbNodeFromParent(pHdb node, void *callData) +{ + pHdb parent = NULL; + pHdb current = NULL; + hdbTreeChangeMessage treeChangeMes; + + parent = node->mama; + if (parent != NULL) { + if (parent->child == node) { + parent->child = node->next; + } else { + current = parent->child; + while (current->next != node) { current = current->next; - count++; + } + current->next = current->next->next; } - return count; + SendTreeChangeMessage(parent, callData); + node->mama = NULL; + } } + +/*----------------------------------------------------------------------*/ +int CountHdbChildren(pHdb node) +{ + int count = 0; + pHdb current = NULL; + current = node->child; + while (current != NULL) { + current = current->next; + count++; + } + return count; +} + /*----------------------------------------------------------------------*/ char *hdbTrim(char *str) { - char *ibuf = str, *obuf = str; - int i = 0, cnt = 0; + char *ibuf = str, *obuf = str; + int i = 0, cnt = 0; - /* - ** Trap NULL - */ + /* + ** Trap NULL + */ - if (str) - { - /* - ** Remove leading spaces (from RMLEAD.C) - */ + if (str) { + /* + ** Remove leading spaces (from RMLEAD.C) + */ - for (ibuf = str; *ibuf && isspace(*ibuf); ++ibuf) - ; - if (str != ibuf) - memmove(str, ibuf, ibuf - str); - - /* - ** Collapse embedded spaces (from LV1WS.C) - */ - - while (*ibuf) - { - if (isspace(*ibuf) && cnt) - ibuf++; - else - { - if (!isspace(*ibuf)) - cnt = 0; - else - { - *ibuf = ' '; - cnt = 1; - } - obuf[i++] = *ibuf++; - } - } - obuf[i] = '\0'; - - /* - ** Remove trailing spaces (from RMTRAIL.C) - */ - - while (--i >= 0) - { - if (!isspace(obuf[i])) - break; - } - obuf[++i] = '\0'; - } - return str; -} -/*------------------------------------------------------------------------*/ -static pHdb locateChild(pHdb root, char *name){ - pHdb current = NULL; - - current = root->child; - while(current != NULL){ - if(strcmp(current->name,name) == 0){ - return current; - } - current = current->next; - } - return NULL; -} -/*================= data functions ========================================*/ -hdbValue makeHdbValue(int datatype, int length){ - hdbValue val; - - memset(&val,0,sizeof(hdbValue)); - val.dataType = datatype; - val.doNotFree = 0; - - switch(datatype){ - case HIPINTAR: - case HIPINTVARAR: - val.arrayLength = length; - val.v.intArray = malloc(length*sizeof(int)); - if(val.v.intArray != NULL){ - memset(val.v.intArray,0,length*sizeof(int)); - } - break; - case HIPFLOATAR: - case HIPFLOATVARAR: - val.arrayLength = length; - val.v.floatArray = malloc(length*sizeof(double)); - if(val.v.floatArray != NULL){ - memset(val.v.floatArray,0,length*sizeof(double)); - } - break; - case HIPTEXT: - val.v.text = strdup("UNKNOWN"); - val.arrayLength = length; - break; - } - return val; -} -/*-------------------------------------------------------------------------*/ -hdbValue MakeHdbInt(int initValue){ - hdbValue result; - - result.dataType = HIPINT; - result.arrayLength = 1; - result.v.intValue = initValue; - return result; -} -/*-------------------------------------------------------------------------*/ -hdbValue MakeHdbFloat(double initValue){ - hdbValue result; - - result.dataType = HIPFLOAT; - result.arrayLength = 1; - result.v.doubleValue = initValue; - return result; -} -/*-------------------------------------------------------------------------*/ -hdbValue MakeHdbText(char *initText){ - hdbValue result; - - result.dataType = HIPTEXT; - result.v.text = initText; /* no strdup here ! */ - result.arrayLength = strlen(initText); - return result; -} -/*-------------------------------------------------------------------------*/ -hdbValue MakeHdbIntArray(int length, int *data){ - hdbValue result; - - result.dataType = HIPINTAR; - result.arrayLength = length; - result.v.intArray = data; - return result; -} -/*-------------------------------------------------------------------------*/ -hdbValue MakeHdbFloatArray(int length, double *data){ - hdbValue result; - - result.dataType = HIPFLOATAR; - result.arrayLength = length; - result.v.floatArray = data; - return result; -} -/*-------------------------------------------------------------------------*/ -hdbValue MakeHdbFunc(voidFunc *func){ - hdbValue result; - - result.dataType = HIPFUNC; - result.v.func = func; - return result; -} -/*-------------------------------------------------------------------------*/ -hdbValue MakeHdbObj(void *obj){ - hdbValue result; - - result.dataType = HIPOBJ; - result.v.obj = obj; - return result; -} -/*-------------------------------------------------------------------------*/ -void ReleaseHdbValue(hdbValue *v){ - - if(v->doNotFree == 1){ - return; - } - switch(v->dataType){ - case HIPTEXT: - if(v->v.text != NULL){ - free(v->v.text); - } - break; - case HIPINTAR: - case HIPINTVARAR: - if(v->v.intArray != NULL){ - free(v->v.intArray); - } - break; - case HIPFLOATAR: - case HIPFLOATVARAR: - if(v->v.floatArray != NULL){ - free(v->v.floatArray); - } - break; - } -} -/*------------------------------------------------------------------------*/ -int compareHdbValue(hdbValue v1, hdbValue v2){ - int i; - - if(v1.dataType != v2.dataType){ - return 0; - } - switch(v1.dataType){ - case HIPNONE: - return 0; - break; - case HIPINT: - if(v1.v.intValue == v2.v.intValue){ - return 1; - } else { - return 0; - } - break; - case HIPFLOAT: - if(ABS(v1.v.doubleValue - v2.v.doubleValue) < .0001)/* DFC */ - { - return 1; - } else { - return 0; - } - break; - case HIPTEXT: - if(v1.v.text == NULL || v2.v.text == NULL){ - return 0; - } - if(strcmp(v1.v.text,v2.v.text) == 0){ - return 1; - } else { - return 0; - } - break; - case HIPINTAR: - case HIPINTVARAR: - if(v1.arrayLength != v2.arrayLength){ - return 0; - } - if(v1.v.intArray == NULL || v2.v.intArray == NULL){ - return 0; - } - for(i = 0; i < v1.arrayLength; i++){ - if(v1.v.intArray[i] != v2.v.intArray[i]){ - return 0; - } - } - return 1; - break; - case HIPFLOATAR: - case HIPFLOATVARAR: - if(v1.arrayLength != v2.arrayLength){ - return 0; - } - if(v1.v.floatArray == NULL || v2.v.floatArray == NULL){ - return 0; - } - for(i = 0; i < v1.arrayLength; i++){ - if(ABS(v1.v.floatArray[i] - v2.v.floatArray[i]) > .01){ - return 0; - } - } - return 1; - break; - case HIPOBJ: - if(v2.v.obj == v1.v.obj) { - return 1; - } else { - return 0; - } - break; - case HIPFUNC: - if(v2.v.func == v1.v.func) { - return 1; - } else { - return 0; - } - break; - default: - assert(0); - break; - } - return 0; -} -/*-------------------------------------------------------------------------*/ -int cloneHdbValue(hdbValue *source, hdbValue *clone){ - - memset(clone,0,sizeof(hdbValue)); - clone->v.text = NULL; /* this sets all pointers in the union to NULL */ - clone->dataType = source->dataType; - return copyHdbValue(source, clone); -} -/*-------------------------------------------------------------------------*/ -int getHdbValueLength(hdbValue v){ - int length = 0; - switch(v.dataType){ - case HIPNONE: - break; - case HIPINT: - length = sizeof(int); - break; - case HIPFLOAT: - length = sizeof(double); - break; - case HIPINTAR: - case HIPINTVARAR: - length = v.arrayLength * sizeof(int); - break; - case HIPFLOATAR: - case HIPFLOATVARAR: - length = v.arrayLength * sizeof(double); - break; - case HIPTEXT: - length = strlen(v.v.text); - break; - case HIPOBJ: - length = sizeof(void *); - break; - case HIPFUNC: - length = sizeof(voidFunc *); - break; - } - return length; -} -/*================= node functions ========================================*/ -pHdb MakeHipadabaNode(char *name, int datatype, int length){ - pHdb pNew = NULL; - - pNew = malloc(sizeof(Hdb)); - if(pNew == NULL){ - return NULL; - } - memset(pNew,0,sizeof(Hdb)); - pNew->magic = HDBMAGICK; - pNew->name = strdup(name); - pNew->value.dataType = datatype; - pNew->properties = CreateStringDict(); - if(pNew->properties == NULL || pNew->name == NULL){ - return NULL; - } - switch(datatype){ - case HIPINTAR: - case HIPINTVARAR: - pNew->value.arrayLength = length; - pNew->value.v.intArray = malloc(length*sizeof(int)); - if(pNew->value.v.intArray == NULL){ - return NULL; - } - memset(pNew->value.v.intArray,0,length*sizeof(int)); - break; - case HIPFLOATAR: - case HIPFLOATVARAR: - pNew->value.arrayLength = length; - pNew->value.v.floatArray = malloc(length*sizeof(double)); - if(pNew->value.v.floatArray == NULL){ - return NULL; - } - memset(pNew->value.v.floatArray,0,length*sizeof(double)); - break; - case HIPTEXT: - pNew->value.arrayLength = length; - pNew->value.v.text = strdup("UNKNOWN"); - break; - } - return pNew; -} -/*-------------------------------------------------------------------------*/ -void AddHipadabaChild(pHdb parent, pHdb child, void *callData){ - pHdb current = NULL, prev = NULL; - - assert(parent != NULL); - if(child == NULL){ - return; - } - - current = parent->child; - child->mama = parent; - if(current == NULL){ - parent->child = child; - child->next = NULL; - } else { - /* - * step to end of child chain - */ - while(current != NULL){ - assert(strcmp(current->name,child->name)!=0); - prev = current; - current = current->next; - } - child->next = NULL; - prev->next = child; - } - SendTreeChangeMessage(parent,callData); -} -/*--------------------------------------------------------------------------*/ -void DeleteHipadabaNode(pHdb node, void *callData){ - pHdb current = NULL, tmp = NULL; - - if(node == NULL){ - return; - } - - RemoveHdbNodeFromParent(node, callData); - - DeleteNodeData(node); -} -/*--------------------------------------------------------------------------*/ -int isHdbNodeValid(pHdb node){ - if(node == NULL){ - return 0; - } - if(node->magic == HDBMAGICK){ - return 1; - } else { - return 0; - } -} -/*--------------------------------------------------------------------------*/ -pHdb GetHipadabaNode(pHdb root, char *puth){ - pHdb resultNode = NULL; - char *separator = NULL; - char *path = NULL, *pathData; + for (ibuf = str; *ibuf && isspace(*ibuf); ++ibuf); + if (str != ibuf) + memmove(str, ibuf, ibuf - str); /* - * I need to make a copy in order to get the path in writable memory. - * Otherwise we SEGFAULT in hdbTrim when this function is called with - * a string constant in puth + ** Collapse embedded spaces (from LV1WS.C) */ - pathData = strdup(puth); - path = pathData; - if(path == NULL){ - return NULL; - } - path = hdbTrim(path); - - if(strcmp(path,"/") == 0 || strlen(path) == 0){ - free(pathData); - return root; - } - - if(path[0] == '/'){ - path++; - } - - separator = strchr(path,'/'); - if(separator == NULL){ - resultNode = locateChild(root,path); - free(pathData); - return resultNode; - } else { - *separator = '\0'; - resultNode = locateChild(root, path); - if(resultNode == NULL){ - free(pathData); - return NULL; - } else { - separator++; - resultNode = GetHipadabaNode(resultNode,separator); - free(pathData); - return resultNode; + + while (*ibuf) { + if (isspace(*ibuf) && cnt) + ibuf++; + else { + if (!isspace(*ibuf)) + cnt = 0; + else { + *ibuf = ' '; + cnt = 1; } + obuf[i++] = *ibuf++; + } } + obuf[i] = '\0'; + + /* + ** Remove trailing spaces (from RMTRAIL.C) + */ + + while (--i >= 0) { + if (!isspace(obuf[i])) + break; + } + obuf[++i] = '\0'; + } + return str; } + +/*------------------------------------------------------------------------*/ +static pHdb locateChild(pHdb root, char *name) +{ + pHdb current = NULL; + + current = root->child; + while (current != NULL) { + if (strcmp(current->name, name) == 0) { + return current; + } + current = current->next; + } + return NULL; +} + +/*================= data functions ========================================*/ +hdbValue makeHdbValue(int datatype, int length) +{ + hdbValue val; + + memset(&val, 0, sizeof(hdbValue)); + val.dataType = datatype; + val.doNotFree = 0; + + switch (datatype) { + case HIPINTAR: + case HIPINTVARAR: + val.arrayLength = length; + val.v.intArray = malloc(length * sizeof(int)); + if (val.v.intArray != NULL) { + memset(val.v.intArray, 0, length * sizeof(int)); + } + break; + case HIPFLOATAR: + case HIPFLOATVARAR: + val.arrayLength = length; + val.v.floatArray = malloc(length * sizeof(double)); + if (val.v.floatArray != NULL) { + memset(val.v.floatArray, 0, length * sizeof(double)); + } + break; + case HIPTEXT: + val.v.text = strdup("UNKNOWN"); + val.arrayLength = length; + break; + } + return val; +} + +/*-------------------------------------------------------------------------*/ +hdbValue MakeHdbInt(int initValue) +{ + hdbValue result; + + result.dataType = HIPINT; + result.arrayLength = 1; + result.v.intValue = initValue; + result.doNotFree = 0; + return result; +} + +/*-------------------------------------------------------------------------*/ +hdbValue MakeHdbFloat(double initValue) +{ + hdbValue result; + + result.dataType = HIPFLOAT; + result.arrayLength = 1; + result.v.doubleValue = initValue; + result.doNotFree = 0; + return result; +} + +/*-------------------------------------------------------------------------*/ +hdbValue MakeHdbText(char *initText) +{ + hdbValue result; + + result.dataType = HIPTEXT; + result.v.text = initText; /* no strdup here ! */ + result.arrayLength = strlen(initText); + result.doNotFree = 0; + return result; +} + +/*-------------------------------------------------------------------------*/ +hdbValue MakeHdbIntArray(int length, int *data) +{ + hdbValue result; + + result.dataType = HIPINTAR; + result.arrayLength = length; + result.v.intArray = data; + result.doNotFree = 0; + return result; +} + +/*-------------------------------------------------------------------------*/ +hdbValue MakeHdbFloatArray(int length, double *data) +{ + hdbValue result; + + result.dataType = HIPFLOATAR; + result.arrayLength = length; + result.v.floatArray = data; + result.doNotFree = 0; + return result; +} + +/*-------------------------------------------------------------------------*/ +hdbValue MakeHdbFunc(voidFunc * func) +{ + hdbValue result; + + result.dataType = HIPFUNC; + result.v.func = func; + result.doNotFree = 0; + return result; +} + +/*-------------------------------------------------------------------------*/ +hdbValue MakeHdbObj(void *obj) +{ + hdbValue result; + + result.dataType = HIPOBJ; + result.v.obj = obj; + result.doNotFree = 0; + return result; +} + +/*-------------------------------------------------------------------------*/ +void ReleaseHdbValue(hdbValue * v) +{ + + if (v->doNotFree == 1) { + return; + } + switch (v->dataType) { + case HIPTEXT: + if (v->v.text != NULL) { + free(v->v.text); + } + break; + case HIPINTAR: + case HIPINTVARAR: + if (v->v.intArray != NULL) { + free(v->v.intArray); + } + break; + case HIPFLOATAR: + case HIPFLOATVARAR: + if (v->v.floatArray != NULL) { + free(v->v.floatArray); + } + break; + } +} +/*-----------------------------------------------------------------------------*/ +static unsigned short fletcher16( char *data, size_t len) +{ + unsigned short sum1 = 0xff, sum2 = 0xff, result; + unsigned char checkA, checkB; + + if(data == NULL){ + return 0; + } + while (len) { + size_t tlen = len > 21 ? 21 : len; + len -= tlen; + do { + sum1 += *data++; + sum2 += sum1; + } while (--tlen); + sum1 = (sum1 & 0xff) + (sum1 >> 8); + sum2 = (sum2 & 0xff) + (sum2 >> 8); + } + /* Second reduction step to reduce sums to 8 bits */ + sum1 = (sum1 & 0xff) + (sum1 >> 8); + sum2 = (sum2 & 0xff) + (sum2 >> 8); + checkA = (unsigned char)sum1; + checkB = (unsigned char)sum2; + result = checkA; + result = result << 8 | checkB; + return result ; +} +/*------------------------------------------------------------------------*/ +#define MAXLEN 65536 +unsigned short getHdbCheckSum(hdbValue *val) +{ + char *data; + size_t len; + + len = getHdbValueLength(*val); + /* + if(len > MAXLEN){ + len = MAXLEN; + } + */ + switch (val->dataType) { + case HIPNONE: + return 0; + break; + case HIPINT: + data = (char *)&val->v.intValue; + return fletcher16(data,len); + break; + case HIPFLOAT: + data = (char *)&val->v.doubleValue; + return fletcher16(data,len); + break; + case HIPTEXT: + data = val->v.text; + return fletcher16(data,len); + break; + case HIPINTAR: + case HIPINTVARAR: + data = (char *)val->v.intArray; + return fletcher16(data,len); + break; + case HIPFLOATAR: + case HIPFLOATVARAR: + data = (char *)val->v.floatArray; + return fletcher16(data,len); + break; + case HIPOBJ: + data = (char *)val->v.obj; + return fletcher16(data,len); + break; + case HIPFUNC: + data = (char *)val->v.func; + return fletcher16(data,len); + break; + default: + assert(0); + break; + } + return 0; +} +/*------------------------------------------------------------------------*/ +int compareHdbValue(hdbValue v1, hdbValue v2) +{ + int i; + + if (v1.dataType != v2.dataType) { + return 0; + } + + if((v1.doNotFree == 1 && v1.v.obj == NULL) + || (v2.doNotFree == 1 && v2.v.obj == NULL)){ + return 0; + } + + switch (v1.dataType) { + case HIPNONE: + return 0; + break; + case HIPINT: + if (v1.v.intValue == v2.v.intValue) { + return 1; + } else { + return 0; + } + break; + case HIPFLOAT: + if (ABS(v1.v.doubleValue - v2.v.doubleValue) < .01) { + return 1; + } else { + return 0; + } + break; + case HIPTEXT: + if (v1.v.text == NULL || v2.v.text == NULL) { + return 0; + } + if (strcmp(v1.v.text, v2.v.text) == 0) { + return 1; + } else { + return 0; + } + break; + case HIPINTAR: + case HIPINTVARAR: + if (v1.arrayLength != v2.arrayLength) { + return 0; + } + if (v1.v.intArray == NULL || v2.v.intArray == NULL) { + return 0; + } + for (i = 0; i < v1.arrayLength; i++) { + if (v1.v.intArray[i] != v2.v.intArray[i]) { + return 0; + } + } + return 1; + break; + case HIPFLOATAR: + case HIPFLOATVARAR: + if (v1.arrayLength != v2.arrayLength) { + return 0; + } + if (v1.v.floatArray == NULL || v2.v.floatArray == NULL) { + return 0; + } + for (i = 0; i < v1.arrayLength; i++) { + if (ABS(v1.v.floatArray[i] - v2.v.floatArray[i]) > .01) { + return 0; + } + } + return 1; + break; + case HIPOBJ: + if (v2.v.obj == v1.v.obj) { + return 1; + } else { + return 0; + } + break; + case HIPFUNC: + if (v2.v.func == v1.v.func) { + return 1; + } else { + return 0; + } + break; + default: + assert(0); + break; + } + return 0; +} + +/*-------------------------------------------------------------------------*/ +int cloneHdbValue(hdbValue * source, hdbValue * clone) +{ + + memset(clone, 0, sizeof(hdbValue)); + clone->v.text = NULL; /* this sets all pointers in the union to NULL */ + clone->dataType = source->dataType; + return copyHdbValue(source, clone); +} + +/*-------------------------------------------------------------------------*/ +int getHdbValueLength(hdbValue v) +{ + int length = 0; + switch (v.dataType) { + case HIPNONE: + break; + case HIPINT: + length = sizeof(int); + break; + case HIPFLOAT: + length = sizeof(double); + break; + case HIPINTAR: + case HIPINTVARAR: + length = v.arrayLength * sizeof(int); + break; + case HIPFLOATAR: + case HIPFLOATVARAR: + length = v.arrayLength * sizeof(double); + break; + case HIPTEXT: + length = strlen(v.v.text); + break; + case HIPOBJ: + length = sizeof(void *); + break; + case HIPFUNC: + length = sizeof(voidFunc *); + break; + } + return length; +} + +/*================= node functions ========================================*/ +pHdb MakeHipadabaNode(char *name, int datatype, int length) +{ + pHdb pNew = NULL; + + pNew = malloc(sizeof(Hdb)); + if (pNew == NULL) { + return NULL; + } + memset(pNew, 0, sizeof(Hdb)); + pNew->magic = HDBMAGICK; + pNew->name = strdup(name); + pNew->value.dataType = datatype; + pNew->properties = CreateStringDict(); + if (pNew->properties == NULL || pNew->name == NULL) { + return NULL; + } + switch (datatype) { + case HIPINTAR: + case HIPINTVARAR: + pNew->value.arrayLength = length; + pNew->value.v.intArray = malloc(length * sizeof(int)); + if (pNew->value.v.intArray == NULL) { + return NULL; + } + memset(pNew->value.v.intArray, 0, length * sizeof(int)); + break; + case HIPFLOATAR: + case HIPFLOATVARAR: + pNew->value.arrayLength = length; + pNew->value.v.floatArray = malloc(length * sizeof(double)); + if (pNew->value.v.floatArray == NULL) { + return NULL; + } + memset(pNew->value.v.floatArray, 0, length * sizeof(double)); + break; + case HIPTEXT: + pNew->value.arrayLength = length; + pNew->value.v.text = strdup("UNKNOWN"); + break; + } + return pNew; +} + +/*-------------------------------------------------------------------------*/ +void AddHipadabaChild(pHdb parent, pHdb child, void *callData) +{ + pHdb current = NULL, prev = NULL; + + assert(parent != NULL); + if (child == NULL) { + return; + } + + current = parent->child; + child->mama = parent; + if (current == NULL) { + parent->child = child; + child->next = NULL; + } else { + /* + * step to end of child chain + */ + while (current != NULL) { + prev = current; + current = current->next; + } + child->next = NULL; + prev->next = child; + } + SendTreeChangeMessage(parent, callData); +} + /*--------------------------------------------------------------------------*/ -char *GetHipadabaPath(pHdb node){ - pHdb nodeStack[64]; - int depth = 0, length = 0, i; - pHdb current = NULL; - char *pPtr = NULL; - +void DeleteHipadabaNode(pHdb node, void *callData) +{ + pHdb current = NULL, tmp = NULL; + + if (node == NULL) { + return; + } + + RemoveHdbNodeFromParent(node, callData); + + DeleteNodeData(node); +} + +/*--------------------------------------------------------------------------*/ +int isHdbNodeValid(pHdb node) +{ + if (node == NULL) { + return 0; + } + if (node->magic == HDBMAGICK) { + return 1; + } else { + return 0; + } +} + +/*--------------------------------------------------------------------------*/ +pHdb GetHipadabaNode(pHdb root, char *puth) +{ + pHdb resultNode = NULL; + char *separator = NULL; + char *path = NULL, *pathData; + + /* + * I need to make a copy in order to get the path in writable memory. + * Otherwise we SEGFAULT in hdbTrim when this function is called with + * a string constant in puth + */ + pathData = strdup(puth); + path = pathData; + if (path == NULL) { + return NULL; + } + path = hdbTrim(path); + + if (strcmp(path, "/") == 0 || strlen(path) == 0) { + free(pathData); + return root; + } + + if (path[0] == '/') { + path++; + } + + separator = strchr(path, '/'); + if (separator == NULL) { + resultNode = locateChild(root, path); + free(pathData); + return resultNode; + } else { + *separator = '\0'; + resultNode = locateChild(root, path); + if (resultNode == NULL) { + free(pathData); + return NULL; + } else { + separator++; + resultNode = GetHipadabaNode(resultNode, separator); + free(pathData); + return resultNode; + } + } +} + +/*--------------------------------------------------------------------------*/ +char *GetHipadabaPath(pHdb node) +{ + pHdb nodeStack[64]; + int depth = 0, length = 0, i; + pHdb current = NULL; + char *pPtr = NULL; + /** * build a nodestack and find out required string length for path */ - current = node; - while(current != NULL){ - length += strlen(current->name) + 1; - nodeStack[depth] = current; - depth++; - assert(depth < 64); - current = current->mama; - } - - pPtr = malloc(length*sizeof(char)); - if(pPtr == NULL){ - return NULL; - } - memset(pPtr,0,length*sizeof(char)); - - /* - * we wish to decremement by one because above loop - * increments one to many and we wish to ignore the - * root node - */ - for(i = depth - 2; i >= 0; i--){ - strcat(pPtr,"/"); - strcat(pPtr,nodeStack[i]->name); - } - node->path = pPtr; - return pPtr; -} + current = node; + while (current != NULL) { + length += strlen(current->name) + 1; + nodeStack[depth] = current; + depth++; + assert(depth < 64); + current = current->mama; + } + + pPtr = malloc(length * sizeof(char)); + if (pPtr == NULL) { + return NULL; + } + memset(pPtr, 0, length * sizeof(char)); + + /* + * we wish to decremement by one because above loop + * increments one to many and we wish to ignore the + * root node + */ + for (i = depth - 2; i >= 0; i--) { + strcat(pPtr, "/"); + strcat(pPtr, nodeStack[i]->name); + } + return pPtr; +} + /*==================== Callback Functions ==================================*/ -pHdbCallback MakeHipadabaCallback(hdbCallbackFunction func, - void *userData, killUserData killFunc){ - pHdbCallback pNew = NULL; - - assert(func != NULL); - - pNew = malloc(sizeof(hdbCallback)); - if(pNew == NULL){ - return NULL; - } - memset(pNew,0,sizeof(hdbCallback)); - - pNew->userCallback = func; - pNew->userData = userData; - pNew->killFunc = killFunc; - return pNew; +pHdbCallback MakeHipadabaCallback(hdbCallbackFunction func, + void *userData, killUserData killFunc) +{ + pHdbCallback pNew = NULL; + + assert(func != NULL); + + pNew = malloc(sizeof(hdbCallback)); + if (pNew == NULL) { + return NULL; + } + memset(pNew, 0, sizeof(hdbCallback)); + + pNew->userCallback = func; + pNew->userData = userData; + pNew->killFunc = killFunc; + return pNew; } + /*-------------------------------------------------------------------*/ -void AppendHipadabaCallback(pHdb node, pHdbCallback newCB){ - pHdbCallback current = NULL; - - assert(node); - current = node->callBackChain; - newCB->next = NULL; - if(current == NULL){ - node->callBackChain = newCB; - return; - } - while(current->next != NULL){ - current = (pHdbCallback)current->next; - } - current->next = newCB; +void AppendHipadabaCallback(pHdb node, pHdbCallback newCB) +{ + pHdbCallback current = NULL; + + assert(node); + current = node->callBackChain; + newCB->next = NULL; + if (current == NULL) { + node->callBackChain = newCB; + return; + } + while (current->next != NULL) { + current = (pHdbCallback) current->next; + } + current->next = newCB; } + /*---------------------------------------------------------------------------*/ -void PrependHipadabaCallback(pHdb node,pHdbCallback newCB){ - assert(node != NULL); - - newCB->next = node->callBackChain; - node->callBackChain = newCB; +void PrependHipadabaCallback(pHdb node, pHdbCallback newCB) +{ + assert(node != NULL); + + newCB->next = node->callBackChain; + node->callBackChain = newCB; } + /*----------------------------------------------------------------------------*/ -void *FindHdbCallbackData(pHdb node, void *userPtr){ +void *FindHdbCallbackData(pHdb node, void *userPtr) +{ hdbDataSearch dsm; - + dsm.type = dataSearch; dsm.testPtr = userPtr; dsm.result = NULL; - InvokeCallbackChain(node, (pHdbMessage)&dsm); + InvokeCallbackChain(node, (pHdbMessage) & dsm); return dsm.result; } + /*=================== parameter interface ====================================*/ -static int canCopy(hdbValue *source, hdbValue *target){ - if(target->dataType == HIPINTVARAR) { - if(source->dataType == HIPINTAR || - source->dataType == HIPINTVARAR){ - return 1; - } +static int canCopy(hdbValue * source, hdbValue * target) +{ + if (target->dataType == HIPINTVARAR) { + if (source->dataType == HIPINTAR || source->dataType == HIPINTVARAR) { + return 1; } - if(target->dataType == HIPFLOATVARAR) { - if(source->dataType == HIPFLOATAR || - source->dataType == HIPFLOATVARAR){ - return 1; - } - } - if(source->dataType != target->dataType){ - return 0; - } else { - return 1; - } -} -/*----------------------------------------------------------------------------*/ -int copyHdbValue(hdbValue *source, hdbValue *target){ - int i; - - if(!canCopy(source,target)){ - return 0; - } - - switch(source->dataType){ - case HIPNONE: - break; - case HIPINT: - target->v.intValue = source->v.intValue; - break; - case HIPFLOAT: - target->v.doubleValue = source->v.doubleValue; - break; - case HIPTEXT: - if(target->v.text != NULL){ - free(target->v.text); - } - target->v.text = strdup(source->v.text); - break; - case HIPINTAR: - case HIPINTVARAR: - if(target->arrayLength != source->arrayLength || target->v.intArray == NULL){ - if(target->v.intArray != NULL){ - free(target->v.intArray); - } - target->v.intArray = malloc(source->arrayLength * sizeof(int)); - if(target->v.intArray == NULL){ - return 0; - } - memset(target->v.intArray,0,source->arrayLength - * sizeof(int)); - target->arrayLength = source->arrayLength; - } - if(source->v.intArray != NULL){ - for(i = 0; i < source->arrayLength; i++){ - target->v.intArray[i] = source->v.intArray[i]; - } - } - break; - case HIPFLOATAR: - case HIPFLOATVARAR: - if(target->arrayLength != source->arrayLength - || target->v.floatArray == NULL){ - if(target->v.floatArray != NULL){ - free(target->v.floatArray); - } - target->v.floatArray = - malloc(source->arrayLength * sizeof(double)); - if(target->v.floatArray == NULL){ - return 0; - } - memset(target->v.floatArray,0,source->arrayLength * - sizeof(double)); - target->arrayLength = source->arrayLength; - } - if(source->v.floatArray != NULL){ - for(i = 0; i < source->arrayLength; i++){ - target->v.floatArray[i] = source->v.floatArray[i]; - } - } - break; - case HIPOBJ: - target->v.obj = source->v.obj; - break; - case HIPFUNC: - target->v.func = source->v.func; - break; - default: - /* - * unknown data type - */ - assert(0); - break; + } + if (target->dataType == HIPFLOATVARAR) { + if (source->dataType == HIPFLOATAR || + source->dataType == HIPFLOATVARAR) { + return 1; } + } + if (source->dataType != target->dataType) { + return 0; + } else { return 1; + } } + +/*----------------------------------------------------------------------------*/ +int copyHdbValue(hdbValue * source, hdbValue * target) +{ + int i; + + if (!canCopy(source, target)) { + return 0; + } + + switch (source->dataType) { + case HIPNONE: + break; + case HIPINT: + target->v.intValue = source->v.intValue; + break; + case HIPFLOAT: + target->v.doubleValue = source->v.doubleValue; + break; + case HIPTEXT: + if (target->v.text != NULL) { + free(target->v.text); + } + target->v.text = strdup(source->v.text); + break; + case HIPINTAR: + case HIPINTVARAR: + if (target->arrayLength != source->arrayLength + || target->v.intArray == NULL) { + if (target->v.intArray != NULL) { + free(target->v.intArray); + } + target->v.intArray = malloc(source->arrayLength * sizeof(int)); + if (target->v.intArray == NULL) { + return 0; + } + memset(target->v.intArray, 0, source->arrayLength * sizeof(int)); + target->arrayLength = source->arrayLength; + } + if (source->v.intArray != NULL) { + /* + for (i = 0; i < source->arrayLength; i++) { + target->v.intArray[i] = source->v.intArray[i]; + } + */ + memcpy(target->v.intArray,source->v.intArray,source->arrayLength*sizeof(int)); + } + break; + case HIPFLOATAR: + case HIPFLOATVARAR: + if (target->arrayLength != source->arrayLength + || target->v.floatArray == NULL) { + if (target->v.floatArray != NULL) { + free(target->v.floatArray); + } + target->v.floatArray = malloc(source->arrayLength * sizeof(double)); + if (target->v.floatArray == NULL) { + return 0; + } + memset(target->v.floatArray, 0, source->arrayLength * + sizeof(double)); + target->arrayLength = source->arrayLength; + } + if (source->v.floatArray != NULL) { + for (i = 0; i < source->arrayLength; i++) { + target->v.floatArray[i] = source->v.floatArray[i]; + } + } + break; + case HIPOBJ: + target->v.obj = source->v.obj; + break; + case HIPFUNC: + target->v.func = source->v.func; + break; + default: + /* + * unknown data type + */ + assert(0); + break; + } + return 1; +} + /*---------------------------------------------------------------------------*/ -static int SendDataMessage(pHdb node, char *type, - hdbValue v, void *callData){ - hdbDataMessage dataMes; +static int SendDataMessage(pHdb node, char *type, + hdbValue *v, void *callData) +{ + hdbDataMessage dataMes; - assert(type == set || type == get || type == update); - dataMes.type = type; - dataMes.v = &v; - dataMes.callData = callData; - return InvokeCallbackChain(node, (pHdbMessage)&dataMes); + assert(type == set || type == get || type == update); + dataMes.type = type; + dataMes.v = v; + dataMes.callData = callData; + return InvokeCallbackChain(node, (pHdbMessage) & dataMes); } + /*----------------------------------------------------------------------------*/ -int SetHipadabaPar(pHdb node, hdbValue v, void *callData){ - return SendDataMessage(node, set, v,callData); +int SetHipadabaPar(pHdb node, hdbValue v, void *callData) +{ + return SendDataMessage(node, set, &v, callData); } -/*-----------------------------------------------------------------------------*/ -int UpdateHipadabaPar(pHdb node, hdbValue v, void *callData){ - int status; - status = SendDataMessage(node, update, v,callData); - if(status == 1){ - copyHdbValue(&v,&node->value); - } - return status; -} /*-----------------------------------------------------------------------------*/ -int NotifyHipadabaPar(pHdb node,void *callData){ - SendDataMessage(node, update, node->value,callData); - return 1; -} -/*-----------------------------------------------------------------------------*/ -int GetHipadabaPar(pHdb node, hdbValue *v, void *callData){ - int status; - - v->dataType = node->value.dataType; - v->doNotFree = 0; - v->v.text = NULL; /* this sets all pointers in the union to NULL */ +int UpdateHipadabaPar(pHdb node, hdbValue v, void *callData) +{ + int status; - status = SendDataMessage(node, get, *v,callData); - if(status != 1 ){ - return status; - } - copyHdbValue(&node->value,v); - return 1; + status = SendDataMessage(node, update, &v, callData); + if (status == 1) { + copyHdbValue(&v, &node->value); + } + return status; } + +/*-----------------------------------------------------------------------------*/ +int NotifyHipadabaPar(pHdb node, void *callData) +{ + SendDataMessage(node, update, &node->value, callData); + return 1; +} + +/*-----------------------------------------------------------------------------*/ +int GetHipadabaPar(pHdb node, hdbValue *v, void *callData) +{ + int status; + unsigned short checksum; + + memset(v,0,sizeof(hdbValue)); + v->dataType = node->value.dataType; + + checksum = getHdbCheckSum(&node->value); + status = SendDataMessage(node, get, v, callData); + copyHdbValue(&node->value, v); + if(getHdbCheckSum(&node->value) != checksum){ + NotifyHipadabaPar(node, callData); + } + if (status != 1) { + return status; + } + return 1; +} + /*----------------------------------------------------------------------------*/ -static int calcDataLength(pHdb node, int testLength){ - int length = 0; +static int calcDataLength(pHdb node, int testLength) +{ + int length = 0; + + length = getHdbValueLength(node->value); + if (node->value.dataType == HIPFLOATVARAR || + node->value.dataType == HIPINTVARAR || + node->value.dataType == HIPTEXT) { + length = testLength; + } + return length; +} - length = getHdbValueLength(node->value); - if(node->value.dataType == HIPFLOATVARAR || - node->value.dataType == HIPINTVARAR || - node->value.dataType == HIPTEXT){ - length = testLength; - } - return length; -} /*============================= Property Functions ==========================*/ - void SetHdbProperty(pHdb node, char *key, char *value){ - if(node != NULL && key != NULL && node->properties != NULL){ - if (value == NULL) { - StringDictDelete(node->properties, key); - } else if(StringDictExists(node->properties, key)){ - StringDictUpdate(node->properties,key,value); - } else { - StringDictAddPair(node->properties,key,value); - } - } - } -/*---------------------------------------------------------------------------*/ -int HasHdbProperty(pHdb node, char *key){ - if(node != NULL && node->properties != NULL){ - return StringDictExists(node->properties,key); - } else { - return 0; - } +void SetHdbProperty(pHdb node, char *key, char *value) +{ + if (node != NULL && key != NULL && node->properties != NULL) { + if (value == NULL) { + StringDictDelete(node->properties, key); + } else if (StringDictExists(node->properties, key)) { + StringDictUpdate(node->properties, key, value); + } else { + StringDictAddPair(node->properties, key, value); + } + } } + /*---------------------------------------------------------------------------*/ -int GetHdbProperty(pHdb node, char *key, char *value, int len){ - if(node != NULL && node->properties != NULL){ - return StringDictGet(node->properties,key,value,len); - } else { - return 0; - } +int GetHdbProperty(pHdb node, char *key, char *value, int len) +{ + if (node != NULL && node->properties != NULL) { + return StringDictGet(node->properties, key, value, len); + } else { + return 0; + } } + /*---------------------------------------------------------------------------*/ -char *GetHdbProp(pHdb node, char *key){ - if(node != NULL && node->properties != NULL){ - return StringDictGetShort(node->properties,key); - } else { - return NULL; - } +char *GetHdbProp(pHdb node, char *key) +{ + if (node != NULL && node->properties != NULL) { + return StringDictGetShort(node->properties, key); + } else { + return NULL; + } } + /*---------------------------------------------------------------------------*/ -void InitHdbPropertySearch(pHdb node){ - if(node != NULL && node->properties != NULL){ - StringDictKillScan(node->properties); - } +void InitHdbPropertySearch(pHdb node) +{ + if (node != NULL && node->properties != NULL) { + StringDictKillScan(node->properties); + } } + /*--------------------------------------------------------------------------*/ -const char *GetNextHdbProperty(pHdb node, char *value ,int len){ - if(node != NULL && node->properties != NULL) { - return StringDictGetNext(node->properties, value, len); - } else { - return NULL; - } -} +const char *GetNextHdbProperty(pHdb node, char *value, int len) +{ + if (node != NULL && node->properties != NULL) { + return StringDictGetNext(node->properties, value, len); + } else { + return NULL; + } +} diff --git a/hipadaba.h b/hipadaba.h index 212cacf6..29523287 100644 --- a/hipadaba.h +++ b/hipadaba.h @@ -49,72 +49,72 @@ typedef void voidFunc(void); typedef struct __hdbValue { - int dataType; - int arrayLength; - int doNotFree; - union __value { - int intValue; - double doubleValue; - char *text; - int *intArray; - double *floatArray; - voidFunc *func; - void *obj; - }v; -}hdbValue; + int dataType; + int arrayLength; + int doNotFree; + union __value { + int intValue; + double doubleValue; + char *text; + int *intArray; + double *floatArray; + voidFunc *func; + void *obj; + } v; +} hdbValue; /*------------------------------------------------------------------------------*/ typedef struct __hipadaba { - int magic; - struct __hipadaba *mama; - struct __hipadaba *child; - struct __hipadaba *next; - struct __hdbcallback *callBackChain; - char *name; - char *path; - hdbValue value; - int protected; - pStringDict properties; - }Hdb, *pHdb; + int magic; + struct __hipadaba *mama; + struct __hipadaba *child; + struct __hipadaba *next; + struct __hdbcallback *callBackChain; + char *name; + hdbValue value; + int protected; + pStringDict properties; +} Hdb, *pHdb; /*-------------- return values for callback functions -------------------------*/ -typedef enum {hdbContinue, - hdbAbort, - hdbKill } hdbCallbackReturn; +typedef enum { hdbContinue, + hdbAbort, + hdbKill +} hdbCallbackReturn; /*======================== Messages ===========================================*/ typedef struct __hdbMessage { - char *type; + char *type; } hdbMessage, *pHdbMessage; /*-----------------------------------------------------------------------------*/ typedef struct { - char *type; - hdbValue *v; - void *callData; -}hdbDataMessage, *pHdbDataMessage; + char *type; + hdbValue *v; + void *callData; +} hdbDataMessage, *pHdbDataMessage; /*-------------------------------------------------------------------------------*/ typedef struct { - char *type; - void *callData; -}hdbTreeChangeMessage, *pHdbTreeChangeMessage; + char *type; + void *callData; +} hdbTreeChangeMessage, *pHdbTreeChangeMessage; /*-------------------------------------------------------------------------------*/ typedef struct { - char *type; - void *testPtr; - void *result; -}hdbDataSearch, *pHdbDataSearch; + char *type; + void *testPtr; + void *result; +} hdbDataSearch, *pHdbDataSearch; /*-------------------------------------------------------------------------------*/ -typedef hdbCallbackReturn (*hdbCallbackFunction)(pHdb currentNode, - void *userData, - pHdbMessage message); +typedef hdbCallbackReturn(*hdbCallbackFunction) (pHdb currentNode, + void *userData, + pHdbMessage message); -typedef void (*killUserData)(void *data); +typedef void (*killUserData) (void *data); /*-------------------------------------------------------------------------------*/ typedef struct __hdbcallback { - void *userData; - killUserData killFunc; - hdbCallbackFunction userCallback; - int killFlag; - struct __hdbcallback *next; - struct __hdbcallback *previous; - }hdbCallback, *pHdbCallback; + void *userData; + killUserData killFunc; + hdbCallbackFunction userCallback; + int killFlag; + struct __hdbcallback *next; + struct __hdbcallback *previous; +} hdbCallback, *pHdbCallback; /*============= Message Test Functions ==========================================*/ /** * Test a message if it is a set message @@ -163,7 +163,7 @@ pHdbMessage GetHdbKillNodeMessage(pHdbMessage toTest); * @param datatype The datatype of the hdbValue * @param length The array length of the hdbValue * @return a suitably defined hdbValue - */ + */ hdbValue makeHdbValue(int datatype, int length); /** * wrap an integer as an hdbValue @@ -195,7 +195,7 @@ hdbValue MakeHdbText(char *initText); * data points to dynamically allocated memory. * @return: A properly initialized hdbValue structure */ -hdbValue MakeHdbIntArray(int length, int *data); +hdbValue MakeHdbIntArray(int length, int *data); /** * wrap a float array as an hdbValue * @param length The length of the int array @@ -205,13 +205,13 @@ hdbValue MakeHdbIntArray(int length, int *data); * data points to dynamically allocated memory. * @return: A properly initialized hdbValue structure */ -hdbValue MakeHdbFloatArray(int length, double *data); +hdbValue MakeHdbFloatArray(int length, double *data); /** * wrap a function as an hdbValue * @param func the function * @return: A properly initialized hdbValue structure */ -hdbValue MakeHdbFunc(voidFunc *func); +hdbValue MakeHdbFunc(voidFunc * func); /** * wrap an object as an hdbValue * @param obj the object @@ -223,14 +223,14 @@ hdbValue MakeHdbObj(void *obj); * @param v The hdbValue to check for dynamic memory allocation to be * released. */ -void ReleaseHdbValue(hdbValue *v); +void ReleaseHdbValue(hdbValue * v); /** * copy a hipadaba value field. Takes care of memory allocation * @param source The hdbValue to copy from * @param target The hdbValue to copy to. * @return 1 on success, 0 when out of memory or when type mismatch */ -int copyHdbValue(hdbValue *source, hdbValue *target); +int copyHdbValue(hdbValue * source, hdbValue * target); /** * compares two hdbValues for identity * @param v1 The first hdbValue @@ -246,13 +246,19 @@ int compareHdbValue(hdbValue v1, hdbValue v2); * @param clone the target hdbValue structure * @return 1 on success, 0 on when out of memory */ -int cloneHdbValue(hdbValue *source, hdbValue *clone); +int cloneHdbValue(hdbValue * source, hdbValue * clone); /** * get the length of the hdbValue in bytes. * @param v The hdbValue to calculate the length for * @return the number of data bytes */ int getHdbValueLength(hdbValue v); +/** + * calculate a checksum of the data in val + * @param val The hdbValue to calcululate the checksum for + * @return The checksum + */ +unsigned short getHdbCheckSum(hdbValue *val); /*========================== function protoypes: Nodes =======================*/ /** * make a new hipadaba node @@ -260,7 +266,7 @@ int getHdbValueLength(hdbValue v); * @param datatype The datatype of the new node * @param length the array length * @return a new node or NULL when out of memory - */ + */ pHdb MakeHipadabaNode(char *name, int datatype, int length); /** * add a child to a node at the end of the child list. @@ -268,12 +274,19 @@ pHdb MakeHipadabaNode(char *name, int datatype, int length); * @param child The node to add * @param callData User data for the tree chnage callback. Can be NULL. */ -void AddHipadabaChild(pHdb parent, pHdb child, void *callData); +void AddHipadabaChild(pHdb parent, pHdb child, void *callData); /** * Delete only the node data, without invoking any callbacks * @param node The node to delete. */ void DeleteNodeData(pHdb node); +/** + * Send a treechange message for node. + * @param node The node whose child list has changed + * @param calldata The connection or calldata associated with this operation. + */ +void SendTreeChangeMessage(pHdb node, void *callData); + /** * delete a hipadaba node and all its children. Then invoke the tree * change callback to notify listeners. @@ -292,14 +305,14 @@ int isHdbNodeValid(pHdb node); * @param root The node where to start the search for the node * @param path The unix path string for the node relative to parent * @return The desired node or NULL when no such node exists - */ + */ pHdb GetHipadabaNode(pHdb root, char *path); /** * given a node, return the full path name to the node * @param node The node to get the path for * @return The full path to the node. This is dynamically allocated memory; * the caller is reponsible for deleting it. Can be NULL when out of memory. - */ + */ char *GetHipadabaPath(pHdb node); /** * removes a node from the parents child list. @@ -322,21 +335,21 @@ int CountHdbChildren(pHdb node); * not be invoked * @return A new suitabaly initialised callback structure or NULL when required elements * are missing or there is nor memory. - */ -pHdbCallback MakeHipadabaCallback(hdbCallbackFunction func, - void *userData, killUserData killFunc); + */ +pHdbCallback MakeHipadabaCallback(hdbCallbackFunction func, + void *userData, killUserData killFunc); /** * add a callback at the end of the callback chain * @param node The node to which to append the callback * @param newCB The callback to append */ -void AppendHipadabaCallback(pHdb node,pHdbCallback newCB); +void AppendHipadabaCallback(pHdb node, pHdbCallback newCB); /** * add a callback at the head of the callback chain * @param node The node to which to append the callback * @param newCB The callback prepend */ -void PrependHipadabaCallback(pHdb node,pHdbCallback newCB); +void PrependHipadabaCallback(pHdb node, pHdbCallback newCB); /** * find the callback data * @param node the node from where callbacks have to be searched @@ -360,7 +373,7 @@ int InvokeCallbackChain(pHdb node, pHdbMessage message); void DeleteCallbackChain(pHdb node); /** * apply message to the node and all its children - * @param node Th node where to start recursing + * @param node The node where to start recursing * @param message The message to send */ void RecurseCallbackChains(pHdb node, pHdbMessage message); @@ -372,7 +385,7 @@ void RecurseCallbackChains(pHdb node, pHdbMessage message); * @param v The new value for the node * @param callData Additonal context data to be passed to the callback functions * @return 0 on failure, 1 on success - */ + */ int SetHipadabaPar(pHdb node, hdbValue v, void *callData); /** * Update a hipadaba parameter. This is an internal update of a parameter, @@ -381,7 +394,7 @@ int SetHipadabaPar(pHdb node, hdbValue v, void *callData); * @param v The new value for the node * @param callData Additonal context data to be passed to the callback functions * @return 0 on failure, 1 on success - */ + */ int UpdateHipadabaPar(pHdb node, hdbValue v, void *callData); /** * notify any update listeners that this node has been internally modifed. @@ -389,7 +402,7 @@ int UpdateHipadabaPar(pHdb node, hdbValue v, void *callData); * @param callData Addtional data for the callback * @return 1 on success, 0 on failure */ -int NotifyHipadabaPar(pHdb node,void *callData); +int NotifyHipadabaPar(pHdb node, void *callData); /** * Read a hipadaba parameter @@ -397,16 +410,17 @@ int NotifyHipadabaPar(pHdb node,void *callData); * @param v The read value for the node * @param callData Additonal context data to be passed to the callback functions * @return 0 on failure, 1 on success - */ -int GetHipadabaPar(pHdb node, hdbValue *v, void *callData); + */ +int GetHipadabaPar(pHdb node, hdbValue * v, void *callData); /*================================ Property Interface ==============================================*/ /** - * set a property + * Set or delete a property * @param node The node to set the property for * @param key The key for the property - * @param value The value of the property + * @param value The value of the property. If this is NULL, the + * property is deleted. */ - void SetHdbProperty(pHdb node, char *key, char *value); +void SetHdbProperty(pHdb node, char *key, char *value); /** * get the value of a property * @param node The node to get the property from @@ -415,14 +429,7 @@ int GetHipadabaPar(pHdb node, hdbValue *v, void *callData); * @param len The length of value * @return 0 on failure, 1 on success */ -/** - * Check if a property exists - * @param node The node to get the property from - * @param key The properties key - * @return 1 or 0 for true or false - */ -int HasHdbProperty(pHdb node, char *key); - int GetHdbProperty(pHdb node, char *key, char *value, int len); +int GetHdbProperty(pHdb node, char *key, char *value, int len); /** * get the value of a property * @param node The node to get the property from @@ -430,11 +437,11 @@ int HasHdbProperty(pHdb node, char *key); * @return the property or NULL on failure. Warning: the string is * only valid as long as the property has not changed */ - char *GetHdbProp(pHdb node, char *key); +char *GetHdbProp(pHdb node, char *key); /** * initialize a property scan on this node * @param node The node for which to scan properties - */ + */ void InitHdbPropertySearch(pHdb node); /** * get the next property in a search @@ -442,6 +449,6 @@ void InitHdbPropertySearch(pHdb node); * @param value An area where to copy the value of the property * @param len The length of value * @return The key of the property or NULL when the property list is exhausted - */ -const char *GetNextHdbProperty(pHdb node, char *value ,int len); + */ +const char *GetNextHdbProperty(pHdb node, char *value, int len); #endif diff --git a/histdriv.c b/histdriv.c index 14304f87..e9f81763 100644 --- a/histdriv.c +++ b/histdriv.c @@ -50,73 +50,71 @@ #include "HistDriv.i" /*--------------------------------------------------------------------------*/ - pHistDriver CreateHistDriver(pStringDict pOption) - { - pHistDriver pNew = NULL; - char pDim[20]; - int i; +pHistDriver CreateHistDriver(pStringDict pOption) +{ + pHistDriver pNew = NULL; + char pDim[20]; + int i; - /* allocate some more memory */ - pNew = (pHistDriver)malloc(sizeof(HistDriver)); - if(!pNew) - { - return NULL; - } - memset(pNew,0,sizeof(HistDriver)); - - pNew->data = makeHMData(); - if(!pNew->data) - { - free(pNew); - return NULL; - } - - /* initialise defaults */ - StringDictAddPair(pOption,"rank","1"); - for(i = 0; i < MAXDIM; i++) - { - sprintf(pDim,"dim%1.1d",i); - StringDictAddPair(pOption,pDim,"-126"); - } - pNew->fCountPreset = 10.; - pNew->eCount = eTimer; - pNew->iReconfig = 1; - pNew->iUpdate = 0; - - return pNew; - } -/*-------------------------------------------------------------------------*/ - void DeleteHistDriver(pHistDriver self) - { - assert(self); - - if(self->FreePrivate) - { - self->FreePrivate(self); - } - if(self->pOption){ - DeleteStringDict(self->pOption); - } - if(self->data) - { - killHMData(self->data); - } - free(self); - } -/*------------------------------------------------------------------------*/ - int HistDriverConfig(pHistDriver self, pStringDict pOpt, SConnection *pCon) - { - int iRet; - char pBueffel[512]; - char pValue[80]; - float fVal; - TokenList *pList = NULL, *pCurrent; - char *pBuf = NULL; - int i; - - assert(self); - assert(pOpt); - assert(pCon); - - return configureHMdata(self->data,pOpt,pCon); + /* allocate some more memory */ + pNew = (pHistDriver) malloc(sizeof(HistDriver)); + if (!pNew) { + return NULL; } + memset(pNew, 0, sizeof(HistDriver)); + + pNew->data = makeHMData(); + if (!pNew->data) { + free(pNew); + return NULL; + } + + /* initialise defaults */ + StringDictAddPair(pOption, "rank", "1"); + for (i = 0; i < MAXDIM; i++) { + snprintf(pDim,sizeof(pDim)-1, "dim%1.1d", i); + StringDictAddPair(pOption, pDim, "-126"); + } + pNew->fCountPreset = 10.; + pNew->eCount = eTimer; + pNew->iReconfig = 1; + pNew->iUpdate = 0; + + return pNew; +} + +/*-------------------------------------------------------------------------*/ +void DeleteHistDriver(pHistDriver self) +{ + assert(self); + + if (self->FreePrivate) { + self->FreePrivate(self); + } + if (self->pOption) { + DeleteStringDict(self->pOption); + } + if (self->data) { + killHMData(self->data); + } + free(self); +} + +/*------------------------------------------------------------------------*/ +int HistDriverConfig(pHistDriver self, pStringDict pOpt, + SConnection * pCon) +{ + int iRet; + char pBueffel[512]; + char pValue[80]; + float fVal; + TokenList *pList = NULL, *pCurrent; + char *pBuf = NULL; + int i; + + assert(self); + assert(pOpt); + assert(pCon); + + return configureHMdata(self->data, pOpt, pCon); +} diff --git a/histmem.c b/histmem.c index 510b882e..aae6d9e3 100644 --- a/histmem.c +++ b/histmem.c @@ -12,6 +12,11 @@ Refactored data handling into separater HMdata class. Mark Koennecke, January 2003 + + Added function to retrieve time delay and to format TOF bin array in order + to speed up TOF configuration for new http based HM's + + Mark Koennecke, March 2009 Copyright: @@ -65,6 +70,8 @@ #include "event.h" #include "status.h" #include "site.h" +#define ABS(x) (x < 0 ? -(x) : (x)) + /* #define LOADDEBUG 1 */ @@ -77,1713 +84,1671 @@ extern pHistDriver CreateRegressHM(pStringDict pOpt); */ extern pHistDriver MakeHMSlaveHM(pStringDict pOpt); /*------------------------------------------------------------------------*/ - static int HistHalt(void *pData) - { - pHistMem self = NULL; +static int HistHalt(void *pData) +{ + pHistMem self = NULL; - self = (pHistMem)pData; - assert(self); + self = (pHistMem) pData; + assert(self); - if(!self->iInit) - { - return 0; - } - return self->pDriv->Halt(self->pDriv); - } -/*------------------------------------------------------------------------*/ - static int HistSave(void *pData, char *name, FILE *fd) - { - pHistMem self = NULL; - char *pMode[] = { - "timer", - "monitor", - NULL - }; - CounterMode eCount; - float fVal; - - self = (pHistMem)pData; - assert(self); - - if(!self->iInit) - { - return 0; - } - - /* counting modes */ - eCount = GetHistCountMode(self); - fprintf(fd,"%s CountMode %s\n",name,pMode[eCount]); - fVal = GetHistPreset(self); - fprintf(fd,"%s preset %f\n",name,fVal); - - /* time binning if TOF */ - if(isInTOFMode(self->pDriv->data)) - { - fprintf(fd,"%s genbin %f %f %d\n", - name, self->pDriv->data->timeBinning[0], - self->pDriv->data->timeBinning[1] - - self->pDriv->data->timeBinning[0], - self->pDriv->data->nTimeChan); - fprintf(fd,"%s init\n",name); - } - - return 1; - } -/*------------------------------------------------------------------------*/ - static void *GetHistInterface(void *pData, int iID) - { - pHistMem self = NULL; - - self = (pHistMem)pData; - if(iID == COUNTID) - { - return self->pCountInt; - } - else if(iID == CALLBACKINTERFACE) - { - return self->pCall; - } - return NULL; + if (!self->iInit) { + return 0; } + return self->pDriv->Halt(self->pDriv); +} + /*------------------------------------------------------------------------*/ - static void HistSetParameter(void *pData, float fPreset, CounterMode eMode) - { - pHistMem self = NULL; +static int HistSave(void *pData, char *name, FILE * fd) +{ + pHistMem self = NULL; + char *pMode[] = { + "timer", + "monitor", + NULL + }; + CounterMode eCount; + float fVal; - self = (pHistMem)pData; - assert(self); + self = (pHistMem) pData; + assert(self); - self->pDriv->eCount = eMode; - self->pDriv->fCountPreset = fPreset; - } -/*-------------------------------------------------------------------------*/ - static int HistStartCount(void *pData, SConnection *pCon) - { - pHistMem self = NULL; - char pBueffel[512]; - char pError[80]; - int iErr, iRet, i; - - self = (pHistMem)pData; - assert(self); - - if(!self->iInit) - { - SCWrite(pCon,"ERROR: histogram memory not initialised",eError); - return 0; - } - - /* try at least three times to do it */ - for(i = 0; i < 3; i++) - { - iRet = self->pDriv->Start(self->pDriv, pCon); - if(iRet == OKOK) - { - /* send a COUNTSTART event */ - InvokeCallBack(self->pCall,COUNTSTART,pCon); - updateHMData(self->pDriv->data); - 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: failed to fix histogram memory problem", - eError); - SCSetInterrupt(pCon,eAbortBatch); - return HWFault; - } - } - } - SCWrite(pCon,"ERROR: failed to fix histogram memory problem",eError); - SCSetInterrupt(pCon,eAbortBatch); - return HWFault; + if (!self->iInit) { + return 0; } + + /* counting modes */ + eCount = GetHistCountMode(self); + fprintf(fd, "%s CountMode %s\n", name, pMode[eCount]); + fVal = GetHistPreset(self); + fprintf(fd, "%s preset %f\n", name, fVal); + + /* time binning if TOF */ + if (isInTOFMode(self->pDriv->data)) { + fprintf(fd, "%s genbin %f %f %d\n", + name, self->pDriv->data->timeBinning[0], + self->pDriv->data->timeBinning[1] - + self->pDriv->data->timeBinning[0], + self->pDriv->data->nTimeChan); + fprintf(fd, "%s init\n", name); + } + + return 1; +} + +/*------------------------------------------------------------------------*/ +static void *GetHistInterface(void *pData, int iID) +{ + pHistMem self = NULL; + + self = (pHistMem) pData; + if (iID == COUNTID) { + return self->pCountInt; + } else if (iID == CALLBACKINTERFACE) { + return self->pCall; + } + return NULL; +} + +/*------------------------------------------------------------------------*/ +static void HistSetParameter(void *pData, float fPreset, CounterMode eMode) +{ + pHistMem self = NULL; + + self = (pHistMem) pData; + assert(self); + + self->pDriv->eCount = eMode; + self->pDriv->fCountPreset = fPreset; +} + /*-------------------------------------------------------------------------*/ - static int HistPause(void *pData, SConnection *pCon) - { - pHistMem self = NULL; - char pBueffel[512]; - char pError[80]; - int iErr, iRet, i; - - self = (pHistMem)pData; - assert(self); +static int HistStartCount(void *pData, SConnection * pCon) +{ + pHistMem self = NULL; + char pBueffel[512]; + char pError[80]; + int iErr, iRet, i; - if(!self->iInit) - { - SCWrite(pCon,"ERROR: histogram memory not initialised",eError); - return 0; - } + self = (pHistMem) pData; + assert(self); - /* try at least three times to do it */ - for(i = 0; i < 3; i++) - { - iRet = self->pDriv->Pause(self->pDriv, pCon); - if(iRet == OKOK) - { - updateHMData(self->pDriv->data); - 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: failed to fix histogram memory problem",eError); - SCSetInterrupt(pCon,eAbortBatch); - return HWFault; - } - } + if (!GetCountLock(self->pCountInt, pCon)) { + return HWFault; + } + + if (!self->iInit) { + SCWrite(pCon, "ERROR: histogram memory not initialised", eLogError); + return 0; + } + + /* try at least three times to do it */ + for (i = 0; i < 3; i++) { + iRet = self->pDriv->Start(self->pDriv, pCon); + if (iRet == OKOK) { + /* send a COUNTSTART event */ + InvokeCallBack(self->pCall, COUNTSTART, pCon); + updateHMData(self->pDriv->data); + return iRet; + } else { + iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79); + snprintf(pBueffel,sizeof(pBueffel)-1, "WARNING: %s ", pError); + SCWrite(pCon, pBueffel, eLogError); + iRet = self->pDriv->TryAndFixIt(self->pDriv, iErr); + if (iRet == COTERM) { + SCWrite(pCon, "ERROR: failed to fix histogram memory problem", + eLogError); + SCSetInterrupt(pCon, eAbortBatch); + ReleaseCountLock(self->pCountInt); + return HWFault; } - SCWrite(pCon,"ERROR: failed to fix histogram memory problem",eError); - SCSetInterrupt(pCon,eAbortBatch); - return HWFault; + } + } + SCWrite(pCon, "ERROR: failed to fix histogram memory problem", eError); + SCSetInterrupt(pCon, eAbortBatch); + ReleaseCountLock(self->pCountInt); + return HWFault; +} + +/*-------------------------------------------------------------------------*/ +static int HistPause(void *pData, SConnection * pCon) +{ + pHistMem self = NULL; + char pBueffel[512]; + char pError[80]; + int iErr, iRet, i; + + self = (pHistMem) pData; + assert(self); + + if (!self->iInit) { + SCWrite(pCon, "ERROR: histogram memory not initialised", eError); + return 0; + } + + /* try at least three times to do it */ + for (i = 0; i < 3; i++) { + iRet = self->pDriv->Pause(self->pDriv, pCon); + if (iRet == OKOK) { + updateHMData(self->pDriv->data); + return iRet; + } else { + iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79); + snprintf(pBueffel,sizeof(pBueffel)-1, "WARNING: %s ", pError); + SCWrite(pCon, pBueffel, eError); + iRet = self->pDriv->TryAndFixIt(self->pDriv, iErr); + if (iRet == COTERM) { + SCWrite(pCon, "ERROR: failed to fix histogram memory problem", + eError); + SCSetInterrupt(pCon, eAbortBatch); + ReleaseCountLock(self->pCountInt); + return HWFault; + } + } + } + SCWrite(pCon, "ERROR: failed to fix histogram memory problem", eError); + SCSetInterrupt(pCon, eAbortBatch); + ReleaseCountLock(self->pCountInt); + return HWFault; +} + +/*-------------------------------------------------------------------------*/ +static int HistContinue(void *pData, SConnection * pCon) +{ + pHistMem self = NULL; + char pBueffel[512]; + char pError[80]; + int iErr, iRet, i; + + self = (pHistMem) pData; + assert(self); + + if (!self->iInit) { + SCWrite(pCon, "ERROR: histogram memory not initialised", eError); + return 0; + } + + /* try at least three times to do it */ + for (i = 0; i < 3; i++) { + iRet = self->pDriv->Continue(self->pDriv, pCon); + if (iRet == OKOK) { + updateHMData(self->pDriv->data); + return iRet; + } else { + iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79); + snprintf(pBueffel,sizeof(pBueffel)-1, "WARNING: %s ", pError); + SCWrite(pCon, pBueffel, eError); + iRet = self->pDriv->TryAndFixIt(self->pDriv, iErr); + if (iRet == COTERM) { + SCWrite(pCon, "ERROR: failed to fix histogram memory problem", + eError); + SCSetInterrupt(pCon, eAbortBatch); + ReleaseCountLock(self->pCountInt); + return HWFault; + } + } + } + SCWrite(pCon, "ERROR: failed to fix histogram memory problem", eError); + ReleaseCountLock(self->pCountInt); + SCSetInterrupt(pCon, eAbortBatch); + return HWFault; +} + +/*-------------------------------------------------------------------------*/ +static int HistCountStatus(void *pData, SConnection * pCon) +{ + pHistMem self = NULL; + int eCt, iRet, iErr; + char pBueffel[512], pError[90]; + + self = (pHistMem) pData; + assert(self); + + if (!self->iInit) { + SCWrite(pCon, "ERROR: histogram memory not initialised", eError); + InvokeCallBack(self->pCall, COUNTEND, NULL); + ReleaseCountLock(self->pCountInt); + return COTERM; + } + + eCt = self->pDriv->GetCountStatus(self->pDriv, pCon); + if (eCt == HWFault) { + iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79); + snprintf(pBueffel,sizeof(pBueffel)-1, "WARNING: %s ", pError); + SCWrite(pCon, pBueffel, eError); + iRet = self->pDriv->TryAndFixIt(self->pDriv, iErr); + if (iRet == COTERM) { + SCWrite(pCon, "ERROR: failed to fix histogram memory problem", + eError); + SCSetInterrupt(pCon, eAbortBatch); + InvokeCallBack(self->pCall, COUNTEND, NULL); + ReleaseCountLock(self->pCountInt); + return eCt; + } else { + updateHMData(self->pDriv->data); + return HWBusy; + } + } + if (eCt == HWBusy){ + updateHMData(self->pDriv->data); } -/*-------------------------------------------------------------------------*/ - static int HistContinue(void *pData, SConnection *pCon) - { - pHistMem self = NULL; - char pBueffel[512]; - char pError[80]; - int iErr, iRet, i; - - self = (pHistMem)pData; - assert(self); - - if(!self->iInit) - { - SCWrite(pCon,"ERROR: histogram memory not initialised",eError); - return 0; - } - - /* try at least three times to do it */ - for(i = 0; i < 3; i++) - { - iRet = self->pDriv->Continue(self->pDriv, pCon); - if(iRet == OKOK) - { - updateHMData(self->pDriv->data); - 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: failed to fix histogram memory problem",eError); - SCSetInterrupt(pCon,eAbortBatch); - return HWFault; - } - } - } - SCWrite(pCon,"ERROR: failed to fix histogram memory problem",eError); - SCSetInterrupt(pCon,eAbortBatch); - return HWFault; + if (eCt == HWIdle) { + /* force an update of local histogram data with next + GetHistogram + */ + updateHMData(self->pDriv->data); + InvokeCallBack(self->pCall, COUNTEND, NULL); + ReleaseCountLock(self->pCountInt); } -/*-------------------------------------------------------------------------*/ - static int HistCountStatus(void *pData, SConnection *pCon) - { - pHistMem self = NULL; - int eCt, iRet, iErr; - char pBueffel[512], pError[90]; - - self = (pHistMem)pData; - assert(self); - - if(!self->iInit) - { - SCWrite(pCon,"ERROR: histogram memory not initialised",eError); - InvokeCallBack(self->pCall,COUNTEND,NULL); - return COTERM; - } - - eCt = self->pDriv->GetCountStatus(self->pDriv,pCon); - if(eCt == HWFault) - { - 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: failed to fix histogram memory problem",eError); - SCSetInterrupt(pCon,eAbortBatch); - InvokeCallBack(self->pCall,COUNTEND,NULL); - return eCt; - } - else - { - updateHMData(self->pDriv->data); - return HWBusy; - } - } - if(eCt == HWBusy) - updateHMData(self->pDriv->data); - - if(eCt == HWIdle) - { - /* force an update of local histogram data with next - GetHistogram - */ - updateHMData(self->pDriv->data); - InvokeCallBack(self->pCall,COUNTEND,NULL); - } - - return eCt; - } + + return eCt; +} + /*------------------------------------------------------------------------- The question arises if the histograms shall be duplicated on the host computer or not. They need to be in order to be written to file! */ - static int HistTransfer(void *pData, SConnection *pCon) - { - pHistMem self = NULL; - int i, iErr, iRet, iStatus; - char pBueffel[512], pError[80]; - - self = (pHistMem)pData; - assert(self); - - if(!self->iInit) - { - SCWrite(pCon,"ERROR: histogram memory not initialised",eError); - return COTERM; +static int HistTransfer(void *pData, SConnection * pCon) +{ + pHistMem self = NULL; + int i, iErr, iRet, iStatus; + char pBueffel[512], pError[80]; + + self = (pHistMem) pData; + assert(self); + + if (!self->iInit) { + SCWrite(pCon, "ERROR: histogram memory not initialised", eError); + return COTERM; + } + + /* try at least three times */ + for (i = 0; i < 3; i++) { + iRet = self->pDriv->GetData(self->pDriv, pCon); + if (iRet == OKOK) { + self->pDriv->iUpdate = 0; + iStatus = iRet; + } else { + iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79); + snprintf(pBueffel,sizeof(pBueffel)-1, "WARNING: %s ", pError); + SCWrite(pCon, pBueffel, eError); + iRet = self->pDriv->TryAndFixIt(self->pDriv, iErr); + if (iRet == COTERM) { + SCWrite(pCon, "ERROR: failed to fix histogram memory problem", + eError); + SCSetInterrupt(pCon, eAbortBatch); + iStatus = HWFault; + } } + } + if (iRet == OKOK) { + return iStatus; + } + SCWrite(pCon, "ERROR: failed to fix histogram memory problem", eError); + SCSetInterrupt(pCon, eAbortBatch); + return HWFault; +} - /* try at least three times */ - for(i = 0; i < 3; i++) - { - iRet = self->pDriv->GetData(self->pDriv, pCon); - if(iRet == OKOK) - { - self->pDriv->iUpdate = 0; - iStatus = 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: failed to fix histogram memory problem", eError); - SCSetInterrupt(pCon,eAbortBatch); - iStatus = HWFault; - } - } - } - if(iRet == OKOK) - { - return iStatus; - } - SCWrite(pCon,"ERROR: failed to fix histogram memory problem",eError); - SCSetInterrupt(pCon,eAbortBatch); - return HWFault; - } /*-------------------------------------------------------------------------*/ - pHistMem CreateHistMemory(char *driver) - { - pHistMem pNew = NULL; - pSite site = NULL; - pStringDict pOption; +pHistMem CreateHistMemory(char *driver) +{ + pHistMem pNew = NULL; + pSite site = NULL; + pStringDict pOption; - /* make memory */ - pNew = (pHistMem)malloc(sizeof(HistMem)); - if(!pNew) - { - return NULL; - } - memset(pNew,0,sizeof(HistMem)); - - /* make object descriptor */ - pNew->pDes = CreateDescriptor("HistMem"); - if(!pNew->pDes) - { - free(pNew); - return NULL; - } - pNew->pDes->SaveStatus = HistSave; - pNew->pDes->GetInterface = GetHistInterface; - - /* initialise countable interface */ - pNew->pCountInt = CreateCountableInterface(); - if(!pNew->pCountInt) - { - DeleteDescriptor(pNew->pDes); - free(pNew); - return NULL; - } - /* initialise callback interface */ - pNew->pCall = CreateCallBackInterface(); - if(!pNew->pCall) - { - DeleteDescriptor(pNew->pDes); - free(pNew); - return NULL; - } - pNew->pCountInt->SetCountParameters = HistSetParameter; - pNew->pCountInt->StartCount = HistStartCount; - pNew->pCountInt->CheckCountStatus = HistCountStatus; - pNew->pCountInt->TransferData = HistTransfer; - pNew->pCountInt->Halt = HistHalt; - pNew->pCountInt->Pause = HistPause; - pNew->pCountInt->Continue = HistContinue; - - /* initialise options dictionary */ - pOption = CreateStringDict(); - if(!pOption) - { - DeleteDescriptor(pNew->pDes); - free(pNew); - return NULL; - } - StringDictAddPair(pOption,"driver",driver); - StringDictAddPair(pOption,"update","0"); + /* make memory */ + pNew = (pHistMem) malloc(sizeof(HistMem)); + if (!pNew) { + return NULL; + } + memset(pNew, 0, sizeof(HistMem)); - /* initialise driver */ - if(strcmp(driver,"sim") == 0) - { - pNew->pDriv = CreateSIMHM(pOption); - } - else if(strcmp(driver,"mcstas") == 0) - { - pNew->pDriv = NewMcStasHM(pOption); - } - else if(strcmp(driver,"regress") == 0) - { - pNew->pDriv = CreateRegressHM(pOption); - } + /* make object descriptor */ + pNew->pDes = CreateDescriptor("HistMem"); + if (!pNew->pDes) { + free(pNew); + return NULL; + } + pNew->pDes->SaveStatus = HistSave; + pNew->pDes->GetInterface = GetHistInterface; + + /* initialise countable interface */ + pNew->pCountInt = CreateCountableInterface(); + if (!pNew->pCountInt) { + DeleteDescriptor(pNew->pDes); + free(pNew); + return NULL; + } + /* initialise callback interface */ + pNew->pCall = CreateCallBackInterface(); + if (!pNew->pCall) { + DeleteDescriptor(pNew->pDes); + free(pNew); + return NULL; + } + pNew->pCountInt->SetCountParameters = HistSetParameter; + pNew->pCountInt->StartCount = HistStartCount; + pNew->pCountInt->CheckCountStatus = HistCountStatus; + pNew->pCountInt->TransferData = HistTransfer; + pNew->pCountInt->Halt = HistHalt; + pNew->pCountInt->Pause = HistPause; + pNew->pCountInt->Continue = HistContinue; + + /* initialise options dictionary */ + pOption = CreateStringDict(); + if (!pOption) { + DeleteDescriptor(pNew->pDes); + free(pNew); + return NULL; + } + StringDictAddPair(pOption, "driver", driver); + StringDictAddPair(pOption, "update", "0"); + + /* initialise driver */ + if (strcmp(driver, "sim") == 0) { + pNew->pDriv = CreateSIMHM(pOption); + } else if (strcmp(driver, "mcstas") == 0) { + pNew->pDriv = NewMcStasHM(pOption); + } else if (strcmp(driver, "regress") == 0) { + pNew->pDriv = CreateRegressHM(pOption); + } /* else if(strcmp(driver,"slave") == 0) { pNew->pDriv = MakeHMSlaveHM(pOption); } -*/ - else - { - site = getSite(); - if(site != NULL) - { - pNew->pDriv = site->CreateHistogramMemoryDriver(driver, - pOption); - } - } - - if(pNew->pDriv == NULL) - { - DeleteDescriptor(pNew->pDes); - DeleteStringDict(pOption); - free(pNew); - return NULL; - } - pNew->iAccess = usUser; - pNew->iExponent = 0; - pNew->iInit = 0; - pNew->pDriv->pOption = pOption; - - return pNew; - } -/*-----------------------------------------------------------------------*/ - void DeleteHistMemory(void *pData) - { - pHistMem self; - - self = (pHistMem)pData; - assert(self); - - if(self->pDriv) - { - DeleteHistDriver(self->pDriv); - } - if(self->pDes) - { - DeleteDescriptor(self->pDes); - } - Fortify_CheckAllMemory(); - - if(self->pCountInt) - { - free(self->pCountInt); - } - if(self->pCall) - { - DeleteCallBackInterface(self->pCall); - } - free(self); +*/ + else { + site = getSite(); + if (site != NULL) { + pNew->pDriv = site->CreateHistogramMemoryDriver(driver, pOption); + } } + + if (pNew->pDriv == NULL) { + DeleteDescriptor(pNew->pDes); + DeleteStringDict(pOption); + free(pNew); + return NULL; + } + pNew->iAccess = usUser; + pNew->iExponent = 0; + pNew->iInit = 0; + pNew->pDriv->pOption = pOption; + + return pNew; +} + +/*-----------------------------------------------------------------------*/ +void DeleteHistMemory(void *pData) +{ + pHistMem self; + + self = (pHistMem) pData; + assert(self); + + if (self->pDriv) { + DeleteHistDriver(self->pDriv); + } + if (self->pDes) { + DeleteDescriptor(self->pDes); + } + (void)Fortify_CheckAllMemory(); + + if (self->pCountInt) { + free(self->pCountInt); + } + if (self->pCall) { + DeleteCallBackInterface(self->pCall); + } + free(self); +} + /*-------------------------------------------------------------------------*/ - int MakeHistMemory(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - pHistMem pNew = NULL; - char pBueffel[512]; - int iRet; - - /* check no of arguments */ - if(argc < 3) - { - sprintf(pBueffel,"ERROR: insufficient no of arguments to %s",argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* make new HM */ - strtolower(argv[2]); - pNew = CreateHistMemory(argv[2]); - if(!pNew) - { - sprintf(pBueffel,"ERROR: failed to create Histogram Memory %s, driver %s may be invalid or no memory", - argv[1], argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } +int MakeHistMemory(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pHistMem pNew = NULL; + char pBueffel[512]; + int iRet; - StringDictAddPair(pNew->pDriv->pOption,"name",argv[1]); - - /* install HM as command */ - iRet = AddCommand(pSics,argv[1],HistAction,DeleteHistMemory,(void *)pNew); - if(!iRet) - { - sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[1]); - SCWrite(pCon,pBueffel,eError); - DeleteHistMemory((void *)pNew); - return 0; - } - return 1; + /* check no of arguments */ + if (argc < 3) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: insufficient no of arguments to %s", + argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; } + + /* make new HM */ + strtolower(argv[2]); + pNew = CreateHistMemory(argv[2]); + if (!pNew) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: failed to create Histogram Memory %s, driver %s may be invalid or no memory", + argv[1], argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + StringDictAddPair(pNew->pDriv->pOption, "name", argv[1]); + + /* install HM as command */ + iRet = + AddCommand(pSics, argv[1], HistAction, DeleteHistMemory, + (void *) pNew); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: duplicate command %s not created", argv[1]); + SCWrite(pCon, pBueffel, eError); + DeleteHistMemory((void *) pNew); + return 0; + } + return 1; +} + /*------------------------------------------------------------------------*/ - int HistGetOption(pHistMem self, char *name, char *result, int iLen) - { - assert(self); - strtolower(name); - return StringDictGet(self->pDriv->pOption,name, result,iLen); - } -/*-----------------------------------------------------------------------*/ - int HistSetOption(pHistMem self, char *name, char *value) - { - int status; +int HistGetOption(pHistMem self, char *name, char *result, int iLen) +{ + assert(self); + strtolower(name); + return StringDictGet(self->pDriv->pOption, name, result, iLen); +} - assert(self); - self->iInit = 1; - strtolower(name); - status = StringDictUpdate(self->pDriv->pOption,name, value); - if(status == 0) - { - return StringDictAddPair(self->pDriv->pOption,name, value); - } - return 1; - } /*-----------------------------------------------------------------------*/ - int HistConfigure(pHistMem self, SConnection *pCon, SicsInterp *pSics) - { - int iRet, iVal; - char pValue[80]; - - assert(self); - assert(pCon); - - iRet = HistDriverConfig(self->pDriv,self->pDriv->pOption,pCon); - if(!iRet) - { - SCWrite(pCon,"ERROR: failed to configure histogram memory",eError); - return 0; - } - iRet = self->pDriv->Configure(self->pDriv,pCon, self->pDriv->pOption,pSics); - if(!iRet) - { - SCWrite(pCon,"ERROR: failed to configure histogram memory",eError); - return 0; - } - return 1; - } -/*--------------------------------------------------------------------------*/ - float GetHistPreset(pHistMem self) - { - int i; - float fVal; - - assert(self); - - fVal = self->pDriv->fCountPreset; - if(self->pDriv->eCount == ePreset) - { - for(i = 0; i < self->iExponent; i++) - { - fVal /= 10.; - } - } - return fVal; - } -/*--------------------------------------------------------------------------*/ - int SetHistPreset(pHistMem self, float fVal) - { - int i; - - assert(self); - - if(fVal < .0) - { - return 0; - } - if(GetHistCountMode(self) == ePreset) - { - for(i = 0; i < self->iExponent;i++) - { - fVal *= 10.; - } - } - self->pDriv->fCountPreset = fVal; - return 1; - } -/*--------------------------------------------------------------------------*/ - int GetHistDim(pHistMem self, int iDim[MAXDIM], int *nDim) - { - - assert(self); +int HistSetOption(pHistMem self, char *name, char *value) +{ + int status; + + assert(self); + self->iInit = 1; + strtolower(name); + status = StringDictUpdate(self->pDriv->pOption, name, value); + if (status == 0) { + return StringDictAddPair(self->pDriv->pOption, name, value); + } + return 1; +} + +/*-----------------------------------------------------------------------*/ +int HistConfigure(pHistMem self, SConnection * pCon, SicsInterp * pSics) +{ + int iRet, iVal; + char pValue[80]; + + assert(self); + assert(pCon); + + if (isRunning(self->pCountInt)) { + SCWrite(pCon, + "ERROR: cannot configure histogram memory while counting", + eError); + return 0; + } + + iRet = HistDriverConfig(self->pDriv, self->pDriv->pOption, pCon); + if (!iRet) { + SCWrite(pCon, "ERROR: failed to configure histogram memory", eError); + return 0; + } + iRet = + self->pDriv->Configure(self->pDriv, pCon, self->pDriv->pOption, + pSics); + if (!iRet) { + SCWrite(pCon, "ERROR: failed to configure histogram memory", eError); + return 0; + } + tracePar(self->pDes->name,"initialized"); + return 1; +} - getHMDataDim(self->pDriv->data,iDim,nDim); - if(isInTOFMode(self->pDriv->data)) - { - iDim[*nDim] = getNoOfTimebins(self->pDriv->data); - *nDim = *nDim + 1; - } - return 1; - } /*--------------------------------------------------------------------------*/ - long HistSum(pHistMem self, SConnection *pCon, - int iStart[MAXDIM], int iEnd[MAXDIM]) - { - assert(self); - return sumHMDataRectangle(self,pCon,iStart,iEnd); - } +float GetHistPreset(pHistMem self) +{ + int i; + float fVal; + + assert(self); + + fVal = self->pDriv->fCountPreset; + if (self->pDriv->eCount == ePreset) { + for (i = 0; i < self->iExponent; i++) { + fVal /= 10.; + } + } + return fVal; +} + +/*--------------------------------------------------------------------------*/ +int SetHistPreset(pHistMem self, float fVal) +{ + int i; + + assert(self); + + if (fVal < .0) { + return 0; + } + if (GetHistCountMode(self) == ePreset) { + for (i = 0; i < self->iExponent; i++) { + fVal *= 10.; + } + } + self->pDriv->fCountPreset = fVal; + return 1; +} + +/*--------------------------------------------------------------------------*/ +int GetHistDim(pHistMem self, int iDim[MAXDIM], int *nDim) +{ + + assert(self); + pDummy pDum; + hdbValue v; + pHdb node; + + pDum = (pDummy)self; + if(strcmp(pDum->pDescriptor->name,"HistMemSec") == 0){ + node = GetHipadabaNode(pDum->pDescriptor->parNode,"dim"); + assert(node != NULL); + GetHipadabaPar(node,&v,NULL); + *nDim = v.arrayLength; + memcpy(iDim,v.v.intArray, *nDim*sizeof(int)); + return 1; + } + + getHMDataDim(self->pDriv->data, iDim, nDim); + if (isInTOFMode(self->pDriv->data)) { + iDim[*nDim] = getNoOfTimebins(self->pDriv->data); + *nDim = *nDim + 1; + } + return 1; +} + +/*--------------------------------------------------------------------------*/ +long HistSum(pHistMem self, SConnection * pCon, + int iStart[MAXDIM], int iEnd[MAXDIM]) +{ + assert(self); + return sumHMDataRectangle(self, pCon, iStart, iEnd); +} + /*---------------------------------------------------------------------------*/ - CounterMode GetHistCountMode(pHistMem self) - { - assert(self); - return self->pDriv->eCount; - } -/*--------------------------------------------------------------------------*/ - int SetHistCountMode(pHistMem self, CounterMode eNew) - { - int i; - - assert(self); - if(eNew == self->pDriv->eCount) - { - return 1; - } - - if(eNew == eTimer) - { - for(i = 0; i < self->iExponent; i++) - { - self->pDriv->fCountPreset /= 10.; - } - } - if(eNew == ePreset) - { - for(i = 0; i < self->iExponent; i++) - { - self->pDriv->fCountPreset *= 10.; - } - } - self->pDriv->eCount = eNew; - return 1; +CounterMode GetHistCountMode(pHistMem self) +{ + assert(self); + return self->pDriv->eCount; +} - } /*--------------------------------------------------------------------------*/ - long GetHistMonitor(pHistMem self, int i, SConnection *pCon) - { - assert(self); - return self->pDriv->GetMonitor(self->pDriv,i,pCon); - } +int SetHistCountMode(pHistMem self, CounterMode eNew) +{ + int i; + + assert(self); + if (eNew == self->pDriv->eCount) { + return 1; + } + + if (eNew == eTimer) { + for (i = 0; i < self->iExponent; i++) { + self->pDriv->fCountPreset /= 10.; + } + } + if (eNew == ePreset) { + for (i = 0; i < self->iExponent; i++) { + self->pDriv->fCountPreset *= 10.; + } + } + self->pDriv->eCount = eNew; + return 1; + +} + +/*--------------------------------------------------------------------------*/ +long GetHistMonitor(pHistMem self, int i, SConnection * pCon) +{ + assert(self); + return self->pDriv->GetMonitor(self->pDriv, i, pCon); +} + /*-----------------------------------------------------------------------*/ void HistDirty(pHistMem self) { assert(self); - updateHMData(self->pDriv->data); + if(self->pDriv != NULL){ + updateHMData(self->pDriv->data); + } } + /*-------------------------------------------------------------------------*/ - const float *GetHistTimeBin(pHistMem self, int *iLength) - { - assert(self); - *iLength = getNoOfTimebins(self->pDriv->data); - return getTimeBinning(self->pDriv->data); - } +const float *GetHistTimeBin(pHistMem self, int *iLength) +{ + assert(self); + *iLength = getNoOfTimebins(self->pDriv->data); + return getTimeBinning(self->pDriv->data); +} + /*-------------------------------------------------------------------------*/ - int GetHistLength(pHistMem self) - { - assert(self); - - return getHMDataLength(self->pDriv->data); - } +int GetHistLength(pHistMem self) +{ + assert(self); + + return getHMDataLength(self->pDriv->data); +} + /*--------------------------------------------------------------------------*/ - float GetHistCountTime(pHistMem self, SConnection *pCon) - { - assert(self); - return self->pDriv->GetTime(self->pDriv,pCon); - } +float GetHistCountTime(pHistMem self, SConnection * pCon) +{ + assert(self); + return self->pDriv->GetTime(self->pDriv, pCon); +} + /*-------------------------------------------------------------------------*/ - int HistDoCount(pHistMem self, SConnection *pCon) - { - assert(self); +int HistDoCount(pHistMem self, SConnection * pCon) +{ + assert(self); - /* start */ - return StartDevice(GetExecutor(),"HistogramMemory", self->pDes, self, - pCon, self->pDriv->fCountPreset); - } + /* start */ + return StartDevice(GetExecutor(), "HistogramMemory", self->pDes, self, + pCon, RUNRUN, self->pDriv->fCountPreset); +} + /*-----------------------------------------------------------------------*/ - int HistBlockCount(pHistMem self, SConnection *pCon) - { - int iRet; - - assert(self); - - /* start counting */ - iRet = StartDevice(GetExecutor(),"HistogramMemory", self->pDes, self, - pCon, self->pDriv->fCountPreset); - if(!iRet) - { - /* error has already been reported */ - return 0; - } - - /* wait till end */ - 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; - } +int HistBlockCount(pHistMem self, SConnection * pCon) +{ + int iRet; - - return iRet; + assert(self); + + /* start counting */ + iRet = StartDevice(GetExecutor(), "HistogramMemory", self->pDes, self, + pCon, RUNDRIVE, self->pDriv->fCountPreset); + if (!iRet) { + /* error has already been reported */ + return 0; + } + + /* wait till end */ + iRet = Wait4Success(GetExecutor()); + if (iRet == DEVINT) { + SCWrite(pCon, "Counting aborted due to Interrupt", eError); + } else if (iRet == DEVERROR) { + SCWrite(pCon, "Counting finished with Problems", eValue); + iRet = 1; + } else { + SCWrite(pCon, "Counting finished", eValue); + iRet = 1; + } + + + return iRet; + +} - } /*-------------------------------------------------------------------------*/ - int SetHistogram(pHistMem self, SConnection *pCon, - int i, int iStart, int iEnd, HistInt *lData) - { - int ii, iErr, iRet; - char pBueffel[512], pError[80]; - - assert(self); +int SetHistogram(pHistMem self, SConnection * pCon, + int i, int iStart, int iEnd, HistInt * lData) +{ + int ii, iErr, iRet; + char pBueffel[512], pError[80]; - if(!self->iInit) - { - SCWrite(pCon,"ERROR: histogram memory not initialised",eError); - return 0; - } + assert(self); - /* try at least three times */ - for(ii = 0; ii < 3; ii++) - { - iRet = self->pDriv->SetHistogram(self->pDriv,pCon, - i,iStart,iEnd,lData); - if(iRet == OKOK) - { - updateHMData(self->pDriv->data); - return 1; - } - else - { - iRet = self->pDriv->GetError(self->pDriv,&iErr,pError,79); - sprintf(pBueffel,"ERROR: %s ",pError); - SCWrite(pCon,pBueffel,eError); - iRet = self->pDriv->TryAndFixIt(self->pDriv,iErr); - if(iRet == COTERM) - { - return 0; - } - } + if (!self->iInit) { + SCWrite(pCon, "ERROR: histogram memory not initialised", eError); + return 0; + } + + /* try at least three times */ + for (ii = 0; ii < 3; ii++) { + iRet = self->pDriv->SetHistogram(self->pDriv, pCon, + i, iStart, iEnd, lData); + if (iRet == OKOK) { + updateHMData(self->pDriv->data); + return 1; + } else { + iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79); + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s ", pError); + SCWrite(pCon, pBueffel, eError); + iRet = self->pDriv->TryAndFixIt(self->pDriv, iErr); + if (iRet == COTERM) { + return 0; } - return 0; - } -/*-------------------------------------------------------------------------*/ - int GetHistogram(pHistMem self, SConnection *pCon, - int i, int iStart, int iEnd, HistInt *lData, int iDataLen) - { - assert(self); - - if(!self->iInit) - { - SCWrite(pCon,"ERROR: histogram memory not initialised",eError); - return 0; - } - - if( (iEnd -iStart) > iDataLen/sizeof(HistInt)) - { - SCWrite(pCon,"WARNING: truncating request to fit data space",eWarning); - iEnd = (iDataLen/sizeof(HistInt)) - 1; - } - return getHMDataHistogram(self,pCon,i,iStart,iEnd,lData); - } -/*-------------------------------------------------------------------------*/ - int GetHistogramDirect(pHistMem self, SConnection *pCon, - int i, int iStart, int iEnd, HistInt *lData, int iDataLen) - { - int ii, iErr, iRet, iCopy; - char pBueffel[512], pError[80]; - HistInt *lHist = NULL; - - assert(self); - - if(!self->iInit) - { - SCWrite(pCon,"ERROR: histogram memory not initialised",eError); - return 0; } + } + return 0; +} + +/*-------------------------------------------------------------------------*/ +int GetHistogram(pHistMem self, SConnection * pCon, + int i, int iStart, int iEnd, HistInt * lData, + int iDataLen) +{ + assert(self); + + if (!self->iInit) { + SCWrite(pCon, "ERROR: histogram memory not initialised", eError); + return 0; + } + + if ((iEnd - iStart) > iDataLen / sizeof(HistInt)) { + SCWrite(pCon, "WARNING: truncating request to fit data space", + eWarning); + iEnd = (iDataLen / sizeof(HistInt)) - 1; + } + return getHMDataHistogram(self, pCon, i, iStart, iEnd, lData); +} + +/*-------------------------------------------------------------------------*/ +int GetHistogramDirect(pHistMem self, SConnection * pCon, + int i, int iStart, int iEnd, HistInt * lData, + int iDataLen) +{ + int ii, iErr, iRet, iCopy; + char pBueffel[512], pError[80]; + HistInt *lHist = NULL; + + assert(self); + + if (!self->iInit) { + SCWrite(pCon, "ERROR: histogram memory not initialised", eError); + return 0; + } - /* try at least three times */ - for(ii = 0; ii < 3; ii++) - { - iRet = self->pDriv->GetHistogram(self->pDriv,pCon, - i,iStart,iEnd, - lData); - if(iRet == OKOK) - { - break; - } - else - { - iRet = self->pDriv->GetError(self->pDriv,&iErr,pError,79); - sprintf(pBueffel,"ERROR: %s ",pError); - SCWrite(pCon,pBueffel,eError); - iRet = self->pDriv->TryAndFixIt(self->pDriv,iErr); - if(iRet == COTERM) - { - return 0; - } - } + /* try at least three times */ + for (ii = 0; ii < 3; ii++) { + iRet = self->pDriv->GetHistogram(self->pDriv, pCon, + i, iStart, iEnd, lData); + if (iRet == OKOK) { + tracePar(self->pDes->name,"!!datachange!!"); + break; + } else { + iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79); + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s ", pError); + SCWrite(pCon, pBueffel, eError); + iRet = self->pDriv->TryAndFixIt(self->pDriv, iErr); + if (iRet == COTERM) { + return 0; + } } + } + return 1; +} + +/*-----------------------------------------------------------------------*/ +HistInt *GetHistogramPointer(pHistMem self, SConnection * pCon) +{ + assert(self); + + if (!self->iInit) { + SCWrite(pCon, "ERROR: histogram memory not initialised", eError); + return NULL; + } + + return getHMDataBufferPointer(self, pCon); +} + +/*--------------------------------------------------------------------------*/ +int PresetHistogram(pHistMem self, SConnection * pCon, HistInt lVal) +{ + int ii, iErr, iRet; + char pBueffel[512], pError[80]; + + assert(self); + + if (!self->iInit) { + SCWrite(pCon, "ERROR: histogram memory not initialised", eError); + return 0; + } + + /* try at least three times */ + for (ii = 0; ii < 3; ii++) { + iRet = self->pDriv->Preset(self->pDriv, pCon, lVal); + if (iRet == OKOK) { + updateHMData(self->pDriv->data); + return 1; + } else { + iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79); + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s ", pError); + SCWrite(pCon, pBueffel, eError); + iRet = self->pDriv->TryAndFixIt(self->pDriv, iErr); + if (iRet == COTERM) { + return 0; + } + } + } + return 0; +} + +/*----------------------------------------------------------------------*/ +static int HMCountInterest(int iEvent, void *pEvent, void *pUser) +{ + SConnection *pCon = NULL; + char pBueffel[512]; + + pCon = (SConnection *) pUser; + + if (pCon == NULL || !SCisConnected(pCon)) { + return -1; + } + + if (iEvent == COUNTSTART && pUser != NULL) { + pCon = (SConnection *) pUser; + assert(pCon); + SCWrite(pCon, "HMCOUNTSTART", eWarning); return 1; - } -/*-----------------------------------------------------------------------*/ - HistInt *GetHistogramPointer(pHistMem self, SConnection *pCon) - { - assert(self); + } else if (iEvent == COUNTEND) { + assert(pCon); + SCWrite(pCon, "HMCOUNTEND", eWarning); + return 1; + } + return 0; +} - if(!self->iInit) - { - SCWrite(pCon,"ERROR: histogram memory not initialised",eError); - return NULL; - } - - return getHMDataBufferPointer(self,pCon); - } -/*--------------------------------------------------------------------------*/ - int PresetHistogram(pHistMem self, SConnection *pCon, HistInt lVal) - { - int ii, iErr, iRet; - char pBueffel[512], pError[80]; - - assert(self); - - if(!self->iInit) - { - SCWrite(pCon,"ERROR: histogram memory not initialised",eError); - return 0; - } - - /* try at least three times */ - for(ii = 0; ii < 3; ii++) - { - iRet = self->pDriv->Preset(self->pDriv,pCon,lVal); - if(iRet == OKOK) - { - updateHMData(self->pDriv->data); - return 1; - } - else - { - iRet = self->pDriv->GetError(self->pDriv,&iErr,pError,79); - sprintf(pBueffel,"ERROR: %s ",pError); - SCWrite(pCon,pBueffel,eError); - iRet = self->pDriv->TryAndFixIt(self->pDriv,iErr); - if(iRet == COTERM) - { - return 0; - } - } - } - return 0; - } /*----------------------------------------------------------------------*/ - static int HMCountInterest(int iEvent, void *pEvent, void *pUser, - commandContext cc) - { - SConnection *pCon = NULL; - char pBueffel[512]; - - if(iEvent == COUNTSTART) - { - pCon = (SConnection *)pUser; - assert(pCon); - SCWriteInContext(pCon,"HMCOUNTSTART",eWarning,cc); - return 1; - } - else if(iEvent == COUNTEND) - { - pCon = (SConnection *)pUser; - assert(pCon); - SCWriteInContext(pCon,"HMCOUNTEND",eWarning,cc); - return 1; - } - return 0; - } -/*----------------------------------------------------------------------*/ -static int checkHMEnd(pHistMem self, char *text){ +static int checkHMEnd(pHistMem self, char *text) +{ int iTest, iEnd; iEnd = getHMDataLength(self->pDriv->data); - if(text == NULL){ + if (text == NULL) { return iEnd; } else { iTest = atoi(text); - if(iTest > iEnd){ + if (iTest > iEnd) { return iEnd; } else { return iTest; } } } -/*--------------------------------------------------------------------------*/ - void HMListOption(pHistMem self, SConnection *pCon) - { - char pBuffer[512]; - char name[20]; - char pValue[128]; - const char *pKey; - int i,iRet,iLen,iRank,iDiscard,tofMode; - float fVal; - char *pMode[] = {"timer","monitor",NULL}; - - memset(pBuffer, 0, sizeof(pBuffer)); - memset(pValue, 0, sizeof(pValue)); - memset(name, 0, sizeof(name)); - - iRet = StringDictGet(self->pDriv->pOption,"name",name,19); - if(0==iRet) { - strcpy(name,"*"); - } - iRet = StringDictGet(self->pDriv->pOption,"driver",pValue,sizeof(pValue)-1); - if(0pDriv->pOption,"update",&fVal); - if(0pDriv->pOption,"rank",&fVal); - if(0pDriv->pOption,pValue,&fVal); - if(0pDriv->pOption,pValue,sizeof(pValue)-1); - while(pKey != NULL) { - iDiscard=0; - if(0==strcmp("name",pKey)) iDiscard=1; - if(0==strcmp("driver",pKey)) iDiscard=1; - if(0==strcmp("update",pKey)) iDiscard=1; - if(0==strcmp("rank",pKey)) iDiscard=1; - if(NULL!=strstr(pKey,"dim")) iDiscard=1; - if(0==iDiscard) { - snprintf(pBuffer,511,"%s.%s = %s",name,pKey,pValue); - SCWrite(pCon,pBuffer,eStatus); - } - pKey = StringDictGetNext(self->pDriv->pOption,pValue,sizeof(pValue)-1); - } - - /* Display Count Mode */ - sprintf(pBuffer,"%s.CountMode = %s",name,pMode[self->pDriv->eCount]); - SCWrite(pCon,pBuffer,eStatus); - - /* Display Preset */ - sprintf(pBuffer,"%s.preset = %f",name,self->pDriv->fCountPreset); - SCWrite(pCon,pBuffer,eStatus); - - if(self->pDriv->data->nTimeChan > 2) { - tofMode = 1; - } else { - tofMode = 0; - } - sprintf(pBuffer,"%s.tofMode = %d",name,tofMode); - SCWrite(pCon,pBuffer,eStatus); +/*--------------------------------------------------------------------------*/ +void HMListOption(pHistMem self, SConnection * pCon) +{ + char pBuffer[512]; + char name[20]; + char pValue[128]; + const char *pKey; + int i, iRet, iLen, iRank, iDiscard, tofMode; + float fVal; + char *pMode[] = { "timer", "monitor", NULL }; + pDynString buf = NULL; + + memset(pBuffer, 0, sizeof(pBuffer)); + memset(pValue, 0, sizeof(pValue)); + memset(name, 0, sizeof(name)); + + buf = CreateDynString(256,256); + if(buf == NULL){ + SCWrite(pCon,"ERROR: out of memory listing HM Options",eError); + return; } -/*--------------------------------------------------------------------------*/ + iRet = StringDictGet(self->pDriv->pOption, "name", name, 19); + if (0 == iRet) { + strcpy(name, "*"); + } + iRet = + StringDictGet(self->pDriv->pOption, "driver", pValue, + sizeof(pValue) - 1); + if (0 < iRet) { + snprintf(pBuffer,sizeof(pBuffer)-1, "%s.driver = %s", name, pValue); + DynStringConcatLine(buf,pBuffer); + } + + iRet = StringDictGetAsNumber(self->pDriv->pOption, "update", &fVal); + if (0 < iRet) { + snprintf(pBuffer,sizeof(pBuffer)-1, "%s.update = %d", name, (int) rint(fVal)); + } else { + snprintf(pBuffer,sizeof(pBuffer)-1, "%s.update = 0 (no buffering)", name); + } + DynStringConcatLine(buf,pBuffer); + + iRet = StringDictGetAsNumber(self->pDriv->pOption, "rank", &fVal); + if (0 < iRet) { + iRank = (int) rint(fVal); + snprintf(pBuffer,sizeof(pBuffer)-1, "%s.rank = %d", name, iRank); + DynStringConcatLine(buf,pBuffer); + } else { + iRank = 0; + } + for (i = 0; i < iRank; i++) { + snprintf(pValue,sizeof(pValue)-1, "dim%1.1d", i); + iRet = StringDictGetAsNumber(self->pDriv->pOption, pValue, &fVal); + if (0 < iRet) { + snprintf(pBuffer,sizeof(pBuffer)-1, "%s.dim%1.1d = %d", name, i, (int) rint(fVal)); + DynStringConcatLine(buf,pBuffer); + } + } + + pKey = + StringDictGetNext(self->pDriv->pOption, pValue, sizeof(pValue) - 1); + while (pKey != NULL) { + iDiscard = 0; + if (0 == strcmp("name", pKey)) + iDiscard = 1; + if (0 == strcmp("driver", pKey)) + iDiscard = 1; + if (0 == strcmp("update", pKey)) + iDiscard = 1; + if (0 == strcmp("rank", pKey)) + iDiscard = 1; + if (NULL != strstr(pKey, "dim")) + iDiscard = 1; + if (0 == iDiscard) { + snprintf(pBuffer, 511, "%s.%s = %s", name, pKey, pValue); + DynStringConcatLine(buf,pBuffer); + } + pKey = + StringDictGetNext(self->pDriv->pOption, pValue, + sizeof(pValue) - 1); + } + + /* Display Count Mode */ + snprintf(pBuffer,sizeof(pBuffer)-1, "%s.CountMode = %s", name, pMode[self->pDriv->eCount]); + DynStringConcatLine(buf,pBuffer); + SCWrite(pCon, pBuffer, eValue); + + /* Display Preset */ + snprintf(pBuffer,sizeof(pBuffer)-1, "%s.preset = %f", name, self->pDriv->fCountPreset); + DynStringConcatLine(buf,pBuffer); + + if (self->pDriv->data->nTimeChan > 2) { + tofMode = 1; + } else { + tofMode = 0; + } + snprintf(pBuffer,sizeof(pBuffer)-1, "%s.tofMode = %d", name, tofMode); + DynStringConcatLine(buf,pBuffer); + SCWrite(pCon, GetCharArray(buf), eValue); + DeleteDynString(buf); +} /*--------------------------------------------------------------------------*/ - int HistAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - pHistMem self = NULL; - char pBueffel[512], pNumber[20]; - int iaStart[MAXDIM], iaEnd[MAXDIM]; - Tcl_DString tResult; - int iRet, iVal; - char *pBuf = NULL, *pPtr; - float fVal; - long lVal; - HistInt *lData = NULL; - int iStart, iEnd, iNum, i; - CounterMode eCount; - char *pMode[] = { - "timer", - "monitor", - NULL - }; - double dStart, dStep; - int nDim, iSwitch; - long lID; +static pDynString formatTOF(pHistMem self) +{ + const float *timebin; + int iLength, i, delay, delta; + char number[20]; + pDynString result = NULL; + + timebin = GetHistTimeBin(self, &iLength); + if(timebin != NULL){ + delay = timebin[0]; + result = CreateDynString(512,512); + if(result == NULL){ + return NULL; + } + for(i = 0; i < iLength; i++){ + snprintf(number,20," %12d", (int)(timebin[i] - delay)); + DynStringConcat(result,number); + if(i % 5 == 0 && i != 0){ + DynStringConcatChar(result,'\n'); + } + } + /* + * add the extra one + */ + if(iLength > 3){ + delta = ABS(timebin[iLength -2] - timebin[iLength -1]); + } + snprintf(number,20," %12d", (int)(timebin[iLength -1] + delta - delay )); + DynStringConcat(result,number); + return result; + } else { + return NULL; + } +} +/*--------------------------------------------------------------------------*/ +int HistAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pHistMem self = NULL; + char pBueffel[512], pNumber[20]; + int iaStart[MAXDIM], iaEnd[MAXDIM]; + Tcl_DString tResult; + int iRet, iVal; + char *pBuf = NULL, *pPtr; + float fVal; + long lVal; + HistInt *lData = NULL; + int iStart, iEnd, iNum, i; + pDynString tofres = NULL; + CounterMode eCount; + char *pMode[] = { + "timer", + "monitor", + NULL + }; + double dStart, dStep; + int nDim, iSwitch; + long lID; - - assert(pCon); - assert(pSics); - assert(pData); - - self = (pHistMem)pData; - - /* check arguments */ - if(argc < 2) - { - sprintf(pBueffel,"ERROR: no arguments specified to %s", argv[0]); - SCWrite(pCon,pBueffel,eError); + + assert(pCon); + assert(pSics); + assert(pData); + + self = (pHistMem) pData; + + /* check arguments */ + if (argc < 2) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: no arguments specified to %s", argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* interest command */ + strtolower(argv[1]); + if (strcmp(argv[1], "interest") == 0) { + lID = RegisterCallback(self->pCall, + COUNTSTART, HMCountInterest, + SCCopyConnection(pCon), SCDeleteConnection); + lID = RegisterCallback(self->pCall, + COUNTEND, HMCountInterest, + SCCopyConnection(pCon), SCDeleteConnection); + SCSendOK(pCon); + return 1; + } else if (strcmp(argv[1], "configure") == 0) { + /* enough arguments ? */ + if (argc < 4) { + if (argc < 3) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: not enough arguments to %s configure", + argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } else { /* get value case */ + + strtolower(argv[2]); + iRet = HistGetOption(self, argv[2], NULL, 0); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: option %s not known", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + pBuf = (char *) malloc((iRet + 60) * sizeof(char)); + if (!pBuf) { + SCWrite(pCon, "ERROR: no memory in HistAction", eError); + return 0; + } + memset(pBuf, 0, iRet + 60); + HistGetOption(self, argv[2], pBuf, iRet + 60); + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.%s = %s", argv[0], argv[2], pBuf); + SCWrite(pCon, pBueffel, eValue); + free(pBuf); + return 1; + } + } + /* do it */ + Arg2Text(argc - 3, &argv[3], pBueffel, 511); + /* authorise */ + if (!SCMatchRights(pCon, usMugger)) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: you need to be manager in order to configure %s", + argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + strtolower(argv[2]); + iRet = HistSetOption(self, argv[2], pBueffel); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: option %s not known", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + SCSendOK(pCon); + return 1; + } else if (strcmp(argv[1], "preset") == 0) { /* preset */ + if (argc < 3) { /* get value */ + fVal = GetHistPreset(self); + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.preset = %f", argv[0], fVal); + SCWrite(pCon, pBueffel, eValue); + return 1; + } else { /* set case */ + + if (isRunning(self->pCountInt)) { + SCWrite(pCon, "ERROR: cannot change preset while counting", + eError); return 0; } - - /* interest command */ - strtolower(argv[1]); - if(strcmp(argv[1],"interest") == 0) - { - lID = RegisterCallback(self->pCall, SCGetContext(pCon), - COUNTSTART, HMCountInterest, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); - lID = RegisterCallback(self->pCall, SCGetContext(pCon), - COUNTEND, HMCountInterest, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); - SCSendOK(pCon); - return 1; + fVal = atof(argv[2]); + if (!SCMatchRights(pCon, self->iAccess)) { + return 0; } - else if(strcmp(argv[1],"configure") == 0) - { - /* enough arguments ? */ - if(argc < 4) - { - if(argc < 3) - { - sprintf(pBueffel,"ERROR: not enough arguments to %s configure", - argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - else /* get value case */ - { - strtolower(argv[2]); - iRet = HistGetOption(self,argv[2],NULL,0); - if(!iRet) - { - sprintf(pBueffel,"ERROR: option %s not known", argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - pBuf = (char *)malloc((iRet+60)*sizeof(char)); - if(!pBuf) - { - SCWrite(pCon,"ERROR: no memory in HistAction",eError); - return 0; - } - memset(pBuf,0,iRet+60); - HistGetOption(self,argv[2],pBuf,iRet+60); - sprintf(pBueffel,"%s.%s = %s",argv[0],argv[2],pBuf); - SCWrite(pCon,pBueffel,eValue); - free(pBuf); - return 1; - } - } - /* do it */ - Arg2Text(argc - 3, &argv[3],pBueffel, 511); - /* authorise */ - if(!SCMatchRights(pCon,usUser)) /* FIXME ffr stupid hack */ - { - sprintf(pBueffel, - "ERROR: you need to be manager in order to configure %s", - argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - strtolower(argv[2]); - iRet = HistSetOption(self,argv[2],pBueffel); - if(!iRet) - { - sprintf(pBueffel,"ERROR: option %s not known", argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - SCSendOK(pCon); - return 1; - } - else if(strcmp(argv[1],"preset") == 0) /* preset */ - { - if(argc < 3) /* get value */ - { - fVal = GetHistPreset(self); - sprintf(pBueffel,"%s.preset = %f",argv[0],fVal); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - else /* set case */ - { - fVal = atof(argv[2]); - if(!SCMatchRights(pCon,self->iAccess)) - { - return 0; - } - iRet = SetHistPreset(self,fVal); - SCparChange(pCon); - SCSendOK(pCon); - return 1; - } - } - else if(strcmp(argv[1],"exponent") == 0) /* preset */ - { - if(argc < 3) /* get value */ - { - sprintf(pBueffel,"%s.exponent = %d",argv[0],self->iExponent); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - else /* set case */ - { - if(!SCMatchRights(pCon,self->iAccess)) - { - return 0; - } - self->iExponent = atoi(argv[2]); - SCparChange(pCon); - SCSendOK(pCon); - return 1; - } - } - else if(strcmp(argv[1],"countmode") == 0) /* countmode */ - { - if(argc < 3) /* get value */ - { - eCount = GetHistCountMode(self); - sprintf(pBueffel,"%s.CountMode = %s",argv[0],pMode[eCount]); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - else /* set case */ - { - strtolower(argv[2]); - if(!SCMatchRights(pCon,self->iAccess)) - { - return 0; - } - if(strcmp(argv[2],"timer") == 0) - { - eCount = eTimer; - } - else if(strcmp(argv[2],"monitor") == 0) - { - eCount = ePreset; - } - else - { - sprintf(pBueffel,"ERROR: %s invalid as CountMode",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - iRet = SetHistCountMode(self,eCount); - SCparChange(pCon); - SCSendOK(pCon); - return 1; - } - - } - else if(strcmp(argv[1],"init") == 0) - { - if(GetStatus() != eEager) - { - SCWrite(pCon,"ERROR: cannot initialize HM while running", - eError); - return 0; - } - if(SCMatchRights(pCon,usUser)) /* FIXME ffr stupid hack */ - { - iRet = HistConfigure(self,pCon,pSics); - if(iRet) - { - self->iInit = 1; - SCSendOK(pCon); - } - else - { - self->iInit = 0; - } - return iRet; - } - else - { - return 0; - } - } - else if(strcmp(argv[1],"list") == 0) - { - HMListOption(self,pCon); - return 1; - } - /* stop */ - else if(strcmp(argv[1],"stop") == 0) - { if(!SCMatchRights(pCon,usUser)) - { - return 0; - } - self->pDriv->Halt(self->pDriv); - SCSendOK(pCon); - return 1; - } - /* pause */ - else if(strcmp(argv[1],"pause") == 0) - { if(!SCMatchRights(pCon,usUser)) - { - return 0; - } - self->pDriv->Pause(self->pDriv,pCon); - SCSendOK(pCon); - return 1; - } - /* normal counting*/ - else if(strcmp(argv[1],"count") == 0) - { - if(SCMatchRights(pCon,self->iAccess)) - { - if(IsCounting(pServ->pExecutor)) - { - SCWrite(pCon,"WARNING: already counting!",eWarning); - return 1; - } - iRet = HistDoCount(self,pCon); - if(iRet == 1) - { - SCSendOK(pCon); - } - return iRet; - } - else - { - return 0; - } - } - /* forced count, for the case several hm need to be started */ - else if(strcmp(argv[1],"countf") == 0) - { - if(SCMatchRights(pCon,self->iAccess)) - { - iRet = HistDoCount(self,pCon); - if(iRet == 1) - { - SCSendOK(pCon); - } - return iRet; - } - else - { - return 0; - } - } -/* count in blocking mode */ - else if(strcmp(argv[1],"countblock") == 0) - { - if(SCMatchRights(pCon,self->iAccess)) - { - iRet = HistBlockCount(self,pCon); - if(iRet == 1) - { - SCSendOK(pCon); - } - return iRet; - } - else - { - return 0; - } - } - else if(strcmp(argv[1],"initval") == 0) /* initialize to a value */ - { - /* check user rights */ - if(!SCMatchRights(pCon,self->iAccess)) - { - return 0; - } - - /* enough arguments */ - if(argc < 3) - { - sprintf(pBueffel,"ERROR: insufficient number of arguments to %s %s", - argv[0], argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - lVal = atoi(argv[2]); - iRet = PresetHistogram(self,pCon,lVal); - if(iRet) - { - SCSendOK(pCon); - } - return iRet; - } - else if(strcmp(argv[1],"initfile") == 0) /* initialize from a file */ - { - /* check user rights */ - if(!SCMatchRights(pCon,self->iAccess)) - { - return 0; - } - - /* enough arguments */ - if(argc < 3) - { - sprintf(pBueffel,"ERROR: insufficient number of arguments to %s %s", - argv[0], argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - iRet = loadHMData(self->pDriv->data,pCon,argv[2]); - self->pDriv->SetHistogram(self->pDriv,pCon,0,0,GetHistLength(self), - self->pDriv->data->localBuffer); - if(iRet) - { - SCSendOK(pCon); - } - return iRet; - } - else if(strcmp(argv[1],"get") == 0) /* get a histogram */ - { - /* check parameters, first required: no of Hist */ - if(argc < 3) - { - sprintf(pBueffel,"ERROR: insufficient number of arguments to %s %s", - argv[0], argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - iNum = atoi(argv[2]); + iRet = SetHistPreset(self, fVal); + SCparChange(pCon); + SCSendOK(pCon); + return 1; + } + } else if (strcmp(argv[1], "exponent") == 0) { /* preset */ + if (argc < 3) { /* get value */ + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.exponent = %d", argv[0], self->iExponent); + SCWrite(pCon, pBueffel, eValue); + return 1; + } else { /* set case */ - /* optional iStart, default 0 */ - iStart = 0; - if(argc > 3 ) - { - iStart = atoi(argv[3]); - } - - /* check iStart */ - if(iStart < 0) - { - SCWrite(pCon,"WARNING: Invalid start position defaulted to 0",eWarning); - iStart = 0; - } - - if(argc > 4){ - iEnd = checkHMEnd(self,argv[4]); - } else { - iEnd = checkHMEnd(self,NULL); - } - - if(iNum != 0 && argc > 4) - { - iEnd = atoi(argv[4]); - } - - /* allocate data storage and get it */ - lData = (HistInt *)malloc(iEnd*sizeof(HistInt)); - if(!lData) - { - SCWrite(pCon,"ERROR: no memory in HistAction/get",eError); - return 0; - } - memset(lData,0,iEnd*sizeof(HistInt)); - if(iNum == 0) - { - iRet = GetHistogram(self,pCon,iNum,iStart,iEnd, - lData,iEnd*sizeof(long)); - } else { - iRet = GetHistogramDirect(self,pCon,iNum,iStart, iEnd, - lData, iEnd*sizeof(long)); - } - if(!iRet) - { - sprintf(pBueffel,"ERROR: cannot retrieve histogram %d",iNum); - SCWrite(pCon,pBueffel,eError); - free(lData); - return 0; - } - - /* OK, got it, convert to text using Tcl's Dstring for lazyness */ - Tcl_DStringInit(&tResult); - Tcl_DStringAppend(&tResult,"Histogram =",-1); - for(i = 0; i < iEnd - iStart; i++) - { - sprintf(pNumber," %d",lData[i]); - Tcl_DStringAppend(&tResult,pNumber,-1); - } - - /* Write it */ - SCWrite(pCon,Tcl_DStringValue(&tResult),eValue); - - /* clean up and go */ - free(lData); - Tcl_DStringFree(&tResult); - return 1; + if (!SCMatchRights(pCon, self->iAccess)) { + return 0; } + self->iExponent = atoi(argv[2]); + SCparChange(pCon); + SCSendOK(pCon); + return 1; + } + } else if (strcmp(argv[1], "countmode") == 0) { /* countmode */ + if (argc < 3) { /* get value */ + eCount = GetHistCountMode(self); + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.CountMode = %s", argv[0], pMode[eCount]); + SCWrite(pCon, pBueffel, eValue); + return 1; + } else { /* set case */ + + strtolower(argv[2]); + if (isRunning(self->pCountInt)) { + SCWrite(pCon, "ERROR: cannot change countmode while counting", + eError); + return 0; + } + if (!SCMatchRights(pCon, self->iAccess)) { + return 0; + } + if (strcmp(argv[2], "timer") == 0) { + eCount = eTimer; + } else if (strcmp(argv[2], "monitor") == 0) { + eCount = ePreset; + } else { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s invalid as CountMode", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + iRet = SetHistCountMode(self, eCount); + SCparChange(pCon); + SCSendOK(pCon); + return 1; + } + + } else if (strcmp(argv[1], "init") == 0) { + if (GetStatus() != eEager) { + SCWrite(pCon, "ERROR: cannot initialize HM while running", eError); + return 0; + } + if (SCMatchRights(pCon, usMugger)) { + iRet = HistConfigure(self, pCon, pSics); + if (iRet) { + self->iInit = 1; + InvokeCallBack(self->pCall,DIMCHANGE,NULL); + SCSendOK(pCon); + } else { + self->iInit = 0; + } + return iRet; + } else { + return 0; + } + } else if (strcmp(argv[1], "list") == 0) { + HMListOption(self, pCon); + return 1; + } + /* stop */ + else if (strcmp(argv[1], "stop") == 0) { + if (!SCMatchRights(pCon, usUser)) { + return 0; + } + self->pDriv->Halt(self->pDriv); + SCSendOK(pCon); + return 1; + } + /* pause */ + else if (strcmp(argv[1], "pause") == 0) { + if (!SCMatchRights(pCon, usUser)) { + return 0; + } + self->pDriv->Pause(self->pDriv, pCon); + SCSendOK(pCon); + return 1; + } + /* normal counting */ + else if (strcmp(argv[1], "count") == 0) { + if (SCMatchRights(pCon, self->iAccess)) { + if (IsCounting(pServ->pExecutor)) { + SCWrite(pCon, "WARNING: already counting!", eWarning); + return 1; + } + iRet = HistDoCount(self, pCon); + if (iRet == 1) { + SCSendOK(pCon); + } + return iRet; + } else { + return 0; + } + } + /* forced count, for the case several hm need to be started */ + else if (strcmp(argv[1], "countf") == 0) { + if (SCMatchRights(pCon, self->iAccess)) { + iRet = HistDoCount(self, pCon); + if (iRet == 1) { + SCSendOK(pCon); + } + return iRet; + } else { + return 0; + } + } +/* count in blocking mode */ + else if (strcmp(argv[1], "countblock") == 0) { + if (SCMatchRights(pCon, self->iAccess)) { + iRet = HistBlockCount(self, pCon); + if (iRet == 1) { + SCSendOK(pCon); + } + return iRet; + } else { + return 0; + } + } else if (strcmp(argv[1], "initval") == 0) { /* initialize to a value */ + /* check user rights */ + if (!SCMatchRights(pCon, self->iAccess)) { + return 0; + } + + /* enough arguments */ + if (argc < 3) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: insufficient number of arguments to %s %s", + argv[0], argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + lVal = atoi(argv[2]); + iRet = PresetHistogram(self, pCon, lVal); + if (iRet) { + SCSendOK(pCon); + } + return iRet; + } else if (strcmp(argv[1], "initfile") == 0) { /* initialize from a file */ + /* check user rights */ + if (!SCMatchRights(pCon, self->iAccess)) { + return 0; + } + + /* enough arguments */ + if (argc < 3) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: insufficient number of arguments to %s %s", + argv[0], argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + iRet = loadHMData(self->pDriv->data, pCon, argv[2]); + self->pDriv->SetHistogram(self->pDriv, pCon, 0, 0, GetHistLength(self), + self->pDriv->data->localBuffer); + if (iRet) { + SCSendOK(pCon); + } + return iRet; + } else if (strcmp(argv[1], "get") == 0) { /* get a histogram */ + /* check parameters, first required: no of Hist */ + if (argc < 3) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: insufficient number of arguments to %s %s", + argv[0], argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + iNum = atoi(argv[2]); + + /* optional iStart, default 0 */ + iStart = 0; + if (argc > 3) { + iStart = atoi(argv[3]); + } + + /* check iStart */ + if (iStart < 0) { + SCWrite(pCon, "WARNING: Invalid start position defaulted to 0", + eWarning); + iStart = 0; + } + + if (argc > 4) { + iEnd = checkHMEnd(self, argv[4]); + } else { + iEnd = checkHMEnd(self, NULL); + } + + if (iNum != 0 && argc > 4) { + iEnd = atoi(argv[4]); + } + + /* allocate data storage and get it */ + lData = (HistInt *) malloc(iEnd * sizeof(HistInt)); + if (!lData) { + SCWrite(pCon, "ERROR: no memory in HistAction/get", eError); + return 0; + } + memset(lData, 0, iEnd * sizeof(HistInt)); + if (iNum == 0) { + iRet = GetHistogram(self, pCon, iNum, iStart, iEnd, + lData, iEnd * sizeof(long)); + } else { + iRet = GetHistogramDirect(self, pCon, iNum, iStart, iEnd, + lData, iEnd * sizeof(long)); + } + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: cannot retrieve histogram %d", iNum); + SCWrite(pCon, pBueffel, eError); + free(lData); + return 0; + } + + /* OK, got it, convert to text using Tcl's Dstring for lazyness */ + Tcl_DStringInit(&tResult); + Tcl_DStringAppend(&tResult, "Histogram =", -1); + for (i = 0; i < iEnd - iStart; i++) { + snprintf(pNumber,sizeof(pNumber)-1, " %d", lData[i]); + Tcl_DStringAppend(&tResult, pNumber, -1); + } + + /* Write it */ + SCWrite(pCon, Tcl_DStringValue(&tResult), eValue); + + /* clean up and go */ + free(lData); + Tcl_DStringFree(&tResult); + return 1; + } /*-------- get uuencoded */ - else if(strcmp(argv[1],"uuget") == 0) /* get a histogram */ - { - /* check parameters, first required: no of Hist */ - if(argc < 3) - { - sprintf(pBueffel,"ERROR: insufficient number of arguments to %s %s", - argv[0], argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - iNum = atoi(argv[2]); + else if (strcmp(argv[1], "uuget") == 0) { /* get a histogram */ + /* check parameters, first required: no of Hist */ + if (argc < 3) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: insufficient number of arguments to %s %s", + argv[0], argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + iNum = atoi(argv[2]); - /* optional iStart, default 0 */ - iStart = 0; - if(argc > 3 ) - { - iStart = atoi(argv[3]); - } - - /* check iStart */ - if(iStart < 0) - { - SCWrite(pCon,"WARNING: Invalid start position defaulted to 0",eWarning); - iStart = 0; - } + /* optional iStart, default 0 */ + iStart = 0; + if (argc > 3) { + iStart = atoi(argv[3]); + } - if(argc > 4){ - iEnd = checkHMEnd(self,argv[4]); - } else { - iEnd = checkHMEnd(self,NULL); - } + /* check iStart */ + if (iStart < 0) { + SCWrite(pCon, "WARNING: Invalid start position defaulted to 0", + eWarning); + iStart = 0; + } - /* allocate data storage and get it */ - lData = (HistInt *)malloc((iEnd+1)*sizeof(HistInt)); - if(!lData) - { - SCWrite(pCon,"ERROR: no memory in HistAction/get",eError); - return 0; - } - memset(lData,0,(iEnd+1)*sizeof(HistInt)); - iRet = GetHistogram(self,pCon,iNum,iStart,iEnd, - &lData[1],iEnd*sizeof(HistInt)); - if(!iRet) - { - sprintf(pBueffel,"ERROR: cannot retrieve histogram %d",iNum); - SCWrite(pCon,pBueffel,eError); - free(lData); - return 0; - } - /* lData[0] is the length of the histogram */ - lData[0] = iEnd; - - /* convert to network byte order */ - for(i = 0; i < iEnd+1; i++) - { - lData[i] = htonl(lData[i]); - } - /* Write it */ - SCWriteUUencoded(pCon,"SicsHistogram",lData,(iEnd+1)*sizeof(HistInt)); - - /* clean up and go */ - free(lData); - return 1; - } - else if(strcmp(argv[1],"zipget") == 0) /* get a histogram */ - { - /* check parameters, first required: no of Hist */ - if(argc < 3) - { - sprintf(pBueffel,"ERROR: insufficient number of arguments to %s %s", - argv[0], argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - iNum = atoi(argv[2]); + if (argc > 4) { + iEnd = checkHMEnd(self, argv[4]); + } else { + iEnd = checkHMEnd(self, NULL); + } - /* optional iStart, default 0 */ - iStart = 0; - if(argc > 3 ) - { - iStart = atoi(argv[3]); - } - - /* check iStart */ - if(iStart < 0) - { - SCWrite(pCon,"WARNING: Invalid start position defaulted to 0", - eWarning); - iStart = 0; - } - - if(argc > 4){ - iEnd = checkHMEnd(self,argv[4]); - } else { - iEnd = checkHMEnd(self,NULL); - } + /* allocate data storage and get it */ + lData = (HistInt *) malloc((iEnd + 1) * sizeof(HistInt)); + if (!lData) { + SCWrite(pCon, "ERROR: no memory in HistAction/get", eError); + return 0; + } + memset(lData, 0, (iEnd + 1) * sizeof(HistInt)); + iRet = GetHistogram(self, pCon, iNum, iStart, iEnd, + &lData[1], iEnd * sizeof(HistInt)); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: cannot retrieve histogram %d", iNum); + SCWrite(pCon, pBueffel, eError); + free(lData); + return 0; + } + /* lData[0] is the length of the histogram */ + lData[0] = iEnd; - /* allocate data storage and get it */ - lData = (HistInt *)malloc((iEnd+1)*sizeof(HistInt)); - if(!lData) - { - SCWrite(pCon,"ERROR: no memory in HistAction/get",eError); - return 0; - } - memset(lData,0,(iEnd+1)*sizeof(HistInt)); - iRet = GetHistogram(self,pCon,iNum,iStart,iEnd, - &lData[0],iEnd*sizeof(HistInt)); - if(!iRet) - { - sprintf(pBueffel,"ERROR: cannot retrieve histogram %d",iNum); - SCWrite(pCon,pBueffel,eError); - free(lData); - return 0; - } - - /* convert to network byte order */ - for(i = 0; i < iEnd; i++) - { - lData[i] = htonl(lData[i]); - } - /* Write it */ - SCWriteZipped(pCon,argv[0],lData,iEnd*sizeof(HistInt)); - - /* clean up and go */ - free(lData); - return 1; - } - /* retrive no of Timebins */ - else if(strcmp(argv[1],"notimebin") == 0) - { - sprintf(pBueffel, - "%s.notimebin = %d",argv[0], - getNoOfTimebins(self->pDriv->data)); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - /* retrive time binning */ - else if(strcmp(argv[1],"timebin") == 0) - { - Tcl_DStringInit(&tResult); - Tcl_DStringAppend(&tResult,"histogram.timebins =",-1); - for(i = 0; i < self->pDriv->data->nTimeChan; i++) - { - sprintf(pBueffel,"%.2f ", self->pDriv->data->timeBinning[i]); - Tcl_DStringAppend(&tResult,pBueffel,-1); - } - /* Write it */ - SCWrite(pCon,Tcl_DStringValue(&tResult),eValue); - - /* clean up and go */ - Tcl_DStringFree(&tResult); - return 1; - } - /* generate time binning */ - else if(strcmp(argv[1],"genbin") == 0) - { - if(!SCMatchRights(pCon,usMugger)) - { - return 0; - } - if(GetStatus() == eCounting) - { - SCWrite(pCon,"ERROR: cannot modify timebinning while counting", - eError); - return 0; - } - if(argc < 5) - { - SCWrite(pCon,"ERROR: not enough aguments to genbin",eError); - return 0; - } - iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&dStart); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: Failed to convert %s to number",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - iRet = Tcl_GetDouble(pSics->pTcl,argv[3],&dStep); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: Failed to convert %s to number",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - iRet = Tcl_GetInt(pSics->pTcl,argv[4],&iNum); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: Failed to convert %s to number",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - if(iNum >= MAXCHAN) - { - SCWrite(pCon, - "ERROR: number of requested time bins exceeds maximum permissible number", - eError); - return 0; - } - if(iNum <= 0){ - SCWrite(pCon,"ERROR: at least one time bin required!",eError); - return 0; + /* convert to network byte order */ + for (i = 0; i < iEnd + 1; i++) { + lData[i] = htonl(lData[i]); + } + /* Write it */ + SCWriteUUencoded(pCon, "SicsHistogram", lData, + (iEnd + 1) * sizeof(HistInt)); + + /* clean up and go */ + free(lData); + return 1; + } else if (strcmp(argv[1], "zipget") == 0) { /* get a histogram */ + /* check parameters, first required: no of Hist */ + if (argc < 3) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: insufficient number of arguments to %s %s", + argv[0], argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + iNum = atoi(argv[2]); + + /* optional iStart, default 0 */ + iStart = 0; + if (argc > 3) { + iStart = atoi(argv[3]); + } + + /* check iStart */ + if (iStart < 0) { + SCWrite(pCon, "WARNING: Invalid start position defaulted to 0", + eWarning); + iStart = 0; + } + + if (argc > 4) { + iEnd = checkHMEnd(self, argv[4]); + } else { + iEnd = checkHMEnd(self, NULL); + } + + /* allocate data storage and get it */ + lData = (HistInt *) malloc((iEnd + 1) * sizeof(HistInt)); + if (!lData) { + SCWrite(pCon, "ERROR: no memory in HistAction/get", eError); + return 0; + } + memset(lData, 0, (iEnd + 1) * sizeof(HistInt)); + iRet = GetHistogram(self, pCon, iNum, iStart, iEnd, + &lData[0], iEnd * sizeof(HistInt)); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: cannot retrieve histogram %d", iNum); + SCWrite(pCon, pBueffel, eError); + free(lData); + return 0; + } + + /* convert to network byte order */ + for (i = 0; i < iEnd; i++) { + lData[i] = htonl(lData[i]); + } + /* Write it */ + SCWriteZipped(pCon, argv[0], lData, iEnd * sizeof(HistInt)); + + /* clean up and go */ + free(lData); + return 1; + } + /* retrive no of Timebins */ + else if (strcmp(argv[1], "notimebin") == 0) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "%s.notimebin = %d", argv[0], + getNoOfTimebins(self->pDriv->data)); + SCWrite(pCon, pBueffel, eValue); + return 1; + } + /* retrive time binning */ + else if (strcmp(argv[1], "timebin") == 0) { + Tcl_DStringInit(&tResult); + Tcl_DStringAppend(&tResult, "histogram.timebins =", -1); + for (i = 0; i < self->pDriv->data->nTimeChan; i++) { + snprintf(pBueffel,sizeof(pBueffel)-1, "%.2f ", self->pDriv->data->timeBinning[i]); + Tcl_DStringAppend(&tResult, pBueffel, -1); + } + /* Write it */ + SCWrite(pCon, Tcl_DStringValue(&tResult), eValue); + + /* clean up and go */ + Tcl_DStringFree(&tResult); + return 1; + } + /* getdelay */ + else if(strcmp(argv[1],"getdelay") == 0){ + if(self->pDriv->data->nTimeChan > 1) { + iVal = (int)self->pDriv->data->timeBinning[0]; + SCPrintf(pCon,eValue,"hm.delay = %d", iVal); + return 1; + } else { + SCPrintf(pCon,eError,"ERROR: no TOF configured"); + return 0; } - /* do it */ - genTimeBinning(self->pDriv->data, - (float)dStart,(float)dStep,iNum); - SCparChange(pCon); - SCSendOK(pCon); - return 1; - } - /* set a time bin */ - else if(strcmp(argv[1],"setbin") == 0) - { - if(!SCMatchRights(pCon,usMugger)) - { - return 0; - } - if(argc < 4) - { - SCWrite(pCon,"ERROR: not enough aguments to setbin",eError); - return 0; - } - iRet = Tcl_GetInt(pSics->pTcl,argv[2],&iNum); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: Failed to convert %s to number",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - iRet = Tcl_GetDouble(pSics->pTcl,argv[3],&dStep); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: Failed to convert %s to number",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - if( (iNum < 0) || (iNum > MAXCHAN) ) - { - SCWrite(pCon,"ERROR: requested time bin out or permissible range", - eError); - return 0; - } - setTimeBin(self->pDriv->data,iNum, (float)dStep); - self->iInit = 0; - SCSendOK(pCon); - return 1; - } - /* clear time bin info */ - else if(strcmp(argv[1],"clearbin") == 0) - { - clearTimeBinning(self->pDriv->data); - SCSendOK(pCon); - return 1; - } + } + /* formattof */ + else if(strcmp(argv[1],"formattof") == 0){ + tofres = formatTOF(self); + if(tofres == NULL){ + SCWrite(pCon,"ERROR: out of memory or not TOF", eError); + return 0; + } else { + SCWrite(pCon,GetCharArray(tofres), eValue); + DeleteDynString(tofres); + return 1; + } + } + /* generate time binning */ + else if (strcmp(argv[1], "genbin") == 0) { + if (isRunning(self->pCountInt)) { + SCWrite(pCon, "ERROR: cannot change time binning while counting", + eError); + return 0; + } + if (!SCMatchRights(pCon, usMugger)) { + return 0; + } + if (argc < 5) { + SCWrite(pCon, "ERROR: not enough aguments to genbin", eError); + return 0; + } + iRet = Tcl_GetDouble(pSics->pTcl, argv[2], &dStart); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Failed to convert %s to number", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + iRet = Tcl_GetDouble(pSics->pTcl, argv[3], &dStep); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Failed to convert %s to number", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + iRet = Tcl_GetInt(pSics->pTcl, argv[4], &iNum); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Failed to convert %s to number", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + if (iNum >= MAXCHAN) { + SCWrite(pCon, + "ERROR: number of requested time bins exceeds maximum permissible number", + eError); + return 0; + } + if (iNum <= 0) { + SCWrite(pCon, "ERROR: at least one time bin required!", eError); + return 0; + } + /* do it */ + genTimeBinning(self->pDriv->data, (float) dStart, (float) dStep, iNum); + InvokeCallBack(self->pCall,DIMCHANGE,NULL); + SCparChange(pCon); + SCSendOK(pCon); + return 1; + } + /* set a time bin */ + else if (strcmp(argv[1], "setbin") == 0) { + if (isRunning(self->pCountInt)) { + SCWrite(pCon, "ERROR: cannot change time binning while counting", + eError); + return 0; + } + if (!SCMatchRights(pCon, usMugger)) { + return 0; + } + if (argc < 4) { + SCWrite(pCon, "ERROR: not enough aguments to setbin", eError); + return 0; + } + iRet = Tcl_GetInt(pSics->pTcl, argv[2], &iNum); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Failed to convert %s to number", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + iRet = Tcl_GetDouble(pSics->pTcl, argv[3], &dStep); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Failed to convert %s to number", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + if ((iNum < 0) || (iNum > MAXCHAN)) { + SCWrite(pCon, "ERROR: requested time bin out or permissible range", + eError); + return 0; + } + setTimeBin(self->pDriv->data, iNum, (float) dStep); + InvokeCallBack(self->pCall,DIMCHANGE,NULL); + self->iInit = 0; + SCSendOK(pCon); + return 1; + } + /* clear time bin info */ + else if (strcmp(argv[1], "clearbin") == 0) { + if (isRunning(self->pCountInt)) { + SCWrite(pCon, "ERROR: cannot change time binning while counting", + eError); + return 0; + } + clearTimeBinning(self->pDriv->data); + InvokeCallBack(self->pCall,DIMCHANGE,NULL); + SCSendOK(pCon); + return 1; + } /*-------- sum */ - else if(strcmp(argv[1],"sum") == 0) - { - /* read following arguments as ints and put them - into the iStart and iEnd array in succession. - But first check if we have an even number. - */ - if( ((argc-2) % 2) || (argc-2) == 0) - { - SCWrite(pCon, - "ERROR: need start and end for each dimension", - eError); - return 0; - } - nDim = 0; - iSwitch = 0; - for(i = 0; i < argc -2; i++) - { - iRet = Tcl_GetInt(pSics->pTcl,argv[i+2],&iVal); - if(iSwitch) - { - iaEnd[nDim] = iVal; - nDim++; - iSwitch = 0; - } - else - { - iSwitch = 1; - iaStart[nDim] = iVal; - } - } - lVal = HistSum(self,pCon,iaStart,iaEnd); - sprintf(pBueffel,"%s.sum = %ld",argv[0],lVal); - SCWrite(pCon,pBueffel,eValue); - return 1; + else if (strcmp(argv[1], "sum") == 0) { + /* read following arguments as ints and put them + into the iStart and iEnd array in succession. + But first check if we have an even number. + */ + if (((argc - 2) % 2) || (argc - 2) == 0) { + SCWrite(pCon, + "ERROR: need start and end for each dimension", eError); + return 0; + } + nDim = 0; + iSwitch = 0; + for (i = 0; i < argc - 2; i++) { + iRet = Tcl_GetInt(pSics->pTcl, argv[i + 2], &iVal); + if (iSwitch) { + iaEnd[nDim] = iVal; + nDim++; + iSwitch = 0; + } else { + iSwitch = 1; + iaStart[nDim] = iVal; } - else - { - sprintf(pBueffel,"ERROR: %s does not understand command %s", - argv[0], argv[1]); - SCWrite(pCon, pBueffel,eError); - return 0; - } - } - - - - - - - + } + lVal = HistSum(self, pCon, iaStart, iaEnd); + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.sum = %ld", argv[0], lVal); + SCWrite(pCon, pBueffel, eValue); + return 1; + } else { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s does not understand command %s", + argv[0], argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } +} diff --git a/histmemsec.c b/histmemsec.c new file mode 100644 index 00000000..053d82cf --- /dev/null +++ b/histmemsec.c @@ -0,0 +1,259 @@ +/** + * This is a second generation histogram memory object. In contrast + * to counters and motors no attempt is made to provide backwards + * compatability with the old SICS way of doing things. This + * histogram memory object quite sensibly is derived from + * the counter object. It adds a rank, dimensions and variable + * data and a configuration method. For TOF, methods and variables + * for generating and maintaining time binnings are provided too. + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, May 2009 + */ +#include +#include +#include + +#define CONFIG 1005 + +/* from countersec.c. */ +int SecCtrInvokeFunction(pCounter self, SConnection *pCon, int code); + +/*-------------------------------------------------------------------------*/ +static int initArray(pCounter self, int value) +{ + pHdb rank = NULL, dim = NULL, data = NULL, datalength; + int i, length; + hdbValue v; + + rank = GetHipadabaNode(self->pDes->parNode,"rank"); + assert(rank != NULL); + dim = GetHipadabaNode(self->pDes->parNode,"dim"); + assert(dim != NULL); + data = GetHipadabaNode(self->pDes->parNode,"data"); + assert(data != NULL); + datalength = GetHipadabaNode(self->pDes->parNode,"datalength"); + assert(datalength != NULL); + + length = dim->value.v.intArray[0]; + for(i = 1; i < rank->value.v.intValue; i++){ + length *= dim->value.v.intArray[i]; + } + v = MakeHdbInt(length); + UpdateHipadabaPar(datalength, v, NULL); + + v = makeHdbValue(HIPINTVARAR, length); + if(v.v.intArray == NULL){ + return 0; + } + for(i = 0; i < length; i++){ + v.v.intArray[i] = value; + } + UpdateHipadabaPar(data,v,NULL); + ReleaseHdbValue(&v); + return 1; +} +/*-------------------------------------------------------------------------*/ +static hdbCallbackReturn HMDimCallback(pHdb currentNode, void *data, + pHdbMessage message) +{ + pHdbDataMessage update = NULL; + + if((update = GetHdbUpdateMessage(message)) != NULL){ + copyHdbValue(update->v, ¤tNode->value); + initArray((pCounter)data, 0); + } + return hdbContinue; +} +/*--------------------------------------------------------------------------*/ +static int ResetCmd(pSICSOBJ ccmd, SConnection * pCon, + Hdb * cmdNode, Hdb * par[], int nPar) +{ + if(nPar < 1){ + SCWrite(pCon, "ERROR: need a parameter to set", eError); + return 0; + } + + if(!initArray((pCounter) ccmd, par[0]->value.v.intValue )){ + SCWrite(pCon,"ERROR: out of memory initializing HM", eError); + return 0; + } + return 1; +} +/*--------------------------------------------------------------------------*/ +static int GenbinCmd(pSICSOBJ ccmd, SConnection * pCon, + Hdb * cmdNode, Hdb * par[], int nPar) +{ + double start, step; + int np, i; + pHdb tof = NULL, dim = NULL; + hdbValue v; + + if(nPar < 3){ + SCWrite(pCon, "ERROR: need start step n parameters to gengin", + eError); + return 0; + } + + start = par[0]->value.v.doubleValue; + step = par[1]->value.v.doubleValue; + np = par[2]->value.v.intValue; + + tof = GetHipadabaNode(ccmd->pDes->parNode,"time_binning"); + assert(tof != NULL); + + dim = GetHipadabaNode(ccmd->pDes->parNode,"dim"); + assert(dim != NULL); + + v = makeHdbValue(HIPFLOATVARAR,np ); + if(v.v.floatArray == NULL){ + SCWrite(pCon,"ERROR: out of memory in genbin", eError); + return 0; + } + for(i = 0; i < np; i++){ + v.v.floatArray[i] = start + i*step; + } + UpdateHipadabaPar(tof,v,pCon); + ReleaseHdbValue(&v); + + GetHipadabaPar(dim,&v, pCon); + v.v.intArray[v.arrayLength-1] = np; + UpdateHipadabaPar(dim,v,pCon); + + return 1; +} +/*--------------------------------------------------------------------------*/ +static int InitCmd(pSICSOBJ ccmd, SConnection * con, + Hdb * cmdNode, Hdb * par[], int nPar) +{ + return SecCtrInvokeFunction((pCounter)ccmd,con,CONFIG); +} +/*--------------------------------------------------------------------------*/ +static int HMCtrTransferData(void *pData, SConnection *pCon) +{ + pCounter self = (pCounter)pData; + assert(self != NULL); + pHdb node = NULL; + hdbValue v; + int status; + + node = GetHipadabaNode(self->pDes->parNode,"data"); + assert(node != NULL); + self->isUpToDate = 1; + status = GetHipadabaPar(node,&v,pCon); + ReleaseHdbValue(&v); + return status; +} +/*------------------------------------------------------------------------- + * automatically update the last entry of the dim variable when + * setting time_binning +--------------------------------------------------------------------------*/ +static hdbCallbackReturn HMTOFCallback(pHdb currentNode, void *data, + pHdbMessage message) +{ + pHdbDataMessage update = NULL; + hdbValue dim; + pHdb dimNode = NULL; + + if((update = GetHdbUpdateMessage(message)) != NULL){ + dimNode = GetHipadabaNode(currentNode->mama,"dim"); + assert(dimNode != NULL); + GetHipadabaPar(dimNode,&dim,NULL); + dim.v.intArray[dim.arrayLength-1] = update->v->arrayLength; + UpdateHipadabaPar(dimNode, dim, NULL); + } + return hdbContinue; +} + +/*-------------------------------------------------------------------------- + * Usage: + * MakeSecHM name rank (tof) + * -------------------------------------------------------------------------*/ +int MakeSecHM(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pCounter pRes = NULL; + int rank, status; + pHdb node = NULL, child = NULL; + + if(argc < 3) { + SCWrite(pCon,"ERROR: need at least a name and rank to create a HM", + eError); + return 0; + } + + rank = atoi(argv[2]); + + pRes = CreateSecCounter(pCon,"HistMemSec", argv[1], 2); + if(pRes == NULL){ + return 0; + } + pRes->pCountInt->TransferData = HMCtrTransferData; + + node = pRes->objectNode; + child = GetHipadabaNode(node,"values"); + if(child!= NULL){ + DeleteHipadabaNode(child,pCon); + } + + child = MakeSICSHdbPar("rank", usInternal, MakeHdbInt(rank)); + if (child == NULL) { + return 0; + } + AddHipadabaChild(node, child, NULL); + + child = MakeSICSHdbPar("dim", usMugger, makeHdbValue(HIPINTAR,rank)); + if (child == NULL) { + return 0; + } + AppendHipadabaCallback(child, + MakeHipadabaCallback(HMDimCallback, pRes, NULL)); + AddHipadabaChild(node, child, NULL); + + child = MakeSICSHdbPar("datalength", usInternal, MakeHdbInt(100)); + if (child == NULL) { + return 0; + } + AddHipadabaChild(node, child, NULL); + + child = MakeSICSHdbPar("data", usMugger, makeHdbValue(HIPINTVARAR,100)); + if (child == NULL) { + return 0; + } + AddHipadabaChild(node, child, NULL); + + child = AddSICSHdbPar(node,"set", usMugger, MakeSICSFunc(ResetCmd)); + AddSICSHdbPar(child, "value", usUser, MakeHdbInt(0)); + + child = AddSICSHdbPar(node,"init", usMugger, MakeSICSFunc(InitCmd)); + + /* + * test TOF option + */ + if(argc > 3){ + if(strcmp(argv[3],"tof") == 0){ + child = MakeSICSHdbPar("time_binning", usMugger, makeHdbValue(HIPFLOATVARAR,100)); + if (child == NULL) { + return 0; + } + AddHipadabaChild(node, child, NULL); + AppendHipadabaCallback(child, + MakeHipadabaCallback(HMTOFCallback, NULL, NULL)); + + child = AddSICSHdbPar(node,"genbin", usMugger, MakeSICSFunc(GenbinCmd)); + AddSICSHdbPar(child, "start", usMugger, MakeHdbFloat(10.)); + AddSICSHdbPar(child, "step", usMugger, MakeHdbFloat(10.)); + AddSICSHdbPar(child, "np", usMugger, MakeHdbInt(10)); + } + } + + 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/histmemsec.h b/histmemsec.h new file mode 100644 index 00000000..b0b244fe --- /dev/null +++ b/histmemsec.h @@ -0,0 +1,20 @@ +/** + * This is a second generation histogram memory object. In contrast + * to counters and motors no attempt is made to provide backwards + * compatability with the old SICS way of doing things. This + * histogram memory object quite sensibly is derived from + * the counter object. It adds a rank, dimensions and variable + * data and a configuration method. For TOF, methods and variables + * for generating and maintaining time binnings are provided too. + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, May 2009 + */ +#ifndef HISTMEMSEC_H_ +#define HISTMEMSEC_H_ +#include +int MakeSecHM(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); + +#endif /*HISTMEMSEC_H_*/ diff --git a/histregress.c b/histregress.c index 8003e27f..2c01221c 100644 --- a/histregress.c +++ b/histregress.c @@ -28,246 +28,250 @@ static int iSet = 0; static HistInt iSetVal = 0; static HistMode eHistMode; /*--------------------------------------------------------------------------*/ -static int RegressConfig(pHistDriver self, SConnection *pCon, - pStringDict pOption, SicsInterp *pSics) +static int RegressConfig(pHistDriver self, SConnection * pCon, + pStringDict pOption, SicsInterp * pSics) { - int i, iLength = 1, status; - char pData[132]; - float fFail; - pCounterDriver count; + int i, iLength = 1, status; + char pData[132]; + float fFail; + pCounterDriver count; - count = (pCounterDriver)self->pPriv; - - if(eHistMode == eHTOF) - { - for(i = 0; i < self->data->rank; i++) - { - iLength *= self->data->iDim[i]; - } - iLength *= self->data->nTimeChan; + count = (pCounterDriver) self->pPriv; + + if (eHistMode == eHTOF) { + for (i = 0; i < self->data->rank; i++) { + iLength *= self->data->iDim[i]; } + iLength *= self->data->nTimeChan; + } - /* - deal with error settings - */ - status = StringDictGet(pOption,"errortype",pData,131); - if(status) - { - - fFail = atof(pData); - count->Set(count,"errortype",1,fFail); - } - status = StringDictGet(pOption,"recover",pData,131); - if(status) - { - - fFail = atof(pData); - count->Set(count,"recover",1,fFail); - } - status = StringDictGet(pOption,"finish",pData,131); - if(status) - { - - fFail = atof(pData); - count->Set(count,"finish",1,fFail); - } - - /* - configured test value - */ - status = StringDictGet(pOption,"testval",pData,131); - if(status) - { - iSet = 1; - iSetVal = atoi(pData); - } + /* + deal with error settings + */ + status = StringDictGet(pOption, "errortype", pData, 131); + if (status) { + + fFail = atof(pData); + count->Set(count, "errortype", 1, fFail); + } + status = StringDictGet(pOption, "recover", pData, 131); + if (status) { + + fFail = atof(pData); + count->Set(count, "recover", 1, fFail); + } + status = StringDictGet(pOption, "finish", pData, 131); + if (status) { + + fFail = atof(pData); + count->Set(count, "finish", 1, fFail); + } + + /* + configured test value + */ + status = StringDictGet(pOption, "testval", pData, 131); + if (status) { + iSet = 1; + iSetVal = atoi(pData); + } + + return 1; +} - return 1; - } /*-------------------------------------------------------------------------*/ - static int RegressStart(pHistDriver self, SConnection *pCon) - { - pCounterDriver pDriv; - - pDriv = (pCounterDriver)self->pPriv; - pDriv->fPreset = self->fCountPreset; - pDriv->eMode = self->eCount; - return pDriv->Start(pDriv); - } +static int RegressStart(pHistDriver self, SConnection * pCon) +{ + pCounterDriver pDriv; + + pDriv = (pCounterDriver) self->pPriv; + pDriv->fPreset = self->fCountPreset; + pDriv->eMode = self->eCount; + return pDriv->Start(pDriv); +} + /*-------------------------------------------------------------------------*/ - static int RegressPause(pHistDriver self, SConnection *pCon) - { - pCounterDriver pDriv; - - pDriv = (pCounterDriver)self->pPriv; - pDriv->fPreset = self->fCountPreset; - pDriv->eMode = self->eCount; - return pDriv->Pause(pDriv); - } +static int RegressPause(pHistDriver self, SConnection * pCon) +{ + pCounterDriver pDriv; + + pDriv = (pCounterDriver) self->pPriv; + pDriv->fPreset = self->fCountPreset; + pDriv->eMode = self->eCount; + return pDriv->Pause(pDriv); +} + /*------------------------------------------------------------------------*/ - static int RegressContinue(pHistDriver self, SConnection *pCon) - { - pCounterDriver pDriv; - - pDriv = (pCounterDriver)self->pPriv; - pDriv->fPreset = self->fCountPreset; - pDriv->eMode = self->eCount; - return pDriv->Continue(pDriv); - } +static int RegressContinue(pHistDriver self, SConnection * pCon) +{ + pCounterDriver pDriv; + + pDriv = (pCounterDriver) self->pPriv; + pDriv->fPreset = self->fCountPreset; + pDriv->eMode = self->eCount; + return pDriv->Continue(pDriv); +} + /*-------------------------------------------------------------------------*/ - static int RegressHalt(pHistDriver self) - { - pCounterDriver pDriv; - - pDriv = (pCounterDriver)self->pPriv; - return pDriv->Halt(pDriv); - } +static int RegressHalt(pHistDriver self) +{ + pCounterDriver pDriv; + + pDriv = (pCounterDriver) self->pPriv; + return pDriv->Halt(pDriv); +} + /*-------------------------------------------------------------------------*/ - static int RegressGetCountStatus(pHistDriver self, SConnection *pCon) - { - pCounterDriver pDriv; - float fControl; - - pDriv = (pCounterDriver)self->pPriv; - return pDriv->GetStatus(pDriv,&fControl); - } +static int RegressGetCountStatus(pHistDriver self, SConnection * pCon) +{ + pCounterDriver pDriv; + float fControl; + + pDriv = (pCounterDriver) self->pPriv; + return pDriv->GetStatus(pDriv, &fControl); +} + /*-------------------------------------------------------------------------*/ - static int RegressGetError(pHistDriver self, int *iCode, char *pError, int iLen) - { - pCounterDriver pDriv; - - pDriv = (pCounterDriver)self->pPriv; - return pDriv->GetError(pDriv, iCode,pError,iLen); - } +static int RegressGetError(pHistDriver self, int *iCode, char *pError, + int iLen) +{ + pCounterDriver pDriv; + + pDriv = (pCounterDriver) self->pPriv; + return pDriv->GetError(pDriv, iCode, pError, iLen); +} + /*-------------------------------------------------------------------------*/ - static int RegressTryAndFixIt(pHistDriver self, int iCode) - { - pCounterDriver pDriv; - - pDriv = (pCounterDriver)self->pPriv; - return pDriv->TryAndFixIt(pDriv, iCode); - } +static int RegressTryAndFixIt(pHistDriver self, int iCode) +{ + pCounterDriver pDriv; + + pDriv = (pCounterDriver) self->pPriv; + return pDriv->TryAndFixIt(pDriv, iCode); +} + /*--------------------------------------------------------------------------*/ - static int RegressGetData(pHistDriver self, SConnection *pCon) - { - pCounterDriver pDriv; - - pDriv = (pCounterDriver)self->pPriv; +static int RegressGetData(pHistDriver self, SConnection * pCon) +{ + pCounterDriver pDriv; + + pDriv = (pCounterDriver) self->pPriv; + + return pDriv->ReadValues(pDriv); +} - return pDriv->ReadValues(pDriv); - } /*--------------------------------------------------------------------------*/ - static int RegressGetHistogram(pHistDriver self, SConnection *pCon, - int i, int iStart, int iEnd, HistInt *lData) - { - int ii; - - if(i < 0) - { - SCWrite(pCon,"ERROR: histogram out of range",eError); - return 0; - } +static int RegressGetHistogram(pHistDriver self, SConnection * pCon, + int i, int iStart, int iEnd, + HistInt * lData) +{ + int ii; - if(iSet == 1) - { - for(ii = iStart; ii < iEnd; ii++) - { - lData[ii-iStart] = iSetVal; - } - } - else - { - for(ii = iStart; ii < iEnd; ii++) - { - lData[ii-iStart] = random(); - } - } - return 1; - } -/*------------------------------------------------------------------------*/ - static int RegressSetHistogram(pHistDriver self, SConnection *pCon, - int i, int iStart, int iEnd, HistInt *lData) - { - iSet = 1; - iSetVal = lData[0]; - return 1; - } + if (i < 0) { + SCWrite(pCon, "ERROR: histogram out of range", eError); + return 0; + } -/*-------------------------------------------------------------------------*/ - static int RegressPreset(pHistDriver self, SConnection *pCon, HistInt iVal) - { - iSet = 1; - iSetVal = iVal; - return 1; - } -/*------------------------------------------------------------------------*/ - static int RegressFreePrivate(pHistDriver self) - { - pCounterDriver pDriv; - - pDriv = (pCounterDriver)self->pPriv; - DeleteCounterDriver(pDriv); - return 1; - } -/*------------------------------------------------------------------------*/ - static long RegressGetMonitor(pHistDriver self, int i, SConnection *pCon) - { - pCounterDriver pDriv; - long lVal; - - pDriv = (pCounterDriver)self->pPriv; - return pDriv->lCounts[i]; - - } -/*------------------------------------------------------------------------*/ - static float RegressGetTime(pHistDriver self, SConnection *pCon) - { - pCounterDriver pDriv; - long lVal; - - pDriv = (pCounterDriver)self->pPriv; - return pDriv->fTime; - - } -/*-------------------------------------------------------------------------*/ - pHistDriver CreateRegressHM(pStringDict pOpt) - { - pHistDriver pNew = NULL; - - /* create the general driver */ - pNew = CreateHistDriver(pOpt); - if(!pNew) - { - return NULL; - } - - /* put a Regresscounter in */ - pNew->pPriv = (void *)NewRegressCounter("HistoRegress"); - if(!pNew->pPriv) - { - DeleteHistDriver(pNew); - return NULL; + if (iSet == 1) { + for (ii = iStart; ii < iEnd; ii++) { + lData[ii - iStart] = iSetVal; } - - /* configure all those functions */ - pNew->Configure = RegressConfig; - pNew->Start = RegressStart; - pNew->Halt = RegressHalt; - pNew->GetCountStatus = RegressGetCountStatus; - pNew->GetError = RegressGetError; - pNew->TryAndFixIt = RegressTryAndFixIt; - pNew->GetData = RegressGetData; - pNew->GetHistogram = RegressGetHistogram; - pNew->SetHistogram = RegressSetHistogram; - pNew->GetMonitor = RegressGetMonitor; - pNew->GetTime = RegressGetTime; - pNew->Preset = RegressPreset; - pNew->FreePrivate = RegressFreePrivate; - pNew->Pause = RegressPause; - pNew->Continue = RegressContinue; - StringDictAddPair(pOpt,"errortype","0"); - StringDictAddPair(pOpt,"recover","1"); - StringDictAddPair(pOpt,"testval","0"); - - return pNew; - } + } else { + for (ii = iStart; ii < iEnd; ii++) { + lData[ii - iStart] = random(); + } + } + return 1; +} + +/*------------------------------------------------------------------------*/ +static int RegressSetHistogram(pHistDriver self, SConnection * pCon, + int i, int iStart, int iEnd, + HistInt * lData) +{ + iSet = 1; + iSetVal = lData[0]; + return 1; +} + +/*-------------------------------------------------------------------------*/ +static int RegressPreset(pHistDriver self, SConnection * pCon, + HistInt iVal) +{ + iSet = 1; + iSetVal = iVal; + return 1; +} + +/*------------------------------------------------------------------------*/ +static int RegressFreePrivate(pHistDriver self) +{ + pCounterDriver pDriv; + + pDriv = (pCounterDriver) self->pPriv; + DeleteCounterDriver(pDriv); + return 1; +} + +/*------------------------------------------------------------------------*/ +static long RegressGetMonitor(pHistDriver self, int i, SConnection * pCon) +{ + pCounterDriver pDriv; + long lVal; + + pDriv = (pCounterDriver) self->pPriv; + return pDriv->lCounts[i]; + +} + +/*------------------------------------------------------------------------*/ +static float RegressGetTime(pHistDriver self, SConnection * pCon) +{ + pCounterDriver pDriv; + long lVal; + + pDriv = (pCounterDriver) self->pPriv; + return pDriv->fTime; + +} + +/*-------------------------------------------------------------------------*/ +pHistDriver CreateRegressHM(pStringDict pOpt) +{ + pHistDriver pNew = NULL; + + /* create the general driver */ + pNew = CreateHistDriver(pOpt); + if (!pNew) { + return NULL; + } + + /* put a Regresscounter in */ + pNew->pPriv = (void *) NewRegressCounter("HistoRegress"); + if (!pNew->pPriv) { + DeleteHistDriver(pNew); + return NULL; + } + + /* configure all those functions */ + pNew->Configure = RegressConfig; + pNew->Start = RegressStart; + pNew->Halt = RegressHalt; + pNew->GetCountStatus = RegressGetCountStatus; + pNew->GetError = RegressGetError; + pNew->TryAndFixIt = RegressTryAndFixIt; + pNew->GetData = RegressGetData; + pNew->GetHistogram = RegressGetHistogram; + pNew->SetHistogram = RegressSetHistogram; + pNew->GetMonitor = RegressGetMonitor; + pNew->GetTime = RegressGetTime; + pNew->Preset = RegressPreset; + pNew->FreePrivate = RegressFreePrivate; + pNew->Pause = RegressPause; + pNew->Continue = RegressContinue; + StringDictAddPair(pOpt, "errortype", "0"); + StringDictAddPair(pOpt, "recover", "1"); + StringDictAddPair(pOpt, "testval", "0"); + + return pNew; +} diff --git a/histsim.c b/histsim.c index 98eab3df..1813b584 100644 --- a/histsim.c +++ b/histsim.c @@ -49,261 +49,263 @@ #include "HistDriv.i" #include "histsim.h" - static int iSet = 0; - static HistInt iSetVal = 0; - static HistMode eHistMode; +static int iSet = 0; +static HistInt iSetVal = 0; +static HistMode eHistMode; /*--------------------------------------------------------------------------*/ - static int SimConfig(pHistDriver self, SConnection *pCon, - pStringDict pOption, SicsInterp *pSics) - { - int i, iLength = 1, status; - char pData[132]; - float fFail; +static int SimConfig(pHistDriver self, SConnection * pCon, + pStringDict pOption, SicsInterp * pSics) +{ + int i, iLength = 1, status; + char pData[132]; + float fFail; - if(eHistMode == eHTOF) - { - for(i = 0; i < self->data->rank; i++) - { - iLength *= self->data->iDim[i]; - } - iLength *= self->data->nTimeChan; + if (eHistMode == eHTOF) { + for (i = 0; i < self->data->rank; i++) { + iLength *= self->data->iDim[i]; } + iLength *= self->data->nTimeChan; + } - /* - deal with failrate - */ - status = StringDictGet(pOption,"failrate",pData,131); - if(status) - { - fFail = atof(pData); - free(self->pPriv); - self->pPriv = NewSIMCounter("HistoSim",fFail); - } - - /* - configured test value - */ - status = StringDictGet(pOption,"testval",pData,131); - if(status) - { - iSet = 1; - iSetVal = atoi(pData); - } + /* + deal with failrate + */ + status = StringDictGet(pOption, "failrate", pData, 131); + if (status) { + fFail = atof(pData); + free(self->pPriv); + self->pPriv = NewSIMCounter("HistoSim", fFail); + } - return 1; - } -/*-------------------------------------------------------------------------*/ - static int SimStart(pHistDriver self, SConnection *pCon) - { - pCounterDriver pDriv; - - pDriv = (pCounterDriver)self->pPriv; - pDriv->fPreset = self->fCountPreset; - pDriv->eMode = self->eCount; - return pDriv->Start(pDriv); - } -/*-------------------------------------------------------------------------*/ - static int SimPause(pHistDriver self, SConnection *pCon) - { - pCounterDriver pDriv; - - pDriv = (pCounterDriver)self->pPriv; - pDriv->fPreset = self->fCountPreset; - pDriv->eMode = self->eCount; - return pDriv->Pause(pDriv); - } -/*------------------------------------------------------------------------*/ - static int SimContinue(pHistDriver self, SConnection *pCon) - { - pCounterDriver pDriv; - - pDriv = (pCounterDriver)self->pPriv; - pDriv->fPreset = self->fCountPreset; - pDriv->eMode = self->eCount; - return pDriv->Continue(pDriv); - } -/*-------------------------------------------------------------------------*/ - static int SimHalt(pHistDriver self) - { - pCounterDriver pDriv; - - pDriv = (pCounterDriver)self->pPriv; - return pDriv->Halt(pDriv); - } -/*-------------------------------------------------------------------------*/ - static int SimGetCountStatus(pHistDriver self, SConnection *pCon) - { - pCounterDriver pDriv; - float fControl; - - pDriv = (pCounterDriver)self->pPriv; - return pDriv->GetStatus(pDriv,&fControl); - } -/*-------------------------------------------------------------------------*/ - static int SimGetError(pHistDriver self, int *iCode, char *pError, int iLen) - { - pCounterDriver pDriv; - - pDriv = (pCounterDriver)self->pPriv; - return pDriv->GetError(pDriv, iCode,pError,iLen); - } -/*-------------------------------------------------------------------------*/ - static int SimTryAndFixIt(pHistDriver self, int iCode) - { - pCounterDriver pDriv; - - pDriv = (pCounterDriver)self->pPriv; - return pDriv->TryAndFixIt(pDriv, iCode); - } -/*--------------------------------------------------------------------------*/ - static int SimGetData(pHistDriver self, SConnection *pCon) - { - pCounterDriver pDriv; - - pDriv = (pCounterDriver)self->pPriv; + /* + configured test value + */ + status = StringDictGet(pOption, "testval", pData, 131); + if (status) { + iSet = 1; + iSetVal = atoi(pData); + } - return pDriv->ReadValues(pDriv); - } -/*--------------------------------------------------------------------------*/ - static int SimGetHistogram(pHistDriver self, SConnection *pCon, - int i, int iStart, int iEnd, HistInt *lData) - { - int ii; - - if(i < 0) - { - SCWrite(pCon,"ERROR: histogram out of range",eError); - return 0; - } - - if(iSet == 1) - { - for(ii = iStart; ii < iEnd; ii++) - { - lData[ii-iStart] = iSetVal; - } - } - else if(iSet == 2) - { - for(ii = iStart; ii < iEnd; ii++) - { - lData[ii-iStart] = self->data->localBuffer[ii]; - } - } - else - { - for(ii = iStart; ii < iEnd; ii++) - { - lData[ii-iStart] = random(); - } - } - return 1; - } -/*------------------------------------------------------------------------*/ - static int SimSetHistogram(pHistDriver self, SConnection *pCon, - int i, int iStart, int iEnd, HistInt *lData) - { - iSet = 2; - if(self->data->localBuffer == NULL){ - resizeBuffer(self->data); - } - iSetVal = lData[0]; - if(iEnd <= getHMDataLength(self->data)){ - memcpy(self->data->localBuffer+iStart,lData,(iEnd - iStart)*sizeof(HistInt)); - } - return 1; - } - -/*-------------------------------------------------------------------------*/ - static int SimPreset(pHistDriver self, SConnection *pCon, HistInt iVal) - { - iSet = 1; - iSetVal = iVal; - return 1; - } -/*------------------------------------------------------------------------*/ - static int SimFreePrivate(pHistDriver self) - { - pCounterDriver pDriv; - - pDriv = (pCounterDriver)self->pPriv; - DeleteCounterDriver(pDriv); - return 1; - } -/*------------------------------------------------------------------------*/ - static long SimGetMonitor(pHistDriver self, int i, SConnection *pCon) - { - pCounterDriver pDriv; - long lVal; - - pDriv = (pCounterDriver)self->pPriv; - return pDriv->lCounts[i]; - - } -/*------------------------------------------------------------------------*/ - static float SimGetTime(pHistDriver self, SConnection *pCon) - { - pCounterDriver pDriv; - long lVal; - - pDriv = (pCounterDriver)self->pPriv; - return pDriv->fTime; - - } -/*-------------------------------------------------------------------------*/ -HistInt *DefaultSubSample(pHistDriver self, SConnection *pCon, - int bank, char *command){ - HistInt *data = NULL; - char error[132]; - - assert(bank == 0); /* no bank handling yet.. */ - - memset(error,0,132*sizeof(char)); - data = subSample(self->data, command, error, 132); - if(data == NULL){ - SCWrite(pCon,error,eError); - } - return data; + return 1; } + /*-------------------------------------------------------------------------*/ - pHistDriver CreateSIMHM(pStringDict pOpt) - { - pHistDriver pNew = NULL; - - /* create the general driver */ - pNew = CreateHistDriver(pOpt); - if(!pNew) - { - return NULL; - } - - /* put a SIMcounter in */ - pNew->pPriv = (void *)NewSIMCounter("HistoSim",-1.); - if(!pNew->pPriv) - { - DeleteHistDriver(pNew); - return NULL; +static int SimStart(pHistDriver self, SConnection * pCon) +{ + pCounterDriver pDriv; + + pDriv = (pCounterDriver) self->pPriv; + pDriv->fPreset = self->fCountPreset; + pDriv->eMode = self->eCount; + return pDriv->Start(pDriv); +} + +/*-------------------------------------------------------------------------*/ +static int SimPause(pHistDriver self, SConnection * pCon) +{ + pCounterDriver pDriv; + + pDriv = (pCounterDriver) self->pPriv; + pDriv->fPreset = self->fCountPreset; + pDriv->eMode = self->eCount; + return pDriv->Pause(pDriv); +} + +/*------------------------------------------------------------------------*/ +static int SimContinue(pHistDriver self, SConnection * pCon) +{ + pCounterDriver pDriv; + + pDriv = (pCounterDriver) self->pPriv; + pDriv->fPreset = self->fCountPreset; + pDriv->eMode = self->eCount; + return pDriv->Continue(pDriv); +} + +/*-------------------------------------------------------------------------*/ +static int SimHalt(pHistDriver self) +{ + pCounterDriver pDriv; + + pDriv = (pCounterDriver) self->pPriv; + return pDriv->Halt(pDriv); +} + +/*-------------------------------------------------------------------------*/ +static int SimGetCountStatus(pHistDriver self, SConnection * pCon) +{ + pCounterDriver pDriv; + float fControl; + + pDriv = (pCounterDriver) self->pPriv; + return pDriv->GetStatus(pDriv, &fControl); +} + +/*-------------------------------------------------------------------------*/ +static int SimGetError(pHistDriver self, int *iCode, char *pError, + int iLen) +{ + pCounterDriver pDriv; + + pDriv = (pCounterDriver) self->pPriv; + return pDriv->GetError(pDriv, iCode, pError, iLen); +} + +/*-------------------------------------------------------------------------*/ +static int SimTryAndFixIt(pHistDriver self, int iCode) +{ + pCounterDriver pDriv; + + pDriv = (pCounterDriver) self->pPriv; + return pDriv->TryAndFixIt(pDriv, iCode); +} + +/*--------------------------------------------------------------------------*/ +static int SimGetData(pHistDriver self, SConnection * pCon) +{ + pCounterDriver pDriv; + + pDriv = (pCounterDriver) self->pPriv; + + return pDriv->ReadValues(pDriv); +} + +/*--------------------------------------------------------------------------*/ +static int SimGetHistogram(pHistDriver self, SConnection * pCon, + int i, int iStart, int iEnd, HistInt * lData) +{ + int ii; + + if (i < 0) { + SCWrite(pCon, "ERROR: histogram out of range", eError); + return 0; + } + + if (iSet == 1) { + for (ii = iStart; ii < iEnd; ii++) { + lData[ii - iStart] = iSetVal; } - - /* configure all those functions */ - pNew->Configure = SimConfig; - pNew->Start = SimStart; - pNew->Halt = SimHalt; - pNew->GetCountStatus = SimGetCountStatus; - pNew->GetError = SimGetError; - pNew->TryAndFixIt = SimTryAndFixIt; - pNew->GetData = SimGetData; - pNew->GetHistogram = SimGetHistogram; - pNew->SetHistogram = SimSetHistogram; - pNew->GetMonitor = SimGetMonitor; - pNew->GetTime = SimGetTime; - pNew->Preset = SimPreset; - pNew->FreePrivate = SimFreePrivate; - pNew->Pause = SimPause; - pNew->Continue = SimContinue; - pNew->SubSample = DefaultSubSample; - StringDictAddPair(pOpt,"failrate","-1"); - - return pNew; - } - + } else if (iSet == 2) { + for (ii = iStart; ii < iEnd; ii++) { + lData[ii - iStart] = self->data->localBuffer[ii]; + } + } else { + for (ii = iStart; ii < iEnd; ii++) { + lData[ii - iStart] = random(); + } + } + return 1; +} + +/*------------------------------------------------------------------------*/ +static int SimSetHistogram(pHistDriver self, SConnection * pCon, + int i, int iStart, int iEnd, HistInt * lData) +{ + iSet = 2; + if (self->data->localBuffer == NULL) { + resizeBuffer(self->data); + } + iSetVal = lData[0]; + if (iEnd <= getHMDataLength(self->data)) { + memcpy(self->data->localBuffer + iStart, lData, + (iEnd - iStart) * sizeof(HistInt)); + } + return 1; +} + +/*-------------------------------------------------------------------------*/ +static int SimPreset(pHistDriver self, SConnection * pCon, HistInt iVal) +{ + iSet = 1; + iSetVal = iVal; + return 1; +} + +/*------------------------------------------------------------------------*/ +static int SimFreePrivate(pHistDriver self) +{ + pCounterDriver pDriv; + + pDriv = (pCounterDriver) self->pPriv; + DeleteCounterDriver(pDriv); + return 1; +} + +/*------------------------------------------------------------------------*/ +static long SimGetMonitor(pHistDriver self, int i, SConnection * pCon) +{ + pCounterDriver pDriv; + long lVal; + + pDriv = (pCounterDriver) self->pPriv; + return pDriv->lCounts[i]; + +} + +/*------------------------------------------------------------------------*/ +static float SimGetTime(pHistDriver self, SConnection * pCon) +{ + pCounterDriver pDriv; + long lVal; + + pDriv = (pCounterDriver) self->pPriv; + return pDriv->fTime; + +} + +/*-------------------------------------------------------------------------*/ +HistInt *DefaultSubSample(pHistDriver self, SConnection * pCon, + int bank, char *command) +{ + HistInt *data = NULL; + char error[132]; + + assert(bank == 0); /* no bank handling yet.. */ + + memset(error, 0, 132 * sizeof(char)); + data = subSample(self->data, command, error, 132); + if (data == NULL) { + SCWrite(pCon, error, eError); + } + return data; +} + +/*-------------------------------------------------------------------------*/ +pHistDriver CreateSIMHM(pStringDict pOpt) +{ + pHistDriver pNew = NULL; + + /* create the general driver */ + pNew = CreateHistDriver(pOpt); + if (!pNew) { + return NULL; + } + + /* put a SIMcounter in */ + pNew->pPriv = (void *) NewSIMCounter("HistoSim", -1.); + if (!pNew->pPriv) { + DeleteHistDriver(pNew); + return NULL; + } + + /* configure all those functions */ + pNew->Configure = SimConfig; + pNew->Start = SimStart; + pNew->Halt = SimHalt; + pNew->GetCountStatus = SimGetCountStatus; + pNew->GetError = SimGetError; + pNew->TryAndFixIt = SimTryAndFixIt; + pNew->GetData = SimGetData; + pNew->GetHistogram = SimGetHistogram; + pNew->SetHistogram = SimSetHistogram; + pNew->GetMonitor = SimGetMonitor; + pNew->GetTime = SimGetTime; + pNew->Preset = SimPreset; + pNew->FreePrivate = SimFreePrivate; + pNew->Pause = SimPause; + pNew->Continue = SimContinue; + pNew->SubSample = DefaultSubSample; + StringDictAddPair(pOpt, "failrate", "-1"); + + return pNew; +} diff --git a/histsim.h b/histsim.h index e347c969..6c289bad 100644 --- a/histsim.h +++ b/histsim.h @@ -15,7 +15,7 @@ #line 5 "histsim.w" - pHistDriver CreateSIMHM(pStringDict pOpt); +pHistDriver CreateSIMHM(pStringDict pOpt); #line 27 "histsim.w" diff --git a/hkl.c b/hkl.c index 4351f20c..b4030f8b 100644 --- a/hkl.c +++ b/hkl.c @@ -22,6 +22,10 @@ Added handling of the chi ==0 or chi == 180 degree case to tryTweakOmega Mark Koennecke, December 2003 + + Heavily reworked to fit into the new four circle setup + + Mark Koennecke, July 2008 -----------------------------------------------------------------------------*/ #include #include @@ -35,847 +39,353 @@ #include "hkl.h" #include "hkl.i" #include "splitter.h" - +#include "singlex.h" +#include "motorlist.h" +#include "cell.h" +#include "ubfour.h" /* the tolerance in chi we give before we allow to fix omega with phi */ #define CHITOLERANCE 3. -#define ABS(x) (x < 0 ? -(x) : (x)) +#define ABS(x) (x < 0 ? -(x) : (x)) /*-------------------------------------------------------------------------*/ - static int HKLSave(void *pData, char *name, FILE *fd) - { - pHKL self = NULL; +static int HKLSave(void *pData, char *name, FILE * fd) +{ + pHKL self = NULL; - self = (pHKL)pData; - if( (self == NULL) || (fd == NULL) ) - { - return 1; - } - fprintf(fd,"#Crystallographic Settings\n"); - if(self->iManual == 1) - { - fprintf(fd,"%s lambda %f\n",name, self->fLambda); - } - fprintf(fd, - "%s setub %8.6f %8.6f %8.6f %8.6f %8.6f %8.6f %8.6f %8.6f %8.6f\n", - name, - self->fUB[0], self->fUB[1], self->fUB[2], self->fUB[3], self->fUB[4], - self->fUB[5], self->fUB[6], self->fUB[7], self->fUB[8]); - fprintf(fd,"%s hm %d\n",name, self->iHM); - fprintf(fd,"%s scantolerance %f\n", name,self->scanTolerance); - fprintf(fd,"%s nb %d\n", name, self->iNOR); - return 1; - } - -/*---------------------------------------------------------------------------*/ - pHKL CreateHKL(pMotor pTheta, pMotor pOmega, pMotor pChi, - pMotor pPhi, pMotor pNu) - { - pHKL pNew = NULL; - - assert(pTheta); - assert(pOmega); - assert(pChi); - assert(pPhi); - - /* allocate memory */ - pNew = (pHKL)malloc(sizeof(HKL)); - if(!pNew) - { - return NULL; - } - memset(pNew,0,sizeof(HKL)); - - /* create object descriptor */ - pNew->pDes = CreateDescriptor("4-Circle-Calculus"); - if(!pNew->pDes) - { - free(pNew); - return NULL; - } - pNew->pDes->SaveStatus = HKLSave; - - pNew->pTheta = pTheta; - pNew->pOmega = pOmega; - pNew->pChi = pChi; - pNew->pPhi = pPhi; - pNew->pNu = pNu; - pNew->fLambda = 1.38; - pNew->iManual = 1; - pNew->iQuad = 1; - pNew->iHM = 0; - pNew->fUB[0] = 1.; - pNew->fUB[4] = 1.; - pNew->fUB[8] = 1.; - pNew->UBinv = NULL; - pNew->scanTolerance = 2.5; - - return pNew; - } -/*--------------------------------------------------------------------------*/ - void DeleteHKL(void *pData) - { - pHKL self = NULL; - - self = (pHKL)pData; - if(!self) - { - return; - } - - if(self->pDes) - { - DeleteDescriptor(self->pDes); - } - - free(self); - } -/*---------------------------------------------------------------------------*/ - int HKLFactory(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - pMotor pTheta = NULL, pOmega = NULL, pChi = NULL, - pPhi = NULL, pNu = NULL; - pHKL self = NULL; - int iRet; - - /* check no of arguments */ - if(argc < 5) - { - SCWrite(pCon,"ERROR: Insufficient number of arguments to HKLFactory", - eError); - return 0; - } - - /* check motors */ - pTheta = FindMotor(pSics,argv[1]); - if(!pTheta) - { - SCWrite(pCon,"ERROR: cannot find two theta motor",eError); - return 0; - } - pOmega = FindMotor(pSics,argv[2]); - if(!pOmega) - { - SCWrite(pCon,"ERROR: cannot find omega motor",eError); - return 0; - } - pPhi = FindMotor(pSics,argv[3]); - if(!pPhi) - { - SCWrite(pCon,"ERROR: cannot find phi motor",eError); - return 0; - } - pChi = FindMotor(pSics,argv[4]); - if(!pChi) - { - SCWrite(pCon,"ERROR: cannot find chi motor",eError); - return 0; - } - - if(argc >= 6) - { - pNu = FindMotor(pSics,argv[5]); - if(!pNu) - { - SCWrite(pCon,"WARNING: cannot find nu motor",eWarning); - } - } - - /* make a new structure */ - self = CreateHKL(pTheta, pOmega, pPhi, pChi, pNu); - if(!self) - { - SCWrite(pCon,"ERROR: cannot allocate HKL data structure",eError); - return 0; - } - - /* install a command */ - iRet = AddCommand(pSics, - "HKL", - HKLAction, - DeleteHKL, - self); - if(!iRet) - { - SCWrite(pCon,"ERROR: duplicate command HKL not created",eError); - DeleteHKL(self); - return 0; - } - return 1; - } -#include "selvar.i" -/*---------------------------------------------------------------------------*/ - - static int HKLCallback(int iEvent, void *pEvent, void *pUser, - commandContext cc) - { - pHKL self = NULL; - pSelVar pVar = NULL; - float fVal; - - if(iEvent == WLCHANGE) - { - self = (pHKL)pUser; - pVar = (pSelVar)pEvent; - assert(self); - assert(pVar); - - if(pVar->pCon != NULL) - { - fVal = GetSelValue(pVar, pVar->pCon); - if(fVal > -900.) - { - self->fLambda = fVal; - return 1; - } - } - } + self = (pHKL) pData; + if ((self == NULL) || (fd == NULL)) { return 1; - } -/*--------------------------------------------------------------------------*/ - int SetWavelengthVariable(SConnection *pCon, pHKL self, pSelVar pVar) - { - pICallBack pCall = NULL, pCall2 = NULL; - pDummy pDum = NULL; - float fVal; - commandContext comCon; - - assert(pCon); - assert(self); - assert(pVar); + } + fprintf(fd, "#HKL Settings\n"); + fprintf(fd, "%s scantolerance %f\n", name, self->scanTolerance); + return 1; +} +/*---------------------------------------------------------------------------*/ +static void *HKLInterface(void *pData, int iID) +{ + pHKL self = (pHKL)pData; + assert(self != NULL); + + if(iID == DRIVEID){ + return self->pMotDriv; + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +static int HKLHalt(void *pData) +{ + pHKL self = (pHKL)pData; + pSingleDiff single = NULL; + assert(self != NULL); + + single = SXGetDiffractometer(); + assert(single != NULL); + + return self->pMotList->Halt(&single->motList); +} +/*---------------------------------------------------------------------------*/ +static int HKLLimits(void *pData, float val, char *error, int errLen) +{ + pHKL self = (pHKL)pData; + pSingleDiff single = NULL; + assert(self != NULL); + + single = SXGetDiffractometer(); + assert(single != NULL); + + return self->pMotList->CheckLimits(&single->motList, val, error, errLen); +} +/*---------------------------------------------------------------------------*/ +static long HKLSet(void *pData, SConnection *pCon, float val) +{ + pHKL self = (pHKL)pData; + pSingleDiff single = NULL; + assert(self != NULL); + + single = SXGetDiffractometer(); + assert(single != NULL); + + return self->pMotList->SetValue(&single->motList, pCon,val); +} +/*---------------------------------------------------------------------------*/ +static int HKLCheck(void *pData, SConnection *pCon) +{ + pHKL self = (pHKL)pData; + pSingleDiff single = NULL; + assert(self != NULL); + + single = SXGetDiffractometer(); + assert(single != NULL); + + return self->pMotList->CheckStatus(&single->motList, pCon); +} +/*---------------------------------------------------------------------------*/ +static float HKLGet(void *pData, SConnection *pCon) +{ + pHKL self = (pHKL)pData; + pSingleDiff single = NULL; + assert(self != NULL); + + single = SXGetDiffractometer(); + assert(single != NULL); + + return self->pMotList->GetValue(&single->motList, pCon); +} +/*---------------------------------------------------------------------------*/ +pHKL CreateHKL() +{ + pHKL pNew = NULL; + + /* allocate memory */ + pNew = (pHKL) malloc(sizeof(HKL)); + if (!pNew) { + return NULL; + } + memset(pNew, 0, sizeof(HKL)); + + /* create object descriptor */ + pNew->pDes = CreateDescriptor("4-Circle-Calculus"); + pNew->pMotList = makeMotListInterface(); + pNew->pMotDriv = CreateDrivableInterface(); + if (!pNew->pDes || pNew->pMotDriv == NULL || pNew->pMotDriv == NULL) { + free(pNew); + return NULL; + } + pNew->pDes->SaveStatus = HKLSave; + pNew->pDes->GetInterface = HKLInterface; + + pNew->pMotDriv->Halt = HKLHalt; + pNew->pMotDriv->CheckLimits = HKLLimits; + pNew->pMotDriv->CheckStatus = HKLCheck; + pNew->pMotDriv->SetValue = HKLSet; + pNew->pMotDriv->GetValue = HKLGet; + + pNew->iQuad = 1; + pNew->iHM = 0; + pNew->UBinv = NULL; + pNew->scanTolerance = 2.5; + + return pNew; +} + +/*--------------------------------------------------------------------------*/ +void DeleteHKL(void *pData) +{ + pHKL self = NULL; + + self = (pHKL) pData; + if (!self) { + return; + } + + if (self->pDes) { + DeleteDescriptor(self->pDes); + } + if (self->pMotDriv) { + free(self->pMotDriv); + } + + free(self); +} + +/*---------------------------------------------------------------------------*/ +int HKLFactory(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pHKL self = NULL; + int iRet; + + /* make a new structure */ + self = CreateHKL(); + if (!self) { + SCWrite(pCon, "ERROR: cannot allocate HKL data structure", eError); + return 0; + } + + /* install a command */ + iRet = AddCommand(pSics, "HKL", HKLAction, DeleteHKL, self); + if (!iRet) { + SCWrite(pCon, "ERROR: duplicate command HKL not created", eError); + DeleteHKL(self); + return 0; + } + return 1; +} - /* try to get callback interface of the new mono variable */ - pDum = (pDummy)pVar; - pCall2 = pDum->pDescriptor->GetInterface(pDum,CALLBACKINTERFACE); - if(!pCall2) - { - return 0; - } - - /* clear old stuff, if apropriate */ - if(self->pMono) - { - pDum = (pDummy)self->pMono; - pCall = pDum->pDescriptor->GetInterface(pDum,CALLBACKINTERFACE); - if(pCall) - { - RemoveCallback(pCall,self->lID); - self->lID = 0; - self->pMono = NULL; - self->iManual = 1; - } - } - - /* install new callback */ - comCon.transID = 0; - strncpy(comCon.deviceID,"internal",SCDEVIDLEN); - self->lID = RegisterCallback(pCall2, - comCon, - WLCHANGE, - HKLCallback, - self, - NULL); - self->pMono = pVar; - self->iManual = 0; - - /* update the current value */ - fVal = GetSelValue(pVar,pCon); - if(fVal > -900.) - { - self->fLambda = fVal; - } - else - { - return 0; - } - return 1; - } /*-------------------------------------------------------------------------*/ void SetHKLScanTolerance(pHKL self, float fVal) { assert(self); self->scanTolerance = fVal; } -/*-------------------------------------------------------------------------*/ - int SetWavelengthManual(pHKL self, float fVal) - { - pICallBack pCall = NULL; - pDummy pDum = NULL; - - assert(self); - /* clear old stuff, if apropriate */ - if(self->pMono) - { - pDum = (pDummy)self->pMono; - pCall = pDum->pDescriptor->GetInterface(pDum,CALLBACKINTERFACE); - if(pCall) - { - RemoveCallback(pCall,self->lID); - self->lID = 0; - self->pMono = NULL; - self->iManual = 1; - } - } - - self->fLambda = fVal; - return 1; - } /*------------------------------------------------------------------------*/ - int GetLambda(pHKL self, float *fVal) - { - assert(self); - - *fVal = self->fLambda; - return 1; - } -/*-------------------------------------------------------------------------*/ - int GetCurrentHKL(pHKL self, float fHKL[3]) - { - int i; - - assert(self); - - for(i = 0; i < 3; i++) - { - fHKL[i] = self->fLastHKL[i]; - } - return 1; - } -/*-------------------------------------------------------------------------*/ - int SetUB(pHKL self, float fUB[9]) - { - int i; - MATRIX m; - - assert(self); - - for(i = 0; i < 9; i++) - { - self->fUB[i] = fUB[i]; - } - /* invert UB matrix for use in backwards calculation */ - if(self->UBinv != NULL) - { - mat_free(self->UBinv); - } - m = mat_creat(3,3,ZERO_MATRIX); - for(i = 0; i < 3; i++) - { - m[0][i] = self->fUB[i]; - m[1][i] = self->fUB[3+i]; - m[2][i] = self->fUB[6+i]; - } - self->UBinv = mat_inv(m); - mat_free(m); - - return 1; - } -/*-------------------------------------------------------------------------*/ - int GetUB(pHKL self, float fUB[9]) - { - int i; - - assert(self); - - for(i = 0; i < 9; i++) - { - fUB[i] = self->fUB[i]; - } - return 1; - } - -/*--------------------------------------------------------------------------*/ - int SetNOR(pHKL self, int iNOB) - { - assert(self); - - /* cannot set normal beam geometry if no nu motor */ - if( (iNOB == 1) && (self->pNu == NULL)) - return 0; - - self->iNOR = iNOB; - return 1; - } -/*-----------------------------------------------------------------------*/ -static int checkTheta(pHKL self, double *stt){ - char pError[132]; - int iTest; - float fHard; - - iTest = MotorCheckBoundary(self->pTheta,(float)*stt, &fHard,pError,131); - if(!iTest) - { - /* - check if it is on the other detectors - */ - if(self->iHM){ - iTest = MotorCheckBoundary(self->pTheta,(float)*stt-45., - &fHard,pError,131); - if(iTest){ - *stt -= 45.; - } else { - iTest = MotorCheckBoundary(self->pTheta,(float)*stt-90., - &fHard,pError,131); - if(iTest) { - *stt -= 90.; - } - } - } - if(!iTest){ - return -1; - } - } - return 1; -} -/*-----------------------------------------------------------------------*/ -static int checkBisecting(pHKL self, - double *stt, double om, double chi, double phi) +int GetLambda(pHKL self, float *fVal) { - int iTest; - float fHard, fLimit; - char pError[132]; + assert(self); + double val; - /* check two theta */ - iTest = checkTheta(self, stt); - if(!iTest){ - return -1; - } - - /* for omega check against the limits +- SCANBORDER in order to allow for - a omega scan - */ - MotorGetPar(self->pOmega,"softlowerlim",&fLimit); - if((float)om < fLimit + self->scanTolerance){ - iTest = 0; - } else { - iTest = 1; - MotorGetPar(self->pOmega,"softupperlim",&fLimit); - if((float)om > fLimit - self->scanTolerance){ - iTest = 0; - } else { - iTest = 1; - } - } - - /* check chi and phi*/ - iTest += MotorCheckBoundary(self->pChi,(float)chi, &fHard,pError,131); - iTest += MotorCheckBoundary(self->pPhi,(float)phi, &fHard,pError,131); - if(iTest == 3) /* none of them burns */ - { - return 1; - } - return 0; + val = SXGetLambda(); + *fVal = (float) val; + return 1; } -/*-----------------------------------------------------------------------*/ -static int checkNormalBeam(double om, double *gamma, double nu, - float fSet[4], SConnection *pCon, pHKL self) + +/*-------------------------------------------------------------------------*/ +int GetCurrentHKL(pHKL self, float fHKL[3]) { - int iTest; - char pError[132]; - float fHard; - - fSet[0] = (float)*gamma; - fSet[1] = (float)om; - fSet[2] = (float)nu; - - /* check omega, gamma and nu */ - iTest = MotorCheckBoundary(self->pOmega,(float)om, &fHard,pError,131); - iTest += checkTheta(self,gamma); - iTest += MotorCheckBoundary(self->pNu,(float)nu, &fHard,pError,131); - if(iTest == 3) /* none of them burns */ - { - return 1; - } - return 0; -} -/*--------------------------------------------------------------------*/ -static int chiVertical(double chi){ - if(ABS(chi - .0) < CHITOLERANCE){ - return 1; - } - if(ABS(chi - 180.0) < CHITOLERANCE){ - return 1; - } - return 0; -} -/*----------------------------------------------------------------------- - tryOmegaTweak tries to calculate a psi angle in order to put an - offending omega back into range. - - This routine also handles the special case when chi ~ 0 or chi ~ 180. - Then it is possible to fix a omega problem by turing in phi. - -----------------------------------------------------------------------*/ -static int tryOmegaTweak(pHKL self, MATRIX z1, double *stt, double *om, - double *chi, double *phi){ - int status; - float fLower, fUpper, omTarget, omOffset, phiSign; - double dumstt, offom, offchi, offphi; - - - status = checkBisecting(self,stt,*om,*chi,*phi); - if(status < 0){ - return 0; /* stt is burning */ - } else if(status == 1){ - return 1; - } - - /* - Is omega really the problem? - */ - omTarget = -9999; - MotorGetPar(self->pOmega,"softlowerlim",&fLower); - MotorGetPar(self->pOmega,"softupperlim",&fUpper); - if(*om < fLower + self->scanTolerance) { - omTarget = fLower + self->scanTolerance; - } - if(*om > fUpper - self->scanTolerance){ - omTarget = fUpper - self->scanTolerance; - } - if(omTarget < -7000){ - return 0; - } - - /* - calculate omega offset - */ - omOffset = *om - omTarget; - omOffset = -omOffset; - - /* - check for the special case of chi == 0 or chi == 180 - */ - if(chiVertical(*chi)){ - dumstt = *stt; - offom = omTarget; - offchi = *chi; - MotorGetPar(self->pPhi,"sign",&phiSign); - offphi = *phi - omOffset*phiSign; - if(checkBisecting(self,&dumstt,offom,offchi,offphi)){ - *om = offom; - *chi = offchi; - *phi = offphi; - return 1; - } - } - - /* - calculate angles with omega offset - */ - status = z1ToAnglesWithOffset(self->fLambda,z1, omOffset, &dumstt, - &offom, &offchi, &offphi); - if(!status){ - return 0; - } - - if(checkBisecting(self,&dumstt,offom,offchi,offphi)){ - *om = offom; - *chi = offchi; - *phi = offphi; - return 1; - } - return 0; -} -/*-----------------------------------------------------------------------*/ -static MATRIX calculateScatteringVector(pHKL self, float fHKL[3]) -{ - MATRIX z1, hkl, ubm; int i; - hkl = mat_creat(3,1,ZERO_MATRIX); - ubm = mat_creat(3,3,ZERO_MATRIX); - for(i = 0; i < 3; i++) - { - hkl[i][0] = fHKL[i]; - ubm[0][i] = self->fUB[i]; - ubm[1][i] = self->fUB[i+3]; - ubm[2][i] = self->fUB[i+6]; - } - z1 = mat_mul(ubm,hkl); - mat_free(ubm); - mat_free(hkl); + assert(self); - return z1; + for (i = 0; i < 3; i++) { + fHKL[i] = self->fLastHKL[i]; + } + return 1; } -/*---------------------------------------------------------------------*/ -static int calculateBisectingOld(MATRIX z1, pHKL self, SConnection *pCon, - float fSet[4], double myPsi, int iRetry) + +/*-------------------------------------------------------------------------*/ +static void invertMatrix(pHKL self, float fUB[9]) { - double stt, om, chi, phi, psi, ompsi, chipsi, phipsi; - int i, test; + int i; + MATRIX m; - /* - just the plain angle calculation - */ - if(!z1mToBisecting(self->fLambda,z1,&stt,&om,&chi,&phi)) - { - return 0; + if (self->UBinv != NULL) { + mat_free(self->UBinv); } - - /* - check if angles in limits. If omega problem: try to tweak - */ - chi = circlify(chi); - phi = circlify(phi); - if(iRetry > 1) - { - if(tryOmegaTweak(self,z1,&stt,&om,&chi,&phi)){ - fSet[0] = (float)stt; - fSet[1] = (float)om; - fSet[2] = (float)circlify(chi); - fSet[3]= (float)circlify(phi); - return 1; - } - } - /* - if this does not work, try rotating through psi in order to - find a useful setting - */ - for(i = 0; i < iRetry; i++) - { - if(iRetry > 1) - { - psi = i*.5; - } - else - { - psi = myPsi; - } - rotatePsi(om,chi,phi,psi,&ompsi,&chipsi,&phipsi); - chipsi = circlify(chipsi); - phipsi = circlify(phipsi); - test = checkBisecting(self,&stt,ompsi,chipsi,phipsi); - if(test == 1) - { - fSet[0] = (float)stt; - fSet[1] = (float)ompsi; - fSet[2] = (float)chipsi; - fSet[3]= (float)phipsi; - return 1; - } + m = mat_creat(3, 3, ZERO_MATRIX); + for (i = 0; i < 3; i++) { + m[0][i] = fUB[i]; + m[1][i] = fUB[3 + i]; + m[2][i] = fUB[6 + i]; } - - /* - giving up! But calculate one more time in order to show Jurg where - he should be. - */ - z1mToBisecting(self->fLambda,z1,&stt,&om,&chi,&phi); - if(iRetry == 1){ - rotatePsi(om,chi,phi,psi,&ompsi,&chipsi,&phipsi); - fSet[0] = (float)stt; - fSet[1] = (float)ompsi; - fSet[2] = (float)chipsi; - fSet[3]= (float)phipsi; - } else { - fSet[0] = (float)stt; - fSet[1] = (float)om; - fSet[2] = (float)chi; - fSet[3]= (float)phi; - } - - return 0; + self->UBinv = mat_inv(m); + mat_free(m); } -/*----------------------------------------------------------------------*/ -int hklInRange(void *data, float fSet[4], int mask[4]) + +/*-------------------------------------------------------------------------*/ +int SetUB(pHKL self, float fUB[9]) { - pHKL self = (pHKL)data; - float fHard, fLimit; - char pError[132]; - int i, test; - double dTheta; + int i; + double dUB[9]; - /* check two theta */ - dTheta = fSet[0]; - mask[0] = checkTheta(self, &dTheta); - fSet[0] = dTheta; + assert(self); - /* for omega check against the limits +- SCANBORDER in order to allow for - a omega scan. - */ - MotorGetPar(self->pOmega,"softlowerlim",&fLimit); - if((float)fSet[1] < fLimit + self->scanTolerance){ - mask[1] = 0; - } else { - mask[1] = 1; - MotorGetPar(self->pOmega,"softupperlim",&fLimit); - if((float)fSet[1] > fLimit - self->scanTolerance){ - mask[1] = 0; - } else { - mask[1] = 1; - } - } - - /* check chi and phi*/ - mask[2] = MotorCheckBoundary(self->pChi,fSet[2], &fHard,pError,131); - mask[3] = MotorCheckBoundary(self->pPhi,fSet[3], &fHard,pError,131); - for(i = 0, test = 0; i < 4; i++){ - test += mask[i]; - } - if(test != 4) { - return 0; - } else { - return 1; - } -} -/*---------------------------------------------------------------------*/ -static int calculateBisecting(MATRIX z1, pHKL self, SConnection *pCon, - float fSet[4], double myPsi, int iRetry) -{ - double stt, om, chi, phi, psi, ompsi, chipsi, phipsi; - int i, test, mask[4]; - - /* - just the plain angle calculation - */ - if(!z1mToBisecting(self->fLambda,z1,&stt,&om,&chi,&phi)) - { - return 0; + for (i = 0; i < 9; i++) { + dUB[i] = fUB[i]; } - - fSet[0] = stt; - fSet[1] = om; - fSet[2] = chi; - fSet[3] = phi; - if(iRetry == 1) { - rotatePsi(om,chi,phi,myPsi,&ompsi,&chipsi,&phipsi); - fSet[1] = ompsi; - fSet[2] = circlify(chipsi); - fSet[3] = circlify(phipsi); - return 1; - } else { - if(hklInRange(self,fSet, mask) == 1){ - return 1; - } else { - if(tryOmegaTweak(self,z1, &stt, &om, &chi, &phi) == 1){ - fSet[0] = stt; - fSet[1] = om; - fSet[2] = chi; - fSet[3] = phi; - return 1; - } else { - return findAllowedBisecting(self->fLambda, z1, fSet, hklInRange,self); - } - } - } -} -/*-----------------------------------------------------------------------*/ -static int calculateNormalBeam(MATRIX z1, pHKL self, SConnection *pCon, - float fSet[4], double myPsi, int iRetry) -{ - int i, iTest, status; - double stt, om, chi, phi, gamma, nu, psi, omnb; - float currentPhi, currentChi; - double ompsi, chipsi, phipsi; - MATRIX chim, phim, z4, z3; + SXSetUB(dUB); + invertMatrix(self, fUB); - /* - The usual condition for normal beam calculations is that both chi - and phi are 0. This is not the case at TRICS. Therefore we have to - multiply the scattering vector first with the chi and phi rotations - before we start. - */ - iTest = MotorGetSoftPosition(self->pChi,pCon,¤tChi); - if(iTest != 1) - { + return 1; +} + +/*-------------------------------------------------------------------------*/ +int GetUB(pHKL self, float fUB[9]) +{ + int i; + const double *dUB; + + dUB = SXGetUB(); + for (i = 0; i < 9; i++) { + fUB[i] = (float) dUB[i]; + } + return 1; +} + +/*--------------------------------------------------------------------------*/ +int SetNOR(pHKL self, int iNOB) +{ + assert(self); + + /* cannot set normal beam geometry if no nu motor */ + if ((iNOB == 1) && (SXGetMotor(Nu) == NULL)) + return 0; + + switch (iNOB) { + case 0: + SXSetMode(Bisecting); + break; + case 1: + SXSetMode(NB); + break; + default: return 0; } - iTest = MotorGetSoftPosition(self->pPhi,pCon,¤tPhi); - if(iTest != 1) - { - return 0; - } - phim = mat_creat(3,3,ZERO_MATRIX); - phimat(phim,(double)currentPhi); - z4 = mat_mul(phim,z1); - chim = mat_creat(3,3,ZERO_MATRIX); - chimat(chim,(double)currentChi); - z3 = mat_mul(chim,z4); - mat_free(phim); - mat_free(chim); - mat_free(z4); - - - status = z1mToNormalBeam(self->fLambda, z3, &gamma, &omnb, &nu); - /* omnb += 180.; */ - mat_free(z3); - if(status != 1) - { - return 0; - } - if(checkNormalBeam(omnb, &gamma, nu,fSet,pCon,self)){ - return 1; - } else { - if(checkNormalBeam(omnb + 360., &gamma, nu, fSet,pCon,self)){ - return 1; - } else { - return 0; - } - } + return 1; } -/*---------------------------------------------------------------------*/ -static int calculateNormalBeamOmega(MATRIX z1, pHKL self, - SConnection *pCon, - float fSet[4], double omOffset) + + /*-----------------------------------------------------------------------*/ +static int checkTheta(pHKL self, double *stt) { + char pError[132]; int iTest; - double stt, om, chi, phi, gamma, nu, psi; - float currentPhi, currentChi; - double ompsi, chipsi, phipsi; - MATRIX chim, phim, z4, z3; + float fHard; + pMotor pTheta; - /* - The usual condition for normal beam calculations is that both chi - and phi are 0. This is not the case at TRICS. Therefore we have to - multiply the scattering vector first with the chi and phi rotations - before we start. - */ - iTest = MotorGetSoftPosition(self->pChi,pCon,¤tChi); - if(iTest != 1) - { + pTheta = SXGetMotor(TwoTheta); + if (pTheta == NULL) { return 0; } - iTest = MotorGetSoftPosition(self->pPhi,pCon,¤tPhi); - if(iTest != 1) - { - return 0; - } - phim = mat_creat(3,3,ZERO_MATRIX); - phimat(phim,(double)currentPhi); - z4 = mat_mul(phim,z1); - chim = mat_creat(3,3,ZERO_MATRIX); - chimat(chim,(double)currentChi); - z3 = mat_mul(chim,z4); - mat_free(phim); - mat_free(chim); - mat_free(z4); - - /* - do the bisecting angles first - */ - if(!z1ToAnglesWithOffset(self->fLambda,z3, omOffset, &stt, - &ompsi, &chi, &phi)) - { - return 0; + iTest = MotorCheckBoundary(pTheta, (float) *stt, &fHard, pError, 131); + if (!iTest) { + return -1; } - - if(ABS(chi -90.) < .001 && ABS(phi-180.) < .001) - { - chi = .0; - phi = .0; - } - - if(bisToNormalBeam(stt,ompsi,chi,phi, - &om, &gamma, &nu)) - { - if(checkNormalBeam(om, &gamma, nu,fSet,pCon,self)) - { - return 1; - } - } - return 0; + return iTest; } + +/*----------------------------------------------------------------------*/ +int hklInRange(void *data, double fSet[4], int mask[4]) +{ + pHKL self = (pHKL) data; + float fHard, fLimit; + char pError[132]; + int i, test; + double dTheta; + pMotor pOmega, pChi, pPhi; + + pOmega = SXGetMotor(Omega); + pChi = SXGetMotor(Chi); + pPhi = SXGetMotor(Phi); + if (pOmega == NULL || pChi == NULL || pPhi == NULL) { + return 0; + } + + /* check two theta */ + dTheta = fSet[0]; + mask[0] = checkTheta(self, &dTheta); + fSet[0] = dTheta; + + /* for omega check against the limits +- SCANBORDER in order to allow for + a omega scan. + */ + MotorGetPar(pOmega, "softlowerlim", &fLimit); + if ((float) fSet[1] < fLimit + self->scanTolerance) { + mask[1] = 1; + } else { + mask[1] = 0; + MotorGetPar(pOmega, "softupperlim", &fLimit); + if ((float) fSet[1] > fLimit - self->scanTolerance) { + mask[1] = 0; + } else { + mask[1] = 1; + } + } + + /* check chi and phi */ + mask[2] = MotorCheckBoundary(pChi, fSet[2], &fHard, pError, 131); + mask[3] = MotorCheckBoundary(pPhi, fSet[3], &fHard, pError, 131); + for (i = 0, test = 0; i < 4; i++) { + test += mask[i]; + } + if (test != 4) { + return 0; + } else { + return 1; + } +} + /*------------------------------------------------------------------------- calculates the four circle settings. If the position can not be reached because of a limit violation, then psi is rotated in 10 degree steps @@ -883,918 +393,648 @@ static int calculateNormalBeamOmega(MATRIX z1, pHKL self, violation we first try to calculate a delta omega which puts omega into the right range. This is a fix because the omega movement is quite often restricted due to the cryogenic garbage around the sample. -*/ - int CalculateSettings(pHKL self, float fHKL[3], float fPsi, int iHamil, - float fSet[4], SConnection *pCon) - { - char pError[132]; - char pBueffel[512]; - float fHard, fVal, fUpper, fLower; - double myPsi = fPsi; - MATRIX z1; - double stt, om, chi, phi, ompsi, chipsi, phipsi; - int i,iRetry, status; - - /* catch shitty input */ - if( (fHKL[0] == 0.) && (fHKL[1] == 0.) && (fHKL[2] == 0.)) - { - SCWrite(pCon,"ERROR: I will not calculate angles for HKL = (0,0,0) ", - eError); - return 0; - } - - /* some people are stupid.......... */ - myPsi = circlify(fPsi); - - /* - no retries if specific psi requested. - */ - if((myPsi > 0.1) ) - { - iRetry = 1; - } - else - { - iRetry = 699; - } - - - z1 = calculateScatteringVector(self,fHKL); - - if(self->iNOR == 0) - { - status = calculateBisecting(z1,self,pCon,fSet, myPsi, iRetry); - } - else if(self->iNOR == 1) - { - status = calculateNormalBeam(z1,self,pCon,fSet, myPsi, iRetry); - } - else - { - myPsi = fPsi; - status = calculateNormalBeamOmega(z1,self,pCon,fSet, myPsi); - } - - - if(!status) - { - if(iRetry == 1) - { - sprintf(pBueffel, - "ERROR: cannot calculate %4.1f %4.1f %4.1f, psi = %4.1f", - fHKL[0], fHKL[1], fHKL[2], fPsi); - SCWrite(pCon,pBueffel,eError); - } - else - { - sprintf(pBueffel,"ERROR: cannot calculate %4.1f %4.1f %4.1f", - fHKL[0], fHKL[1], fHKL[2]); - SCWrite(pCon,pBueffel,eError); - } - } - mat_free(z1); - - return status; - - return 0; - } -/*------------------------------------------------------------------------*/ -static void stopHKLMotors(pHKL self) +-------------------------------------------------------------------------*/ +int CalculateSettings(pHKL self, float fHKL[3], float fPsi, int iHamil, + float fSet[5], SConnection * pCon) { - if(self->pTheta != NULL) - { - self->pTheta->pDrivInt->Halt(self->pTheta); + char pBueffel[512]; + double myPsi = fPsi; + int i, status; + pSingleDiff single = NULL; + double dHkl[4], dSet[5]; + + /* catch shitty input */ + if ((fHKL[0] == 0.) && (fHKL[1] == 0.) && (fHKL[2] == 0.)) { + SCWrite(pCon, "ERROR: I will not calculate angles for HKL = (0,0,0) ", + eError); + return 0; } - if(self->pOmega != NULL) - { - self->pOmega->pDrivInt->Halt(self->pOmega); + + /* some people are stupid.......... */ + myPsi = circlify(fPsi); + + single = SXGetDiffractometer(); + assert(single != NULL); + + for (i = 0; i < 3; i++) { + dHkl[i] = fHKL[i]; } - if(self->pChi != NULL) - { - self->pChi->pDrivInt->Halt(self->pChi); + dHkl[3] = myPsi; + + status = single->calculateSettings(single, dHkl, dSet); + for (i = 0; i < 5; i++) { + fSet[i] = dSet[i]; } - if(self->pPhi != NULL) - { - self->pPhi->pDrivInt->Halt(self->pPhi); - } - if(self->pNu != NULL) - { - self->pNu->pDrivInt->Halt(self->pNu); + + if (!status) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: cannot calculate %4.1f %4.1f %4.1f, psi = %4.1f", + fHKL[0], fHKL[1], fHKL[2], dHkl[3]); + SCWrite(pCon, pBueffel, eError); } + return status; } + /*------------------------------------------------------------------------*/ -int startHKLMotors(pHKL self, SConnection *pCon, float fSet[4]) +void stopHKLMotors(pHKL self) { - char pBueffel[512]; - pDummy pDum; - int iRet; + pSingleDiff single = NULL; - /* start all the motors */ - pDum = (pDummy)self->pTheta; - iRet = StartDevice(pServ->pExecutor, "HKL", - pDum->pDescriptor, pDum, pCon,fSet[0]); - if(!iRet) - { - SCWrite(pCon,"ERROR: cannot start two theta motor",eError); - stopHKLMotors(self); - return 0; - } - - pDum = (pDummy)self->pOmega; - iRet = StartDevice(pServ->pExecutor, "HKL", - pDum->pDescriptor, pDum, pCon,fSet[1]); - if(!iRet) - { - SCWrite(pCon,"ERROR: cannot start omega motor",eError); - stopHKLMotors(self); - return 0; - } - - /* special case: normal beam */ - if(self->iNOR) - { - pDum = (pDummy)self->pNu; - iRet = StartDevice(pServ->pExecutor, "HKL", - pDum->pDescriptor, pDum, pCon,fSet[2]); - if(!iRet) - { - SCWrite(pCon,"ERROR: cannot start nu motor",eError); - return 0; - } - return 1; - } - - pDum = (pDummy)self->pChi; - iRet = StartDevice(pServ->pExecutor, "HKL", - pDum->pDescriptor, pDum, pCon,fSet[2]); - if(!iRet) - { - SCWrite(pCon,"ERROR: cannot start chi motor",eError); - stopHKLMotors(self); - return 0; - } - pDum = (pDummy)self->pPhi; - iRet = StartDevice(pServ->pExecutor, "HKL", - pDum->pDescriptor, pDum, pCon,fSet[3]); - if(!iRet) - { - SCWrite(pCon,"ERROR: cannot start phi",eError); - stopHKLMotors(self); - return 0; - } - return 1; + single = SXGetDiffractometer(); + assert(single != NULL); + self->pMotList->Halt(&single->motList); } + +/*------------------------------------------------------------------------*/ +int startHKLMotors(pHKL self, SConnection * pCon, float fSet[5]) +{ + char pBueffel[512]; + pSingleDiff single = NULL; + double dSet[5]; + int i, status; + + single = SXGetDiffractometer(); + assert(single != NULL); + + for (i = 0; i < 5; i++) { + dSet[i] = fSet[i]; + } + single->settingsToList(single, dSet); + +/* status = self->pMotDriv->SetValue(&single->motList, pCon, .1); */ + status = StartDevice(pServ->pExecutor, "HKL", self->pDes, self, pCon,RUNDRIVE, .1); + + return status; +} + /*-------------------------------------------------------------------------*/ - int RunHKL(pHKL self, float fHKL[3], - float fPsi, int iHamil, SConnection *pCon) - { - float fSet[4]; - int iRet,i; - char pBueffel[512]; - pDummy pDum; +int RunHKL(pHKL self, float fHKL[3], + float fPsi, int iHamil, SConnection * pCon) +{ + float fSet[5]; + int iRet, i; + char pBueffel[512]; + pDummy pDum; - assert(self); - iRet = CalculateSettings(self,fHKL,fPsi,iHamil,fSet,pCon); - if(!iRet) - { - SCWrite(pCon,"ERROR: NOT started",eError); - return 0; - } + assert(self); + iRet = CalculateSettings(self, fHKL, fPsi, iHamil, fSet, pCon); + if (!iRet) { + SCWrite(pCon, "ERROR: NOT started", eError); + return 0; + } - iRet = startHKLMotors(self,pCon,fSet); - if(iRet != 1){ - return iRet; - } + iRet = startHKLMotors(self, pCon, fSet); + if (iRet != 1) { + return iRet; + } + + for (i = 0; i < 3; i++) { + self->fLastHKL[i] = fHKL[i]; + } + return 1; + +} - for(i = 0; i < 3; i++) - { - self->fLastHKL[i] = fHKL[i]; - } - return 1; - - } /*-------------------------------------------------------------------------*/ - int DriveSettings(pHKL self, float fSet[4], SConnection *pCon) - { - int iRet,i, iReturn; - char pBueffel[512]; - pDummy pDum; +int DriveSettings(pHKL self, float fSet[5], SConnection * pCon) +{ + int iRet; - iReturn = 1; + iRet = startHKLMotors(self, pCon, fSet); + if (iRet != 1) { + stopHKLMotors(self); + } - /* start all the motors */ - pDum = (pDummy)self->pTheta; - iRet = StartDevice(pServ->pExecutor, "HKL", - pDum->pDescriptor, pDum, pCon,fSet[0]); - if(!iRet) - { - SCWrite(pCon,"ERROR: cannot start two theta motor",eError); - StopExe(pServ->pExecutor,"all"); - iReturn = 0; - goto ente; - } - - pDum = (pDummy)self->pOmega; - iRet = StartDevice(pServ->pExecutor, "HKL", - pDum->pDescriptor, pDum, pCon,fSet[1]); - if(!iRet) - { - SCWrite(pCon,"ERROR: cannot start omega motor",eError); - StopExe(pServ->pExecutor,"all"); - iReturn = 0; - goto ente; - } + /* wait for end */ + iRet = Wait4Success(pServ->pExecutor); + switch (iRet) { + case DEVINT: + if (SCGetInterrupt(pCon) == eAbortOperation) { + SCSetInterrupt(pCon, eContinue); + SCWrite(pCon, "Driving to HKL Aborted", eLogError); + } + return 0; + break; + case DEVDONE: + SCWrite(pCon, "Driving to Reflection done", eValue); + break; + default: + SCWrite(pCon, "WARNING: driving to HKL finished with problems", + eWarning); + if (SCGetInterrupt(pCon) != eContinue) { + return 0; + } + break; + } + return iRet; +} - /* special case: normal beam */ - if(self->iNOR) - { - pDum = (pDummy)self->pNu; - iRet = StartDevice(pServ->pExecutor, "HKL", - pDum->pDescriptor, pDum, pCon,fSet[2]); - if(!iRet) - { - SCWrite(pCon,"ERROR: cannot start nu motor",eError); - StopExe(pServ->pExecutor,"all"); - iReturn = 0; - } - goto ente; - } - - pDum = (pDummy)self->pChi; - iRet = StartDevice(pServ->pExecutor, "HKL", - pDum->pDescriptor, pDum, pCon,fSet[2]); - if(!iRet) - { - SCWrite(pCon,"ERROR: cannot start chi motor",eError); - StopExe(pServ->pExecutor,"all"); - iReturn = 0; - goto ente; - } - pDum = (pDummy)self->pPhi; - iRet = StartDevice(pServ->pExecutor, "HKL", - pDum->pDescriptor, pDum, pCon,fSet[3]); - if(!iRet) - { - StopExe(pServ->pExecutor,"all"); - iReturn = 0; - SCWrite(pCon,"ERROR: cannot start phi",eError); - } - -ente: - /* wait for end */ - iRet = Wait4Success(pServ->pExecutor); - switch(iRet) - { - case DEVINT: - if(SCGetInterrupt(pCon) == eAbortOperation) - { - SCSetInterrupt(pCon,eContinue); - SCWrite(pCon,"Driving to HKL Aborted",eStatus); - } - return 0; - break; - case DEVDONE: - SCWrite(pCon,"Driving to Reflection done",eStatus); - break; - default: - SCWrite(pCon,"WARNING: driving to HKL finished with problems", - eWarning); - if(SCGetInterrupt(pCon) != eContinue) - { - return 0; - } - break; - } - return iReturn; - } /*--------------------------------------------------------------------------*/ - int DriveHKL(pHKL self, float fHKL[3], - float fPsi, int iHamil, SConnection *pCon) - { - int iRet, iReturn; - long lID; - char pBueffel[132]; - - assert(self); - - /* start running */ - iReturn = 1; - iRet = RunHKL(self,fHKL,fPsi,iHamil,pCon); - if(!iRet) - { - StopExe(pServ->pExecutor,"all"); - iReturn = 0; - } +int DriveHKL(pHKL self, float fHKL[3], + float fPsi, int iHamil, SConnection * pCon) +{ + int iRet, iReturn; + long lID; + char pBueffel[132]; - /* wait for end */ - iRet = Wait4Success(pServ->pExecutor); - switch(iRet) - { - case DEVINT: - if(SCGetInterrupt(pCon) == eAbortOperation) - { - SCSetInterrupt(pCon,eContinue); - SCWrite(pCon,"Driving to HKL Aborted",eStatus); - } - return 0; - break; - case DEVDONE: - if(fPsi > .01) - { - snprintf(pBueffel,131, - "Driving to %8.4f %8.4f %8.4f, psi = %8.4f done", - fHKL[0], fHKL[1], fHKL[2],fPsi); - } - else - { - snprintf(pBueffel,131,"Driving to %8.4f %8.4f %8.4f done", - fHKL[0], fHKL[1], fHKL[2]); - } - SCWrite(pCon,pBueffel,eStatus); - break; - default: - SCWrite(pCon,"WARNING: driving to HKL finished with problems", - eWarning); - if(SCGetInterrupt(pCon) != eContinue) - { - return 0; - } - break; - } - return iReturn; - } -/*-----------------------------------------------------------------------*/ - int GetCurrentPosition(pHKL self, SConnection *pCon, float fPos[4]) - { - float fVal; - int iRet, iResult; + assert(self); - assert(self); - assert(pCon); - - iResult = 1; - iRet = MotorGetSoftPosition(self->pTheta,pCon, &fVal); - if(iRet == 1) - { - fPos[0] = fVal; - } - else - { - iResult = 0; - } - iRet = MotorGetSoftPosition(self->pOmega,pCon, &fVal); - if(iRet == 1) - { - fPos[1] = fVal; - } - else - { - iResult = 0; - } - - /* normal beam geometry */ - if(self->iNOR == 1) - { - iRet = MotorGetSoftPosition(self->pNu,pCon, &fVal); - if(iRet == 1) - { - fPos[2] = fVal; - } - else - { - iResult = 0; - } - return iResult; - } - - /* bissecting geometry */ - iRet = MotorGetSoftPosition(self->pChi,pCon, &fVal); - if(iRet == 1) - { - fPos[2] = fVal; - } - else - { - iResult = 0; - } - iRet = MotorGetSoftPosition(self->pPhi,pCon, &fVal); - if(iRet == 1) - { - fPos[3] = fVal; - } - else - { - iResult = 0; - } - - return iResult; + /* start running */ + iReturn = 1; + iRet = RunHKL(self, fHKL, fPsi, iHamil, pCon); + if (!iRet) { + StopExe(pServ->pExecutor, "all"); + iReturn = 0; } + + /* wait for end */ + iRet = Wait4Success(pServ->pExecutor); + switch (iRet) { + case DEVINT: + if (SCGetInterrupt(pCon) == eAbortOperation) { + SCSetInterrupt(pCon, eContinue); + SCWrite(pCon, "Driving to HKL Aborted", eError); + } + return 0; + break; + case DEVDONE: + if (fPsi > .01) { + snprintf(pBueffel, 131, + "Driving to %8.4f %8.4f %8.4f, psi = %8.4f done", + fHKL[0], fHKL[1], fHKL[2], fPsi); + } else { + snprintf(pBueffel, 131, "Driving to %8.4f %8.4f %8.4f done", + fHKL[0], fHKL[1], fHKL[2]); + } + SCWrite(pCon, pBueffel, eValue); + break; + default: + SCWrite(pCon, "WARNING: driving to HKL finished with problems", + eWarning); + if (SCGetInterrupt(pCon) != eContinue) { + return 0; + } + break; + } + return iReturn; +} + /*------------------------------------------------------------------------- For the conversion from angles to HKL. -------------------------------------------------------------------------*/ - static int angle2HKL(pHKL self ,double tth, double om, - double chi, double phi, float fHKL[3]) - { - MATRIX rez, z1m; - double z1[3]; - int i; +int GetHKLFromAngles(pHKL self, SConnection * pCon, float fHKL[3]) +{ + pSingleDiff single = NULL; + double dHkl[3]; + int i, status; - if(self->UBinv == NULL){ - return 0; - } - z1FromAngles(self->fLambda,tth,om,chi,phi,z1); - z1m = vectorToMatrix(z1); - /* multiply with UBinv in order to yield HKL */ - rez = mat_mul(self->UBinv,z1m); - for(i = 0; i < 3; i++) - { - fHKL[i] = (float)rez[i][0]; - } - mat_free(z1m); - mat_free(rez); - - return 1; + single = SXGetDiffractometer(); + assert(single != NULL); + + status = single->hklFromAngles(single, dHkl); + for (i = 0; i < 3; i++) { + fHKL[i] = dHkl[i]; } -/*---------------------------------------------------------------------------*/ - int GetHKLFromAngles(pHKL self, SConnection *pCon, float fHKL[3]) - { - int status; - float fAng[4]; - - status = GetCurrentPosition(self,pCon,fAng); - if(status == 1) - { - angle2HKL(self,fAng[0], fAng[1], fAng[2], fAng[3],fHKL); - return 1; - } + return status; +} + +/*--------------------------------------------------------------------------*/ +static int GetCommandData(int argc, char *argv[], float fHKL[3], + float *fPsi, int *iHamil, SConnection * pCon) +{ + int iRet, i; + double d; + char pBueffel[512]; + + if (argc < 3) { + SCWrite(pCon, + "ERROR: Insufficient reflection data specified for calculation", + eError); return 0; } -/*--------------------------------------------------------------------------*/ - static int GetCommandData(int argc, char *argv[], float fHKL[3], - float *fPsi, int *iHamil, SConnection *pCon) - { - int iRet, i; - double d; - char pBueffel[512]; - - if(argc < 3) - { - SCWrite(pCon, - "ERROR: Insufficient reflection data specified for calculation", - eError); - return 0; - } - /* get the reflection */ - for(i = 0; i < 3; i++) - { - if(!isNumeric(argv[i])) - { - sprintf(pBueffel,"ERROR: %s is NOT recognized as a number",argv[i]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - fHKL[i] = atof(argv[i]); - } - - *fPsi = 0.; - *iHamil = 0; - - /* has psi been specicifed ? */ - if(argc > 3) - { - if(!isNumeric(argv[3])) - { - sprintf(pBueffel,"ERROR: %s is NOT recognized as a number",argv[3]); - SCWrite(pCon,pBueffel,eError); - } - *fPsi = atof(argv[3]); - } - - /* has iHamil been specified ? */ - if(argc > 4) - { - if(!isNumeric(argv[4])) - { - sprintf(pBueffel,"ERROR: %s is NOT recognized as a number",argv[4]); - SCWrite(pCon,pBueffel,eError); - } - *iHamil = atof(argv[4]); - } - return 1; + /* get the reflection */ + for (i = 0; i < 3; i++) { + if (!isNumeric(argv[i])) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s is NOT recognized as a number", + argv[i]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + fHKL[i] = atof(argv[i]); } + + *fPsi = 0.; + *iHamil = 0; + + /* has psi been specicifed ? */ + if (argc > 3) { + if (!isNumeric(argv[3])) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s is NOT recognized as a number", + argv[3]); + SCWrite(pCon, pBueffel, eError); + } + *fPsi = atof(argv[3]); + } + + /* has iHamil been specified ? */ + if (argc > 4) { + if (!isNumeric(argv[4])) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s is NOT recognized as a number", + argv[4]); + SCWrite(pCon, pBueffel, eError); + } + *iHamil = atof(argv[4]); + } + return 1; +} + /*--------------------------------------------------------------------------*/ - int HKLAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - int iRet,i, iHamil; - char pBueffel[512]; - float fUB[9], fPsi, fVal; - float fHKL[3], fSet[4]; - double dVal; - pHKL self = NULL; - CommandList *pCom = NULL; - pDummy pDum = NULL; - - assert(pCon); - assert(pSics); - - self = (pHKL)pData; - assert(self); - - /* enough arguments ? */ - if(argc < 2) - { - SCWrite(pCon,"Insufficient number of arguments to HKL",eError); - return 0; - } - +static int HKLCalculateTheta(pHKL self, float fHKL[3], double *stt) +{ + int status, i; + MATRIX B, HC, H; + double theta, d; + const double *cell; + reflection r; + lattice direct; + + B = mat_creat(3, 3, UNIT_MATRIX); + H = mat_creat(3, 1, ZERO_MATRIX); + if (B == NULL) { + return UBNOMEMORY; + } + 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) { + return status; + } + for (i = 0; i < 3; i++) { + H[i][0] = fHKL[i]; + } + HC = mat_mul(B, H); + status = calcTheta(SXGetLambda(), HC, &d, &theta); + mat_free(HC); + mat_free(B); + mat_free(H); + *stt = 2. * theta; + return status; +} +/*--------------------------------------------------------------------------*/ +static int HandleBiToNB(SConnection *pCon, int argc, char *argv[]) +{ + double stt, om, chi, phi, gamma, omnb, nu; + int status; + + if(argc < 6){ + SCWrite(pCon,"ERROR: missing arguments, usage: hkl bitonb stt om chi phi", eError); + return 0; + } + status = Tcl_GetDouble(InterpGetTcl(pServ->pSics),argv[2], &stt); + if(status != 0){ + SCPrintf(pCon,eError,"ERROR: failed to convert %s to double", argv[2]); + return 0; + } + status = Tcl_GetDouble(InterpGetTcl(pServ->pSics),argv[3], &om); + if(status != 0){ + SCPrintf(pCon,eError,"ERROR: failed to convert %s to double", argv[3]); + return 0; + } + status = Tcl_GetDouble(InterpGetTcl(pServ->pSics),argv[4], &chi); + if(status != 0){ + SCPrintf(pCon,eError,"ERROR: failed to convert %s to double", argv[4]); + return 0; + } + status = Tcl_GetDouble(InterpGetTcl(pServ->pSics),argv[5], &phi); + if(status != 0){ + SCPrintf(pCon,eError,"ERROR: failed to convert %s to double", argv[5]); + return 0; + } + status = bisToNormalBeam(stt,om,chi,phi,&omnb, &gamma, &nu); + if(status != 1){ + SCWrite(pCon,"ERROR: not in range for normal beam", eError); + return 0; + } + SCPrintf(pCon,eValue, "NB = %f,%f,%f", gamma, omnb, nu); + return 1; +} +/*--------------------------------------------------------------------------*/ +int HKLAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + int iRet, i, iHamil; + char pBueffel[512]; + float fUB[9], fPsi, fVal; + float fHKL[3], fSet[5]; + double dHKL[3], dSet[5]; + double dVal, lambda, stt; + const double *dUB; + pHKL self = NULL; + CommandList *pCom = NULL; + pDummy pDum = NULL; + pSingleDiff single = NULL; + int mode, nargs; + + assert(pCon); + assert(pSics); + + self = (pHKL) pData; + assert(self); + + single = SXGetDiffractometer(); + + /* enough arguments ? */ + if (argc < 2) { + SCWrite(pCon, "Insufficient number of arguments to HKL", eError); + return 0; + } + /*-------- handle list */ - strtolower(argv[1]); - if(strcmp(argv[1],"list") == 0 ) - { - sprintf(pBueffel, - "lambda = %f Normal Beam = %d Quadrant = %d HM = %d", - self->fLambda, self->iNOR, - self->iQuad,self->iHM); - SCWrite(pCon,pBueffel,eValue); - sprintf(pBueffel,"UB = { %f %f %f", - self->fUB[0], self->fUB[1],self->fUB[2]); - SCWrite(pCon,pBueffel,eValue); - sprintf(pBueffel," %f %f %f", - self->fUB[3], self->fUB[4],self->fUB[5]); - SCWrite(pCon,pBueffel,eValue); - sprintf(pBueffel," %f %f %f }", - self->fUB[6], self->fUB[7],self->fUB[8]); - SCWrite(pCon,pBueffel,eValue); - return 1; - sprintf(pBueffel,"Last HKL: %f %f %f ", - self->fLastHKL[0], self->fLastHKL[1],self->fLastHKL[2]); - SCWrite(pCon,pBueffel,eValue); - snprintf(pBueffel,510,"%s.scantolerance = %f", argv[0], - self->scanTolerance); - SCWrite(pCon,pBueffel,eValue); - return 1; - } -/*----------- current */ - else if(strcmp(argv[1],"current") == 0) - { - if(self->iNOR) - { - sprintf(pBueffel,"Last HKL: %8.4f %8.4f %8.4f ", - self->fLastHKL[0], self->fLastHKL[1],self->fLastHKL[2]); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - else - { - /* do a serious calculation based on angles */ - iRet = GetCurrentPosition(self,pCon,fSet); - if(iRet == 0) - { - return 0; - } - angle2HKL(self,(double)fSet[0],(double)fSet[1], - (double)fSet[2],(double)fSet[3],fHKL); - sprintf(pBueffel,"Current HKL: %8.4f %8.4f %8.4f ", - fHKL[0], fHKL[1],fHKL[2]); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - } - else if(strcmp(argv[1],"fromangles") == 0) - { - if(argc < 6) - { - SCWrite(pCon, + strtolower(argv[1]); + if (strcmp(argv[1], "list") == 0) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "lambda = %f Normal Beam = %d Quadrant = %d HM = %d", + SXGetLambda(), self->iNOR, self->iQuad, self->iHM); + SCWrite(pCon, pBueffel, eValue); + dUB = SXGetUB(); + snprintf(pBueffel,sizeof(pBueffel)-1, "UB = { %f %f %f", dUB[0], dUB[1], dUB[2]); + SCWrite(pCon, pBueffel, eValue); + snprintf(pBueffel,sizeof(pBueffel)-1, " %f %f %f", dUB[3], dUB[4], dUB[5]); + SCWrite(pCon, pBueffel, eValue); + snprintf(pBueffel,sizeof(pBueffel)-1, " %f %f %f }", dUB[6], dUB[7], dUB[8]); + SCWrite(pCon, pBueffel, eValue); + return 1; + snprintf(pBueffel,sizeof(pBueffel)-1, "Last HKL: %f %f %f ", + self->fLastHKL[0], self->fLastHKL[1], self->fLastHKL[2]); + SCWrite(pCon, pBueffel, eValue); + snprintf(pBueffel, 510, "%s.scantolerance = %f", argv[0], + self->scanTolerance); + SCWrite(pCon, pBueffel, eValue); + return 1; + } +/*----------- current */ + else if (strcmp(argv[1], "current") == 0) { + GetHKLFromAngles(self, pCon, fHKL); + snprintf(pBueffel,sizeof(pBueffel)-1, "Current HKL: %8.4f %8.4f %8.4f ", + fHKL[0], fHKL[1], fHKL[2]); + SCWrite(pCon, pBueffel, eValue); + return 1; + } else if (strcmp(argv[1], "fromangles") == 0) { + mode = SXGetMode(); + if(mode == BiNB) { + nargs = 7; + } else { + nargs = 6; + } + if (argc < nargs) { + SCWrite(pCon, "ERROR: need stt, om, chi,phi to calculate HKL from angles", - eError); - return 0; - } - for(i = 0; i < 4; i++) - { - iRet = Tcl_GetDouble(InterpGetTcl(pSics),argv[i+2],&dVal); - if(iRet != TCL_OK) - { - snprintf(pBueffel,511,"ERROR: failed to convert %s to number", - argv[i+2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - fSet[i] = (float)dVal; - } - angle2HKL(self,(double)fSet[0],(double)fSet[1], - (double)fSet[2],(double)fSet[3],fHKL); - sprintf(pBueffel,"HKL from angles: %8.4f %8.4f %8.4f ", - fHKL[0], fHKL[1],fHKL[2]); - SCWrite(pCon,pBueffel,eValue); - return 1; - } + eError); + return 0; + } + for (i = 0; i < nargs-2; i++) { + iRet = Tcl_GetDouble(InterpGetTcl(pSics), argv[i + 2], &dVal); + if (iRet != TCL_OK) { + snprintf(pBueffel, 511, "ERROR: failed to convert %s to number", + argv[i + 2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + dSet[i] = dVal; + } + single->hklFromAnglesGiven(single, dSet, dHKL); + for (i = 0; i < 3; i++) { + fHKL[i] = dHKL[i]; + } + snprintf(pBueffel,sizeof(pBueffel)-1, "HKL from angles: %8.4f %8.4f %8.4f ", + fHKL[0], fHKL[1], fHKL[2]); + SCWrite(pCon, pBueffel, eValue); + return 1; + } /*------------- lambda */ - else if(strcmp(argv[1],"lambda") == 0) - { - if(argc < 3) - { - snprintf(pBueffel,132,"%s.lambda = %f", argv[0],self->fLambda); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - if(!SCMatchRights(pCon,usUser)) - { - return 0; - } - if(!isNumeric(argv[2])) - { - sprintf(pBueffel,"ERROR: %s was not recognized as a number", argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - fVal = atof(argv[2]); - iRet = SetWavelengthManual(self,fVal); - if(!iRet) - { - SCWrite(pCon,"ERROR: cannot set wavelength",eError); - return 0; - } - SCSendOK(pCon); - return 1; - } + else if (strcmp(argv[1], "lambda") == 0) { + lambda = SXGetLambda(); + snprintf(pBueffel, 132, "%s.lambda = %f", argv[0], lambda); + SCWrite(pCon, pBueffel, eValue); + } /*------------- getub*/ - else if(strcmp(argv[1],"getub") == 0) - { - snprintf(pBueffel,510,"%s.ub = %f %f %f %f %f %f %f %f %f", - argv[0], self->fUB[0], self->fUB[1], self->fUB[2], - self->fUB[3], self->fUB[4], self->fUB[5], - self->fUB[6], self->fUB[7], self->fUB[8]); - SCWrite(pCon,pBueffel,eValue); - return 1; - } -/*------- lambdavar*/ - else if(strcmp(argv[1],"lambdavar") == 0) - { - if(argc < 3) - { - SCWrite(pCon,"ERROR: Insufficient number of arguments to HKL lambdavar",eError); - return 0; - } - if(!SCMatchRights(pCon,usUser)) - { - return 0; - } - pCom = FindCommand(pSics,argv[2]); - if(!pCom) - { - sprintf(pBueffel,"ERROR: cannot find variable --> %s <--",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - pDum = (pDummy)pCom->pData; - if(!pDum) - { - sprintf(pBueffel,"ERROR: cannot find variable --> %s <--",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - if(strcmp(pDum->pDescriptor->name,"SicsSelVar") != 0) - { - sprintf(pBueffel,"ERROR: variable --> %s <-- has nothing to do with wavelength",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - iRet = SetWavelengthVariable(pCon,self,(pSelVar)pDum); - if(!iRet) - { - SCWrite(pCon,"ERROR: cannot set wavelength variable",eError); - return 0; - } - SCSendOK(pCon); - return 1; - } + else if (strcmp(argv[1], "getub") == 0) { + dUB = SXGetUB(); + snprintf(pBueffel, 510, "%s.ub = %f %f %f %f %f %f %f %f %f", + argv[0], dUB[0], dUB[1], dUB[2], + dUB[3], dUB[4], dUB[5], dUB[6], dUB[7], dUB[8]); + SCWrite(pCon, pBueffel, eValue); + return 1; + } /*------------ UB */ - else if(strcmp(argv[1],"setub") == 0) - { - if(argc < 11) - { - SCWrite(pCon,"ERROR: Insufficient number of arguments to HKL setUB",eError); - return 0; - } - if(!SCMatchRights(pCon,usUser)) - { - return 0; - } - for(i = 2; i < 11; i++) - { - if(!isNumeric(argv[i])) - { - sprintf(pBueffel,"ERROR: %s was not recognized as a number", argv[i]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - fUB[i-2] = atof(argv[i]); - } - iRet = SetUB(self,fUB); - if(!iRet) - { - SCWrite(pCon,"ERROR: cannot set UB Matrix",eError); - return 0; - } - SCSendOK(pCon); - return 1; - } + else if (strcmp(argv[1], "setub") == 0) { + if (argc < 11) { + SCWrite(pCon, "ERROR: Insufficient number of arguments to HKL setUB", + eError); + return 0; + } + if (!SCMatchRights(pCon, usUser)) { + return 0; + } + for (i = 2; i < 11; i++) { + if (!isNumeric(argv[i])) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s was not recognized as a number", + argv[i]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + fUB[i - 2] = atof(argv[i]); + } + iRet = SetUB(self, fUB); + if (!iRet) { + SCWrite(pCon, "ERROR: cannot set UB Matrix", eError); + return 0; + } + SCSendOK(pCon); + return 1; + } /*------------- HM mode */ - else if(strcmp(argv[1],"hm") == 0) - { - if(argc < 3) - { - sprintf(pBueffel,"%s.hm = %d", argv[0],self->iHM); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - if(!SCMatchRights(pCon,usUser)) - { - return 0; - } - if(!isNumeric(argv[2])) - { - sprintf(pBueffel,"ERROR: %s was not recognized as a number", argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - self->iHM = atoi(argv[2]); - SCSendOK(pCon); - return 1; - } + else if (strcmp(argv[1], "hm") == 0) { + if (argc < 3) { + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.hm = %d", argv[0], self->iHM); + SCWrite(pCon, pBueffel, eValue); + return 1; + } + if (!SCMatchRights(pCon, usUser)) { + return 0; + } + if (!isNumeric(argv[2])) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s was not recognized as a number", + argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + self->iHM = atoi(argv[2]); + SCSendOK(pCon); + return 1; + } /*------------- normal beam */ - else if(strcmp(argv[1],"nb") == 0) - { - if(argc < 3) - { - snprintf(pBueffel,511,"%s.nb = %d",argv[0],self->iNOR); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - if(!SCMatchRights(pCon,usUser)) - { - return 0; - } - if(!isNumeric(argv[2])) - { - sprintf(pBueffel,"ERROR: %s was not recognized as a number", argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - iRet = SetNOR(self,atoi(argv[2])); - if(!iRet) - { - SCWrite(pCon, - "ERROR: cannot set Normal Beam geometry, probably nu motor undefined", - eError); - return 0; - } - SCSendOK(pCon); - return 1; - } + else if (strcmp(argv[1], "nb") == 0) { + if (argc < 3) { + snprintf(pBueffel, 511, "%s.nb = %d", argv[0], self->iNOR); + SCWrite(pCon, pBueffel, eValue); + return 1; + } + if (!SCMatchRights(pCon, usUser)) { + return 0; + } + if (!isNumeric(argv[2])) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s was not recognized as a number", + argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + iRet = SetNOR(self, atoi(argv[2])); + if (!iRet) { + SCWrite(pCon, + "ERROR: cannot set Normal Beam geometry, probably nu motor undefined", + eError); + return 0; + } + SCSendOK(pCon); + return 1; + } /*------------- quadrant */ - else if(strcmp(argv[1],"quadrant") == 0) - { - if(argc < 3) - { - SCWrite(pCon,"ERROR: Insufficient number of arguments to HKL quadrant",eError); - return 0; - } - if(!SCMatchRights(pCon,usUser)) - { - return 0; - } - if(!isNumeric(argv[2])) - { - sprintf(pBueffel,"ERROR: %s was not recognized as a number", argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - iRet = atoi(argv[2]); - if(!( (iRet == 1) || (iRet == 0)) ) - { - sprintf(pBueffel,"ERROR: Invalid parameter %d for quadrant, posiible: 0,1", - iRet); - SCWrite(pCon,pBueffel,eError); - return 0; - } - self->iQuad = iRet; - SCSendOK(pCon); - return 1; - } + else if (strcmp(argv[1], "quadrant") == 0) { + if (argc < 3) { + SCWrite(pCon, + "ERROR: Insufficient number of arguments to HKL quadrant", + eError); + return 0; + } + if (!SCMatchRights(pCon, usUser)) { + return 0; + } + if (!isNumeric(argv[2])) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s was not recognized as a number", + argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + iRet = atoi(argv[2]); + if (!((iRet == 1) || (iRet == 0))) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: Invalid parameter %d for quadrant, posiible: 0,1", + iRet); + SCWrite(pCon, pBueffel, eError); + return 0; + } + self->iQuad = iRet; + SCSendOK(pCon); + return 1; + } /*------------- scantolerance */ - else if(strcmp(argv[1],"scantolerance") == 0) - { - if(argc < 3) - { - snprintf(pBueffel,510,"%s.scantolerance = %f",argv[0], - self->scanTolerance); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - if(!SCMatchRights(pCon,usUser)) - { - return 0; - } - if(!isNumeric(argv[2])) - { - sprintf(pBueffel,"ERROR: %s was not recognized as a number", argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - self->scanTolerance = atof(argv[2]); - SCSendOK(pCon); - return 1; - } -/*------------- calculate */ - else if(strcmp(argv[1],"calc") == 0) - { - iRet = GetCommandData(argc-2,&argv[2],fHKL, &fPsi, &iHamil,pCon); - if(!iRet) - { - return 0; - } - iRet = CalculateSettings(self,fHKL, fPsi, iHamil, fSet,pCon); - if(self->iNOR) - { - sprintf(pBueffel," gamma = %f, omega = %f, nu = %f", - fSet[0], fSet[1], fSet[2]); - SCWrite(pCon,pBueffel,eValue); - } - else - { - sprintf(pBueffel," 2-theta = %f, omega = %f, chi = %f, phi = %f", - fSet[0], fSet[1], fSet[2],fSet[3]); - SCWrite(pCon,pBueffel,eValue); - } - if(!iRet) - { - SCWrite(pCon, - "WARNING: Cannot drive to the hkl of your desire", - eWarning); - return 0; - } - return 1; - } + else if (strcmp(argv[1], "scantolerance") == 0) { + if (argc < 3) { + snprintf(pBueffel, 510, "%s.scantolerance = %f", argv[0], + self->scanTolerance); + SCWrite(pCon, pBueffel, eValue); + return 1; + } + if (!SCMatchRights(pCon, usUser)) { + return 0; + } + if (!isNumeric(argv[2])) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s was not recognized as a number", + argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + self->scanTolerance = atof(argv[2]); + SCSendOK(pCon); + return 1; + } +/*------------- calculate */ + else if (strcmp(argv[1], "calc") == 0) { + iRet = GetCommandData(argc - 2, &argv[2], fHKL, &fPsi, &iHamil, pCon); + if (!iRet) { + return 0; + } + iRet = CalculateSettings(self, fHKL, fPsi, iHamil, fSet, pCon); + if (SXGetMode() == NB) { + snprintf(pBueffel,sizeof(pBueffel)-1, " gamma = %f, omega = %f, nu = %f", + fSet[0], fSet[1], fSet[2]); + SCWrite(pCon, pBueffel, eValue); + } else if(SXGetMode() == BiNB){ + snprintf(pBueffel,sizeof(pBueffel)-1, " 2-theta = %f, omega = %f, chi = %f, phi = %f, nu = %f", + fSet[0], fSet[1], fSet[2], fSet[3], fSet[4]); + SCWrite(pCon, pBueffel, eValue); + } else { + snprintf(pBueffel,sizeof(pBueffel)-1, " 2-theta = %f, omega = %f, chi = %f, phi = %f", + fSet[0], fSet[1], fSet[2], fSet[3]); + SCWrite(pCon, pBueffel, eValue); + } + if (!iRet) { + SCWrite(pCon, + "WARNING: Cannot drive to the hkl of your desire", eWarning); + return 0; + } + return 1; + } +/*------------- calculate theta*/ + else if (strcmp(argv[1], "calctth") == 0) { + iRet = GetCommandData(argc - 2, &argv[2], fHKL, &fPsi, &iHamil, pCon); + if (!iRet) { + return 0; + } + HKLCalculateTheta(self, fHKL, &stt); + SCPrintf(pCon, eValue, "two-theta = %lf", stt); + return 1; + } /*------------------ run */ - else if(strcmp(argv[1],"run") == 0) - { - if(!SCMatchRights(pCon,usUser)) - { - return 0; - } - iRet = GetCommandData(argc-2,&argv[2],fHKL, &fPsi, &iHamil,pCon); - if(!iRet) - { - return 0; - } - iRet = RunHKL(self,fHKL,fPsi, iHamil, pCon); - if(!iRet) - { - return 0; - } - else - { - SCSendOK(pCon); - return 1; - } - } + else if (strcmp(argv[1], "run") == 0) { + if (!SCMatchRights(pCon, usUser)) { + return 0; + } + iRet = GetCommandData(argc - 2, &argv[2], fHKL, &fPsi, &iHamil, pCon); + if (!iRet) { + return 0; + } + iRet = RunHKL(self, fHKL, fPsi, iHamil, pCon); + if (!iRet) { + return 0; + } else { + SCSendOK(pCon); + return 1; + } + } /*------------------ drive */ - else if(strcmp(argv[1],"drive") == 0) - { - if(!SCMatchRights(pCon,usUser)) - { - return 0; - } - iRet = GetCommandData(argc-2,&argv[2],fHKL, &fPsi, &iHamil,pCon); - if(!iRet) - { - return 0; - } - iRet = DriveHKL(self,fHKL,fPsi, iHamil, pCon); - if(!iRet) - { - return 0; - } - else - { - SCSendOK(pCon); - return 1; - } - } - else - { - sprintf(pBueffel,"ERROR: subcommand --> %s <-- not recognized", - argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - return 0; /* not reached */ - } - - - - - + else if (strcmp(argv[1], "drive") == 0) { + if (!SCMatchRights(pCon, usUser)) { + return 0; + } + iRet = GetCommandData(argc - 2, &argv[2], fHKL, &fPsi, &iHamil, pCon); + if (!iRet) { + return 0; + } + iRet = DriveHKL(self, fHKL, fPsi, iHamil, pCon); + if (!iRet) { + return 0; + } else { + SCSendOK(pCon); + return 1; + } + } + /*------------------ bitonb */ + else if (strcmp(argv[1], "bitonb") == 0) { + return HandleBiToNB(pCon, argc, argv); + } else { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: subcommand --> %s <-- not recognized", + argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + return 0; /* not reached */ +} diff --git a/hkl.h b/hkl.h index 4f4c081b..5f8374eb 100644 --- a/hkl.h +++ b/hkl.h @@ -19,15 +19,12 @@ typedef struct __HKL *pHKL; /*-------------------------------------------------------------------------*/ - pHKL CreateHKL(pMotor pTheta, pMotor pOmega, - pMotor pChi, pMotor pPhi, pMotor pNu); + pHKL CreateHKL(); void DeleteHKL(void *pData); int HKLFactory(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); /*------------------------------------------------------------------------*/ - int SetWavelengthVariable(SConnection *pCon, pHKL self, pSelVar pVar); - int SetWavelengthManual(pHKL self, float fVal); void SetHKLScanTolerance(pHKL self, float value); int SetUB(pHKL self, float fUB[9]); int GetUB(pHKL self, float fUB[9]); @@ -48,7 +45,8 @@ int HKLAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); - int hklInRange(void *data, float fSet[4], int mask[4]); + int hklInRange(void *data, double fSet[4], int mask[4]); int startHKLMotors(pHKL self, SConnection *pCon, float fSet[4]); + void stopHKLMotors(pHKL self); #endif diff --git a/hkl.i b/hkl.i index 14cbaed0..5f499997 100644 --- a/hkl.i +++ b/hkl.i @@ -9,24 +9,18 @@ typedef struct __HKL { pObjectDescriptor pDes; - double fUB[9]; MATRIX UBinv; - double fLambda; int iManual; double fLastHKL[5]; int iNOR; int iQuad; int iHM; - pMotor pTheta; - pMotor pOmega; - pMotor pChi; - pMotor pPhi; - pMotor pNu; - pSelVar pMono; long lID; float scanTolerance; float targetHKL[3]; int targetDirty; + pIDrivable pMotDriv; + pIDrivable pMotList; } HKL; diff --git a/hkl.tex b/hkl.tex index bed73427..d05d14ea 100644 --- a/hkl.tex +++ b/hkl.tex @@ -20,26 +20,20 @@ $\langle$hkldat {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@@\\ \mbox{}\verb@ typedef struct __HKL {@\\ \mbox{}\verb@ pObjectDescriptor pDes;@\\ -\mbox{}\verb@ double fUB[9];@\\ \mbox{}\verb@ MATRIX UBinv;@\\ -\mbox{}\verb@ double fLambda;@\\ \mbox{}\verb@ int iManual;@\\ \mbox{}\verb@ double fLastHKL[5];@\\ \mbox{}\verb@ int iNOR;@\\ \mbox{}\verb@ int iQuad;@\\ \mbox{}\verb@ int iHM;@\\ -\mbox{}\verb@ pMotor pTheta;@\\ -\mbox{}\verb@ pMotor pOmega;@\\ -\mbox{}\verb@ pMotor pChi;@\\ -\mbox{}\verb@ pMotor pPhi;@\\ -\mbox{}\verb@ pMotor pNu;@\\ -\mbox{}\verb@ pSelVar pMono;@\\ \mbox{}\verb@ long lID;@\\ \mbox{}\verb@ float scanTolerance;@\\ \mbox{}\verb@ float targetHKL[3];@\\ \mbox{}\verb@ int targetDirty;@\\ +\mbox{}\verb@ pIDrivable pMotDriv;@\\ +\mbox{}\verb@ pIDrivable pMotList;@\\ \mbox{}\verb@ } HKL;@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} @@ -51,23 +45,12 @@ $\langle$hkldat {\footnotesize ?}$\rangle\equiv$ The fields are more or less self explaining: \begin{description} \item[pDes] The standard object descriptor. -\item[fUB] The UB matrix. -\item[iUB] is a flag which spcifies if a UB is specified. -\item[fLambda] The wavelength of the neutrons. \item[iManual] A flag which defines if the wavelength has been set manually or is updated automatically from a wavelength variable. \item[fLastHKL] the HKL of the last reflection calculated. \item[iNor] a flag for normal beam calculation mode. \item[iHM] a flag for histogram memory mode. In this mode two theta limits are checked alos for detector 2 and 3. -\item[pTheta] The two theta motor. All motor are needed for boundary -checking. -\item[pOmega] The omega axis motor. -\item[pChi] The chi axis motor. -\item[pPhi] the phi axis motor. -\item[pNu] the nu axis motor for normal beam geometry. - This is detector tilt. -\item[pMono] The selector variable doing the wavelength. \item[scanTolerance] The hkl module refuses to position a reflection if it is to close to omega limits for scanning. This is the tolerance to use. \item[targetHKL] The target HKL values to support the H, K, L virtual motors @@ -95,15 +78,12 @@ $\langle$hklint {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@@\\ \mbox{}\verb@ typedef struct __HKL *pHKL;@\\ \mbox{}\verb@/*-------------------------------------------------------------------------*/@\\ -\mbox{}\verb@ pHKL CreateHKL(pMotor pTheta, pMotor pOmega, @\\ -\mbox{}\verb@ pMotor pChi, pMotor pPhi, pMotor pNu);@\\ +\mbox{}\verb@ pHKL CreateHKL();@\\ \mbox{}\verb@ void DeleteHKL(void *pData);@\\ \mbox{}\verb@ @\\ \mbox{}\verb@ int HKLFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\ \mbox{}\verb@ int argc, char *argv[]);@\\ \mbox{}\verb@/*------------------------------------------------------------------------*/@\\ -\mbox{}\verb@ int SetWavelengthVariable(SConnection *pCon, pHKL self, pSelVar pVar);@\\ -\mbox{}\verb@ int SetWavelengthManual(pHKL self, float fVal);@\\ \mbox{}\verb@ void SetHKLScanTolerance(pHKL self, float value);@\\ \mbox{}\verb@ int SetUB(pHKL self, float fUB[9]);@\\ \mbox{}\verb@ int GetUB(pHKL self, float fUB[9]);@\\ @@ -124,9 +104,10 @@ $\langle$hklint {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@@\\ \mbox{}\verb@ int HKLAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\ \mbox{}\verb@ int argc, char *argv[]); @\\ -\mbox{}\verb@ int hklInRange(void *data, float fSet[4], int mask[4]);@\\ +\mbox{}\verb@ int hklInRange(void *data, double fSet[4], int mask[4]);@\\ \mbox{}\verb@ int startHKLMotors(pHKL self, SConnection *pCon, float fSet[4]);@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@ void stopHKLMotors(pHKL self);@\\ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} @@ -197,7 +178,7 @@ drive properly. \mbox{}\verb@----------------------------------------------------------------------------*/@\\ \mbox{}\verb@@$\langle$hkldat {\footnotesize ?}$\rangle$\verb@@\\ \mbox{}\verb@@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-2ex} \end{minipage}\\[4ex] @@ -227,7 +208,7 @@ drive properly. \mbox{}\verb@#include "selvar.h"@\\ \mbox{}\verb@@$\langle$hklint {\footnotesize ?}$\rangle$\verb@@\\ \mbox{}\verb@#endif @\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-2ex} \end{minipage}\\[4ex] @@ -257,7 +238,7 @@ $\langle$hklmotdat {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ pIDrivable pDriv;@\\ \mbox{}\verb@ int index;@\\ \mbox{}\verb@ }HKLMot, *pHKLMot;@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} @@ -303,7 +284,7 @@ functions. The interpreter interface is minimal: only a value request is support \mbox{}\verb@#endif@\\ \mbox{}\verb@@\\ \mbox{}\verb@ @\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-2ex} \end{minipage}\\[4ex] diff --git a/hkl.w b/hkl.w index a1b510d3..98d3834b 100644 --- a/hkl.w +++ b/hkl.w @@ -15,47 +15,30 @@ The object uses the following object data structure: @d hkldat @{ typedef struct __HKL { pObjectDescriptor pDes; - double fUB[9]; MATRIX UBinv; - double fLambda; int iManual; double fLastHKL[5]; int iNOR; int iQuad; int iHM; - pMotor pTheta; - pMotor pOmega; - pMotor pChi; - pMotor pPhi; - pMotor pNu; - pSelVar pMono; long lID; float scanTolerance; float targetHKL[3]; int targetDirty; + pIDrivable pMotDriv; + pIDrivable pMotList; } HKL; @} The fields are more or less self explaining: \begin{description} \item[pDes] The standard object descriptor. -\item[fUB] The UB matrix. -\item[iUB] is a flag which spcifies if a UB is specified. -\item[fLambda] The wavelength of the neutrons. \item[iManual] A flag which defines if the wavelength has been set manually or is updated automatically from a wavelength variable. \item[fLastHKL] the HKL of the last reflection calculated. \item[iNor] a flag for normal beam calculation mode. \item[iHM] a flag for histogram memory mode. In this mode two theta limits are checked alos for detector 2 and 3. -\item[pTheta] The two theta motor. All motor are needed for boundary -checking. -\item[pOmega] The omega axis motor. -\item[pChi] The chi axis motor. -\item[pPhi] the phi axis motor. -\item[pNu] the nu axis motor for normal beam geometry. - This is detector tilt. -\item[pMono] The selector variable doing the wavelength. \item[scanTolerance] The hkl module refuses to position a reflection if it is to close to omega limits for scanning. This is the tolerance to use. \item[targetHKL] The target HKL values to support the H, K, L virtual motors @@ -78,15 +61,12 @@ module: @d hklint @{ typedef struct __HKL *pHKL; /*-------------------------------------------------------------------------*/ - pHKL CreateHKL(pMotor pTheta, pMotor pOmega, - pMotor pChi, pMotor pPhi, pMotor pNu); + pHKL CreateHKL(); void DeleteHKL(void *pData); int HKLFactory(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); /*------------------------------------------------------------------------*/ - int SetWavelengthVariable(SConnection *pCon, pHKL self, pSelVar pVar); - int SetWavelengthManual(pHKL self, float fVal); void SetHKLScanTolerance(pHKL self, float value); int SetUB(pHKL self, float fUB[9]); int GetUB(pHKL self, float fUB[9]); @@ -107,8 +87,9 @@ module: int HKLAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); - int hklInRange(void *data, float fSet[4], int mask[4]); + int hklInRange(void *data, double fSet[4], int mask[4]); int startHKLMotors(pHKL self, SConnection *pCon, float fSet[4]); + void stopHKLMotors(pHKL self); @} All functions return 0 on failure, 1 on success if not stated otherwise. Most functions take a pointer to a HKL data structure as first parameter. diff --git a/hklmot.c b/hklmot.c index 2d897360..ab6f1183 100644 --- a/hklmot.c +++ b/hklmot.c @@ -15,140 +15,178 @@ #include "hkl.h" #include "hkl.i" #include "hklmot.h" +#include "singlex.h" /*=================== Object Descriptor Interface ===================================================*/ -static void *HKLGetInterface(void *pData, int iID){ +static void *HKLGetInterface(void *pData, int iID) +{ pHKLMot self = NULL; - self = (pHKLMot)pData; - if(self == NULL){ + self = (pHKLMot) pData; + if (self == NULL) { return NULL; } - if(iID == DRIVEID){ + if (iID == DRIVEID) { return self->pDriv; } return NULL; } + +/*--------------------------------------------------------------------------------------------------*/ +extern void stopHKLMotors(pHKL hkl); /*=================== Drivable Interface ============================================================*/ -static int HKLHalt(void *pData){ +static int HKLHalt(void *pData) +{ pHKLMot self = NULL; - self = (pHKLMot)pData; + self = (pHKLMot) pData; assert(self != NULL); - - self->pHkl->pTheta->pDrivInt->Halt(self->pHkl->pTheta); - self->pHkl->pOmega->pDrivInt->Halt(self->pHkl->pOmega); - if(self->pHkl->iNOR == 1){ - self->pHkl->pNu->pDrivInt->Halt(self->pHkl->pNu); - } else { - self->pHkl->pChi->pDrivInt->Halt(self->pHkl->pChi); - self->pHkl->pPhi->pDrivInt->Halt(self->pHkl->pPhi); - } + stopHKLMotors(self->pHkl); return 1; } + /*-----------------------------------------------------------------------------------------------------*/ -static int HKLCheckLimits(void *self, float fVal, char *error, int errLen){ +static int HKLCheckLimits(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 long HKLSetValue(void *pData, SConnection *pCon, float fVal){ +static long HKLSetValue(void *pData, SConnection * pCon, float fVal) +{ pHKLMot self = NULL; - if(!SCMatchRights(pCon,usUser)){ + if (!SCMatchRights(pCon, usUser)) { return 0; } - self = (pHKLMot)pData; + self = (pHKLMot) pData; assert(self != NULL); self->pHkl->targetHKL[self->index] = fVal; self->pHkl->targetDirty = 1; return OKOK; } -/*---------------------------------------------------------------------------------------------------*/ -static int checkMotors(pHKLMot self, SConnection *pCon){ - int status; - status = self->pHkl->pTheta->pDrivInt->CheckStatus(self->pHkl->pTheta, pCon); - if(status != HWIdle && status != OKOK){ +/*---------------------------------------------------------------------------------------------------*/ +static int checkMotors(pHKLMot self, SConnection * pCon) +{ + int status; + pMotor pTheta, pOmega, pChi, pPhi, pNu; + + pTheta = SXGetMotor(TwoTheta); + pOmega = SXGetMotor(Omega); + pChi = SXGetMotor(Chi); + pPhi = SXGetMotor(Phi); + if (pTheta == NULL || pOmega == NULL) { + SCWrite(pCon, "ERROR: configuration problem, stt,om motors not found,", + eError); + return HWFault; + } + + + status = pTheta->pDrivInt->CheckStatus(pTheta, pCon); + if (status != HWIdle && status != OKOK) { return status; } - status = self->pHkl->pOmega->pDrivInt->CheckStatus(self->pHkl->pOmega, pCon); - if(status != HWIdle && status != OKOK){ + status = pOmega->pDrivInt->CheckStatus(pOmega, pCon); + if (status != HWIdle && status != OKOK) { return status; } - if(self->pHkl->iNOR == 1){ - status = self->pHkl->pNu->pDrivInt->CheckStatus(self->pHkl->pNu, pCon); - if(status != HWIdle && status != OKOK){ + if (SXGetMode() == NB) { + pNu = SXGetMotor(Nu); + if (pNu == NULL) { + SCWrite(pCon, "ERROR: configuration problem, nu motor not found,", + eError); + return HWFault; + + } + status = pNu->pDrivInt->CheckStatus(pNu, pCon); + if (status != HWIdle && status != OKOK) { return status; } } else { - status = self->pHkl->pChi->pDrivInt->CheckStatus(self->pHkl->pChi, pCon); - if(status != HWIdle && status != OKOK){ + pChi = SXGetMotor(Chi); + pPhi = SXGetMotor(Phi); + if (pTheta == NULL || pOmega == NULL) { + SCWrite(pCon, + "ERROR: configuration problem, chi, phi motors not found,", + eError); + return HWFault; + } + status = pChi->pDrivInt->CheckStatus(pChi, pCon); + if (status != HWIdle && status != OKOK) { return status; } - status = self->pHkl->pPhi->pDrivInt->CheckStatus(self->pHkl->pPhi, pCon); - if(status != HWIdle && status != OKOK){ + status = pPhi->pDrivInt->CheckStatus(pPhi, pCon); + if (status != HWIdle && status != OKOK) { return status; } } return HWIdle; } + /*-----------------------------------------------------------------------------------------------------*/ -static int HKLCheckStatus(void *pData, SConnection *pCon){ +static int HKLCheckStatus(void *pData, SConnection * pCon) +{ pHKLMot self = NULL; int status; - self = (pHKLMot)pData; + self = (pHKLMot) pData; assert(self != NULL); - if(self->pHkl->targetDirty == 1){ - status = RunHKL(self->pHkl,self->pHkl->targetHKL,.0,0,pCon); + if (self->pHkl->targetDirty == 1) { + status = RunHKL(self->pHkl, self->pHkl->targetHKL, .0, 0, pCon); self->pHkl->targetDirty = 0; - if(status != 1){ - SCSetInterrupt(pCon,eAbortOperation); + if (status != 1) { + SCSetInterrupt(pCon, eAbortOperation); return HWFault; } return HWBusy; } else { - return checkMotors(self,pCon); + return checkMotors(self, pCon); } } + /*-----------------------------------------------------------------------------------------------------*/ -static float HKLGetValue(void *pData, SConnection *pCon){ +static float HKLGetValue(void *pData, SConnection * pCon) +{ pHKLMot self = NULL; float fVal[3]; int status; - self = (pHKLMot)pData; + self = (pHKLMot) pData; assert(self != NULL); - status = GetHKLFromAngles(self->pHkl,pCon,fVal); - if(status != 1){ - SCWrite(pCon,"ERROR: failed to read positions or convert to HKL",eError); + status = GetHKLFromAngles(self->pHkl, pCon, fVal); + if (status != 1) { + SCWrite(pCon, "ERROR: failed to read positions or convert to HKL", + eError); return -9999.99; } return fVal[self->index]; } + /*=============================== Live and Death ====================================*/ -static pHKLMot MakeHKLMot(pHKL pHkl, int index){ +static pHKLMot MakeHKLMot(pHKL pHkl, int index) +{ pHKLMot self = NULL; assert(pHkl != NULL); assert(index >= 0 && index < 3); - self = (pHKLMot)malloc(sizeof(HKLMot)); - if(self == NULL){ + self = (pHKLMot) malloc(sizeof(HKLMot)); + if (self == NULL) { return NULL; } - memset(self,0,sizeof(HKLMot)); + memset(self, 0, sizeof(HKLMot)); self->pDes = CreateDescriptor("HKLMot"); self->pDriv = CreateDrivableInterface(); - if(self->pDes == NULL || self->pDriv == NULL){ + if (self->pDes == NULL || self->pDriv == NULL) { free(self); return NULL; } @@ -162,86 +200,95 @@ static pHKLMot MakeHKLMot(pHKL pHkl, int index){ self->index = index; return self; } + /*----------------------------------------------------------------------------------*/ -static void KillHklMot(void *pData){ +static void KillHklMot(void *pData) +{ pHKLMot self = NULL; - self = (pHKLMot)pData; - if(self == NULL){ + self = (pHKLMot) pData; + if (self == NULL) { return; } - if(self->pDes != NULL){ + if (self->pDes != NULL) { DeleteDescriptor(self->pDes); } - if(self->pDriv){ + if (self->pDriv) { free(self->pDriv); } free(self); } + /*=============================== Interpreter Interface ============================*/ -int HKLMotAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ +int HKLMotAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ pHKLMot self = NULL; float value; char pBuffer[132]; - self = (pHKLMot)pData; + self = (pHKLMot) pData; assert(self != NULL); - value = self->pDriv->GetValue(self,pCon); - if(value < -9000.){ - snprintf(pBuffer,131,"ERROR: failed to read %s",argv[0]); - SCWrite(pCon,pBuffer,eError); + 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); + snprintf(pBuffer, 131, "%s = %f", argv[0], value); + SCWrite(pCon, pBuffer, eValue); return 1; } + /*------------------------------------------------------------------------------------------*/ -int HKLMotInstall(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ +int HKLMotInstall(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ pHKL pHkl; pHKLMot pMot = NULL; char pBuffer[131]; - if(argc < 2){ - SCWrite(pCon,"ERROR: Insifficient number of arguments to HKLMotInstall",eError); - return 0; + if (argc < 2) { + pHkl = (pHKL) FindCommandData(pSics, "hkl", "4-Circle-Calculus"); + } else { + strtolower(argv[1]); + pHkl = (pHKL) FindCommandData(pSics, argv[1], "4-Circle-Calculus"); } - strtolower(argv[1]); - pHkl = (pHKL)FindCommandData(pSics,argv[1],"4-Circle-Calculus"); - if(pHkl == NULL){ - snprintf(pBuffer,131,"ERROR: %s is not present or no HKL object",argv[1]); - SCWrite(pCon,pBuffer,eError); + if (pHkl == NULL) { + snprintf(pBuffer, 131, "ERROR: %s is not present or no HKL object", + argv[1]); + SCWrite(pCon, pBuffer, eError); return 0; } pMot = MakeHKLMot(pHkl, 0); - if(pMot == NULL){ - SCWrite(pCon,"ERROR: out of memory creating H Motor",eError); + if (pMot == NULL) { + SCWrite(pCon, "ERROR: out of memory creating H Motor", eError); return 0; } - if(!AddCommand(pSics,"H",HKLMotAction,KillHklMot,pMot)){ - SCWrite(pCon,"ERROR: duplicate command H not created",eError); + if (!AddCommand(pSics, "H", HKLMotAction, KillHklMot, pMot)) { + SCWrite(pCon, "ERROR: duplicate command H not created", eError); return 0; } pMot = MakeHKLMot(pHkl, 1); - if(pMot == NULL){ - SCWrite(pCon,"ERROR: out of memory creating K Motor",eError); + if (pMot == NULL) { + SCWrite(pCon, "ERROR: out of memory creating K Motor", eError); return 0; } - if(!AddCommand(pSics,"K",HKLMotAction,KillHklMot,pMot)){ - SCWrite(pCon,"ERROR: duplicate command K not created",eError); + if (!AddCommand(pSics, "K", HKLMotAction, KillHklMot, pMot)) { + SCWrite(pCon, "ERROR: duplicate command K not created", eError); return 0; } pMot = MakeHKLMot(pHkl, 2); - if(pMot == NULL){ - SCWrite(pCon,"ERROR: out of memory creating L Motor",eError); + if (pMot == NULL) { + SCWrite(pCon, "ERROR: out of memory creating L Motor", eError); return 0; } - if(!AddCommand(pSics,"L",HKLMotAction,KillHklMot,pMot)){ - SCWrite(pCon,"ERROR: duplicate command L not created",eError); + if (!AddCommand(pSics, "L", HKLMotAction, KillHklMot, pMot)) { + SCWrite(pCon, "ERROR: duplicate command L not created", eError); return 0; } return 1; diff --git a/hklscan.c b/hklscan.c deleted file mode 100644 index 6ed90cdd..00000000 --- a/hklscan.c +++ /dev/null @@ -1,455 +0,0 @@ -/*-------------------------------------------------------------------------- - H K L S C A N - - A class for doing scans in reciprocal space for a four circle - diffractometer. All the hard work is done in the scan and hkl objects. - - copyright: see copyright.h - - Mark Koennecke, June 1999 - - This is obsolete: h,k,l are now drivable. Logged variables have been added - to the scan module. The command is now implemented through scripts. - This module is left in the source tree in order to allow for a quick - reinstallation in case of problems but should be retired from the - source tree in the shutdown 2007 - - Mark Koennecke, January 2006 - --------------------------------------------------------------------------*/ -#include -#include -#include -#include -#include "fortify.h" -#include "sics.h" -#include "scan.h" -#include "hkl.h" -#include "scan.i" -#include "matrix/matrix.h" -#include "hkl.i" -#include "hklscan.i" -#include "hklscan.h" - -/*-----------------------------------------------------------------------*/ - static void KillHklscan(void *pData) - { - pHklscan self = NULL; - - self = (pHklscan)pData; - if(!self) - { - return; - } - if(self->pDes) - { - DeleteDescriptor(self->pDes); - } - free(self); - } -/*------------------------------------------------------------------------*/ - int HklscanFactory(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[4]) - { - pHklscan pNew = NULL; - char pBueffel[512]; - int iRet; - - /* check number of arguments */ - if(argc < 3) - { - SCWrite(pCon, - "ERROR: expected two arguments to MakeHklscan",eError); - return 0; - } - - /* allocate space */ - pNew = (pHklscan)malloc(sizeof(sHklscan)); - if(!pNew) - { - SCWrite(pCon,"ERROR: out of memory in MakeHklscan",eError); - return 0; - } - memset(pNew,0,sizeof(sHklscan)); - pNew->pDes = CreateDescriptor("Hklscan"); - - /* find scan object */ - pNew->pScan = (pScanData)FindCommandData(pSics,argv[1],"ScanObject"); - if(!pNew->pScan) - { - sprintf(pBueffel,"ERROR: %s not found or no scan object",argv[1]); - SCWrite(pCon,pBueffel,eError); - KillHklscan(pNew); - return 0; - } - - /* find HKL object */ - pNew->pCalc = (pHKL)FindCommandData(pSics,argv[2], - "4-Circle-Calculus"); - if(!pNew->pCalc) - { - sprintf(pBueffel,"ERROR: %s not found or no HKL object",argv[2]); - SCWrite(pCon,pBueffel,eError); - KillHklscan(pNew); - return 0; - } - - /* alright. Install command */ - iRet = AddCommand(pSics, "__hklscan", - HklscanAction,KillHklscan,pNew); - if(!iRet) - { - SCWrite(pCon,"ERROR: duplicate command hklscan NOT created",eError); - KillHklscan(pNew); - return 0; - } - return 1; - } -/*------------------------------------------------------------------------*/ - static int HklscanDrive(pScanData pScan, int iPoint) - { - pHklscan self = NULL; - int i, iRet; - - assert(pScan); - self = (pHklscan)pScan->pSpecial; - assert(self); - - /* calculate new Positions */ - for(i = 0; i < 3; i++) - { - self->fPos[i] = self->fStart[i] + iPoint * self->fStep[i]; - } - iRet = DriveHKL(self->pCalc, self->fPos, 0.,0,pScan->pCon); - if(!iRet) - { - SCWrite(pScan->pCon,"ERROR: aborting hklscan",eError); - } - return iRet; - } -/*------------------------------------------------------------------------*/ - static int WriteHklscanPoint(pScanData self, int iPoint) - { - pHklscan pHaSca = NULL; - int i, i2; - char pLine[512], pItem[30], pInfo[512]; - pVarEntry pVar = NULL; - pCountEntry pData = NULL; - void *pPtr = NULL; - - assert(self); - pHaSca = (pHklscan)self->pSpecial; - assert(pHaSca); - - - assert(self->pCon); - assert(self->pSics); - - if(!self->fd) - { - self->fd = fopen(self->pFile,"r+"); - if(!self->fd) - { - SCWrite(self->pCon,"ERROR: failed to reopen scan file during scan",eError); - return 0; - } - } - - /* jump to end of header */ - fseek(self->fd,self->lPos, SEEK_SET); - if(self->iChannel != 0) - { - fprintf(self->fd,"WARNING: Scanning monitor %d\n",self->iChannel); - } - - /* make the data header */ - sprintf(pLine,"%-5s","NP"); - sprintf(pInfo,"Scanning Variables: H, K, L STEP: %8.3f %8.3f %8.3f", - pHaSca->fStep[0],pHaSca->fStep[1], pHaSca->fStep[2]); - strcat(pLine,"H K L "); - for(i = 0; i < self->iScanVar;i++) - { - DynarGet(self->pScanVar,i,&pPtr); - pVar = (pVarEntry)pPtr; - if(pVar) - { - sprintf(pItem,"%-6.6s ",pVar->Name); - strcat(pLine,pItem); - } - } - strcat(pLine,"Counts "); - strcat(pLine," Monitor1 "); - sprintf(pItem,"\n%d Points,",self->iNP); - strcat(pInfo,pItem); - if(self->iMode == eTimer) - { - strcat(pInfo," Mode: Timer,"); - } - else - { - strcat(pInfo," Mode: Monitor,"); - } - sprintf(pItem," Preset %f",self->fPreset); - strcat(pInfo,pItem); - fprintf(self->fd,"%s\n",pInfo); - fprintf(self->fd,"%s\n",pLine); - - /* print an addon to the status line going to the screen */ - sprintf(pLine,"NP H K L "); - SCWrite(self->pCon,pLine,eWarning); - sprintf(pLine,"%-5d%-8.4f%-8.4f%-8.4f ",iPoint,pHaSca->fPos[0], - pHaSca->fPos[1], pHaSca->fPos[2]); - SCWrite(self->pCon,pLine,eWarning); - - /* now the scan points */ - for(i = 0; i < self->iCounts; i++) - { - sprintf(pLine,"%-5d",i); - /* print HKL */ - for(i2 = 0; i2 < 3; i2++) - { - sprintf(pItem," %-8.4f",pHaSca->fStart[i2] + i * pHaSca->fStep[i2]); - strcat(pLine,pItem); - } - /* print chi, ph, om */ - for(i2 = 0; i2 < self->iScanVar; i2++) - { - DynarGet(self->pScanVar,i2,&pPtr); - pVar = (pVarEntry)pPtr; - if(pVar) - { - sprintf(pItem," %-7.2f",GetScanVarPos(pVar,i)); - strcat(pLine,pItem); - } - } - /* print Counts & Monitor */ - DynarGet(self->pCounts,i,&pPtr); - pData = (pCountEntry)pPtr; - if(pData) - { - sprintf(pItem," %-13ld",pData->lCount); - strcat(pLine,pItem); - sprintf(pItem," %-12ld",pData->Monitors[0]); - strcat(pLine,pItem); - } - fprintf(self->fd,"%s\n",pLine); - } - - /* done */ - fprintf(self->fd,"END-OF-DATA\n"); - fclose(self->fd); - self->fd = NULL; - return 1; - } -/*-------------------------------------------------------------------*/ - int Hklscan(pHklscan self, SConnection *pCon, - int iNP, int iMode, float fPreset) - { - int iRet; - float fVal; - - assert(self); - - /* configure the scan thing for our bizarre purpose */ - ClearScanVar(self->pScan); - MotorGetPar(self->pCalc->pTheta, "softlowerlim",&fVal); - fVal += .5; - AddScanVar(self->pScan,pServ->pSics,pCon,self->pCalc->pTheta->name, - fVal,0.); - MotorGetPar(self->pCalc->pOmega, "softlowerlim",&fVal); - fVal += .5; - AddScanVar(self->pScan,pServ->pSics,pCon,self->pCalc->pOmega->name, - fVal,0.); - MotorGetPar(self->pCalc->pChi, "softlowerlim",&fVal); - fVal += .5; - AddScanVar(self->pScan,pServ->pSics,pCon,self->pCalc->pChi->name, - fVal,0.); - MotorGetPar(self->pCalc->pPhi, "softlowerlim",&fVal); - fVal += .5; - AddScanVar(self->pScan,pServ->pSics,pCon,self->pCalc->pPhi->name, - fVal,0.); - self->pScan->WriteScanPoints = WriteHklscanPoint; - self->pScan->ScanDrive = HklscanDrive; - self->pScan->pSpecial = self; - self->pScan->PrepareScan = NonCheckPrepare; - - /* scan */ - iRet = DoScan(self->pScan,iNP, iMode, fPreset, pServ->pSics,pCon); - - /* unset all */ - ClearScanVar(self->pScan); - ResetScanFunctions(self->pScan); - self->pScan->pSpecial = NULL; - - return iRet; - } -/*-------------------------------------------------------------------------*/ - int HklscanAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - char pBueffel[512]; - int iRet, iMode, iNP, iPoint; - pHklscan self = NULL; - double dVal; - float fPreset; - void *pPtr; - - assert(pCon); - assert(pSics); - assert(pData); - - self = (pHklscan)pData; - - /* check for the command word */ - if(argc < 2) - { - SCWrite(pCon,"ERROR: Insufficient number of arguments to hklscan", - eError); - return 0; - } - - /* do work according to command word */ - strtolower(argv[1]); - if(strcmp(argv[1],"start") == 0) - { - if(!SCMatchRights(pCon,usUser)) - { - return 0; - } - if(argc < 5) - { - SCWrite(pCon, - "Insufficient number of arguments to hklscan", - eError); - return 0; - } - iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&dVal); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: failed to convert %s to number", - argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - self->fStart[0] = (float)dVal; - iRet = Tcl_GetDouble(pSics->pTcl,argv[3],&dVal); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: failed to convert %s to number", - argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - self->fStart[1] = (float)dVal; - iRet = Tcl_GetDouble(pSics->pTcl,argv[4],&dVal); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: failed to convert %s to number", - argv[4]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - self->fStart[2] = (float)dVal; - SCSendOK(pCon); - return 1; - } - else if(strcmp(argv[1],"step") == 0) - { - if(!SCMatchRights(pCon,usUser)) - { - return 0; - } - if(argc < 5) - { - SCWrite(pCon, - "Insufficient number of arguments to hklscan", - eError); - return 0; - } - iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&dVal); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: failed to convert %s to number", - argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - self->fStep[0] = (float)dVal; - iRet = Tcl_GetDouble(pSics->pTcl,argv[3],&dVal); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: failed to convert %s to number", - argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - self->fStep[1] = (float)dVal; - iRet = Tcl_GetDouble(pSics->pTcl,argv[4],&dVal); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: failed to convert %s to number", - argv[4]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - self->fStep[2] = (float)dVal; - SCSendOK(pCon); - return 1; - } - else if(strcmp(argv[1],"run") == 0) - { - if(!SCMatchRights(pCon,usUser)) - { - return 0; - } - if(argc < 5) - { - SCWrite(pCon, - "Insufficient number of arguments to hklscan run", - eError); - return 0; - } - iRet = Tcl_GetInt(pSics->pTcl,argv[2],&iNP); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: failed to convert %s to number", - argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - /* interpret Mode */ - if(strcmp(argv[3],"timer") == 0) - { - iMode = eTimer; - } - else if(strcmp(argv[3],"monitor") == 0) - { - iMode = ePreset; - } - else - { - sprintf(pBueffel,"ERROR: %s not recognized as valid counter mode", - argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - /* preset */ - iRet = Tcl_GetDouble(pSics->pTcl,argv[4],&dVal); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - fPreset = (float)dVal; - iRet = Hklscan(self,pCon,iNP,iMode,fPreset); - if(iRet) - { - SCSendOK(pCon); - } - return iRet; - } - sprintf(pBueffel, - "ERROR: %s not recognized as command word to hklscan",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } diff --git a/hklscan.h b/hklscan.h deleted file mode 100644 index d505030d..00000000 --- a/hklscan.h +++ /dev/null @@ -1,25 +0,0 @@ - -/*-------------------------------------------------------------------------- - H K L S C A N - - A class for doing scans in reciprocal space. This makes only sense at an - four circle diffractometer. Most of the work is done in the HKL and scan - objects. This class just adapts and used both objects to do the right thing. - - Mark Koennecke, June 1999 ----------------------------------------------------------------------------*/ -#ifndef HKLSCAN -#define HKLSCAN - - typedef struct __HKLSCAN *pHklscan; -/*--------------------------------------------------------------------------*/ - int HklScan(pHklscan self, SConnection *pCon, int iNP, int iMode, - float fPreset); -/*---------------- interpreter functions -----------------------------------*/ - int HklscanFactory(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - int HklscanAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - - -#endif diff --git a/hklscan.i b/hklscan.i deleted file mode 100644 index aca593d6..00000000 --- a/hklscan.i +++ /dev/null @@ -1,17 +0,0 @@ - -/*------------------------------------------------------------------------- - Internal data structure for the hklscan object. DO NOT MODIFY. - Modifications only in hklscan.i - - Mark Koennecke, June 1999 ---------------------------------------------------------------------------*/ - - typedef struct __HKLSCAN { - pObjectDescriptor pDes; - pScanData pScan; - pHKL pCalc; - float fStart[3]; - float fStep[3]; - float fPos[3]; - } sHklscan; - diff --git a/hklscan.tex b/hklscan.tex deleted file mode 100644 index 26869069..00000000 --- a/hklscan.tex +++ /dev/null @@ -1,111 +0,0 @@ -\subsection{hklscan} -hklscan is an object which implements scanning in reciprocal space. It belongs - to the four circle diffraction line of commands. It requires the hkl object - for doing four circle calculations and a scan object for doing the scanning. - The scan object is configured by overloading its WriteScanPoints and - ScanDrive functions to do the right thing for this. Thus most of the work - is done in scan and hkl. - -hklscan has its own data structure looking like this: - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap1} -$\langle$hklscandat {\footnotesize ?}$\rangle\equiv$ -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ typedef struct __HKLSCAN {@\\ -\mbox{}\verb@ pObjectDescriptor pDes;@\\ -\mbox{}\verb@ pScanData pScan;@\\ -\mbox{}\verb@ pHKL pCalc; @\\ -\mbox{}\verb@ float fStart[3];@\\ -\mbox{}\verb@ float fStep[3];@\\ -\mbox{}\verb@ float fPos[3];@\\ -\mbox{}\verb@ } sHklscan;@\\ -\mbox{}\verb@@$\diamond$ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}} -\item Macro referenced in scrap ?. -\end{list} -\end{minipage}\\[4ex] -\end{flushleft} -\begin{description} -\item[pDes] The standard object descriptor. -\item[pScan] The scan object used for scanning. -\item[pCalc] The hkl object used for crystallographic computations. -\item[fStart] The start values in H, K, L for scanning. -\item[fStep] The step width in H, K, L. -\item[fPos] The last position in H, K, L. -\end{description} - -The hklscan object defines the following external interface: - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap2} -$\langle$hklscanfunc {\footnotesize ?}$\rangle\equiv$ -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ typedef struct __HKLSCAN *pHklscan;@\\ -\mbox{}\verb@/*--------------------------------------------------------------------------*/@\\ -\mbox{}\verb@ int HklScan(pHklscan self, SConnection *pCon, int iNP, int iMode,@\\ -\mbox{}\verb@ float fPreset);@\\ -\mbox{}\verb@/*---------------- interpreter functions -----------------------------------*/@\\ -\mbox{}\verb@ int HklscanFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\ -\mbox{}\verb@ int argc, char *argv[]);@\\ -\mbox{}\verb@ int HklscanAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\ -\mbox{}\verb@ int argc, char *argv[]);@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@@$\diamond$ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}} -\item Macro referenced in scrap ?. -\end{list} -\end{minipage}\\[4ex] -\end{flushleft} -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap3} -\verb@"hklscan.i"@ {\footnotesize ? }$\equiv$ -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@/*-------------------------------------------------------------------------@\\ -\mbox{}\verb@ Internal data structure for the hklscan object. DO NOT MODIFY. @\\ -\mbox{}\verb@ Modifications only in hklscan.i@\\ -\mbox{}\verb@ @\\ -\mbox{}\verb@ Mark Koennecke, June 1999@\\ -\mbox{}\verb@--------------------------------------------------------------------------*/@\\ -\mbox{}\verb@@$\langle$hklscandat {\footnotesize ?}$\rangle$\verb@@\\ -\mbox{}\verb@@$\diamond$ -\end{list} -\vspace{-2ex} -\end{minipage}\\[4ex] -\end{flushleft} -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap4} -\verb@"hklscan.h"@ {\footnotesize ? }$\equiv$ -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@/*--------------------------------------------------------------------------@\\ -\mbox{}\verb@ H K L S C A N@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ A class for doing scans in reciprocal space. This makes only sense at an@\\ -\mbox{}\verb@ four circle diffractometer. Most of the work is done in the HKL and scan@\\ -\mbox{}\verb@ objects. This class just adapts and used both objects to do the right thing.@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ Mark Koennecke, June 1999@\\ -\mbox{}\verb@---------------------------------------------------------------------------*/@\\ -\mbox{}\verb@#ifndef HKLSCAN@\\ -\mbox{}\verb@#define HKLSCAN@\\ -\mbox{}\verb@@$\langle$hklscanfunc {\footnotesize ?}$\rangle$\verb@@\\ -\mbox{}\verb@#endif@\\ -\mbox{}\verb@@$\diamond$ -\end{list} -\vspace{-2ex} -\end{minipage}\\[4ex] -\end{flushleft} diff --git a/hklscan.w b/hklscan.w deleted file mode 100644 index deba3828..00000000 --- a/hklscan.w +++ /dev/null @@ -1,70 +0,0 @@ -\subsection{hklscan} -hklscan is an object which implements scanning in reciprocal space. It belongs - to the four circle diffraction line of commands. It requires the hkl object - for doing four circle calculations and a scan object for doing the scanning. - The scan object is configured by overloading its WriteScanPoints and - ScanDrive functions to do the right thing for this. Thus most of the work - is done in scan and hkl. - -hklscan has its own data structure looking like this: - -@d hklscandat @{ - typedef struct __HKLSCAN { - pObjectDescriptor pDes; - pScanData pScan; - pHKL pCalc; - float fStart[3]; - float fStep[3]; - float fPos[3]; - } sHklscan; -@} -\begin{description} -\item[pDes] The standard object descriptor. -\item[pScan] The scan object used for scanning. -\item[pCalc] The hkl object used for crystallographic computations. -\item[fStart] The start values in H, K, L for scanning. -\item[fStep] The step width in H, K, L. -\item[fPos] The last position in H, K, L. -\end{description} - -The hklscan object defines the following external interface: - -@d hklscanfunc @{ - typedef struct __HKLSCAN *pHklscan; -/*--------------------------------------------------------------------------*/ - int HklScan(pHklscan self, SConnection *pCon, int iNP, int iMode, - float fPreset); -/*---------------- interpreter functions -----------------------------------*/ - int HklscanFactory(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - int HklscanAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - -@} - -@o hklscan.i @{ -/*------------------------------------------------------------------------- - Internal data structure for the hklscan object. DO NOT MODIFY. - Modifications only in hklscan.i - - Mark Koennecke, June 1999 ---------------------------------------------------------------------------*/ -@ -@} - -@o hklscan.h @{ -/*-------------------------------------------------------------------------- - H K L S C A N - - A class for doing scans in reciprocal space. This makes only sense at an - four circle diffractometer. Most of the work is done in the HKL and scan - objects. This class just adapts and used both objects to do the right thing. - - Mark Koennecke, June 1999 ----------------------------------------------------------------------------*/ -#ifndef HKLSCAN -#define HKLSCAN -@ -#endif -@} - diff --git a/hmcontrol.c b/hmcontrol.c index 758ed638..aed00d55 100644 --- a/hmcontrol.c +++ b/hmcontrol.c @@ -9,11 +9,26 @@ copyright: see copyright.h Mark Koennecke, June 2001 + + Added a flag which does not call halt after the counter + finished. This feauture is necessary to allow normal + counting on CCD camera. When they get interrupted, the + image is invalid. This is not what is wanted. + + Mark Koennecke, July 2011 + + Made a special status function for BOA which aborts the CCD when the + camera overruns the counter for more then 120 seconds and repeats the + measurement. + + Mark Koennecke, July 2012 -------------------------------------------------------------------------*/ #include #include #include +#include +#include #include "fortify.h" #include "hmcontrol.h" #include "HistMem.h" @@ -25,181 +40,275 @@ static void *HMCGetInterface(void *pData, int ID) { pHMcontrol self = NULL; - self = (pHMcontrol)pData; + self = (pHMcontrol) pData; assert(self); - if(ID == COUNTID) + if (ID == COUNTID) return self->pCount; else return NULL; } + /*------------------------------------------------------------------------*/ static int HMCHalt(void *pData) { int i, retVal = OKOK, status; pHMcontrol self = NULL; - self = (pHMcontrol)pData; + self = (pHMcontrol) pData; assert(self); - for(i = 0; i < self->nSlaves; i++) - { + for (i = 0; i < self->nSlaves; i++) { status = self->slaves[i]->Halt(self->slaveData[i]); - if(status != OKOK) + ReleaseCountLock(self->slaves[i]); + if (status != OKOK) retVal = status; } + ReleaseCountLock(self->pCount); return retVal; } + /*-----------------------------------------------------------------------*/ -static int HMCStart(void *pData, SConnection *pCon) +static int HMCStart(void *pData, SConnection * pCon) { int i, status; pHMcontrol self = NULL; - self = (pHMcontrol)pData; + self = (pHMcontrol) pData; assert(self); - - for(i = 0; i < self->nSlaves; i++) - { - status = self->slaves[i]->StartCount(self->slaveData[i],pCon); - if(status != OKOK) - { - HMCHalt(self); - return status; - } + + if (!GetCountLock(self->pCount, pCon)) { + return HWFault; } - return OKOK; -} -/*----------------------------------------------------------------------*/ -static int HMCStatus(void *pData, SConnection *pCon) -{ - int status,i; - pHMcontrol self = NULL; - self = (pHMcontrol)pData; - assert(self); - - status = self->slaves[0]->CheckCountStatus(self->slaveData[0],pCon); - if(status == HWIdle || status == HWFault) - { - /* - stop counting on slaves when finished or when an error - occurred. - */ - InvokeCallBack(self->pCall,COUNTEND,pCon); - HMCHalt(self); + for (i = 1; i < self->nSlaves; i++) { + ReleaseCountLock(self->slaves[i]); + status = self->slaves[i]->StartCount(self->slaveData[i], pCon); + if (status != OKOK) { + HMCHalt(self); + return status; + } } /* - Warning: this assumes that salves 1 - MAXSLAVE are histogram memories. - If this assumption does not hold, change this code to check if this - is really a histogram memory. - */ - for(i = 1; i < MAXSLAVE; i++) - { - if(self->slaves[i] != NULL) - { - HistDirty((pHistMem)self->slaveData[i]); - } + * This starts the counter: always 0, last.This should be the + * right thing as the HM do not start counting in earnest before + * the busy line from the counter box is set. + */ + ReleaseCountLock(self->slaves[0]); + status = self->slaves[0]->StartCount(self->slaveData[0], pCon); + if (status != OKOK) { + HMCHalt(self); + return status; } + + /* + Warning: this assumes that slaves 1 - MAXSLAVE are histogram memories. + If this assumption does not hold, change this code to check if this + is really a histogram memory. + */ + for (i = 1; i < MAXSLAVE; i++) { + if (self->slaves[i] != NULL) { + HistDirty((pHistMem) self->slaveData[i]); + } + } + self->checkSlaves = 0; + return OKOK; +} + +/*----------------------------------------------------------------------*/ +static int HMCStatus(void *pData, SConnection * pCon) +{ + int status, i; + pHMcontrol self = NULL; + + self = (pHMcontrol) pData; + assert(self); + + if(self->checkSlaves == 0) { + status = self->slaves[0]->CheckCountStatus(self->slaveData[0], pCon); + /* + Warning: this assumes that slaves 1 - MAXSLAVE are histogram memories. + If this assumption does not hold, change this code to check if this + is really a histogram memory. + */ + for (i = 1; i < MAXSLAVE; i++) { + if (self->slaves[i] != NULL) { + HistDirty((pHistMem) self->slaveData[i]); + } + } + if (status == HWIdle || status == HWFault) { + /* + stop counting on slaves when finished or when an error + occurred. + */ + if(self->stopSlaves){ + HMCHalt(self); + } + ReleaseCountLock(self->pCount); + self->checkSlaves = 1; + status = HWBusy; + } + } else { + /* + * wait for the detectors to report finish too. Otherwise, with the second + * generation HM data may not be fully transferred. + */ + for(i = 1; i < self->nSlaves; i++){ + status = self->slaves[i]->CheckCountStatus(self->slaveData[i], pCon); + if(status != HWIdle || status != HWFault){ + return status; + } + } + status = HWIdle; + InvokeCallBack(self->pCall, COUNTEND, pCon); + self->checkSlaves = 0; + } + return status; +} +/*----------------------------------------------------------------------*/ +static int HMCBoaStatus(void *pData, SConnection * pCon) +{ + int status, i, j; + pHMcontrol self = NULL; + + self = (pHMcontrol) pData; + assert(self); + + /* check counter */ + if(self->checkSlaves == 0) { + status = self->slaves[0]->CheckCountStatus(self->slaveData[0], pCon); + if (status == HWIdle || status == HWFault) { + ReleaseCountLock(self->pCount); + self->checkSlaves = 1; + self->counterStop = time(NULL); + status = HWBusy; + } + } else { + /* check HM */ + for(i = 1; i < self->nSlaves; i++){ + status = self->slaves[i]->CheckCountStatus(self->slaveData[i], pCon); + if(status != HWIdle || status != HWFault){ + if(time(NULL) > self->counterStop + 100) { + SCWrite(pCon,"WARNING: CCD overrun, restarting counting...", eLogError); + HMCHalt(self); + ReleaseCountLock(self->pCount); + self->checkSlaves = 0; + for(j = 0; j < 100; j++){ + SicsWait(1); + status = self->slaves[i]->CheckCountStatus(self->slaveData[i], pCon); + if(status == HWIdle || status == HWFault) { + HMCStart(self, pCon); + return HWBusy; + } + } + } + return status; + } + } + status = HWIdle; + InvokeCallBack(self->pCall, COUNTEND, pCon); + self->checkSlaves = 0; + } return status; } /*-------------------------------------------------------------------------*/ -static int HMCPause(void *pData, SConnection *pCon) +static int HMCPause(void *pData, SConnection * pCon) { int i, status; pHMcontrol self = NULL; - self = (pHMcontrol)pData; + self = (pHMcontrol) pData; assert(self); - for(i = 0; i < self->nSlaves; i++) - { - status = self->slaves[i]->Pause(self->slaveData[i],pCon); - if(status != OKOK) - { + for (i = 0; i < self->nSlaves; i++) { + status = self->slaves[i]->Pause(self->slaveData[i], pCon); + if (status != OKOK) { HMCHalt(self); return status; } } return OKOK; } + /*------------------------------------------------------------------------*/ -static int HMCContinue(void *pData, SConnection *pCon) +static int HMCContinue(void *pData, SConnection * pCon) { int i, status; pHMcontrol self = NULL; - self = (pHMcontrol)pData; + self = (pHMcontrol) pData; assert(self); - for(i = 0; i < self->nSlaves; i++) - { - status = self->slaves[i]->Continue(self->slaveData[i],pCon); - if(status != OKOK) - { + for (i = 0; i < self->nSlaves; i++) { + status = self->slaves[i]->Continue(self->slaveData[i], pCon); + if (status != OKOK) { HMCHalt(self); return status; } } return OKOK; } + /*----------------------------------------------------------------------*/ -static int HMCTransfer(void *pData, SConnection *pCon) +static int HMCTransfer(void *pData, SConnection * pCon) { int i, retVal = OKOK, status; pHMcontrol self = NULL; char pBueffel[132]; - self = (pHMcontrol)pData; + self = (pHMcontrol) pData; assert(self); - for(i = 0; i < self->nSlaves; i++) - { + for (i = 0; i < self->nSlaves; i++) { status = self->slaves[i]->TransferData(self->slaveData[i], pCon); - if(status != OKOK) - { + if (status != OKOK) { retVal = status; - sprintf(pBueffel,"WARNING: slave histogram %d failed to transfer data", - i); - SCWrite(pCon,pBueffel,eWarning); + snprintf(pBueffel,sizeof(pBueffel)-1, + "WARNING: slave histogram %d failed to transfer data", i); + SCWrite(pCon, pBueffel, eWarning); } } return retVal; } + /*-----------------------------------------------------------------------*/ -static void HMCParameter(void *pData, float fPreset, CounterMode eMode ) +static void HMCParameter(void *pData, float fPreset, CounterMode eMode) { int i; pHMcontrol self = NULL; - self = (pHMcontrol)pData; + self = (pHMcontrol) pData; assert(self); - for(i = 0; i < self->nSlaves; i++) - { + if(isRunning(self->pCount)){ + return; + } + for (i = 0; i < self->nSlaves; i++) { self->slaves[i]->SetCountParameters(self->slaveData[i], fPreset, eMode); } } + /*----------------------------------------------------------------------*/ static void KillHMcontrol(void *pData) { pHMcontrol self; - self = (pHMcontrol)pData; - if(!self) + self = (pHMcontrol) pData; + if (!self) return; - if(self->pDes) + if (self->pDes) DeleteDescriptor(self->pDes); - if(self->pCount) + if (self->pCount) free(self->pCount); free(self); -} +} + /*-----------------------------------------------------------------------*/ -int MakeHMControl(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]) +int MakeHMControl(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]) { int i, status; pHMcontrol pNew = NULL; @@ -208,38 +317,36 @@ int MakeHMControl(SConnection *pCon, SicsInterp *pSics, pICountable pCount; /* - need at least two parameters - */ - if(argc < 3) - { - SCWrite(pCon,"ERROR: insufficient number of arguments to MakeHMControl", - eError); + need at least two parameters + */ + if (argc < 3) { + SCWrite(pCon, + "ERROR: insufficient number of arguments to MakeHMControl", + eError); return 0; } /* allocate our data structure - */ - pNew = (pHMcontrol)malloc(sizeof(HMcontrol)); - if(!pNew) - { - SCWrite(pCon,"ERROR: out of memory in MakeHMControl",eError); + */ + pNew = (pHMcontrol) malloc(sizeof(HMcontrol)); + if (!pNew) { + SCWrite(pCon, "ERROR: out of memory in MakeHMControl", eError); return 0; } - memset(pNew,0,sizeof(HMcontrol)); + memset(pNew, 0, sizeof(HMcontrol)); pNew->pDes = CreateDescriptor("HMcontrol"); pNew->pCount = CreateCountableInterface(); pNew->pCall = CreateCallBackInterface(); - if(!pNew->pDes || ! pNew->pCount) - { - SCWrite(pCon,"ERROR: out of memory in MakeHMControl",eError); + if (!pNew->pDes || !pNew->pCount) { + SCWrite(pCon, "ERROR: out of memory in MakeHMControl", eError); KillHMcontrol(pNew); return 0; } - + /* - assign interface functions - */ + assign interface functions + */ pNew->pDes->GetInterface = HMCGetInterface; pNew->pCount->Halt = HMCHalt; pNew->pCount->StartCount = HMCStart; @@ -250,52 +357,49 @@ int MakeHMControl(SConnection *pCon, SicsInterp *pSics, pNew->pCount->SetCountParameters = HMCParameter; /* - now loop through the remaining arguments, thereby entering them into - the slave list. - */ - for(i = 2; i < argc; i++) - { - pCom = FindCommand(pSics,argv[i]); - if(!pCom) - { - sprintf(pBueffel,"ERROR: object %s not found in MakeHMcontrol", + now loop through the remaining arguments, thereby entering them into + the slave list. + */ + for (i = 2; i < argc; i++) { + pCom = FindCommand(pSics, argv[i]); + if (!pCom) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: object %s not found in MakeHMcontrol", argv[i]); - SCWrite(pCon,pBueffel,eError); + SCWrite(pCon, pBueffel, eError); continue; } pCount = GetCountableInterface(pCom->pData); - if(!pCount) - { - sprintf(pBueffel,"ERROR: object %s is NOT countable", - argv[i]); - SCWrite(pCon,pBueffel,eError); + if (!pCount) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: object %s is NOT countable", argv[i]); + SCWrite(pCon, pBueffel, eError); continue; } pNew->slaves[pNew->nSlaves] = pCount; pNew->slaveData[pNew->nSlaves] = pCom->pData; pNew->nSlaves++; + pNew->stopSlaves = 1; } /* - now install our action command and we are done - */ - status = AddCommand(pSics,argv[1],HMControlAction,KillHMcontrol, - pNew); - if(!status) - { - sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[1]); - SCWrite(pCon,pBueffel,eError); + now install our action command and we are done + */ + status = AddCommand(pSics, argv[1], HMControlAction, KillHMcontrol, + pNew); + if (!status) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: duplicate command %s not created", argv[1]); + SCWrite(pCon, pBueffel, eError); KillHMcontrol(pNew); return 0; - } - + } + return 1; } + /*----------------------------------------------------------------------- Syntax: whatever start preset mode ------------------------------------------------------------------------*/ -int HMControlAction(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]) +int HMControlAction(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]) { pHMcontrol self; char pBueffel[132]; @@ -304,63 +408,71 @@ int HMControlAction(SConnection *pCon, SicsInterp *pSics, int status; /* - checks + checks */ - self = (pHMcontrol)pData; + self = (pHMcontrol) pData; assert(self); - if(argc < 4) - { - snprintf(pBueffel,131,"ERROR: Usage %s start preset mode", argv[0]); - SCWrite(pCon,pBueffel,eError); + if (argc < 2) { + snprintf(pBueffel, 131, "ERROR: Usage %s start preset mode", argv[0]); + SCWrite(pCon, pBueffel, eError); return 0; } strtolower(argv[1]); - if(strcmp(argv[1],"start") == 0) - { - /* - interpret count parameters - */ - status = Tcl_GetDouble(pSics->pTcl,argv[2],&dPreset); - if(status != TCL_OK) - { - sprintf(pBueffel,"ERROR: failed to convert %s to number", - argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - strtolower(argv[3]); - if(strcmp(argv[3],"timer") == 0) - eMode = eTimer; - else if(strcmp(argv[3],"monitor") == 0) - eMode = ePreset; - else - { - sprintf(pBueffel,"ERROR: %s is no recognized count mode",argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } + if (strcmp(argv[1], "start") == 0) { + if (argc < 4) { + snprintf(pBueffel, 131, "ERROR: Usage %s start preset mode", argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + /* + interpret count parameters + */ + status = Tcl_GetDouble(pSics->pTcl, argv[2], &dPreset); + if (status != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: failed to convert %s to number", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + strtolower(argv[3]); + if (strcmp(argv[3], "timer") == 0) + eMode = eTimer; + else if (strcmp(argv[3], "monitor") == 0) + eMode = ePreset; + else { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s is no recognized count mode", argv[3]); + SCWrite(pCon, pBueffel, eError); + return 0; + } - /* - set count parameters and go - */ - self->pCount->SetCountParameters(self,(float)dPreset,eMode); - status = StartDevice(pServ->pExecutor,"hmcontrol",self->pDes, - self,pCon,99); - if(!status) - { - SCWrite(pCon,"ERROR: failed to start counting",eError); - return 0; - } - InvokeCallBack(self->pCall,COUNTSTART,pCon); - SCSendOK(pCon); - } - else - { - SCWrite(pCon,"ERROR: subcommand not recognized",eError); - return 0; + /* + set count parameters and go + */ + self->pCount->SetCountParameters(self, (float) dPreset, eMode); + status = StartDevice(pServ->pExecutor, "hmcontrol", self->pDes, + self, pCon, RUNRUN, 99); + if (!status) { + SCWrite(pCon, "ERROR: failed to start counting", eError); + return 0; + } + InvokeCallBack(self->pCall, COUNTSTART, pCon); + SCSendOK(pCon); + }else if(strcmp(argv[1],"stopslaves") == 0){ + if(argc < 3){ + SCPrintf(pCon,eValue,"hm.stopslaves = %d", self->stopSlaves); + return 1; + } else { + self->stopSlaves = atoi(argv[2]); + SCPrintf(pCon,eValue,"hm.stopslaves = %d", self->stopSlaves); + return 1; + } + }else if(strcmp(argv[1],"boamode") == 0){ + self->pCount->CheckCountStatus = HMCBoaStatus; + SCSendOK(pCon); + return 1; + } else { + SCWrite(pCon, "ERROR: subcommand not recognized", eError); + return 0; } return 1; -} - - +} diff --git a/hmcontrol.h b/hmcontrol.h index e73f2a7a..c9113182 100644 --- a/hmcontrol.h +++ b/hmcontrol.h @@ -23,24 +23,26 @@ the maximum number of slaves #define MAXSLAVE 5 - typedef struct { - pObjectDescriptor pDes; - pICountable pCount; - pICountable slaves[MAXSLAVE]; - void *slaveData[MAXSLAVE]; - int nSlaves; - float fPreset; - CounterMode eMode; - pICallBack pCall; - } HMcontrol, *pHMcontrol; +typedef struct { + pObjectDescriptor pDes; + pICountable pCount; + pICountable slaves[MAXSLAVE]; + void *slaveData[MAXSLAVE]; + int nSlaves; + float fPreset; + CounterMode eMode; + pICallBack pCall; + int checkSlaves; + int stopSlaves; + time_t counterStop; +} HMcontrol, *pHMcontrol; - int MakeHMControl(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]); - int HMControlAction(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]); +int MakeHMControl(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]); +int HMControlAction(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]); #endif - diff --git a/hmdata.c b/hmdata.c index 627fae56..cc801e8c 100644 --- a/hmdata.c +++ b/hmdata.c @@ -23,217 +23,243 @@ #include "countdriv.h" #include "stptok.h" /*----------------------------------------------------------------------*/ -pHMdata makeHMData(void) { +pHMdata makeHMData(void) +{ pHMdata self = NULL; - self = (pHMdata)malloc(sizeof(HMdata)); - if(self == NULL){ + self = (pHMdata) malloc(sizeof(HMdata)); + if (self == NULL) { return NULL; } - memset(self,0,sizeof(HMdata)); + memset(self, 0, sizeof(HMdata)); self->nTimeChan = 1; - self->updateFlag = 1; - + return self; } + /*---------------------------------------------------------------------*/ -void killHMData(pHMdata self){ - if(self->localBuffer != NULL){ +void killHMData(pHMdata self) +{ + if (self->localBuffer != NULL) { free(self->localBuffer); } free(self); } + /*---------------------------------------------------------------------*/ -void clearHMData(pHMdata self){ - long size; - int i; - size = 1; - for(i = 0; i < self->rank; i++){ - size *= self->iDim[i]; - } - if(self->tofMode){ - size *= getNoOfTimebins(self); - } - memset(self->localBuffer,0,size*sizeof(HistInt)); +void clearHMData(pHMdata self) +{ + long size; + int i; + size = 1; + for (i = 0; i < self->rank; i++) { + size *= self->iDim[i]; + } + if (self->tofMode) { + size *= getNoOfTimebins(self); + } + memset(self->localBuffer, 0, size * sizeof(HistInt)); } + /*----------------------------------------------------------------------*/ -int resizeBuffer(pHMdata self){ +int resizeBuffer(pHMdata self) +{ long size; int i; size = 1; - for(i = 0; i < self->rank; i++){ + for (i = 0; i < self->rank; i++) { size *= self->iDim[i]; } - if(self->tofMode){ + if (self->tofMode) { size *= getNoOfTimebins(self); } - if(self->localBuffer != NULL){ + if (self->localBuffer != NULL) { free(self->localBuffer); self->localBuffer = NULL; } - self->localBuffer = (HistInt *)malloc(size*sizeof(HistInt)); - if(!self->localBuffer){ + self->localBuffer = (HistInt *) malloc(size * sizeof(HistInt)); + if (!self->localBuffer) { return 0; } - memset(self->localBuffer,0,size*sizeof(HistInt)); - self->updateFlag = 1; + memset(self->localBuffer, 0, size * sizeof(HistInt)); + self->nextUpdate = 0; return 1; } + /*-----------------------------------------------------------------------*/ -int configureHMdata(pHMdata self, pStringDict pOpt, - SConnection *pCon){ +int configureHMdata(pHMdata self, pStringDict pOpt, SConnection * pCon) +{ int status, i; float fVal; char pValue[80]; pHistMem master = NULL; - if(self->nTimeChan > 2) { + if (self->nTimeChan > 2) { self->tofMode = 1; } else { self->tofMode = 0; } - status = StringDictGetAsNumber(pOpt,"rank",&fVal); - if(!status){ - SCWrite(pCon,"ERROR: critical configuration problem: no rank found", - eError); + status = StringDictGetAsNumber(pOpt, "rank", &fVal); + if (!status) { + SCWrite(pCon, "ERROR: critical configuration problem: no rank found", + eError); return 0; } - self->rank = (int)rint(fVal); + self->rank = (int) rint(fVal); - for(i = 0; i < self->rank; i++){ - sprintf(pValue,"dim%1.1d",i); - status = StringDictGetAsNumber(pOpt,pValue,&fVal); - if(!status){ - sprintf(pValue,"ERROR dimension %d not found!!", i); + for (i = 0; i < self->rank; i++) { + snprintf(pValue,sizeof(pValue)-1, "dim%1.1d", i); + status = StringDictGetAsNumber(pOpt, pValue, &fVal); + if (!status) { + snprintf(pValue,sizeof(pValue)-1, "ERROR dimension %d not found!!", i); return 0; } - self->iDim[i] = (int)rint(fVal); - } - - status = StringDictGetAsNumber(pOpt,"update",&fVal); - if(!status){ - self->updateIntervall = 0; /* no buffering */ - } else { - self->updateIntervall = (int)rint(fVal); + self->iDim[i] = (int) rint(fVal); } - status = StringDictGet(pOpt,"timeslave",pValue, 79); - if(status == 1) { - master = (pHistMem)FindCommandData(pServ->pSics,pValue,"HistMem"); - if(master == NULL){ - SCWrite(pCon,"ERROR: timeslave requested, but master HM not found", - eError); + status = StringDictGetAsNumber(pOpt, "update", &fVal); + if (!status) { + self->updateIntervall = 0; /* no buffering */ + } else { + self->updateIntervall = (int) rint(fVal); + } + + status = StringDictGet(pOpt, "timeslave", pValue, 79); + if (status == 1) { + master = (pHistMem) FindCommandData(pServ->pSics, pValue, "HistMem"); + if (master == NULL) { + SCWrite(pCon, "ERROR: timeslave requested, but master HM not found", + eError); } else { - self->timeslave = master->pDriv->data; - self->tofMode = 1; + self->timeslave = master->pDriv->data; + self->tofMode = 1; } - } + } /* - invalidate buffer - */ - if(self->localBuffer != NULL){ + invalidate buffer + */ + if (self->localBuffer != NULL) { free(self->localBuffer); self->localBuffer = NULL; } /* - note: remove update request in histmem.c - */ - if(self->updateIntervall > 0){ + note: remove update request in histmem.c + */ + if (self->updateIntervall > 0) { /* - we do buffer - */ + we do buffer + */ status = resizeBuffer(self); - if(!status){ - SCWrite(pCon,"ERROR: failed to resize buffer",eError); + if (!status) { + SCWrite(pCon, "ERROR: failed to resize buffer", eError); return 0; } } return 1; } + /*----------------------------------------------------------------------*/ -int genTimeBinning(pHMdata self, float start, float step, int noSteps){ +int genTimeBinning(pHMdata self, float start, float step, int noSteps) +{ int i; - if(noSteps >= MAXCHAN || self->timeslave != NULL){ + if (noSteps >= MAXCHAN || self->timeslave != NULL) { return 0; } - for(i = 0; i < noSteps; i++){ - self->timeBinning[i] = start + i*step; + for (i = 0; i < noSteps; i++) { + self->timeBinning[i] = start + i * step; } self->tofMode = 1; self->nTimeChan = noSteps; return resizeBuffer(self); } + /*----------------------------------------------------------------------*/ -int setTimeBin(pHMdata self, int index, float value){ - if(self->timeslave != NULL){ +int setTimeBin(pHMdata self, int index, float value) +{ + if (self->timeslave != NULL) { return 0; } - - if(index >= 0 && index < MAXCHAN){ + + if (index >= 0 && index < MAXCHAN) { self->timeBinning[index] = value; } else { return 0; } self->tofMode = 1; - if(index > self->nTimeChan){ - self->nTimeChan = index+1; + if (index >= self->nTimeChan) { + self->nTimeChan = index + 1; return resizeBuffer(self); } return 1; } + /*-------------------------------------------------------------------*/ -int isInTOFMode(pHMdata self){ +int isInTOFMode(pHMdata self) +{ return self->tofMode; } + /*---------------------------------------------------------------------*/ -int getNoOfTimebins(pHMdata self){ - if(self->timeslave != NULL){ +int getNoOfTimebins(pHMdata self) +{ + if (self->timeslave != NULL) { return getNoOfTimebins(self->timeslave); - } else { - return self->nTimeChan; + } else { + return self->nTimeChan; } } + /*---------------------------------------------------------------------*/ -float *getTimeBinning(pHMdata self){ - if(self->timeslave != NULL){ +float *getTimeBinning(pHMdata self) +{ + if (self->timeslave != NULL) { return getTimeBinning(self->timeslave); - } else { - return self->timeBinning; + } else { + return self->timeBinning; } } + /*-------------------------------------------------------------------*/ -void clearTimeBinning(pHMdata self){ - if(self->timeslave == NULL){ - self->nTimeChan = 1; +void clearTimeBinning(pHMdata self) +{ + if (self->timeslave == NULL) { + self->nTimeChan = 1; self->tofMode = 0; resizeBuffer(self); } } + /*--------------------------------------------------------------------*/ -void getHMDataDim(pHMdata self, int iDim[MAXDIM], int *rank){ - memcpy(iDim,self->iDim,self->rank*sizeof(int)); +void getHMDataDim(pHMdata self, int iDim[MAXDIM], int *rank) +{ + memcpy(iDim, self->iDim, self->rank * sizeof(int)); *rank = self->rank; } + /*---------------------------------------------------------------------*/ -long getHMDataLength(pHMdata self){ +long getHMDataLength(pHMdata self) +{ long length = 1; int i; - for(i = 0; i < self->rank; i++){ + for (i = 0; i < self->rank; i++) { length *= self->iDim[i]; } - if(self->tofMode){ + if (self->tofMode) { length *= getNoOfTimebins(self); } return length; } + /*---------------------------------------------------------------------*/ -void updateHMData(pHMdata self){ - self->updateFlag = 1; +void updateHMData(pHMdata self) +{ + self->nextUpdate = 0; } + /*-------------------------------------------------------------------- The idea here is that upper level code sets the updateFlag through updateHMData (above) whenever the HM changes (counts). If this flag is set @@ -245,99 +271,105 @@ void updateHMData(pHMdata self){ to buffer all HM) use GetHistogramDirect (histogram.c) instead which acts on the driver level. --------------------------------------------------------------------------*/ -static int mustUpdate(pHMdata self){ - if(self->updateFlag == 1 && time(NULL) >= self->nextUpdate){ +static int mustUpdate(pHMdata self) +{ + if (time(NULL) >= self->nextUpdate) { return 1; } else { return 0; } } + /*---------------------------------------------------------------------*/ -static int updateHMbuffer(pHistMem hist, int bank, SConnection *pCon){ +static int updateHMbuffer(pHistMem hist, int bank, SConnection * pCon) +{ int status, iErr, i; char pError[80], pBueffel[256]; pHMdata self = hist->pDriv->data; assert(self); - if(self->timeslave != NULL){ + if (self->timeslave != NULL) { resizeBuffer(self); } - for(i = 0; i < 3; i++){ - status = hist->pDriv->GetHistogram(hist->pDriv,pCon, - bank,0,getHMDataLength(self), - self->localBuffer); - if(status == OKOK){ + for (i = 0; i < 3; i++) { + status = hist->pDriv->GetHistogram(hist->pDriv, pCon, + bank, 0, getHMDataLength(self), + self->localBuffer); + if (status == OKOK) { self->nextUpdate = time(NULL) + self->updateIntervall; - self->updateFlag = 0; + tracePar(hist->pDes->name,"!!datachange!!"); break; - } else{ - status = hist->pDriv->GetError(hist->pDriv,&iErr,pError,79); - sprintf(pBueffel,"ERROR: %s ",pError); - SCWrite(pCon,pBueffel,eError); - status = hist->pDriv->TryAndFixIt(hist->pDriv,iErr); - if(status == COTERM) { - return 0; - } + } else { + status = hist->pDriv->GetError(hist->pDriv, &iErr, pError, 79); + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s ", pError); + SCWrite(pCon, pBueffel, eError); + status = hist->pDriv->TryAndFixIt(hist->pDriv, iErr); + if (status == COTERM) { + return 0; + } } } - if(status == OKOK){ + if (status == OKOK) { return 1; } else { return HWFault; } } + /*----------------------------------------------------------------------*/ -int getHMDataHistogram(pHistMem hist, SConnection *pCon, - int bank, int start, int length, - HistInt *lData){ +int getHMDataHistogram(pHistMem hist, SConnection * pCon, + int bank, int start, int length, HistInt * lData) +{ int status; pHMdata self = hist->pDriv->data; HistInt *lStart; assert(self); - if(self->localBuffer == NULL){ + if (self->localBuffer == NULL) { resizeBuffer(self); } /* - update buffer if necessary - */ - if(mustUpdate(self)){ - status = updateHMbuffer(hist,bank,pCon); - if(status != OKOK){ + update buffer if necessary + */ + if (mustUpdate(self)) { + status = updateHMbuffer(hist, bank, pCon); + if (status != OKOK) { return status; } } /* - copy buffered data to lData - */ + copy buffered data to lData + */ lStart = self->localBuffer + start; - if(start + length > getHMDataLength(self)){ + if (start + length > getHMDataLength(self)) { length = getHMDataLength(self) - start - 1; } - memcpy(lData,lStart,length*sizeof(HistInt)); + memcpy(lData, lStart, length * sizeof(HistInt)); return 1; } + /*-----------------------------------------------------------------------*/ -HistInt *getHMDataBufferPointer(pHistMem hist,SConnection *pCon){ +HistInt *getHMDataBufferPointer(pHistMem hist, SConnection * pCon) +{ int status; pHMdata self = hist->pDriv->data; assert(self); - if(self->localBuffer == NULL || self->timeslave != NULL){ + if (self->localBuffer == NULL || self->timeslave != NULL) { resizeBuffer(self); } /* - update buffer if necessary - */ - if(mustUpdate(self)){ - status = updateHMbuffer(hist,0,pCon); - if(status != OKOK){ + update buffer if necessary + */ + if (mustUpdate(self)) { + status = updateHMbuffer(hist, 0, pCon); + if (status != OKOK) { return NULL; } } @@ -345,23 +377,26 @@ HistInt *getHMDataBufferPointer(pHistMem hist,SConnection *pCon){ } /*------------------------------------------------------------------------*/ -static long SumRow(HistInt *iData, int iDataLength, int iStart, int iEnd){ - int i; - long lSum; +static long SumRow(HistInt * iData, int iDataLength, int iStart, int iEnd) +{ + int i; + long lSum; - if(iEnd > iDataLength){ - return -1; - } + if (iEnd > iDataLength) { + return -1; + } + + lSum = 0; + for (i = iStart; i < iEnd; i++) { + lSum += iData[i]; + } + return lSum; +} - lSum = 0; - for(i = iStart; i < iEnd; i++){ - lSum += iData[i]; - } - return lSum; - } /*--------------------------------------------------------------------------*/ -long sumHMDataRectangle(pHistMem hist, SConnection *pCon, - int iStart[MAXDIM], int iEnd[MAXDIM]) { +long sumHMDataRectangle(pHistMem hist, SConnection * pCon, + int iStart[MAXDIM], int iEnd[MAXDIM]) +{ HistInt *iData; pHMdata self = hist->pDriv->data; int i, iHistLength, status, iIndex, myrank; @@ -371,168 +406,171 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon, assert(self); /* - error checking - */ + error checking + */ myrank = self->rank; - if(isInTOFMode(self)){ + if (isInTOFMode(self)) { self->iDim[self->rank] = getNoOfTimebins(self); myrank++; } - for(i = 0; i < myrank; i++){ - if( (iStart[i] < 0) || (iStart[i] > self->iDim[i]) ) { - sprintf(pBueffel,"ERROR: %d is out of data dimension range", - iStart[i]); - SCWrite(pCon,pBueffel,eError); - return -1; - } - if( (iEnd[i] < 0) || (iEnd[i] > self->iDim[i]) ){ - sprintf(pBueffel,"ERROR: %d is out of data dimension range", - iEnd[i]); - SCWrite(pCon,pBueffel,eError); - return -1; - } + for (i = 0; i < myrank; i++) { + if ((iStart[i] < 0) || (iStart[i] > self->iDim[i])) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %d is out of data dimension range", + iStart[i]); + SCWrite(pCon, pBueffel, eError); + return -1; + } + if ((iEnd[i] < 0) || (iEnd[i] > self->iDim[i])) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %d is out of data dimension range", + iEnd[i]); + SCWrite(pCon, pBueffel, eError); + return -1; + } } - - if(self->localBuffer == NULL){ + + if (self->localBuffer == NULL) { resizeBuffer(self); } /* - get an update of the HM if necessary - */ - if(mustUpdate(self)){ - status = updateHMbuffer(hist,0,pCon); - if(status != OKOK){ + get an update of the HM if necessary + */ + if (mustUpdate(self)) { + status = updateHMbuffer(hist, 0, pCon); + if (status != OKOK) { return -1; } } iHistLength = getHMDataLength(self); - /* actually sum */ - switch(myrank) - { - case 1: - lSum = SumRow(self->localBuffer, iHistLength, - iStart[0], iEnd[0]); - break; - case 2: - if(isInTOFMode(self)){ - lSum = 0; - for(i = iStart[0]; i < iEnd[0]; i++){ - iIndex = i*self->iDim[1]; - lRowSum = SumRow(self->localBuffer,iHistLength, - iIndex+iStart[1], iIndex+iEnd[1]); - lSum += lRowSum; - } - } else { - lSum = 0; - for(i = iStart[1]; i < iEnd[1]; i++){ - iIndex = i*self->iDim[0]; - lRowSum = SumRow(self->localBuffer,iHistLength, - iIndex+iStart[0], iIndex+iEnd[0]); - lSum += lRowSum; - } - } - break; - default: - sprintf(pBueffel, - "ERROR: summing in %d dimensions not yet implemented", - myrank); - SCWrite(pCon,pBueffel,eError); - return -1; - break; - } - if(lSum < 0){ - lSum = -lSum; + /* actually sum */ + switch (myrank) { + case 1: + lSum = SumRow(self->localBuffer, iHistLength, iStart[0], iEnd[0]); + break; + case 2: + if (isInTOFMode(self)) { + lSum = 0; + for (i = iStart[0]; i < iEnd[0]; i++) { + iIndex = i * self->iDim[1]; + lRowSum = SumRow(self->localBuffer, iHistLength, + iIndex + iStart[1], iIndex + iEnd[1]); + lSum += lRowSum; + } + } else { + lSum = 0; + for (i = iStart[1]; i < iEnd[1]; i++) { + iIndex = i * self->iDim[0]; + lRowSum = SumRow(self->localBuffer, iHistLength, + iIndex + iStart[0], iIndex + iEnd[0]); + lSum += lRowSum; + } } - return lSum; - } -/*--------------------------------------------------------------------------*/ -int loadHMData(pHMdata self, SConnection *pCon, char *filename){ - FILE *fd = NULL; - char buffer[1024], pNumber[80], *pPtr; - long i = 0, length; - HistInt *data = NULL; - - fd = fopen(filename,"r"); - if(fd == NULL){ - snprintf(buffer,1023,"ERROR: failed to open file %s", filename); - SCWrite(pCon,buffer,eError); - return 0; - } - length = getHMDataLength(self); - if(self->localBuffer == NULL || self->timeslave != NULL){ - resizeBuffer(self); - } - data = self->localBuffer; - if(data == NULL){ - SCWrite(pCon,"ERROR: failed to allocate HM", eError); - fclose(fd); - return 0; - } - while(i < length && fgets(buffer,1024,fd) != NULL){ - pPtr = buffer; - while(pPtr != NULL){ - pPtr = sicsNextNumber(pPtr,pNumber); - if(pPtr != NULL){ - data[i] = atoi(pNumber); - i++; - } - } - } - if(i < length-1){ - SCWrite(pCon,"WARNING: not enough data in file to fill HM",eWarning); - } - fclose(fd); - return 1; + break; + default: + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: summing in %d dimensions not yet implemented", myrank); + SCWrite(pCon, pBueffel, eError); + return -1; + break; + } + if (lSum < 0) { + lSum = -lSum; + } + return lSum; } + +/*--------------------------------------------------------------------------*/ +int loadHMData(pHMdata self, SConnection * pCon, char *filename) +{ + FILE *fd = NULL; + char buffer[1024], pNumber[80], *pPtr; + long i = 0, length; + HistInt *data = NULL; + + fd = fopen(filename, "r"); + if (fd == NULL) { + snprintf(buffer, 1023, "ERROR: failed to open file %s", filename); + SCWrite(pCon, buffer, eError); + return 0; + } + length = getHMDataLength(self); + if (self->localBuffer == NULL || self->timeslave != NULL) { + resizeBuffer(self); + } + data = self->localBuffer; + if (data == NULL) { + SCWrite(pCon, "ERROR: failed to allocate HM", eError); + fclose(fd); + return 0; + } + while (i < length && fgets(buffer, 1024, fd) != NULL) { + pPtr = buffer; + while (pPtr != NULL) { + pPtr = sicsNextNumber(pPtr, pNumber); + if (pPtr != NULL) { + data[i] = atoi(pNumber); + i++; + } + } + } + if (i < length - 1) { + SCWrite(pCon, "WARNING: not enough data in file to fill HM", eWarning); + } + fclose(fd); + return 1; +} + /*========================================================================== * subsampling was stolen from the SinqHTTP histogram memory code and * thus contains some additional indirections. * =========================================================================*/ -static pNXDS hmDataToNXDataset(pHMdata self){ - pNXDS result = NULL; - int i; - - result = malloc(sizeof(NXDS)); - if(result == NULL){ - return NULL; - } - memset(result,0,sizeof(NXDS)); - result->magic = MAGIC; - result->type = NX_INT32; - result->rank = self->rank; - if(isInTOFMode(self)){ - result->rank++; - } - result->dim = malloc(self->rank*sizeof(int)); - if(result->dim == NULL){ - free(result); - return NULL; - } - for(i = 0; i < self->rank; i++){ - result->dim[i] = self->iDim[i]; - } - if(isInTOFMode(self)){ - result->dim[result->rank-1] = getNoOfTimebins(self); - } - if(self->localBuffer == NULL){ - resizeBuffer(self); - } - result->u.iPtr = self->localBuffer; - return result; +static pNXDS hmDataToNXDataset(pHMdata self) +{ + pNXDS result = NULL; + int i; + + result = malloc(sizeof(NXDS)); + if (result == NULL) { + return NULL; + } + memset(result, 0, sizeof(NXDS)); + result->magic = MAGIC; + result->type = NX_INT32; + result->rank = self->rank; + if (isInTOFMode(self)) { + result->rank++; + } + result->dim = malloc(self->rank * sizeof(int)); + if (result->dim == NULL) { + free(result); + return NULL; + } + for (i = 0; i < self->rank; i++) { + result->dim[i] = self->iDim[i]; + } + if (isInTOFMode(self)) { + result->dim[result->rank - 1] = getNoOfTimebins(self); + } + if (self->localBuffer == NULL) { + resizeBuffer(self); + } + result->u.iPtr = self->localBuffer; + return result; } + /*---------------------------------------------------------------------------*/ -static pNXDS subSampleCommand(pNXDS source, char *command, - char *error, int errLen){ - int startDim[NX_MAXRANK], endDim[NX_MAXRANK]; +static pNXDS subSampleCommand(pNXDS source, char *command, + char *error, int errLen) +{ + int64_t startDim[NX_MAXRANK], endDim[NX_MAXRANK]; int dim = 0, start = 0, i; char *pPtr = NULL, token[80]; - - pPtr = stptok(command,token,79,":\0"); - while((pPtr = stptok(pPtr,token,79,":\0")) != NULL){ - if(start == 0){ + + pPtr = stptok(command, token, 79, ":\0"); + while ((pPtr = stptok(pPtr, token, 79, ":\0")) != NULL) { + if (start == 0) { startDim[dim] = atoi(token); start = 1; } else { @@ -542,99 +580,112 @@ static pNXDS subSampleCommand(pNXDS source, char *command, } } - if(dim < source->rank - 1){ - strncpy(error,"ERROR: Not enough border values specified for subsampling",errLen); + if (dim < source->rank - 1) { + strlcpy(error, + "ERROR: Not enough border values specified for subsampling", + errLen); return NULL; - } - for(i = 0; i < source->rank; i++){ - if(startDim[i] < 0 || startDim[i] >= source->dim[i]){ - snprintf(error,errLen,"ERROR: invalid start value %d for dimension %d", startDim[1], i); + } + for (i = 0; i < source->rank; i++) { + if (startDim[i] < 0 || startDim[i] >= source->dim[i]) { + snprintf(error, errLen, + "ERROR: invalid start value %d for dimension %d", + (int)startDim[1], i); return NULL; } - if(endDim[i] < startDim[i] || endDim[i] >= source->dim[i]){ - snprintf(error,errLen,"ERROR: invalid end value %d for dimension %d", endDim[1], i); + if (endDim[i] < startDim[i] || endDim[i] >= source->dim[i]) { + snprintf(error, errLen, + "ERROR: invalid end value %d for dimension %d", (int)endDim[1], + i); return NULL; } } - - return cutNXDataset(source,startDim,endDim); -} -/*-----------------------------------------------------------------------------*/ -static pNXDS sumCommand(pNXDS source, char *command, char *error, int errlen){ - int dimNo = -1, start = -1, end = -1; - char *pPtr = NULL; - char token[80]; - - pPtr = stptok(command,token,79,":\0"); - pPtr = stptok(pPtr,token,79,":\0"); - if(pPtr != NULL){ - dimNo = atoi(token); - } - pPtr = stptok(pPtr,token,79,":\0"); - if(pPtr != NULL){ - start = atoi(token); - } - pPtr = stptok(pPtr,token,79,":\0"); - if(pPtr != NULL){ - end = atoi(token); - } - if(dimNo < 0 || dimNo > source->rank - 1){ - snprintf(error,errlen,"ERROR: invalid dimension %d requestd to sum", dimNo); - return NULL; - } - if(end < 0 || end > source->dim[dimNo] || start < 0 || start > end){ - snprintf(error,errlen,"ERROR: invalid summing limits %d to %d requested", start,end); - return NULL; - } - - return sumNXDataset(source,dimNo, start, end); - } -/*--------------------------------------------------------------------------*/ -HistInt *subSample(pHMdata self, char *command, - char *error, int errLen){ - pNXDS source = NULL, start = NULL; - pNXDS result = NULL; - char *pPtr = NULL; - char subCommand[132]; - HistInt *data = NULL; - int length; - - start = hmDataToNXDataset(self); - if(start == NULL){ - strncpy(error,"Out-Of-Memory or no data while subsampling ", - errLen); - return NULL; - } - - source = start; - pPtr = command; - while((pPtr = stptok(pPtr,subCommand,131,";\0\r\n")) != NULL){ - if(strstr(subCommand,"sample") != NULL){ - result = subSampleCommand(source,subCommand,error, errLen); - } else if(strstr(subCommand,"sum") != NULL){ - result = sumCommand(source,subCommand,error, errLen); - } else { - strncpy(error,"ERROR: invalid subcommand to process requested",errLen); - return NULL; - } - if(result == NULL){ - return NULL; - } - if(source != start){ - dropNXDataset(source); - } - source = result; - } - length = getNXDatasetLength(result); - data = malloc((length+1)*sizeof(int)); - if(data == NULL){ - strncpy(error,"Out-Of-Mmeory in Subsample", errLen); - dropNXDataset(result); - return NULL; - } - data[0] = length; - memcpy(data+1,result->u.iPtr, length*sizeof(int)); - dropNXDataset(result); - return data; + return cutNXDataset(source, startDim, endDim); +} + +/*-----------------------------------------------------------------------------*/ +static pNXDS sumCommand(pNXDS source, char *command, char *error, + int errlen) +{ + int dimNo = -1, start = -1, end = -1; + char *pPtr = NULL; + char token[80]; + + pPtr = stptok(command, token, 79, ":\0"); + pPtr = stptok(pPtr, token, 79, ":\0"); + if (pPtr != NULL) { + dimNo = atoi(token); + } + pPtr = stptok(pPtr, token, 79, ":\0"); + if (pPtr != NULL) { + start = atoi(token); + } + pPtr = stptok(pPtr, token, 79, ":\0"); + if (pPtr != NULL) { + end = atoi(token); + } + if (dimNo < 0 || dimNo > source->rank - 1) { + snprintf(error, errlen, "ERROR: invalid dimension %d requestd to sum", + dimNo); + return NULL; + } + if (end < 0 || end > source->dim[dimNo] || start < 0 || start > end) { + snprintf(error, errlen, + "ERROR: invalid summing limits %d to %d requested", start, + end); + return NULL; + } + + return sumNXDataset(source, dimNo, start, end); +} + +/*--------------------------------------------------------------------------*/ +HistInt *subSample(pHMdata self, char *command, char *error, int errLen) +{ + pNXDS source = NULL, start = NULL; + pNXDS result = NULL; + char *pPtr = NULL; + char subCommand[132]; + HistInt *data = NULL; + int length; + + + start = hmDataToNXDataset(self); + if (start == NULL) { + strlcpy(error, "Out-Of-Memory or no data while subsampling ", errLen); + return NULL; + } + + source = start; + pPtr = command; + while ((pPtr = stptok(pPtr, subCommand, 131, ";\0\r\n")) != NULL) { + if (strstr(subCommand, "sample") != NULL) { + result = subSampleCommand(source, subCommand, error, errLen); + } else if (strstr(subCommand, "sum") != NULL) { + result = sumCommand(source, subCommand, error, errLen); + } else { + strlcpy(error, "ERROR: invalid subcommand to process requested", + errLen); + return NULL; + } + if (result == NULL) { + return NULL; + } + if (source != start) { + dropNXDataset(source); + } + source = result; + } + length = getNXDatasetLength(result); + data = malloc((length + 1) * sizeof(int)); + if (data == NULL) { + strlcpy(error, "Out-Of-Mmeory in Subsample", errLen); + dropNXDataset(result); + return NULL; + } + data[0] = length; + memcpy(data + 1, result->u.iPtr, length * sizeof(int)); + dropNXDataset(result); + return data; } diff --git a/hmdata.h b/hmdata.h index ebacd051..0cb43c5e 100644 --- a/hmdata.h +++ b/hmdata.h @@ -12,56 +12,50 @@ #include "sics.h" #include "HistMem.h" #include "stringdict.h" -#define MAXCHAN 16834 +#define MAXCHAN 16834 #define MAXDIM 3 - typedef struct __hmdata{ - int rank; - int iDim[MAXDIM]; - int nTimeChan; - float timeBinning[MAXCHAN]; - int tofMode; - time_t nextUpdate; - int updateIntervall; - int updateFlag; - HistInt *localBuffer; - struct __hmdata *timeslave; -} HMdata, *pHMdata; +typedef struct __hmdata { + int rank; + int iDim[MAXDIM]; + int nTimeChan; + float timeBinning[MAXCHAN]; + int tofMode; + time_t nextUpdate; + int updateIntervall; + HistInt *localBuffer; + struct __hmdata *timeslave; +} HMdata, *pHMdata; - pHMdata makeHMData(void); - void killHMData(pHMdata self); - void clearHMData(pHMdata self); - - int configureHMdata(pHMdata self, pStringDict pOpt, - SConnection *pCon); - int resizeBuffer(pHMdata self); - int genTimeBinning(pHMdata self, float start, float step, - int noSteps); - int setTimeBin(pHMdata self, int index, float value); +pHMdata makeHMData(void); +void killHMData(pHMdata self); +void clearHMData(pHMdata self); - int getNoOfTimebins(pHMdata self); - float *getTimeBinning(pHMdata self); - int isInTOFMode(pHMdata self); - void clearTimeBinning(pHMdata self); +int configureHMdata(pHMdata self, pStringDict pOpt, SConnection * pCon); +int resizeBuffer(pHMdata self); +int genTimeBinning(pHMdata self, float start, float step, int noSteps); +int setTimeBin(pHMdata self, int index, float value); - void getHMDataDim(pHMdata self, int iDIM[MAXDIM], int *rank); - long getHMDataLength(pHMdata self); +int getNoOfTimebins(pHMdata self); +float *getTimeBinning(pHMdata self); +int isInTOFMode(pHMdata self); +void clearTimeBinning(pHMdata self); - int getHMDataHistogram(pHistMem hist, SConnection *pCon, - int bank, int start, int length, - HistInt *lData); - void updateHMData(pHMdata self); - HistInt *getHMDataBufferPointer(pHistMem hist, SConnection *pCon); +void getHMDataDim(pHMdata self, int iDIM[MAXDIM], int *rank); +long getHMDataLength(pHMdata self); - long sumHMDataRectangle(pHistMem self, SConnection *pCon, - int start[MAXDIM], int end[MAXDIM]); - int loadHMData(pHMdata self, SConnection *pCon, char *filename); +int getHMDataHistogram(pHistMem hist, SConnection * pCon, + int bank, int start, int length, HistInt * lData); +void updateHMData(pHMdata self); +HistInt *getHMDataBufferPointer(pHistMem hist, SConnection * pCon); - HistInt *subSample(pHMdata self, char *command, - char *error, int errLen); +long sumHMDataRectangle(pHistMem self, SConnection * pCon, + int start[MAXDIM], int end[MAXDIM]); +int loadHMData(pHMdata self, SConnection * pCon, char *filename); + +HistInt *subSample(pHMdata self, char *command, char *error, int errLen); #endif - diff --git a/hmslave.c b/hmslave.c index 0a59538f..8615c3a0 100644 --- a/hmslave.c +++ b/hmslave.c @@ -16,7 +16,7 @@ * copyright: see file COPYRIGHT * * Mark Koennecke, March 2007 - */ + */ #include #include #include @@ -27,267 +27,303 @@ #include typedef struct { - pHistMem master; - int bank; - }*HMSlave, sHMSlave; + pHistMem master; + int bank; +} *HMSlave, sHMSlave; /*------------------------------------------------------------------- Configures the HM from the options in pOpt and the HM data structure Returns 1 on success, 0 on failure ---------------------------------------------------------------------*/ -static int HMSlaveConfigure(pHistDriver self, SConnection *pCon, - pStringDict pOpt, SicsInterp *pSics){ - HMSlave pPriv = NULL; - char buffer[80], error[256]; - - pPriv =(HMSlave)self->pPriv; +static int HMSlaveConfigure(pHistDriver self, SConnection * pCon, + pStringDict pOpt, SicsInterp * pSics) +{ + HMSlave pPriv = NULL; + char buffer[80], error[256]; - if(StringDictGet(pOpt,"master",buffer, 79) == 1){ - pPriv->master = (pHistMem)FindCommandData(pServ->pSics,buffer,"HistMem"); - if(pPriv->master == NULL){ - snprintf(error,255,"ERROR: failed to find master HM %s", buffer); - SCWrite(pCon,error,eError); - return 0; - } - } else { - SCWrite(pCon,"ERROR: required configuration option master missing", - eError); - return 0; - } + pPriv = (HMSlave) self->pPriv; - if(StringDictGet(pOpt,"bank",buffer, 79) == 1){ - pPriv->bank = atoi(buffer); - } else { - SCWrite(pCon,"ERROR: required configuration option bank missing", - eError); - return 0; + if (StringDictGet(pOpt, "master", buffer, 79) == 1) { + pPriv->master = + (pHistMem) FindCommandData(pServ->pSics, buffer, "HistMem"); + if (pPriv->master == NULL) { + snprintf(error, 255, "ERROR: failed to find master HM %s", buffer); + SCWrite(pCon, error, eError); + return 0; } - - return 1; + } else { + SCWrite(pCon, "ERROR: required configuration option master missing", + eError); + return 0; + } + + if (StringDictGet(pOpt, "bank", buffer, 79) == 1) { + pPriv->bank = atoi(buffer); + } else { + SCWrite(pCon, "ERROR: required configuration option bank missing", + eError); + return 0; + } + + return 1; } + /*-------------------------------------------------------------------- Start histogramming, Returns HWFault on failure, 1 on success ----------------------------------------------------------------------*/ -static int HMSlaveStart(pHistDriver self,SConnection *pCon){ - HMSlave pPriv = NULL; - - pPriv =(HMSlave)self->pPriv; - return 1; +static int HMSlaveStart(pHistDriver self, SConnection * pCon) +{ + HMSlave pPriv = NULL; + + pPriv = (HMSlave) self->pPriv; + return 1; } + /*-------------------------------------------------------------------- Stops histogramming, Returns HWFault on failure, 1 on success ----------------------------------------------------------------------*/ -static int HMSlaveHalt(pHistDriver self){ - HMSlave pPriv = NULL; - - pPriv =(HMSlave)self->pPriv; - return 1; +static int HMSlaveHalt(pHistDriver self) +{ + HMSlave pPriv = NULL; + + pPriv = (HMSlave) self->pPriv; + return 1; } + /*-------------------------------------------------------------------- Checks histogramming status, Returns HWFault on failure, HWIdle when finished, HWBusy when counting ----------------------------------------------------------------------*/ -static int HMSlaveCountStatus(pHistDriver self,SConnection *pCon){ - HMSlave pPriv = NULL; - - pPriv =(HMSlave)self->pPriv; - return HWIdle; +static int HMSlaveCountStatus(pHistDriver self, SConnection * pCon) +{ + HMSlave pPriv = NULL; + + pPriv = (HMSlave) self->pPriv; + return HWIdle; } + /*-------------------------------------------------------------------- Get info on error after last HWFault, returns 1 always. Puts an int error code into *code and errLen chars of error description into error ----------------------------------------------------------------------*/ -static int HMSlaveGetError(pHistDriver self,int *code, - char *error, int errLen){ - HMSlave pPriv = NULL; - - pPriv =(HMSlave)self->pPriv; - strncpy(error,"Weird status: slaves do not err..",errLen); - *code = -77; - return 1; +static int HMSlaveGetError(pHistDriver self, int *code, + char *error, int errLen) +{ + HMSlave pPriv = NULL; + + pPriv = (HMSlave) self->pPriv; + strlcpy(error, "Weird status: slaves do not err..", errLen); + *code = -77; + return 1; } + /*-------------------------------------------------------------------- Try to fix the HM error in code. Returns COREDO when the last operation needs to be redone, COTERM when the error cannot be fixed. ----------------------------------------------------------------------*/ -static int HMSlaveFixIt(pHistDriver self,int code){ - HMSlave pPriv = NULL; - - pPriv =(HMSlave)self->pPriv; - return COTERM; +static int HMSlaveFixIt(pHistDriver self, int code) +{ + HMSlave pPriv = NULL; + + pPriv = (HMSlave) self->pPriv; + return COTERM; } + /*-------------------------------------------------------------------- GetData reads updates the internal cache of monitor values from the hardware, Returns 1 or HWFault ----------------------------------------------------------------------*/ -static int HMSlaveGetData(pHistDriver self,SConnection *pCon){ - HMSlave pPriv = NULL; - - pPriv =(HMSlave)self->pPriv; - return 1; +static int HMSlaveGetData(pHistDriver self, SConnection * pCon) +{ + HMSlave pPriv = NULL; + + pPriv = (HMSlave) self->pPriv; + return 1; } + /*-------------------------------------------------------------------- GetMonitor reads the monitor value i. Returns either the monitor value or -9999 if no such monitor exists or an error occurred ----------------------------------------------------------------------*/ -static long HMSlaveGetMonitor(pHistDriver self,int i, SConnection *pCon){ - HMSlave pPriv = NULL; - - pPriv =(HMSlave)self->pPriv; - return -9999; +static long HMSlaveGetMonitor(pHistDriver self, int i, SConnection * pCon) +{ + HMSlave pPriv = NULL; + + pPriv = (HMSlave) self->pPriv; + return -9999; } + /*-------------------------------------------------------------------- GetTime reads the total counting time. Returns either the value or -9999.99 if no such value exists or an error occurred ----------------------------------------------------------------------*/ -static float HMSlaveGetTime(pHistDriver self,SConnection *pCon){ - HMSlave pPriv = NULL; - - pPriv =(HMSlave)self->pPriv; - return -9999.99; +static float HMSlaveGetTime(pHistDriver self, SConnection * pCon) +{ + HMSlave pPriv = NULL; + + pPriv = (HMSlave) self->pPriv; + return -9999.99; } + /*-------------------------------------------------------------------- Pause histogramming, Returns HWFault on failure, 1 on success ----------------------------------------------------------------------*/ -static int HMSlavePause(pHistDriver self,SConnection *pCon){ - HMSlave pPriv = NULL; - - pPriv =(HMSlave)self->pPriv; - return 1; +static int HMSlavePause(pHistDriver self, SConnection * pCon) +{ + HMSlave pPriv = NULL; + + pPriv = (HMSlave) self->pPriv; + return 1; } + /*-------------------------------------------------------------------- Continue histogramming, Returns HWFault on failure, 1 on success ----------------------------------------------------------------------*/ -static int HMSlaveContinue(pHistDriver self,SConnection *pCon){ - HMSlave pPriv = NULL; - - pPriv =(HMSlave)self->pPriv; - return 1; +static int HMSlaveContinue(pHistDriver self, SConnection * pCon) +{ + HMSlave pPriv = NULL; + + pPriv = (HMSlave) self->pPriv; + return 1; } + /*-------------------------------------------------------------------- Free the data associated with the private data structure of the driver ----------------------------------------------------------------------*/ -static int HMSlaveFree(pHistDriver self){ - HMSlave pPriv = NULL; - - pPriv =(HMSlave)self->pPriv; - if(pPriv != NULL){ - free(pPriv); - } - self->pPriv = NULL; - return 1; +static int HMSlaveFree(pHistDriver self) +{ + HMSlave pPriv = NULL; + + pPriv = (HMSlave) self->pPriv; + if (pPriv != NULL) { + free(pPriv); + } + self->pPriv = NULL; + return 1; } + /*------------------------------------------------------------------- * fixTimebinning assures that our time binning dn the masters * time binning are the same. So that diemsnions are right * ------------------------------------------------------------------*/ - static int fixTimeBinning(pHistDriver self, SConnection *pCon){ - HMSlave pPriv = NULL; - - pPriv =(HMSlave)self->pPriv; - if(isInTOFMode(pPriv->master->pDriv->data) && - getNoOfTimebins(pPriv->master->pDriv->data) != - getNoOfTimebins(self->data)){ - self->data->tofMode = 1; - self->data->nTimeChan = getNoOfTimebins(pPriv->master->pDriv->data); - if(!resizeBuffer(self->data)) { - SCWrite(pCon, - "ERROR: out of memory allocating HMData for slave", - eError); - return 0; - } +static int fixTimeBinning(pHistDriver self, SConnection * pCon) +{ + HMSlave pPriv = NULL; + + pPriv = (HMSlave) self->pPriv; + if (isInTOFMode(pPriv->master->pDriv->data) && + getNoOfTimebins(pPriv->master->pDriv->data) != + getNoOfTimebins(self->data)) { + self->data->tofMode = 1; + self->data->nTimeChan = getNoOfTimebins(pPriv->master->pDriv->data); + if (!resizeBuffer(self->data)) { + SCWrite(pCon, + "ERROR: out of memory allocating HMData for slave", eError); + return 0; } - return 1; - } + } + return 1; +} + /*-------------------------------------------------------------------- Set The HM data or a subset of it. Returns HWFault or 1 ----------------------------------------------------------------------*/ static int HMSlaveSetHistogram(pHistDriver self, - SConnection *pCon, - int i, int iStart, int iEnd, HistInt *pData){ - HMSlave pPriv = NULL; - HistInt *start = NULL; - - pPriv =(HMSlave)self->pPriv; - if(fixTimeBinning(self,pCon) == 1){ - start = self->data->localBuffer + iStart; - memcpy(start,pData,(iEnd - iStart)*sizeof(HistInt)); - return 1; - } else { - return 0; - } + SConnection * pCon, + int i, int iStart, int iEnd, + HistInt * pData) +{ + HMSlave pPriv = NULL; + HistInt *start = NULL; + + pPriv = (HMSlave) self->pPriv; + if (fixTimeBinning(self, pCon) == 1) { + start = self->data->localBuffer + iStart; + memcpy(start, pData, (iEnd - iStart) * sizeof(HistInt)); + return 1; + } else { + return 0; + } } + /*-------------------------------------------------------------------- Set HM to a preset value, Returns HWFault on failure, 1 on success ----------------------------------------------------------------------*/ -static int HMSlavePreset(pHistDriver self,SConnection *pCon, - HistInt value){ - HMSlave pPriv = NULL; - int i; - - pPriv =(HMSlave)self->pPriv; - if(fixTimeBinning(self,pCon) == 1){ - for(i = 0; i < getHMDataLength(self->data); i++){ - self->data->localBuffer[i] = value; - } - return 1; - } else { - return 0; +static int HMSlavePreset(pHistDriver self, SConnection * pCon, + HistInt value) +{ + HMSlave pPriv = NULL; + int i; + + pPriv = (HMSlave) self->pPriv; + if (fixTimeBinning(self, pCon) == 1) { + for (i = 0; i < getHMDataLength(self->data); i++) { + self->data->localBuffer[i] = value; } + return 1; + } else { + return 0; + } } + /*-------------------------------------------------------------------- get The HM data or a subset of it. Returns HWFault or 1 ----------------------------------------------------------------------*/ static int HMSlaveGetHistogram(pHistDriver self, - SConnection *pCon, - int i, int iStart, int iEnd, HistInt *pData){ - HMSlave pPriv = NULL; - - pPriv = (HMSlave)self->pPriv; - return pPriv->master->pDriv->GetHistogram(pPriv->master->pDriv, - pCon, pPriv->bank, iStart, iEnd, pData); + SConnection * pCon, + int i, int iStart, int iEnd, + HistInt * pData) +{ + HMSlave pPriv = NULL; + + pPriv = (HMSlave) self->pPriv; + return pPriv->master->pDriv->GetHistogram(pPriv->master->pDriv, + pCon, pPriv->bank, iStart, + iEnd, pData); } + /*-------------------------------------------------------------------- Make the HMDriver, returns a driver or NULL on failure ----------------------------------------------------------------------*/ -pHistDriver MakeHMSlaveHM(pStringDict pOption){ - pHistDriver pNew = NULL; - HMSlave pPriv = NULL; +pHistDriver MakeHMSlaveHM(pStringDict pOption) +{ + pHistDriver pNew = NULL; + HMSlave pPriv = NULL; - /* create the general driver */ - pNew = CreateHistDriver(pOption); - if(!pNew){ - return NULL; - } + /* create the general driver */ + pNew = CreateHistDriver(pOption); + if (!pNew) { + return NULL; + } - /*Create private data structure*/ - pPriv = (HMSlave)malloc(sizeof(sHMSlave)); - if(pPriv == NULL){ - return NULL; - } - pNew->pPriv = pPriv; - - /* add our options */ - StringDictAddPair(pOption,"master","unknown"); - StringDictAddPair(pOption,"bank","1"); + /*Create private data structure */ + pPriv = (HMSlave) malloc(sizeof(sHMSlave)); + if (pPriv == NULL) { + return NULL; + } + pNew->pPriv = pPriv; - /* configure all those functions */ - pNew->Configure = HMSlaveConfigure; - pNew->Start = HMSlaveStart; - pNew->Halt = HMSlaveHalt; - pNew->GetCountStatus = HMSlaveCountStatus; - pNew->GetError = HMSlaveGetError; - pNew->TryAndFixIt = HMSlaveFixIt; - pNew->GetData = HMSlaveGetData; - pNew->GetHistogram = HMSlaveGetHistogram; - pNew->SetHistogram = HMSlaveSetHistogram; - pNew->GetMonitor = HMSlaveGetMonitor; - pNew->GetTime = HMSlaveGetTime; - pNew->Preset = HMSlavePreset; - pNew->FreePrivate = HMSlaveFree; - pNew->Pause = HMSlavePause; - pNew->Continue = HMSlaveContinue; + /* add our options */ + StringDictAddPair(pOption, "master", "unknown"); + StringDictAddPair(pOption, "bank", "1"); - return pNew; + /* configure all those functions */ + pNew->Configure = HMSlaveConfigure; + pNew->Start = HMSlaveStart; + pNew->Halt = HMSlaveHalt; + pNew->GetCountStatus = HMSlaveCountStatus; + pNew->GetError = HMSlaveGetError; + pNew->TryAndFixIt = HMSlaveFixIt; + pNew->GetData = HMSlaveGetData; + pNew->GetHistogram = HMSlaveGetHistogram; + pNew->SetHistogram = HMSlaveSetHistogram; + pNew->GetMonitor = HMSlaveGetMonitor; + pNew->GetTime = HMSlaveGetTime; + pNew->Preset = HMSlavePreset; + pNew->FreePrivate = HMSlaveFree; + pNew->Pause = HMSlavePause; + pNew->Continue = HMSlaveContinue; + + return pNew; } diff --git a/ifile.c b/ifile.c index 04640f5e..a35fc862 100644 --- a/ifile.c +++ b/ifile.c @@ -43,208 +43,228 @@ #include #include #include +#include #include "ifile.h" /*====================== Locals ============================================*/ - static IPair *CreateNewEntry(char *name, char *val, IPair *pN) - { - IPair *pRes = NULL; - - pRes = (IPair *)malloc(sizeof(IPair)); - if(!pRes) - return NULL; - memset(pRes,0,sizeof(IPair)); - if(name) - pRes->name = strdup(name); - if(val) - pRes->value = strdup(val); - pRes->pNext = pN; - return pRes; - } +static IPair *CreateNewEntry(char *name, char *val, IPair * pN) +{ + IPair *pRes = NULL; + + pRes = (IPair *) malloc(sizeof(IPair)); + if (!pRes) + return NULL; + memset(pRes, 0, sizeof(IPair)); + if (name) + pRes->name = strdup(name); + if (val) + pRes->value = strdup(val); + pRes->pNext = pN; + return pRes; +} + /*--------------------------------------------------------------------------*/ - static void RemoveWhiteSpace(char *pText) - { - int i, ii, i3; - char *pPtr; - - assert(pText); - - /* find start */ - i = 0; - while(isspace(pText[i])) - { - i++; - } - - /* find end */ - ii = strlen(pText); +static void RemoveWhiteSpace(char *pText) +{ + int i, ii, i3; + char *pPtr; + + assert(pText); + + /* find start */ + i = 0; + while (isspace(pText[i])) { + i++; + } + + /* find end */ + ii = strlen(pText); + ii--; + while ((isspace(pText[ii])) || (pText[ii] == '\n')) { ii--; - while( (isspace(pText[ii])) || (pText[ii] == '\n') ) - { - ii--; - } - - /* copy it */ - pPtr = pText; - for(i3 = i; i3 < (ii+1); i3++) - { - *pPtr = pText[i3]; - pPtr++; - } - *pPtr = '\0'; - } + } + + /* copy it */ + pPtr = pText; + for (i3 = i; i3 < (ii + 1); i3++) { + *pPtr = pText[i3]; + pPtr++; + } + *pPtr = '\0'; +} + /*===========================================================================*/ - IPair *IFReadConfigFile(FILE *fd) - { - IPair *pList = NULL; - char pBueffel[256]; - char pName[132]; - char pValue[132]; - char *pPos; - int iLen; - - assert(fd); - - while(!feof(fd)) - { - fgets(pBueffel,255,fd); - if(feof(fd)) - continue; +IPair *IFReadConfigFile(FILE * fd) +{ + IPair *pList = NULL; + char pBueffel[256]; + char pName[132]; + char pValue[132]; + char *pPos; + int iLen; - pPos = strchr(pBueffel,'='); - if(!pPos) - continue; - if(pBueffel[0] == '#') - continue; - - iLen = pPos - pBueffel; - strncpy(pName,pBueffel,iLen); - pName[iLen] = '\0'; - strcpy(pValue,(pPos+1)); - RemoveWhiteSpace(pName); - RemoveWhiteSpace(pValue); - pList = CreateNewEntry(pName,pValue,pList); - if(!pList) - return NULL; - } - return pList; - } -/*--------------------------------------------------------------------------*/ - char *IFindOption(IPair *pList, char *name) - { - IPair *pCurrent; - - if(!pList) - { - return NULL; - } - - pCurrent = pList; - while(pCurrent) - { - if(strcmp(name,pCurrent->name) == 0) - return pCurrent->value; - pCurrent = pCurrent->pNext; - } - return NULL; - } -/*--------------------------------------------------------------------------*/ - IPair *IFAddOption(IPair *pList,char *name, char *value) - { - return CreateNewEntry(name,value,pList); + assert(fd); + + while (!feof(fd)) { + fgets(pBueffel, 255, fd); + if (feof(fd)) + continue; + + pPos = strchr(pBueffel, '='); + if (!pPos) + continue; + if (pBueffel[0] == '#') + continue; + + iLen = pPos - pBueffel; + strncpy(pName, pBueffel, iLen); + pName[iLen] = '\0'; + strlcpy(pValue, (pPos + 1),131); + RemoveWhiteSpace(pName); + RemoveWhiteSpace(pValue); + pList = CreateNewEntry(pName, pValue, pList); + if (!pList) + return NULL; } + return pList; +} /*--------------------------------------------------------------------------*/ - IPair *IFSetOption(IPair *pList,char *name, char *value) - { - IPair *pCurrent; - if(NULL!=pList) - { - pCurrent = pList; - while((NULL!=pCurrent) && (0!=strcmp(name,pCurrent->name))) - { - pCurrent = pCurrent->pNext; - } - if(NULL!=pCurrent) - { /* replace value */ - free(pCurrent->value); - pCurrent->value = strdup(value); - return pCurrent; - } +char *IFindOption(IPair * pList, char *name) +{ + IPair *pCurrent; + + if (!pList) { + return NULL; + } + + pCurrent = pList; + while (pCurrent) { + if (strcmp(name, pCurrent->name) == 0) + return pCurrent->value; + pCurrent = pCurrent->pNext; + } + return NULL; +} + +/*--------------------------------------------------------------------------*/ +IPair *IFAddOption(IPair * pList, char *name, char *value) +{ + return CreateNewEntry(name, value, pList); +} + +/*--------------------------------------------------------------------------*/ +IPair *IFSetOption(IPair * pList, char *name, char *value) +{ + IPair *pCurrent; + if (NULL != pList) { + pCurrent = pList; + while ((NULL != pCurrent) && (0 != strcmp(name, pCurrent->name))) { + pCurrent = pCurrent->pNext; + } + if (NULL != pCurrent) { /* replace value */ + free(pCurrent->value); + pCurrent->value = strdup(value); + return pCurrent; } - return CreateNewEntry(name,value,pList); } + return CreateNewEntry(name, value, pList); +} /*-------------------------------------------------------------------------*/ - int IFSaveOptions(IPair *pList,FILE *fd) - { - IPair *pCurrent; - - assert(fd); - assert(pList); - - pCurrent = pList; - while(pCurrent) - { - fprintf(fd,"%s = %s \n", pCurrent->name, pCurrent->value); - pCurrent = pCurrent->pNext; - } - return 1; - } +int IFSaveOptions(IPair * pList, FILE * fd) +{ + IPair *pCurrent; + + assert(fd); + assert(pList); + + pCurrent = pList; + while (pCurrent) { + fprintf(fd, "%s = %s \n", pCurrent->name, pCurrent->value); + pCurrent = pCurrent->pNext; + } + return 1; +} + /*--------------------------------------------------------------------------*/ - void IFDeleteOptions(IPair *pList) - { - IPair *pCurrent, *pTemp; - - pCurrent = pList; - while(pCurrent) - { - pTemp = pCurrent->pNext; - if(pCurrent->name) - { - free(pCurrent->name); - } - if(pCurrent->value) - { - free(pCurrent->value); - } - free(pCurrent); - pCurrent = pTemp; +void IFDeleteOptions(IPair * pList) +{ + IPair *pCurrent, *pTemp; + + pCurrent = pList; + while (pCurrent) { + pTemp = pCurrent->pNext; + if (pCurrent->name) { + free(pCurrent->name); } + if (pCurrent->value) { + free(pCurrent->value); + } + free(pCurrent); + pCurrent = pTemp; } +} + +/*----------------------- Server options creation -------------------------*/ +int IFServerOption(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]) +{ + char pBueffel[512]; + + assert(pSics); + assert(pCon); + + /* check authorisation */ + if (!SCMatchRights(pCon, usMugger)) { + SCWrite(pCon, "Insufficient privilege to set options", eError); + return 0; + } + + /* test if sufficient arguments */ + if (argc < 3) { + snprintf(pBueffel,sizeof(pBueffel)-1, "Syntax: %s name value ", argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* just do it */ + pSICSOptions = IFAddOption(pSICSOptions, argv[1], argv[2]); + return 1; +} + /*=========================================================================== Testcode: Define MAIN to activate it. Needs a file test.txt as input */ #ifdef MAIN - int main(int argc, char *argv[]) - { - FILE *fd; - IPair *pList = NULL; - char *pPos = NULL; - - fd = fopen("test.txt","r"); - if(!fd) - exit(2); - - - pList = IFReadConfigFile(fd); - if(!pList) - exit(2); - fclose(fd); - - pPos = IFindOption(pList,"Gabi"); - if(pPos) - puts(pPos); - - fd = fopen("lala.txt","w"); - IFSaveOptions(pList,fd); - IFDeleteOptions(pList); - - } -#endif +int main(int argc, char *argv[]) +{ + FILE *fd; + IPair *pList = NULL; + char *pPos = NULL; + fd = fopen("test.txt", "r"); + if (!fd) + exit(2); + + + pList = IFReadConfigFile(fd); + if (!pList) + exit(2); + fclose(fd); + + pPos = IFindOption(pList, "Gabi"); + if (pPos) + puts(pPos); + + fd = fopen("lala.txt", "w"); + IFSaveOptions(pList, fd); + IFDeleteOptions(pList); + +} +#endif diff --git a/ifile.h b/ifile.h index 69b3d819..78389086 100644 --- a/ifile.h +++ b/ifile.h @@ -13,22 +13,21 @@ #define MKIFILE #include -typedef struct __IFileE - { - char *name; - char *value; - struct __IFileE *pNext; - } IPair; - - IPair *IFReadConfigFile(FILE *fp); - char *IFindOption(IPair *pList,char *name); +typedef struct __IFileE { + char *name; + char *value; + struct __IFileE *pNext; +} IPair; + +IPair *IFReadConfigFile(FILE * fp); +char *IFindOption(IPair * pList, char *name); /* returns a value for a name - */ - IPair *IFAddOption(IPair *pList,char *name, char *value); - IPair *IFSetOption(IPair *pList,char *name, char *value); - - int IFSaveOptions(IPair *pList,FILE *fp); - void IFDeleteOptions(IPair *pList); - - extern IPair *pSICSOptions; + */ +IPair *IFAddOption(IPair * pList, char *name, char *value); +IPair *IFSetOption(IPair * pList, char *name, char *value); + +int IFSaveOptions(IPair * pList, FILE * fp); +void IFDeleteOptions(IPair * pList); + +extern IPair *pSICSOptions; #endif diff --git a/init8.c b/init8.c index 0f022f37..8c4ae857 100644 --- a/init8.c +++ b/init8.c @@ -1,293 +1,293 @@ #include -static char init_tcl[] = -"# init.tcl --\n#\n# Default system startup file for Tcl-based appli" -"cations. Defines\n# \"unknown\" procedure and auto-load facilities." -"\n#\n# SCCS: @(#) init.tcl 1.66 96/10/06 14:29:28\n#\n# Copyright (c)" -" 1991-1993 The Regents of the University of California.\n# Copyrig" -"ht (c) 1994-1996 Sun Microsystems, Inc.\n#\n# See the file \"license" -".terms\" for information on usage and redistribution\n# of this fil" -"e, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n#-------------------" -"---------------------------------------------------------\n#\n# Mod" -"ified by Mark Koennecke in order to redirect unknown into the Sic" -"s\n# mechanism. Thereby disabling command shortcuts and execution " -"of shell\n# commands for security reasons.\n#\n# February 1997\n# Hac" -"ked for Tcl 8.0 September 1997, bad hack if problems start anew\n#" -"\n#---------------------------------------------------------------" -"------------\n \nif {[info commands package] == \"\"} {\n error \"ve" -"rsion mismatch: library\\nscripts expect Tcl version 7.5b1 or late" -"r but the loaded version is\\nonly [info patchlevel]\"\n}\npackage re" -"quire -exact Tcl 8.0\n#if [catch {set auto_path $env(TCLLIBPATH)}]" -" {\n# set auto_path \"\"\n#}\nif {[lsearch -exact $auto_path [info " -"library]] < 0} {\n lappend auto_path [info library]\n}\ncatch {\n " -" foreach dir $tcl_pkgPath {\n\tif {[lsearch -exact $auto_path $di" -"r] < 0} {\n\t lappend auto_path $dir\n\t}\n }\n unset dir\n}\npa" -"ckage unknown tclPkgUnknown\n\n# Some machines, such as the Macinto" -"sh, do not have exec. Also, on all\n# platforms, safe interpreters" -" do not have exec.\n# exec hereby disabled for Security reasons! M" -"K\n set auto_noexec 1\n\n\nset errorCode \"\"\nset errorInfo \"\"\n\n# un" -"known --\n# This procedure is called when a Tcl command is invoked" -" that doesn't\n# exist in the interpreter. It takes the following" -" steps to make the\n# command available:\n#\n#\t1. See if the autoloa" -"d facility can locate the command in a\n#\t Tcl script file. If " -"so, load it and execute it.\n#\t2. If the command was invoked inter" -"actively at top-level:\n#\t (a) see if the command exists as an " -"executable UNIX program.\n#\t\tIf so, \"exec\" the command.\n#\t (b) " -"see if the command requests csh-like history substitution\n#\t\tin o" -"ne of the common forms !!, !, or ^old^new. If\n#\t\tso, emu" -"late csh's history substitution.\n#\t (c) see if the command is " -"a unique abbreviation for another\n#\t\tcommand. If so, invoke the " -"command.\n#\n# Arguments:\n# args -\tA list whose elements are the wo" -"rds of the original\n#\t\tcommand, including the command name.\n\nproc" -" unknown args {\n global auto_noexec auto_noload env unknown_pe" -"nding tcl_interactive\n global errorCode errorInfo\n\n # Save " -"the values of errorCode and errorInfo variables, since they\n #" -" may get modified if caught errors occur below. The variables wi" -"ll\n # be restored just before re-executing the missing command" -".\n\n set savedErrorCode $errorCode\n set savedErrorInfo $erro" -"rInfo\n set name [lindex $args 0]\n if ![info exists auto_nol" -"oad] {\n\t#\n\t# Make sure we're not trying to load the same proc twi" -"ce.\n\t#\n\tif [info exists unknown_pending($name)] {\n\t return -co" -"de error \"self-referential recursion in \\\"unknown\\\" for command \\" -"\"$name\\\"\";\n\t}\n\tset unknown_pending($name) pending;\n\tset ret [catc" -"h {auto_load $name} msg]\n\tunset unknown_pending($name);\n\tif {$ret" -" != 0} {\n\t return -code $ret -errorcode $errorCode \\\n\t\t\"error " -"while autoloading \\\"$name\\\": $msg\"\n\t}\n\tif ![array size unknown_pe" -"nding] {\n\t unset unknown_pending\n\t}\n\tif $msg {\n\t set errorC" -"ode $savedErrorCode\n\t set errorInfo $savedErrorInfo\n\t set c" -"ode [catch {uplevel $args} msg]\n\t if {$code == 1} {\n\t\t#\n\t\t# S" -"trip the last five lines off the error stack (they're\n\t\t# from th" -"e \"uplevel\" command).\n\t\t#\n\n\t\tset new [split $errorInfo \\n]\n\t\tset " -"new [join [lrange $new 0 [expr [llength $new] - 6]] \\n]\n\t\treturn " -"-code error -errorcode $errorCode \\\n\t\t\t-errorinfo $new $msg\n\t " -"} else {\n\t\treturn -code $code $msg\n\t }\n\t}\n }\n \n # Try" -" running SICS for a change\n set ret [catch {uplevel #0 SicsUnk" -"nown $args} msg]\n if {$ret == 1} {\n return -code error " -"$msg\n } else {\n return -code ok $msg\n }\n}\n\n# auto_lo" -"ad --\n# Checks a collection of library directories to see if a pr" -"ocedure\n# is defined in one of them. If so, it sources the appro" -"priate\n# library file to create the procedure. Returns 1 if it s" -"uccessfully\n# loaded the procedure, 0 otherwise.\n#\n# Arguments: \n" -"# cmd -\t\t\tName of the command to find and load.\n\nproc auto_load c" -"md {\n global auto_index auto_oldpath auto_path env errorInfo e" -"rrorCode\n\n if [info exists auto_index($cmd)] {\n\tuplevel #0 $au" -"to_index($cmd)\n\treturn [expr {[info commands $cmd] != \"\"}]\n }\n" -" if ![info exists auto_path] {\n\treturn 0\n }\n if [info ex" -"ists auto_oldpath] {\n\tif {$auto_oldpath == $auto_path} {\n\t ret" -"urn 0\n\t}\n }\n set auto_oldpath $auto_path\n for {set i [ex" -"pr [llength $auto_path] - 1]} {$i >= 0} {incr i -1} {\n\tset dir [l" -"index $auto_path $i]\n\tset f \"\"\n\tif [catch {set f [open [file join" -" $dir tclIndex]]}] {\n\t continue\n\t}\n\tset error [catch {\n\t se" -"t id [gets $f]\n\t if {$id == \"# Tcl autoload index file, versio" -"n 2.0\"} {\n\t\teval [read $f]\n\t } elseif {$id == \"# Tcl autoload " -"index file: each line identifies a Tcl\"} {\n\t\twhile {[gets $f line" -"] >= 0} {\n\t\t if {([string index $line 0] == \"#\")\n\t\t\t || ([l" -"length $line] != 2)} {\n\t\t\tcontinue\n\t\t }\n\t\t set name [lindex" -" $line 0]\n\t\t set auto_index($name) \\\n\t\t\t\"source [file join $di" -"r [lindex $line 1]]\"\n\t\t}\n\t } else {\n\t\terror \"[file join $dir t" -"clIndex] isn't a proper Tcl index file\"\n\t }\n\t} msg]\n\tif {$f !=" -" \"\"} {\n\t close $f\n\t}\n\tif $error {\n\t error $msg $errorInfo $" -"errorCode\n\t}\n }\n if [info exists auto_index($cmd)] {\n\tuplev" -"el #0 $auto_index($cmd)\n\tif {[info commands $cmd] != \"\"} {\n\t r" -"eturn 1\n\t}\n }\n return 0\n}\n\nif {[string compare $tcl_platfor" -"m(platform) windows] == 0} {\n\n# auto_execok --\n#\n# Returns string" -" that indicates name of program to execute if \n# name corresponds" -" to a shell builtin or an executable in the\n# Windows search path" -", or \"\" otherwise. Builds an associative \n# array auto_execs tha" -"t caches information about previous checks, \n# for speed.\n#\n# Arg" -"uments: \n# name -\t\t\tName of a command.\n\n# Windows version.\n#\n# No" -"te that info executable doesn't work under Windows, so we have to" -"\n# look for files with .exe, .com, or .bat extensions. Also, the" -" path\n# may be in the Path or PATH environment variables, and pat" -"h\n# components are separated with semicolons, not colons as under" -" Unix.\n#\nproc auto_execok name {\n global auto_execs env tcl_pl" -"atform\n\n if [info exists auto_execs($name)] {\n\treturn $auto_ex" -"ecs($name)\n }\n set auto_execs($name) \"\"\n\n if {[lsearch -" -"exact {cls copy date del erase dir echo mkdir md rename \n\t ren" -" rmdir rd time type ver vol} $name] != -1} {\n\tif {[info exists en" -"v(COMSPEC)]} {\n\t set comspec $env(COMSPEC) \n\t} elseif {[info e" -"xists env(ComSpec)]} {\n\t set comspec $env(ComSpec)\n\t} elseif {" -"$tcl_platform(os) == \"Windows NT\"} {\n\t set comspec \"cmd.exe\"\n\t" -"} else {\n\t set comspec \"command.com\"\n\t}\n\treturn [set auto_exec" -"s($name) [list $comspec /c $name]]\n }\n\n if {[llength [file " -"split $name]] != 1} {\n\tforeach ext {{} .com .exe .bat} {\n\t set" -" file ${name}${ext}\n\t if {[file exists $file] && ![file isdire" -"ctory $file]} {\n\t\treturn [set auto_execs($name) $file]\n\t }\n\t}\n" -"\treturn \"\"\n }\n\n set path \"[file dirname [info nameof]];.;\"\n" -" if {[info exists env(WINDIR)]} {\n\tset windir $env(WINDIR) \n " -" } elseif {[info exists env(windir)]} {\n\tset windir $env(windir)" -"\n }\n if {[info exists windir]} {\n\tif {$tcl_platform(os) == " -"\"Windows NT\"} {\n\t append path \"$windir/system32;\"\n\t}\n\tappend p" -"ath \"$windir/system;$windir;\"\n }\n\n if {! [info exists env(P" -"ATH)]} {\n\tif [info exists env(Path)] {\n\t append path $env(Path" -")\n\t} else {\n\t return \"\"\n\t}\n } else {\n\tappend path $env(PATH" -")\n }\n\n foreach dir [split $path {;}] {\n\tif {$dir == \"\"} {\n\t" -" set dir .\n\t}\n\tforeach ext {{} .com .exe .bat} {\n\t set file" -" [file join $dir ${name}${ext}]\n\t if {[file exists $file] && !" -"[file isdirectory $file]} {\n\t\treturn [set auto_execs($name) $file" -"]\n\t }\n\t}\n }\n return \"\"\n}\n\n} else {\n\n# auto_execok --\n#\n#" -" Returns string that indicates name of program to execute if \n# n" -"ame corresponds to an executable in the path. Builds an associati" -"ve \n# array auto_execs that caches information about previous che" -"cks, \n# for speed.\n#\n# Arguments: \n# name -\t\t\tName of a command.\n" -"\n# Unix version.\n#\nproc auto_execok name {\n global auto_execs " -"env\n\n if [info exists auto_execs($name)] {\n\treturn $auto_execs" -"($name)\n }\n set auto_execs($name) \"\"\n if {[llength [file" -" split $name]] != 1} {\n\tif {[file executable $name] && ![file isd" -"irectory $name]} {\n\t set auto_execs($name) $name\n\t}\n\treturn $a" -"uto_execs($name)\n }\n foreach dir [split $env(PATH) :] {\n\tif" -" {$dir == \"\"} {\n\t set dir .\n\t}\n\tset file [file join $dir $name" -"]\n\tif {[file executable $file] && ![file isdirectory $file]} {\n\t " -" set auto_execs($name) $file\n\t return $file\n\t}\n }\n ret" -"urn \"\"\n}\n\n}\n# auto_reset --\n# Destroy all cached information for " -"auto-loading and auto-execution,\n# so that the information gets r" -"ecomputed the next time it's needed.\n# Also delete any procedures" -" that are listed in the auto-load index\n# except those defined in" -" this file.\n#\n# Arguments: \n# None.\n\nproc auto_reset {} {\n glo" -"bal auto_execs auto_index auto_oldpath\n foreach p [info procs]" -" {\n\tif {[info exists auto_index($p)] && ![string match auto_* $p]" -"\n\t\t&& ([lsearch -exact {unknown pkg_mkIndex tclPkgSetup\n\t\t\ttclPkg" -"Unknown} $p] < 0)} {\n\t rename $p {}\n\t}\n }\n catch {unset " -"auto_execs}\n catch {unset auto_index}\n catch {unset auto_ol" -"dpath}\n}\n\n# auto_mkindex --\n# Regenerate a tclIndex file from Tcl" -" source files. Takes as argument\n# the name of the directory in " -"which the tclIndex file is to be placed,\n# followed by any number" -" of glob patterns to use in that directory to\n# locate all of the" -" relevant files.\n#\n# Arguments: \n# dir -\t\t\tName of the directory " -"in which to create an index.\n# args -\t\tAny number of additional a" -"rguments giving the\n#\t\t\tnames of files within dir. If no additio" -"nal\n#\t\t\tare given auto_mkindex will look for *.tcl.\n\nproc auto_mk" -"index {dir args} {\n global errorCode errorInfo\n set oldDir " -"[pwd]\n cd $dir\n set dir [pwd]\n append index \"# Tcl autol" -"oad index file, version 2.0\\n\"\n append index \"# This file is g" -"enerated by the \\\"auto_mkindex\\\" command\\n\"\n append index \"# a" -"nd sourced to set up indexing information for one or\\n\"\n appen" -"d index \"# more commands. Typically each line is a command that\\" -"n\"\n append index \"# sets an element in the auto_index array, w" -"here the\\n\"\n append index \"# element name is the name of a com" -"mand and the value is\\n\"\n append index \"# a script that loads " -"the command.\\n\\n\"\n if {$args == \"\"} {\n\tset args *.tcl\n }\n " -" foreach file [eval glob $args] {\n\tset f \"\"\n\tset error [catch {\n" -"\t set f [open $file]\n\t while {[gets $f line] >= 0} {\n\t\tif [" -"regexp {^proc[ \t]+([^ \t]*)} $line match procName] {\n\t\t append " -"index \"set [list auto_index($procName)]\"\n\t\t append index \" \\[l" -"ist source \\[file join \\$dir [list $file]\\]\\]\\n\"\n\t\t}\n\t }\n\t " -"close $f\n\t} msg]\n\tif $error {\n\t set code $errorCode\n\t set i" -"nfo $errorInfo\n\t catch {close $f}\n\t cd $oldDir\n\t error $" -"msg $info $code\n\t}\n }\n set f \"\"\n set error [catch {\n\tset" -" f [open tclIndex w]\n\tputs $f $index nonewline\n\tclose $f\n\tcd $old" -"Dir\n } msg]\n if $error {\n\tset code $errorCode\n\tset info $er" -"rorInfo\n\tcatch {close $f}\n\tcd $oldDir\n\terror $msg $info $code\n " -" }\n}\n\n# pkg_mkIndex --\n# This procedure creates a package index i" -"n a given directory. The\n# package index consists of a \"pkgIndex" -".tcl\" file whose contents are\n# a Tcl script that sets up package" -" information with \"package require\"\n# commands. The commands des" -"cribe all of the packages defined by the\n# files given as argumen" -"ts.\n#\n# Arguments:\n# dir -\t\t\tName of the directory in which to cr" -"eate the index.\n# args -\t\tAny number of additional arguments, eac" -"h giving\n#\t\t\ta glob pattern that matches the names of one or\n#\t\t\t" -"more shared libraries or Tcl script files in\n#\t\t\tdir.\n\nproc pkg_m" -"kIndex {dir args} {\n global errorCode errorInfo\n append ind" -"ex \"# Tcl package index file, version 1.0\\n\"\n append index \"# " -"This file is generated by the \\\"pkg_mkIndex\\\" command\\n\"\n appe" -"nd index \"# and sourced either when an application starts up or\\n" -"\"\n append index \"# by a \\\"package unknown\\\" script. It invoke" -"s the\\n\"\n append index \"# \\\"package ifneeded\\\" command to set " -"up package-related\\n\"\n append index \"# information so that pac" -"kages will be loaded automatically\\n\"\n append index \"# in resp" -"onse to \\\"package require\\\" commands. When this\\n\"\n append in" -"dex \"# script is sourced, the variable \\$dir must contain the\\n\"\n" -" append index \"# full path name of this file's directory.\\n\"\n " -" set oldDir [pwd]\n cd $dir\n foreach file [eval glob $args" -"] {\n\t# For each file, figure out what commands and packages it pr" -"ovides.\n\t# To do this, create a child interpreter, load the file " -"into the\n\t# interpreter, and get a list of the new commands and p" -"ackages\n\t# that are defined. Define an empty \"package unknown\" s" -"cript so\n\t# that there are no recursive package inclusions.\n\n\tset" -" c [interp create]\n\n\t# If Tk is loaded in the parent interpreter," -" load it into the\n\t# child also, in case the extension depends on" -" it.\n\n\tforeach pkg [info loaded] {\n\t if {[lindex $pkg 1] == \"T" -"k\"} {\n\t\t$c eval {set argv {-geometry +0+0}}\n\t\tload [lindex $pkg 0" -"] Tk $c\n\t\tbreak\n\t }\n\t}\n\t$c eval [list set file $file]\n\tif [cat" -"ch {\n\t $c eval {\n\t\tproc dummy args {}\n\t\tpackage unknown dummy\n" -"\t\tset origCmds [info commands]\n\t\tset dir \"\"\t\t;# in case file is p" -"kgIndex.tcl\n\t\tset pkgs \"\"\n\n\t\t# Try to load the file if it has the" -" shared library extension,\n\t\t# otherwise source it. It's importa" -"nt not to try to load\n\t\t# files that aren't shared libraries, bec" -"ause on some systems\n\t\t# (like SunOS) the loader will abort the w" -"hole application\n\t\t# when it gets an error.\n\n\t\tif {[string compar" -"e [file extension $file] \\\n\t\t\t[info sharedlibextension]] == 0} {\n" -"\n\t\t # The \"file join .\" command below is necessary. Without\n\t" -"\t # it, if the file name has no \\'s and we're on UNIX, the\n\t\t " -" # load command will invoke the LD_LIBRARY_PATH search\n\t\t # " -"mechanism, which could cause the wrong file to be used.\n\n\t\t lo" -"ad [file join . $file]\n\t\t set type load\n\t\t} else {\n\t\t sourc" -"e $file\n\t\t set type source\n\t\t}\n\t\tforeach i [info commands] {\n\t" -"\t set cmds($i) 1\n\t\t}\n\t\tforeach i $origCmds {\n\t\t catch {unse" -"t cmds($i)}\n\t\t}\n\t\tforeach i [package names] {\n\t\t if {([string " -"compare [package provide $i] \"\"] != 0)\n\t\t\t && ([string compare" -" $i Tcl] != 0)\n\t\t\t && ([string compare $i Tk] != 0)} {\n\t\t\tlapp" -"end pkgs [list $i [package provide $i]]\n\t\t }\n\t\t}\n\t }\n\t} msg" -"] {\n\t puts \"error while loading or sourcing $file: $msg\"\n\t}\n\tf" -"oreach pkg [$c eval set pkgs] {\n\t lappend files($pkg) [list $f" -"ile [$c eval set type] \\\n\t\t [lsort [$c eval array names cmds]]" -"]\n\t}\n\tinterp delete $c\n }\n foreach pkg [lsort [array names " -"files]] {\n\tappend index \"\\npackage ifneeded $pkg\\\n\t\t\\[list tclPkg" -"Setup \\$dir [lrange $pkg 0 0] [lrange $pkg 1 1]\\\n\t\t[list $files($" -"pkg)]\\]\"\n }\n set f [open pkgIndex.tcl w]\n puts $f $index" -"\n close $f\n cd $oldDir\n}\n\n# tclPkgSetup --\n# This is a util" -"ity procedure use by pkgIndex.tcl files. It is invoked\n# as part" -" of a \"package ifneeded\" script. It calls \"package provide\"\n# to" -" indicate that a package is available, then sets entries in the\n#" -" auto_index array so that the package's files will be auto-loaded" -" when\n# the commands are used.\n#\n# Arguments:\n# dir -\t\t\tDirectory" -" containing all the files for this package.\n# pkg -\t\t\tName of the" -" package (no version number).\n# version -\t\tVersion number for the" -" package, such as 2.1.3.\n# files -\t\tList of files that constitute" -" the package. Each\n#\t\t\telement is a sub-list with three elements" -". The first\n#\t\t\tis the name of a file relative to $dir, the seco" -"nd is\n#\t\t\t\"load\" or \"source\", indicating whether the file is a\n#\t" -"\t\tloadable binary or a script to source, and the third\n#\t\t\tis a l" -"ist of commands defined by this file.\n\nproc tclPkgSetup {dir pkg " -"version files} {\n global auto_index\n\n package provide $pkg " -"$version\n foreach fileInfo $files {\n\tset f [lindex $fileInfo 0" -"]\n\tset type [lindex $fileInfo 1]\n\tforeach cmd [lindex $fileInfo 2" -"] {\n\t if {$type == \"load\"} {\n\t\tset auto_index($cmd) [list load" -" [file join $dir $f] $pkg]\n\t } else {\n\t\tset auto_index($cmd) [" -"list source [file join $dir $f]]\n\t } \n\t}\n }\n}\n\n# tclMacPkgS" -"earch --\n# The procedure is used on the Macintosh to search a giv" -"en directory for files\n# with a TEXT resource named \"pkgIndex\". " -"If it exists it is sourced in to the\n# interpreter to setup the p" -"ackage database.\n\nproc tclMacPkgSearch {dir} {\n foreach x [glo" -"b -nocomplain [file join $dir *.shlb]] {\n\tif [file isfile $x] {\n\t" -" set res [resource open $x]\n\t foreach y [resource list TEXT" -" $res] {\n\t\tif {$y == \"pkgIndex\"} {source -rsrc pkgIndex}\n\t }\n\t" -" resource close $res\n\t}\n }\n}\n\n# tclPkgUnknown --\n# This pro" -"cedure provides the default for the \"package unknown\" function.\n#" -" It is invoked when a package that's needed can't be found. It s" -"cans\n# the auto_path directories and their immediate children loo" -"king for\n# pkgIndex.tcl files and sources any such files that are" -" found to setup\n# the package database. (On the Macintosh we als" -"o search for pkgIndex\n# TEXT resources in all files.)\n#\n# Argumen" -"ts:\n# name -\t\tName of desired package. Not used.\n# version -\t\tVe" -"rsion of desired package. Not used.\n# exact -\t\tEither \"-exact\" o" -"r omitted. Not used.\n\nproc tclPkgUnknown {name version {exact {}" -"}} {\n global auto_path tcl_platform env\n\n if ![info exists " -"auto_path] {\n\treturn\n }\n for {set i [expr [llength $auto_pa" -"th] - 1]} {$i >= 0} {incr i -1} {\n\tset dir [lindex $auto_path $i]" -"\n\tset file [file join $dir pkgIndex.tcl]\n\tif [file readable $file" -"] {\n\t source $file\n\t}\n\tforeach file [glob -nocomplain [file jo" -"in $dir * pkgIndex.tcl]] {\n\t if [file readable $file] {\n\t\tset " -"dir [file dirname $file]\n\t\tsource $file\n\t }\n\t}\n\t# On the Macin" -"tosh we also look in the resource fork \n\t# of shared libraries\n\ti" -"f {$tcl_platform(platform) == \"macintosh\"} {\n\t set dir [lindex" -" $auto_path $i]\n\t tclMacPkgSearch $dir\n\t foreach x [glob -n" -"ocomplain [file join $dir *]] {\n\t\tif [file isdirectory $x] {\n\t\t " -" set dir $x\n\t\t tclMacPkgSearch $dir\n\t\t}\n\t }\n\t}\n }\n}\n" -; -int initcl_Init(Tcl_Interp* interp) +static char init_tcl[] = + "# init.tcl --\n#\n# Default system startup file for Tcl-based appli" + "cations. Defines\n# \"unknown\" procedure and auto-load facilities." + "\n#\n# SCCS: @(#) init.tcl 1.66 96/10/06 14:29:28\n#\n# Copyright (c)" + " 1991-1993 The Regents of the University of California.\n# Copyrig" + "ht (c) 1994-1996 Sun Microsystems, Inc.\n#\n# See the file \"license" + ".terms\" for information on usage and redistribution\n# of this fil" + "e, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n#-------------------" + "---------------------------------------------------------\n#\n# Mod" + "ified by Mark Koennecke in order to redirect unknown into the Sic" + "s\n# mechanism. Thereby disabling command shortcuts and execution " + "of shell\n# commands for security reasons.\n#\n# February 1997\n# Hac" + "ked for Tcl 8.0 September 1997, bad hack if problems start anew\n#" + "\n#---------------------------------------------------------------" + "------------\n \nif {[info commands package] == \"\"} {\n error \"ve" + "rsion mismatch: library\\nscripts expect Tcl version 7.5b1 or late" + "r but the loaded version is\\nonly [info patchlevel]\"\n}\npackage re" + "quire -exact Tcl 8.0\n#if [catch {set auto_path $env(TCLLIBPATH)}]" + " {\n# set auto_path \"\"\n#}\nif {[lsearch -exact $auto_path [info " + "library]] < 0} {\n lappend auto_path [info library]\n}\ncatch {\n " + " foreach dir $tcl_pkgPath {\n\tif {[lsearch -exact $auto_path $di" + "r] < 0} {\n\t lappend auto_path $dir\n\t}\n }\n unset dir\n}\npa" + "ckage unknown tclPkgUnknown\n\n# Some machines, such as the Macinto" + "sh, do not have exec. Also, on all\n# platforms, safe interpreters" + " do not have exec.\n# exec hereby disabled for Security reasons! M" + "K\n set auto_noexec 1\n\n\nset errorCode \"\"\nset errorInfo \"\"\n\n# un" + "known --\n# This procedure is called when a Tcl command is invoked" + " that doesn't\n# exist in the interpreter. It takes the following" + " steps to make the\n# command available:\n#\n#\t1. See if the autoloa" + "d facility can locate the command in a\n#\t Tcl script file. If " + "so, load it and execute it.\n#\t2. If the command was invoked inter" + "actively at top-level:\n#\t (a) see if the command exists as an " + "executable UNIX program.\n#\t\tIf so, \"exec\" the command.\n#\t (b) " + "see if the command requests csh-like history substitution\n#\t\tin o" + "ne of the common forms !!, !, or ^old^new. If\n#\t\tso, emu" + "late csh's history substitution.\n#\t (c) see if the command is " + "a unique abbreviation for another\n#\t\tcommand. If so, invoke the " + "command.\n#\n# Arguments:\n# args -\tA list whose elements are the wo" + "rds of the original\n#\t\tcommand, including the command name.\n\nproc" + " unknown args {\n global auto_noexec auto_noload env unknown_pe" + "nding tcl_interactive\n global errorCode errorInfo\n\n # Save " + "the values of errorCode and errorInfo variables, since they\n #" + " may get modified if caught errors occur below. The variables wi" + "ll\n # be restored just before re-executing the missing command" + ".\n\n set savedErrorCode $errorCode\n set savedErrorInfo $erro" + "rInfo\n set name [lindex $args 0]\n if ![info exists auto_nol" + "oad] {\n\t#\n\t# Make sure we're not trying to load the same proc twi" + "ce.\n\t#\n\tif [info exists unknown_pending($name)] {\n\t return -co" + "de error \"self-referential recursion in \\\"unknown\\\" for command \\" + "\"$name\\\"\";\n\t}\n\tset unknown_pending($name) pending;\n\tset ret [catc" + "h {auto_load $name} msg]\n\tunset unknown_pending($name);\n\tif {$ret" + " != 0} {\n\t return -code $ret -errorcode $errorCode \\\n\t\t\"error " + "while autoloading \\\"$name\\\": $msg\"\n\t}\n\tif ![array size unknown_pe" + "nding] {\n\t unset unknown_pending\n\t}\n\tif $msg {\n\t set errorC" + "ode $savedErrorCode\n\t set errorInfo $savedErrorInfo\n\t set c" + "ode [catch {uplevel $args} msg]\n\t if {$code == 1} {\n\t\t#\n\t\t# S" + "trip the last five lines off the error stack (they're\n\t\t# from th" + "e \"uplevel\" command).\n\t\t#\n\n\t\tset new [split $errorInfo \\n]\n\t\tset " + "new [join [lrange $new 0 [expr [llength $new] - 6]] \\n]\n\t\treturn " + "-code error -errorcode $errorCode \\\n\t\t\t-errorinfo $new $msg\n\t " + "} else {\n\t\treturn -code $code $msg\n\t }\n\t}\n }\n \n # Try" + " running SICS for a change\n set ret [catch {uplevel #0 SicsUnk" + "nown $args} msg]\n if {$ret == 1} {\n return -code error " + "$msg\n } else {\n return -code ok $msg\n }\n}\n\n# auto_lo" + "ad --\n# Checks a collection of library directories to see if a pr" + "ocedure\n# is defined in one of them. If so, it sources the appro" + "priate\n# library file to create the procedure. Returns 1 if it s" + "uccessfully\n# loaded the procedure, 0 otherwise.\n#\n# Arguments: \n" + "# cmd -\t\t\tName of the command to find and load.\n\nproc auto_load c" + "md {\n global auto_index auto_oldpath auto_path env errorInfo e" + "rrorCode\n\n if [info exists auto_index($cmd)] {\n\tuplevel #0 $au" + "to_index($cmd)\n\treturn [expr {[info commands $cmd] != \"\"}]\n }\n" + " if ![info exists auto_path] {\n\treturn 0\n }\n if [info ex" + "ists auto_oldpath] {\n\tif {$auto_oldpath == $auto_path} {\n\t ret" + "urn 0\n\t}\n }\n set auto_oldpath $auto_path\n for {set i [ex" + "pr [llength $auto_path] - 1]} {$i >= 0} {incr i -1} {\n\tset dir [l" + "index $auto_path $i]\n\tset f \"\"\n\tif [catch {set f [open [file join" + " $dir tclIndex]]}] {\n\t continue\n\t}\n\tset error [catch {\n\t se" + "t id [gets $f]\n\t if {$id == \"# Tcl autoload index file, versio" + "n 2.0\"} {\n\t\teval [read $f]\n\t } elseif {$id == \"# Tcl autoload " + "index file: each line identifies a Tcl\"} {\n\t\twhile {[gets $f line" + "] >= 0} {\n\t\t if {([string index $line 0] == \"#\")\n\t\t\t || ([l" + "length $line] != 2)} {\n\t\t\tcontinue\n\t\t }\n\t\t set name [lindex" + " $line 0]\n\t\t set auto_index($name) \\\n\t\t\t\"source [file join $di" + "r [lindex $line 1]]\"\n\t\t}\n\t } else {\n\t\terror \"[file join $dir t" + "clIndex] isn't a proper Tcl index file\"\n\t }\n\t} msg]\n\tif {$f !=" + " \"\"} {\n\t close $f\n\t}\n\tif $error {\n\t error $msg $errorInfo $" + "errorCode\n\t}\n }\n if [info exists auto_index($cmd)] {\n\tuplev" + "el #0 $auto_index($cmd)\n\tif {[info commands $cmd] != \"\"} {\n\t r" + "eturn 1\n\t}\n }\n return 0\n}\n\nif {[string compare $tcl_platfor" + "m(platform) windows] == 0} {\n\n# auto_execok --\n#\n# Returns string" + " that indicates name of program to execute if \n# name corresponds" + " to a shell builtin or an executable in the\n# Windows search path" + ", or \"\" otherwise. Builds an associative \n# array auto_execs tha" + "t caches information about previous checks, \n# for speed.\n#\n# Arg" + "uments: \n# name -\t\t\tName of a command.\n\n# Windows version.\n#\n# No" + "te that info executable doesn't work under Windows, so we have to" + "\n# look for files with .exe, .com, or .bat extensions. Also, the" + " path\n# may be in the Path or PATH environment variables, and pat" + "h\n# components are separated with semicolons, not colons as under" + " Unix.\n#\nproc auto_execok name {\n global auto_execs env tcl_pl" + "atform\n\n if [info exists auto_execs($name)] {\n\treturn $auto_ex" + "ecs($name)\n }\n set auto_execs($name) \"\"\n\n if {[lsearch -" + "exact {cls copy date del erase dir echo mkdir md rename \n\t ren" + " rmdir rd time type ver vol} $name] != -1} {\n\tif {[info exists en" + "v(COMSPEC)]} {\n\t set comspec $env(COMSPEC) \n\t} elseif {[info e" + "xists env(ComSpec)]} {\n\t set comspec $env(ComSpec)\n\t} elseif {" + "$tcl_platform(os) == \"Windows NT\"} {\n\t set comspec \"cmd.exe\"\n\t" + "} else {\n\t set comspec \"command.com\"\n\t}\n\treturn [set auto_exec" + "s($name) [list $comspec /c $name]]\n }\n\n if {[llength [file " + "split $name]] != 1} {\n\tforeach ext {{} .com .exe .bat} {\n\t set" + " file ${name}${ext}\n\t if {[file exists $file] && ![file isdire" + "ctory $file]} {\n\t\treturn [set auto_execs($name) $file]\n\t }\n\t}\n" + "\treturn \"\"\n }\n\n set path \"[file dirname [info nameof]];.;\"\n" + " if {[info exists env(WINDIR)]} {\n\tset windir $env(WINDIR) \n " + " } elseif {[info exists env(windir)]} {\n\tset windir $env(windir)" + "\n }\n if {[info exists windir]} {\n\tif {$tcl_platform(os) == " + "\"Windows NT\"} {\n\t append path \"$windir/system32;\"\n\t}\n\tappend p" + "ath \"$windir/system;$windir;\"\n }\n\n if {! [info exists env(P" + "ATH)]} {\n\tif [info exists env(Path)] {\n\t append path $env(Path" + ")\n\t} else {\n\t return \"\"\n\t}\n } else {\n\tappend path $env(PATH" + ")\n }\n\n foreach dir [split $path {;}] {\n\tif {$dir == \"\"} {\n\t" + " set dir .\n\t}\n\tforeach ext {{} .com .exe .bat} {\n\t set file" + " [file join $dir ${name}${ext}]\n\t if {[file exists $file] && !" + "[file isdirectory $file]} {\n\t\treturn [set auto_execs($name) $file" + "]\n\t }\n\t}\n }\n return \"\"\n}\n\n} else {\n\n# auto_execok --\n#\n#" + " Returns string that indicates name of program to execute if \n# n" + "ame corresponds to an executable in the path. Builds an associati" + "ve \n# array auto_execs that caches information about previous che" + "cks, \n# for speed.\n#\n# Arguments: \n# name -\t\t\tName of a command.\n" + "\n# Unix version.\n#\nproc auto_execok name {\n global auto_execs " + "env\n\n if [info exists auto_execs($name)] {\n\treturn $auto_execs" + "($name)\n }\n set auto_execs($name) \"\"\n if {[llength [file" + " split $name]] != 1} {\n\tif {[file executable $name] && ![file isd" + "irectory $name]} {\n\t set auto_execs($name) $name\n\t}\n\treturn $a" + "uto_execs($name)\n }\n foreach dir [split $env(PATH) :] {\n\tif" + " {$dir == \"\"} {\n\t set dir .\n\t}\n\tset file [file join $dir $name" + "]\n\tif {[file executable $file] && ![file isdirectory $file]} {\n\t " + " set auto_execs($name) $file\n\t return $file\n\t}\n }\n ret" + "urn \"\"\n}\n\n}\n# auto_reset --\n# Destroy all cached information for " + "auto-loading and auto-execution,\n# so that the information gets r" + "ecomputed the next time it's needed.\n# Also delete any procedures" + " that are listed in the auto-load index\n# except those defined in" + " this file.\n#\n# Arguments: \n# None.\n\nproc auto_reset {} {\n glo" + "bal auto_execs auto_index auto_oldpath\n foreach p [info procs]" + " {\n\tif {[info exists auto_index($p)] && ![string match auto_* $p]" + "\n\t\t&& ([lsearch -exact {unknown pkg_mkIndex tclPkgSetup\n\t\t\ttclPkg" + "Unknown} $p] < 0)} {\n\t rename $p {}\n\t}\n }\n catch {unset " + "auto_execs}\n catch {unset auto_index}\n catch {unset auto_ol" + "dpath}\n}\n\n# auto_mkindex --\n# Regenerate a tclIndex file from Tcl" + " source files. Takes as argument\n# the name of the directory in " + "which the tclIndex file is to be placed,\n# followed by any number" + " of glob patterns to use in that directory to\n# locate all of the" + " relevant files.\n#\n# Arguments: \n# dir -\t\t\tName of the directory " + "in which to create an index.\n# args -\t\tAny number of additional a" + "rguments giving the\n#\t\t\tnames of files within dir. If no additio" + "nal\n#\t\t\tare given auto_mkindex will look for *.tcl.\n\nproc auto_mk" + "index {dir args} {\n global errorCode errorInfo\n set oldDir " + "[pwd]\n cd $dir\n set dir [pwd]\n append index \"# Tcl autol" + "oad index file, version 2.0\\n\"\n append index \"# This file is g" + "enerated by the \\\"auto_mkindex\\\" command\\n\"\n append index \"# a" + "nd sourced to set up indexing information for one or\\n\"\n appen" + "d index \"# more commands. Typically each line is a command that\\" + "n\"\n append index \"# sets an element in the auto_index array, w" + "here the\\n\"\n append index \"# element name is the name of a com" + "mand and the value is\\n\"\n append index \"# a script that loads " + "the command.\\n\\n\"\n if {$args == \"\"} {\n\tset args *.tcl\n }\n " + " foreach file [eval glob $args] {\n\tset f \"\"\n\tset error [catch {\n" + "\t set f [open $file]\n\t while {[gets $f line] >= 0} {\n\t\tif [" + "regexp {^proc[ \t]+([^ \t]*)} $line match procName] {\n\t\t append " + "index \"set [list auto_index($procName)]\"\n\t\t append index \" \\[l" + "ist source \\[file join \\$dir [list $file]\\]\\]\\n\"\n\t\t}\n\t }\n\t " + "close $f\n\t} msg]\n\tif $error {\n\t set code $errorCode\n\t set i" + "nfo $errorInfo\n\t catch {close $f}\n\t cd $oldDir\n\t error $" + "msg $info $code\n\t}\n }\n set f \"\"\n set error [catch {\n\tset" + " f [open tclIndex w]\n\tputs $f $index nonewline\n\tclose $f\n\tcd $old" + "Dir\n } msg]\n if $error {\n\tset code $errorCode\n\tset info $er" + "rorInfo\n\tcatch {close $f}\n\tcd $oldDir\n\terror $msg $info $code\n " + " }\n}\n\n# pkg_mkIndex --\n# This procedure creates a package index i" + "n a given directory. The\n# package index consists of a \"pkgIndex" + ".tcl\" file whose contents are\n# a Tcl script that sets up package" + " information with \"package require\"\n# commands. The commands des" + "cribe all of the packages defined by the\n# files given as argumen" + "ts.\n#\n# Arguments:\n# dir -\t\t\tName of the directory in which to cr" + "eate the index.\n# args -\t\tAny number of additional arguments, eac" + "h giving\n#\t\t\ta glob pattern that matches the names of one or\n#\t\t\t" + "more shared libraries or Tcl script files in\n#\t\t\tdir.\n\nproc pkg_m" + "kIndex {dir args} {\n global errorCode errorInfo\n append ind" + "ex \"# Tcl package index file, version 1.0\\n\"\n append index \"# " + "This file is generated by the \\\"pkg_mkIndex\\\" command\\n\"\n appe" + "nd index \"# and sourced either when an application starts up or\\n" + "\"\n append index \"# by a \\\"package unknown\\\" script. It invoke" + "s the\\n\"\n append index \"# \\\"package ifneeded\\\" command to set " + "up package-related\\n\"\n append index \"# information so that pac" + "kages will be loaded automatically\\n\"\n append index \"# in resp" + "onse to \\\"package require\\\" commands. When this\\n\"\n append in" + "dex \"# script is sourced, the variable \\$dir must contain the\\n\"\n" + " append index \"# full path name of this file's directory.\\n\"\n " + " set oldDir [pwd]\n cd $dir\n foreach file [eval glob $args" + "] {\n\t# For each file, figure out what commands and packages it pr" + "ovides.\n\t# To do this, create a child interpreter, load the file " + "into the\n\t# interpreter, and get a list of the new commands and p" + "ackages\n\t# that are defined. Define an empty \"package unknown\" s" + "cript so\n\t# that there are no recursive package inclusions.\n\n\tset" + " c [interp create]\n\n\t# If Tk is loaded in the parent interpreter," + " load it into the\n\t# child also, in case the extension depends on" + " it.\n\n\tforeach pkg [info loaded] {\n\t if {[lindex $pkg 1] == \"T" + "k\"} {\n\t\t$c eval {set argv {-geometry +0+0}}\n\t\tload [lindex $pkg 0" + "] Tk $c\n\t\tbreak\n\t }\n\t}\n\t$c eval [list set file $file]\n\tif [cat" + "ch {\n\t $c eval {\n\t\tproc dummy args {}\n\t\tpackage unknown dummy\n" + "\t\tset origCmds [info commands]\n\t\tset dir \"\"\t\t;# in case file is p" + "kgIndex.tcl\n\t\tset pkgs \"\"\n\n\t\t# Try to load the file if it has the" + " shared library extension,\n\t\t# otherwise source it. It's importa" + "nt not to try to load\n\t\t# files that aren't shared libraries, bec" + "ause on some systems\n\t\t# (like SunOS) the loader will abort the w" + "hole application\n\t\t# when it gets an error.\n\n\t\tif {[string compar" + "e [file extension $file] \\\n\t\t\t[info sharedlibextension]] == 0} {\n" + "\n\t\t # The \"file join .\" command below is necessary. Without\n\t" + "\t # it, if the file name has no \\'s and we're on UNIX, the\n\t\t " + " # load command will invoke the LD_LIBRARY_PATH search\n\t\t # " + "mechanism, which could cause the wrong file to be used.\n\n\t\t lo" + "ad [file join . $file]\n\t\t set type load\n\t\t} else {\n\t\t sourc" + "e $file\n\t\t set type source\n\t\t}\n\t\tforeach i [info commands] {\n\t" + "\t set cmds($i) 1\n\t\t}\n\t\tforeach i $origCmds {\n\t\t catch {unse" + "t cmds($i)}\n\t\t}\n\t\tforeach i [package names] {\n\t\t if {([string " + "compare [package provide $i] \"\"] != 0)\n\t\t\t && ([string compare" + " $i Tcl] != 0)\n\t\t\t && ([string compare $i Tk] != 0)} {\n\t\t\tlapp" + "end pkgs [list $i [package provide $i]]\n\t\t }\n\t\t}\n\t }\n\t} msg" + "] {\n\t puts \"error while loading or sourcing $file: $msg\"\n\t}\n\tf" + "oreach pkg [$c eval set pkgs] {\n\t lappend files($pkg) [list $f" + "ile [$c eval set type] \\\n\t\t [lsort [$c eval array names cmds]]" + "]\n\t}\n\tinterp delete $c\n }\n foreach pkg [lsort [array names " + "files]] {\n\tappend index \"\\npackage ifneeded $pkg\\\n\t\t\\[list tclPkg" + "Setup \\$dir [lrange $pkg 0 0] [lrange $pkg 1 1]\\\n\t\t[list $files($" + "pkg)]\\]\"\n }\n set f [open pkgIndex.tcl w]\n puts $f $index" + "\n close $f\n cd $oldDir\n}\n\n# tclPkgSetup --\n# This is a util" + "ity procedure use by pkgIndex.tcl files. It is invoked\n# as part" + " of a \"package ifneeded\" script. It calls \"package provide\"\n# to" + " indicate that a package is available, then sets entries in the\n#" + " auto_index array so that the package's files will be auto-loaded" + " when\n# the commands are used.\n#\n# Arguments:\n# dir -\t\t\tDirectory" + " containing all the files for this package.\n# pkg -\t\t\tName of the" + " package (no version number).\n# version -\t\tVersion number for the" + " package, such as 2.1.3.\n# files -\t\tList of files that constitute" + " the package. Each\n#\t\t\telement is a sub-list with three elements" + ". The first\n#\t\t\tis the name of a file relative to $dir, the seco" + "nd is\n#\t\t\t\"load\" or \"source\", indicating whether the file is a\n#\t" + "\t\tloadable binary or a script to source, and the third\n#\t\t\tis a l" + "ist of commands defined by this file.\n\nproc tclPkgSetup {dir pkg " + "version files} {\n global auto_index\n\n package provide $pkg " + "$version\n foreach fileInfo $files {\n\tset f [lindex $fileInfo 0" + "]\n\tset type [lindex $fileInfo 1]\n\tforeach cmd [lindex $fileInfo 2" + "] {\n\t if {$type == \"load\"} {\n\t\tset auto_index($cmd) [list load" + " [file join $dir $f] $pkg]\n\t } else {\n\t\tset auto_index($cmd) [" + "list source [file join $dir $f]]\n\t } \n\t}\n }\n}\n\n# tclMacPkgS" + "earch --\n# The procedure is used on the Macintosh to search a giv" + "en directory for files\n# with a TEXT resource named \"pkgIndex\". " + "If it exists it is sourced in to the\n# interpreter to setup the p" + "ackage database.\n\nproc tclMacPkgSearch {dir} {\n foreach x [glo" + "b -nocomplain [file join $dir *.shlb]] {\n\tif [file isfile $x] {\n\t" + " set res [resource open $x]\n\t foreach y [resource list TEXT" + " $res] {\n\t\tif {$y == \"pkgIndex\"} {source -rsrc pkgIndex}\n\t }\n\t" + " resource close $res\n\t}\n }\n}\n\n# tclPkgUnknown --\n# This pro" + "cedure provides the default for the \"package unknown\" function.\n#" + " It is invoked when a package that's needed can't be found. It s" + "cans\n# the auto_path directories and their immediate children loo" + "king for\n# pkgIndex.tcl files and sources any such files that are" + " found to setup\n# the package database. (On the Macintosh we als" + "o search for pkgIndex\n# TEXT resources in all files.)\n#\n# Argumen" + "ts:\n# name -\t\tName of desired package. Not used.\n# version -\t\tVe" + "rsion of desired package. Not used.\n# exact -\t\tEither \"-exact\" o" + "r omitted. Not used.\n\nproc tclPkgUnknown {name version {exact {}" + "}} {\n global auto_path tcl_platform env\n\n if ![info exists " + "auto_path] {\n\treturn\n }\n for {set i [expr [llength $auto_pa" + "th] - 1]} {$i >= 0} {incr i -1} {\n\tset dir [lindex $auto_path $i]" + "\n\tset file [file join $dir pkgIndex.tcl]\n\tif [file readable $file" + "] {\n\t source $file\n\t}\n\tforeach file [glob -nocomplain [file jo" + "in $dir * pkgIndex.tcl]] {\n\t if [file readable $file] {\n\t\tset " + "dir [file dirname $file]\n\t\tsource $file\n\t }\n\t}\n\t# On the Macin" + "tosh we also look in the resource fork \n\t# of shared libraries\n\ti" + "f {$tcl_platform(platform) == \"macintosh\"} {\n\t set dir [lindex" + " $auto_path $i]\n\t tclMacPkgSearch $dir\n\t foreach x [glob -n" + "ocomplain [file join $dir *]] {\n\t\tif [file isdirectory $x] {\n\t\t " + " set dir $x\n\t\t tclMacPkgSearch $dir\n\t\t}\n\t }\n\t}\n }\n}\n"; +int initcl_Init(Tcl_Interp * interp) { - Tcl_SetVar(interp, "package_name", "init", TCL_GLOBAL_ONLY); - if (Tcl_GlobalEval(interp, init_tcl) != TCL_OK) return TCL_ERROR; - Tcl_UnsetVar(interp, "package_name", TCL_GLOBAL_ONLY); - return TCL_OK; + Tcl_SetVar(interp, "package_name", "init", TCL_GLOBAL_ONLY); + if (Tcl_GlobalEval(interp, init_tcl) != TCL_OK) + return TCL_ERROR; + Tcl_UnsetVar(interp, "package_name", TCL_GLOBAL_ONLY); + return TCL_OK; } diff --git a/initcl.c b/initcl.c index 911e7ca9..df0ea132 100644 --- a/initcl.c +++ b/initcl.c @@ -1,292 +1,292 @@ #include -static char init_tcl[] = -"# init.tcl --\n#\n# Default system startup file for Tcl-based appli" -"cations. Defines\n# \"unknown\" procedure and auto-load facilities." -"\n#\n# SCCS: @(#) init.tcl 1.66 96/10/06 14:29:28\n#\n# Copyright (c)" -" 1991-1993 The Regents of the University of California.\n# Copyrig" -"ht (c) 1994-1996 Sun Microsystems, Inc.\n#\n# See the file \"license" -".terms\" for information on usage and redistribution\n# of this fil" -"e, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n#-------------------" -"---------------------------------------------------------\n#\n# Mod" -"ified by Mark Koennecke in order to redirect unknown into the Sic" -"s\n# mechanism. Thereby disabling command shortcuts and execution " -"of shell\n# commands for security reasons.\n#\n# February 1997\n#\n#--" -"-----------------------------------------------------------------" -"--------\n \nif {[info commands package] == \"\"} {\n error \"versio" -"n mismatch: library\\nscripts expect Tcl version 7.5b1 or later bu" -"t the loaded version is\\nonly [info patchlevel]\"\n}\npackage requir" -"e -exact Tcl 7.6\n#if [catch {set auto_path $env(TCLLIBPATH)}] {\n#" -" set auto_path \"\"\n#}\nif {[lsearch -exact $auto_path [info libr" -"ary]] < 0} {\n lappend auto_path [info library]\n}\ncatch {\n f" -"oreach dir $tcl_pkgPath {\n\tif {[lsearch -exact $auto_path $dir] <" -" 0} {\n\t lappend auto_path $dir\n\t}\n }\n unset dir\n}\npackag" -"e unknown tclPkgUnknown\n\n# Some machines, such as the Macintosh, " -"do not have exec. Also, on all\n# platforms, safe interpreters do " -"not have exec.\n# exec hereby disabled for Security reasons! MK\n " -" set auto_noexec 1\n\n\nset errorCode \"\"\nset errorInfo \"\"\n\n# unknow" -"n --\n# This procedure is called when a Tcl command is invoked tha" -"t doesn't\n# exist in the interpreter. It takes the following ste" -"ps to make the\n# command available:\n#\n#\t1. See if the autoload fa" -"cility can locate the command in a\n#\t Tcl script file. If so, " -"load it and execute it.\n#\t2. If the command was invoked interacti" -"vely at top-level:\n#\t (a) see if the command exists as an exec" -"utable UNIX program.\n#\t\tIf so, \"exec\" the command.\n#\t (b) see " -"if the command requests csh-like history substitution\n#\t\tin one o" -"f the common forms !!, !, or ^old^new. If\n#\t\tso, emulate" -" csh's history substitution.\n#\t (c) see if the command is a un" -"ique abbreviation for another\n#\t\tcommand. If so, invoke the comm" -"and.\n#\n# Arguments:\n# args -\tA list whose elements are the words " -"of the original\n#\t\tcommand, including the command name.\n\nproc unk" -"nown args {\n global auto_noexec auto_noload env unknown_pendin" -"g tcl_interactive\n global errorCode errorInfo\n\n # Save the " -"values of errorCode and errorInfo variables, since they\n # may" -" get modified if caught errors occur below. The variables will\n " -" # be restored just before re-executing the missing command.\n\n " -" set savedErrorCode $errorCode\n set savedErrorInfo $errorInf" -"o\n set name [lindex $args 0]\n if ![info exists auto_noload]" -" {\n\t#\n\t# Make sure we're not trying to load the same proc twice.\n" -"\t#\n\tif [info exists unknown_pending($name)] {\n\t return -code e" -"rror \"self-referential recursion in \\\"unknown\\\" for command \\\"$na" -"me\\\"\";\n\t}\n\tset unknown_pending($name) pending;\n\tset ret [catch {a" -"uto_load $name} msg]\n\tunset unknown_pending($name);\n\tif {$ret != " -"0} {\n\t return -code $ret -errorcode $errorCode \\\n\t\t\"error whil" -"e autoloading \\\"$name\\\": $msg\"\n\t}\n\tif ![array size unknown_pendin" -"g] {\n\t unset unknown_pending\n\t}\n\tif $msg {\n\t set errorCode " -"$savedErrorCode\n\t set errorInfo $savedErrorInfo\n\t set code " -"[catch {uplevel $args} msg]\n\t if {$code == 1} {\n\t\t#\n\t\t# Strip" -" the last five lines off the error stack (they're\n\t\t# from the \"u" -"plevel\" command).\n\t\t#\n\n\t\tset new [split $errorInfo \\n]\n\t\tset new " -"[join [lrange $new 0 [expr [llength $new] - 6]] \\n]\n\t\treturn -cod" -"e error -errorcode $errorCode \\\n\t\t\t-errorinfo $new $msg\n\t } el" -"se {\n\t\treturn -code $code $msg\n\t }\n\t}\n }\n \n # Try run" -"ning SICS for a change\n set ret [catch {uplevel #0 SicsUnknown" -" $args} msg]\n if {$ret == 1} {\n return -code error $msg" -"\n } else {\n return -code ok $msg\n }\n}\n\n# auto_load -" -"-\n# Checks a collection of library directories to see if a proced" -"ure\n# is defined in one of them. If so, it sources the appropria" -"te\n# library file to create the procedure. Returns 1 if it succe" -"ssfully\n# loaded the procedure, 0 otherwise.\n#\n# Arguments: \n# cm" -"d -\t\t\tName of the command to find and load.\n\nproc auto_load cmd {" -"\n global auto_index auto_oldpath auto_path env errorInfo error" -"Code\n\n if [info exists auto_index($cmd)] {\n\tuplevel #0 $auto_i" -"ndex($cmd)\n\treturn [expr {[info commands $cmd] != \"\"}]\n }\n " -"if ![info exists auto_path] {\n\treturn 0\n }\n if [info exists" -" auto_oldpath] {\n\tif {$auto_oldpath == $auto_path} {\n\t return " -"0\n\t}\n }\n set auto_oldpath $auto_path\n for {set i [expr [" -"llength $auto_path] - 1]} {$i >= 0} {incr i -1} {\n\tset dir [linde" -"x $auto_path $i]\n\tset f \"\"\n\tif [catch {set f [open [file join $di" -"r tclIndex]]}] {\n\t continue\n\t}\n\tset error [catch {\n\t set id" -" [gets $f]\n\t if {$id == \"# Tcl autoload index file, version 2." -"0\"} {\n\t\teval [read $f]\n\t } elseif {$id == \"# Tcl autoload inde" -"x file: each line identifies a Tcl\"} {\n\t\twhile {[gets $f line] >=" -" 0} {\n\t\t if {([string index $line 0] == \"#\")\n\t\t\t || ([lleng" -"th $line] != 2)} {\n\t\t\tcontinue\n\t\t }\n\t\t set name [lindex $li" -"ne 0]\n\t\t set auto_index($name) \\\n\t\t\t\"source [file join $dir [l" -"index $line 1]]\"\n\t\t}\n\t } else {\n\t\terror \"[file join $dir tclIn" -"dex] isn't a proper Tcl index file\"\n\t }\n\t} msg]\n\tif {$f != \"\"}" -" {\n\t close $f\n\t}\n\tif $error {\n\t error $msg $errorInfo $erro" -"rCode\n\t}\n }\n if [info exists auto_index($cmd)] {\n\tuplevel #" -"0 $auto_index($cmd)\n\tif {[info commands $cmd] != \"\"} {\n\t retur" -"n 1\n\t}\n }\n return 0\n}\n\nif {[string compare $tcl_platform(pl" -"atform) windows] == 0} {\n\n# auto_execok --\n#\n# Returns string tha" -"t indicates name of program to execute if \n# name corresponds to " -"a shell builtin or an executable in the\n# Windows search path, or" -" \"\" otherwise. Builds an associative \n# array auto_execs that ca" -"ches information about previous checks, \n# for speed.\n#\n# Argumen" -"ts: \n# name -\t\t\tName of a command.\n\n# Windows version.\n#\n# Note t" -"hat info executable doesn't work under Windows, so we have to\n# l" -"ook for files with .exe, .com, or .bat extensions. Also, the pat" -"h\n# may be in the Path or PATH environment variables, and path\n# " -"components are separated with semicolons, not colons as under Uni" -"x.\n#\nproc auto_execok name {\n global auto_execs env tcl_platfo" -"rm\n\n if [info exists auto_execs($name)] {\n\treturn $auto_execs(" -"$name)\n }\n set auto_execs($name) \"\"\n\n if {[lsearch -exac" -"t {cls copy date del erase dir echo mkdir md rename \n\t ren rmd" -"ir rd time type ver vol} $name] != -1} {\n\tif {[info exists env(CO" -"MSPEC)]} {\n\t set comspec $env(COMSPEC) \n\t} elseif {[info exist" -"s env(ComSpec)]} {\n\t set comspec $env(ComSpec)\n\t} elseif {$tcl" -"_platform(os) == \"Windows NT\"} {\n\t set comspec \"cmd.exe\"\n\t} el" -"se {\n\t set comspec \"command.com\"\n\t}\n\treturn [set auto_execs($n" -"ame) [list $comspec /c $name]]\n }\n\n if {[llength [file spli" -"t $name]] != 1} {\n\tforeach ext {{} .com .exe .bat} {\n\t set fil" -"e ${name}${ext}\n\t if {[file exists $file] && ![file isdirector" -"y $file]} {\n\t\treturn [set auto_execs($name) $file]\n\t }\n\t}\n\tret" -"urn \"\"\n }\n\n set path \"[file dirname [info nameof]];.;\"\n " -"if {[info exists env(WINDIR)]} {\n\tset windir $env(WINDIR) \n } " -"elseif {[info exists env(windir)]} {\n\tset windir $env(windir)\n " -" }\n if {[info exists windir]} {\n\tif {$tcl_platform(os) == \"Win" -"dows NT\"} {\n\t append path \"$windir/system32;\"\n\t}\n\tappend path " -"\"$windir/system;$windir;\"\n }\n\n if {! [info exists env(PATH)" -"]} {\n\tif [info exists env(Path)] {\n\t append path $env(Path)\n\t}" -" else {\n\t return \"\"\n\t}\n } else {\n\tappend path $env(PATH)\n " -" }\n\n foreach dir [split $path {;}] {\n\tif {$dir == \"\"} {\n\t " -"set dir .\n\t}\n\tforeach ext {{} .com .exe .bat} {\n\t set file [fi" -"le join $dir ${name}${ext}]\n\t if {[file exists $file] && ![fil" -"e isdirectory $file]} {\n\t\treturn [set auto_execs($name) $file]\n\t " -" }\n\t}\n }\n return \"\"\n}\n\n} else {\n\n# auto_execok --\n#\n# Ret" -"urns string that indicates name of program to execute if \n# name " -"corresponds to an executable in the path. Builds an associative \n" -"# array auto_execs that caches information about previous checks," -" \n# for speed.\n#\n# Arguments: \n# name -\t\t\tName of a command.\n\n# U" -"nix version.\n#\nproc auto_execok name {\n global auto_execs env\n" -"\n if [info exists auto_execs($name)] {\n\treturn $auto_execs($na" -"me)\n }\n set auto_execs($name) \"\"\n if {[llength [file spl" -"it $name]] != 1} {\n\tif {[file executable $name] && ![file isdirec" -"tory $name]} {\n\t set auto_execs($name) $name\n\t}\n\treturn $auto_" -"execs($name)\n }\n foreach dir [split $env(PATH) :] {\n\tif {$d" -"ir == \"\"} {\n\t set dir .\n\t}\n\tset file [file join $dir $name]\n\ti" -"f {[file executable $file] && ![file isdirectory $file]} {\n\t s" -"et auto_execs($name) $file\n\t return $file\n\t}\n }\n return " -"\"\"\n}\n\n}\n# auto_reset --\n# Destroy all cached information for auto" -"-loading and auto-execution,\n# so that the information gets recom" -"puted the next time it's needed.\n# Also delete any procedures tha" -"t are listed in the auto-load index\n# except those defined in thi" -"s file.\n#\n# Arguments: \n# None.\n\nproc auto_reset {} {\n global " -"auto_execs auto_index auto_oldpath\n foreach p [info procs] {\n\t" -"if {[info exists auto_index($p)] && ![string match auto_* $p]\n\t\t&" -"& ([lsearch -exact {unknown pkg_mkIndex tclPkgSetup\n\t\t\ttclPkgUnkn" -"own} $p] < 0)} {\n\t rename $p {}\n\t}\n }\n catch {unset auto" -"_execs}\n catch {unset auto_index}\n catch {unset auto_oldpat" -"h}\n}\n\n# auto_mkindex --\n# Regenerate a tclIndex file from Tcl sou" -"rce files. Takes as argument\n# the name of the directory in whic" -"h the tclIndex file is to be placed,\n# followed by any number of " -"glob patterns to use in that directory to\n# locate all of the rel" -"evant files.\n#\n# Arguments: \n# dir -\t\t\tName of the directory in w" -"hich to create an index.\n# args -\t\tAny number of additional argum" -"ents giving the\n#\t\t\tnames of files within dir. If no additional\n" -"#\t\t\tare given auto_mkindex will look for *.tcl.\n\nproc auto_mkinde" -"x {dir args} {\n global errorCode errorInfo\n set oldDir [pwd" -"]\n cd $dir\n set dir [pwd]\n append index \"# Tcl autoload " -"index file, version 2.0\\n\"\n append index \"# This file is gener" -"ated by the \\\"auto_mkindex\\\" command\\n\"\n append index \"# and s" -"ourced to set up indexing information for one or\\n\"\n append in" -"dex \"# more commands. Typically each line is a command that\\n\"\n " -" append index \"# sets an element in the auto_index array, where" -" the\\n\"\n append index \"# element name is the name of a command" -" and the value is\\n\"\n append index \"# a script that loads the " -"command.\\n\\n\"\n if {$args == \"\"} {\n\tset args *.tcl\n }\n fo" -"reach file [eval glob $args] {\n\tset f \"\"\n\tset error [catch {\n\t " -" set f [open $file]\n\t while {[gets $f line] >= 0} {\n\t\tif [rege" -"xp {^proc[ \t]+([^ \t]*)} $line match procName] {\n\t\t append inde" -"x \"set [list auto_index($procName)]\"\n\t\t append index \" \\[list " -"source \\[file join \\$dir [list $file]\\]\\]\\n\"\n\t\t}\n\t }\n\t clos" -"e $f\n\t} msg]\n\tif $error {\n\t set code $errorCode\n\t set info " -"$errorInfo\n\t catch {close $f}\n\t cd $oldDir\n\t error $msg " -"$info $code\n\t}\n }\n set f \"\"\n set error [catch {\n\tset f [" -"open tclIndex w]\n\tputs $f $index nonewline\n\tclose $f\n\tcd $oldDir\n" -" } msg]\n if $error {\n\tset code $errorCode\n\tset info $errorI" -"nfo\n\tcatch {close $f}\n\tcd $oldDir\n\terror $msg $info $code\n }\n}" -"\n\n# pkg_mkIndex --\n# This procedure creates a package index in a " -"given directory. The\n# package index consists of a \"pkgIndex.tcl" -"\" file whose contents are\n# a Tcl script that sets up package inf" -"ormation with \"package require\"\n# commands. The commands describ" -"e all of the packages defined by the\n# files given as arguments.\n" -"#\n# Arguments:\n# dir -\t\t\tName of the directory in which to create" -" the index.\n# args -\t\tAny number of additional arguments, each gi" -"ving\n#\t\t\ta glob pattern that matches the names of one or\n#\t\t\tmore" -" shared libraries or Tcl script files in\n#\t\t\tdir.\n\nproc pkg_mkInd" -"ex {dir args} {\n global errorCode errorInfo\n append index \"" -"# Tcl package index file, version 1.0\\n\"\n append index \"# This" -" file is generated by the \\\"pkg_mkIndex\\\" command\\n\"\n append i" -"ndex \"# and sourced either when an application starts up or\\n\"\n " -" append index \"# by a \\\"package unknown\\\" script. It invokes th" -"e\\n\"\n append index \"# \\\"package ifneeded\\\" command to set up p" -"ackage-related\\n\"\n append index \"# information so that package" -"s will be loaded automatically\\n\"\n append index \"# in response" -" to \\\"package require\\\" commands. When this\\n\"\n append index " -"\"# script is sourced, the variable \\$dir must contain the\\n\"\n " -"append index \"# full path name of this file's directory.\\n\"\n s" -"et oldDir [pwd]\n cd $dir\n foreach file [eval glob $args] {\n" -"\t# For each file, figure out what commands and packages it provid" -"es.\n\t# To do this, create a child interpreter, load the file into" -" the\n\t# interpreter, and get a list of the new commands and packa" -"ges\n\t# that are defined. Define an empty \"package unknown\" scrip" -"t so\n\t# that there are no recursive package inclusions.\n\n\tset c [" -"interp create]\n\n\t# If Tk is loaded in the parent interpreter, loa" -"d it into the\n\t# child also, in case the extension depends on it." -"\n\n\tforeach pkg [info loaded] {\n\t if {[lindex $pkg 1] == \"Tk\"} " -"{\n\t\t$c eval {set argv {-geometry +0+0}}\n\t\tload [lindex $pkg 0] Tk" -" $c\n\t\tbreak\n\t }\n\t}\n\t$c eval [list set file $file]\n\tif [catch {" -"\n\t $c eval {\n\t\tproc dummy args {}\n\t\tpackage unknown dummy\n\t\tse" -"t origCmds [info commands]\n\t\tset dir \"\"\t\t;# in case file is pkgIn" -"dex.tcl\n\t\tset pkgs \"\"\n\n\t\t# Try to load the file if it has the sha" -"red library extension,\n\t\t# otherwise source it. It's important n" -"ot to try to load\n\t\t# files that aren't shared libraries, because" -" on some systems\n\t\t# (like SunOS) the loader will abort the whole" -" application\n\t\t# when it gets an error.\n\n\t\tif {[string compare [f" -"ile extension $file] \\\n\t\t\t[info sharedlibextension]] == 0} {\n\n\t\t " -" # The \"file join .\" command below is necessary. Without\n\t\t " -" # it, if the file name has no \\'s and we're on UNIX, the\n\t\t #" -" load command will invoke the LD_LIBRARY_PATH search\n\t\t # mech" -"anism, which could cause the wrong file to be used.\n\n\t\t load [" -"file join . $file]\n\t\t set type load\n\t\t} else {\n\t\t source $f" -"ile\n\t\t set type source\n\t\t}\n\t\tforeach i [info commands] {\n\t\t " -" set cmds($i) 1\n\t\t}\n\t\tforeach i $origCmds {\n\t\t catch {unset cm" -"ds($i)}\n\t\t}\n\t\tforeach i [package names] {\n\t\t if {([string comp" -"are [package provide $i] \"\"] != 0)\n\t\t\t && ([string compare $i " -"Tcl] != 0)\n\t\t\t && ([string compare $i Tk] != 0)} {\n\t\t\tlappend " -"pkgs [list $i [package provide $i]]\n\t\t }\n\t\t}\n\t }\n\t} msg] {\n" -"\t puts \"error while loading or sourcing $file: $msg\"\n\t}\n\tforea" -"ch pkg [$c eval set pkgs] {\n\t lappend files($pkg) [list $file " -"[$c eval set type] \\\n\t\t [lsort [$c eval array names cmds]]]\n\t}" -"\n\tinterp delete $c\n }\n foreach pkg [lsort [array names file" -"s]] {\n\tappend index \"\\npackage ifneeded $pkg\\\n\t\t\\[list tclPkgSetu" -"p \\$dir [lrange $pkg 0 0] [lrange $pkg 1 1]\\\n\t\t[list $files($pkg)" -"]\\]\"\n }\n set f [open pkgIndex.tcl w]\n puts $f $index\n " -" close $f\n cd $oldDir\n}\n\n# tclPkgSetup --\n# This is a utility " -"procedure use by pkgIndex.tcl files. It is invoked\n# as part of " -"a \"package ifneeded\" script. It calls \"package provide\"\n# to ind" -"icate that a package is available, then sets entries in the\n# aut" -"o_index array so that the package's files will be auto-loaded whe" -"n\n# the commands are used.\n#\n# Arguments:\n# dir -\t\t\tDirectory con" -"taining all the files for this package.\n# pkg -\t\t\tName of the pac" -"kage (no version number).\n# version -\t\tVersion number for the pac" -"kage, such as 2.1.3.\n# files -\t\tList of files that constitute the" -" package. Each\n#\t\t\telement is a sub-list with three elements. T" -"he first\n#\t\t\tis the name of a file relative to $dir, the second i" -"s\n#\t\t\t\"load\" or \"source\", indicating whether the file is a\n#\t\t\tlo" -"adable binary or a script to source, and the third\n#\t\t\tis a list " -"of commands defined by this file.\n\nproc tclPkgSetup {dir pkg vers" -"ion files} {\n global auto_index\n\n package provide $pkg $ver" -"sion\n foreach fileInfo $files {\n\tset f [lindex $fileInfo 0]\n\ts" -"et type [lindex $fileInfo 1]\n\tforeach cmd [lindex $fileInfo 2] {\n" -"\t if {$type == \"load\"} {\n\t\tset auto_index($cmd) [list load [fi" -"le join $dir $f] $pkg]\n\t } else {\n\t\tset auto_index($cmd) [list" -" source [file join $dir $f]]\n\t } \n\t}\n }\n}\n\n# tclMacPkgSearc" -"h --\n# The procedure is used on the Macintosh to search a given d" -"irectory for files\n# with a TEXT resource named \"pkgIndex\". If i" -"t exists it is sourced in to the\n# interpreter to setup the packa" -"ge database.\n\nproc tclMacPkgSearch {dir} {\n foreach x [glob -n" -"ocomplain [file join $dir *.shlb]] {\n\tif [file isfile $x] {\n\t " -"set res [resource open $x]\n\t foreach y [resource list TEXT $re" -"s] {\n\t\tif {$y == \"pkgIndex\"} {source -rsrc pkgIndex}\n\t }\n\t " -"resource close $res\n\t}\n }\n}\n\n# tclPkgUnknown --\n# This procedu" -"re provides the default for the \"package unknown\" function.\n# It " -"is invoked when a package that's needed can't be found. It scans" -"\n# the auto_path directories and their immediate children looking" -" for\n# pkgIndex.tcl files and sources any such files that are fou" -"nd to setup\n# the package database. (On the Macintosh we also se" -"arch for pkgIndex\n# TEXT resources in all files.)\n#\n# Arguments:\n" -"# name -\t\tName of desired package. Not used.\n# version -\t\tVersio" -"n of desired package. Not used.\n# exact -\t\tEither \"-exact\" or om" -"itted. Not used.\n\nproc tclPkgUnknown {name version {exact {}}} {" -"\n global auto_path tcl_platform env\n\n if ![info exists auto" -"_path] {\n\treturn\n }\n for {set i [expr [llength $auto_path] " -"- 1]} {$i >= 0} {incr i -1} {\n\tset dir [lindex $auto_path $i]\n\tse" -"t file [file join $dir pkgIndex.tcl]\n\tif [file readable $file] {\n" -"\t source $file\n\t}\n\tforeach file [glob -nocomplain [file join $" -"dir * pkgIndex.tcl]] {\n\t if [file readable $file] {\n\t\tset dir " -"[file dirname $file]\n\t\tsource $file\n\t }\n\t}\n\t# On the Macintosh" -" we also look in the resource fork \n\t# of shared libraries\n\tif {$" -"tcl_platform(platform) == \"macintosh\"} {\n\t set dir [lindex $au" -"to_path $i]\n\t tclMacPkgSearch $dir\n\t foreach x [glob -nocom" -"plain [file join $dir *]] {\n\t\tif [file isdirectory $x] {\n\t\t se" -"t dir $x\n\t\t tclMacPkgSearch $dir\n\t\t}\n\t }\n\t}\n }\n}\n" -; -int initcl_Init(Tcl_Interp* interp) +static char init_tcl[] = + "# init.tcl --\n#\n# Default system startup file for Tcl-based appli" + "cations. Defines\n# \"unknown\" procedure and auto-load facilities." + "\n#\n# SCCS: @(#) init.tcl 1.66 96/10/06 14:29:28\n#\n# Copyright (c)" + " 1991-1993 The Regents of the University of California.\n# Copyrig" + "ht (c) 1994-1996 Sun Microsystems, Inc.\n#\n# See the file \"license" + ".terms\" for information on usage and redistribution\n# of this fil" + "e, and for a DISCLAIMER OF ALL WARRANTIES.\n#\n#-------------------" + "---------------------------------------------------------\n#\n# Mod" + "ified by Mark Koennecke in order to redirect unknown into the Sic" + "s\n# mechanism. Thereby disabling command shortcuts and execution " + "of shell\n# commands for security reasons.\n#\n# February 1997\n#\n#--" + "-----------------------------------------------------------------" + "--------\n \nif {[info commands package] == \"\"} {\n error \"versio" + "n mismatch: library\\nscripts expect Tcl version 7.5b1 or later bu" + "t the loaded version is\\nonly [info patchlevel]\"\n}\npackage requir" + "e -exact Tcl 7.6\n#if [catch {set auto_path $env(TCLLIBPATH)}] {\n#" + " set auto_path \"\"\n#}\nif {[lsearch -exact $auto_path [info libr" + "ary]] < 0} {\n lappend auto_path [info library]\n}\ncatch {\n f" + "oreach dir $tcl_pkgPath {\n\tif {[lsearch -exact $auto_path $dir] <" + " 0} {\n\t lappend auto_path $dir\n\t}\n }\n unset dir\n}\npackag" + "e unknown tclPkgUnknown\n\n# Some machines, such as the Macintosh, " + "do not have exec. Also, on all\n# platforms, safe interpreters do " + "not have exec.\n# exec hereby disabled for Security reasons! MK\n " + " set auto_noexec 1\n\n\nset errorCode \"\"\nset errorInfo \"\"\n\n# unknow" + "n --\n# This procedure is called when a Tcl command is invoked tha" + "t doesn't\n# exist in the interpreter. It takes the following ste" + "ps to make the\n# command available:\n#\n#\t1. See if the autoload fa" + "cility can locate the command in a\n#\t Tcl script file. If so, " + "load it and execute it.\n#\t2. If the command was invoked interacti" + "vely at top-level:\n#\t (a) see if the command exists as an exec" + "utable UNIX program.\n#\t\tIf so, \"exec\" the command.\n#\t (b) see " + "if the command requests csh-like history substitution\n#\t\tin one o" + "f the common forms !!, !, or ^old^new. If\n#\t\tso, emulate" + " csh's history substitution.\n#\t (c) see if the command is a un" + "ique abbreviation for another\n#\t\tcommand. If so, invoke the comm" + "and.\n#\n# Arguments:\n# args -\tA list whose elements are the words " + "of the original\n#\t\tcommand, including the command name.\n\nproc unk" + "nown args {\n global auto_noexec auto_noload env unknown_pendin" + "g tcl_interactive\n global errorCode errorInfo\n\n # Save the " + "values of errorCode and errorInfo variables, since they\n # may" + " get modified if caught errors occur below. The variables will\n " + " # be restored just before re-executing the missing command.\n\n " + " set savedErrorCode $errorCode\n set savedErrorInfo $errorInf" + "o\n set name [lindex $args 0]\n if ![info exists auto_noload]" + " {\n\t#\n\t# Make sure we're not trying to load the same proc twice.\n" + "\t#\n\tif [info exists unknown_pending($name)] {\n\t return -code e" + "rror \"self-referential recursion in \\\"unknown\\\" for command \\\"$na" + "me\\\"\";\n\t}\n\tset unknown_pending($name) pending;\n\tset ret [catch {a" + "uto_load $name} msg]\n\tunset unknown_pending($name);\n\tif {$ret != " + "0} {\n\t return -code $ret -errorcode $errorCode \\\n\t\t\"error whil" + "e autoloading \\\"$name\\\": $msg\"\n\t}\n\tif ![array size unknown_pendin" + "g] {\n\t unset unknown_pending\n\t}\n\tif $msg {\n\t set errorCode " + "$savedErrorCode\n\t set errorInfo $savedErrorInfo\n\t set code " + "[catch {uplevel $args} msg]\n\t if {$code == 1} {\n\t\t#\n\t\t# Strip" + " the last five lines off the error stack (they're\n\t\t# from the \"u" + "plevel\" command).\n\t\t#\n\n\t\tset new [split $errorInfo \\n]\n\t\tset new " + "[join [lrange $new 0 [expr [llength $new] - 6]] \\n]\n\t\treturn -cod" + "e error -errorcode $errorCode \\\n\t\t\t-errorinfo $new $msg\n\t } el" + "se {\n\t\treturn -code $code $msg\n\t }\n\t}\n }\n \n # Try run" + "ning SICS for a change\n set ret [catch {uplevel #0 SicsUnknown" + " $args} msg]\n if {$ret == 1} {\n return -code error $msg" + "\n } else {\n return -code ok $msg\n }\n}\n\n# auto_load -" + "-\n# Checks a collection of library directories to see if a proced" + "ure\n# is defined in one of them. If so, it sources the appropria" + "te\n# library file to create the procedure. Returns 1 if it succe" + "ssfully\n# loaded the procedure, 0 otherwise.\n#\n# Arguments: \n# cm" + "d -\t\t\tName of the command to find and load.\n\nproc auto_load cmd {" + "\n global auto_index auto_oldpath auto_path env errorInfo error" + "Code\n\n if [info exists auto_index($cmd)] {\n\tuplevel #0 $auto_i" + "ndex($cmd)\n\treturn [expr {[info commands $cmd] != \"\"}]\n }\n " + "if ![info exists auto_path] {\n\treturn 0\n }\n if [info exists" + " auto_oldpath] {\n\tif {$auto_oldpath == $auto_path} {\n\t return " + "0\n\t}\n }\n set auto_oldpath $auto_path\n for {set i [expr [" + "llength $auto_path] - 1]} {$i >= 0} {incr i -1} {\n\tset dir [linde" + "x $auto_path $i]\n\tset f \"\"\n\tif [catch {set f [open [file join $di" + "r tclIndex]]}] {\n\t continue\n\t}\n\tset error [catch {\n\t set id" + " [gets $f]\n\t if {$id == \"# Tcl autoload index file, version 2." + "0\"} {\n\t\teval [read $f]\n\t } elseif {$id == \"# Tcl autoload inde" + "x file: each line identifies a Tcl\"} {\n\t\twhile {[gets $f line] >=" + " 0} {\n\t\t if {([string index $line 0] == \"#\")\n\t\t\t || ([lleng" + "th $line] != 2)} {\n\t\t\tcontinue\n\t\t }\n\t\t set name [lindex $li" + "ne 0]\n\t\t set auto_index($name) \\\n\t\t\t\"source [file join $dir [l" + "index $line 1]]\"\n\t\t}\n\t } else {\n\t\terror \"[file join $dir tclIn" + "dex] isn't a proper Tcl index file\"\n\t }\n\t} msg]\n\tif {$f != \"\"}" + " {\n\t close $f\n\t}\n\tif $error {\n\t error $msg $errorInfo $erro" + "rCode\n\t}\n }\n if [info exists auto_index($cmd)] {\n\tuplevel #" + "0 $auto_index($cmd)\n\tif {[info commands $cmd] != \"\"} {\n\t retur" + "n 1\n\t}\n }\n return 0\n}\n\nif {[string compare $tcl_platform(pl" + "atform) windows] == 0} {\n\n# auto_execok --\n#\n# Returns string tha" + "t indicates name of program to execute if \n# name corresponds to " + "a shell builtin or an executable in the\n# Windows search path, or" + " \"\" otherwise. Builds an associative \n# array auto_execs that ca" + "ches information about previous checks, \n# for speed.\n#\n# Argumen" + "ts: \n# name -\t\t\tName of a command.\n\n# Windows version.\n#\n# Note t" + "hat info executable doesn't work under Windows, so we have to\n# l" + "ook for files with .exe, .com, or .bat extensions. Also, the pat" + "h\n# may be in the Path or PATH environment variables, and path\n# " + "components are separated with semicolons, not colons as under Uni" + "x.\n#\nproc auto_execok name {\n global auto_execs env tcl_platfo" + "rm\n\n if [info exists auto_execs($name)] {\n\treturn $auto_execs(" + "$name)\n }\n set auto_execs($name) \"\"\n\n if {[lsearch -exac" + "t {cls copy date del erase dir echo mkdir md rename \n\t ren rmd" + "ir rd time type ver vol} $name] != -1} {\n\tif {[info exists env(CO" + "MSPEC)]} {\n\t set comspec $env(COMSPEC) \n\t} elseif {[info exist" + "s env(ComSpec)]} {\n\t set comspec $env(ComSpec)\n\t} elseif {$tcl" + "_platform(os) == \"Windows NT\"} {\n\t set comspec \"cmd.exe\"\n\t} el" + "se {\n\t set comspec \"command.com\"\n\t}\n\treturn [set auto_execs($n" + "ame) [list $comspec /c $name]]\n }\n\n if {[llength [file spli" + "t $name]] != 1} {\n\tforeach ext {{} .com .exe .bat} {\n\t set fil" + "e ${name}${ext}\n\t if {[file exists $file] && ![file isdirector" + "y $file]} {\n\t\treturn [set auto_execs($name) $file]\n\t }\n\t}\n\tret" + "urn \"\"\n }\n\n set path \"[file dirname [info nameof]];.;\"\n " + "if {[info exists env(WINDIR)]} {\n\tset windir $env(WINDIR) \n } " + "elseif {[info exists env(windir)]} {\n\tset windir $env(windir)\n " + " }\n if {[info exists windir]} {\n\tif {$tcl_platform(os) == \"Win" + "dows NT\"} {\n\t append path \"$windir/system32;\"\n\t}\n\tappend path " + "\"$windir/system;$windir;\"\n }\n\n if {! [info exists env(PATH)" + "]} {\n\tif [info exists env(Path)] {\n\t append path $env(Path)\n\t}" + " else {\n\t return \"\"\n\t}\n } else {\n\tappend path $env(PATH)\n " + " }\n\n foreach dir [split $path {;}] {\n\tif {$dir == \"\"} {\n\t " + "set dir .\n\t}\n\tforeach ext {{} .com .exe .bat} {\n\t set file [fi" + "le join $dir ${name}${ext}]\n\t if {[file exists $file] && ![fil" + "e isdirectory $file]} {\n\t\treturn [set auto_execs($name) $file]\n\t " + " }\n\t}\n }\n return \"\"\n}\n\n} else {\n\n# auto_execok --\n#\n# Ret" + "urns string that indicates name of program to execute if \n# name " + "corresponds to an executable in the path. Builds an associative \n" + "# array auto_execs that caches information about previous checks," + " \n# for speed.\n#\n# Arguments: \n# name -\t\t\tName of a command.\n\n# U" + "nix version.\n#\nproc auto_execok name {\n global auto_execs env\n" + "\n if [info exists auto_execs($name)] {\n\treturn $auto_execs($na" + "me)\n }\n set auto_execs($name) \"\"\n if {[llength [file spl" + "it $name]] != 1} {\n\tif {[file executable $name] && ![file isdirec" + "tory $name]} {\n\t set auto_execs($name) $name\n\t}\n\treturn $auto_" + "execs($name)\n }\n foreach dir [split $env(PATH) :] {\n\tif {$d" + "ir == \"\"} {\n\t set dir .\n\t}\n\tset file [file join $dir $name]\n\ti" + "f {[file executable $file] && ![file isdirectory $file]} {\n\t s" + "et auto_execs($name) $file\n\t return $file\n\t}\n }\n return " + "\"\"\n}\n\n}\n# auto_reset --\n# Destroy all cached information for auto" + "-loading and auto-execution,\n# so that the information gets recom" + "puted the next time it's needed.\n# Also delete any procedures tha" + "t are listed in the auto-load index\n# except those defined in thi" + "s file.\n#\n# Arguments: \n# None.\n\nproc auto_reset {} {\n global " + "auto_execs auto_index auto_oldpath\n foreach p [info procs] {\n\t" + "if {[info exists auto_index($p)] && ![string match auto_* $p]\n\t\t&" + "& ([lsearch -exact {unknown pkg_mkIndex tclPkgSetup\n\t\t\ttclPkgUnkn" + "own} $p] < 0)} {\n\t rename $p {}\n\t}\n }\n catch {unset auto" + "_execs}\n catch {unset auto_index}\n catch {unset auto_oldpat" + "h}\n}\n\n# auto_mkindex --\n# Regenerate a tclIndex file from Tcl sou" + "rce files. Takes as argument\n# the name of the directory in whic" + "h the tclIndex file is to be placed,\n# followed by any number of " + "glob patterns to use in that directory to\n# locate all of the rel" + "evant files.\n#\n# Arguments: \n# dir -\t\t\tName of the directory in w" + "hich to create an index.\n# args -\t\tAny number of additional argum" + "ents giving the\n#\t\t\tnames of files within dir. If no additional\n" + "#\t\t\tare given auto_mkindex will look for *.tcl.\n\nproc auto_mkinde" + "x {dir args} {\n global errorCode errorInfo\n set oldDir [pwd" + "]\n cd $dir\n set dir [pwd]\n append index \"# Tcl autoload " + "index file, version 2.0\\n\"\n append index \"# This file is gener" + "ated by the \\\"auto_mkindex\\\" command\\n\"\n append index \"# and s" + "ourced to set up indexing information for one or\\n\"\n append in" + "dex \"# more commands. Typically each line is a command that\\n\"\n " + " append index \"# sets an element in the auto_index array, where" + " the\\n\"\n append index \"# element name is the name of a command" + " and the value is\\n\"\n append index \"# a script that loads the " + "command.\\n\\n\"\n if {$args == \"\"} {\n\tset args *.tcl\n }\n fo" + "reach file [eval glob $args] {\n\tset f \"\"\n\tset error [catch {\n\t " + " set f [open $file]\n\t while {[gets $f line] >= 0} {\n\t\tif [rege" + "xp {^proc[ \t]+([^ \t]*)} $line match procName] {\n\t\t append inde" + "x \"set [list auto_index($procName)]\"\n\t\t append index \" \\[list " + "source \\[file join \\$dir [list $file]\\]\\]\\n\"\n\t\t}\n\t }\n\t clos" + "e $f\n\t} msg]\n\tif $error {\n\t set code $errorCode\n\t set info " + "$errorInfo\n\t catch {close $f}\n\t cd $oldDir\n\t error $msg " + "$info $code\n\t}\n }\n set f \"\"\n set error [catch {\n\tset f [" + "open tclIndex w]\n\tputs $f $index nonewline\n\tclose $f\n\tcd $oldDir\n" + " } msg]\n if $error {\n\tset code $errorCode\n\tset info $errorI" + "nfo\n\tcatch {close $f}\n\tcd $oldDir\n\terror $msg $info $code\n }\n}" + "\n\n# pkg_mkIndex --\n# This procedure creates a package index in a " + "given directory. The\n# package index consists of a \"pkgIndex.tcl" + "\" file whose contents are\n# a Tcl script that sets up package inf" + "ormation with \"package require\"\n# commands. The commands describ" + "e all of the packages defined by the\n# files given as arguments.\n" + "#\n# Arguments:\n# dir -\t\t\tName of the directory in which to create" + " the index.\n# args -\t\tAny number of additional arguments, each gi" + "ving\n#\t\t\ta glob pattern that matches the names of one or\n#\t\t\tmore" + " shared libraries or Tcl script files in\n#\t\t\tdir.\n\nproc pkg_mkInd" + "ex {dir args} {\n global errorCode errorInfo\n append index \"" + "# Tcl package index file, version 1.0\\n\"\n append index \"# This" + " file is generated by the \\\"pkg_mkIndex\\\" command\\n\"\n append i" + "ndex \"# and sourced either when an application starts up or\\n\"\n " + " append index \"# by a \\\"package unknown\\\" script. It invokes th" + "e\\n\"\n append index \"# \\\"package ifneeded\\\" command to set up p" + "ackage-related\\n\"\n append index \"# information so that package" + "s will be loaded automatically\\n\"\n append index \"# in response" + " to \\\"package require\\\" commands. When this\\n\"\n append index " + "\"# script is sourced, the variable \\$dir must contain the\\n\"\n " + "append index \"# full path name of this file's directory.\\n\"\n s" + "et oldDir [pwd]\n cd $dir\n foreach file [eval glob $args] {\n" + "\t# For each file, figure out what commands and packages it provid" + "es.\n\t# To do this, create a child interpreter, load the file into" + " the\n\t# interpreter, and get a list of the new commands and packa" + "ges\n\t# that are defined. Define an empty \"package unknown\" scrip" + "t so\n\t# that there are no recursive package inclusions.\n\n\tset c [" + "interp create]\n\n\t# If Tk is loaded in the parent interpreter, loa" + "d it into the\n\t# child also, in case the extension depends on it." + "\n\n\tforeach pkg [info loaded] {\n\t if {[lindex $pkg 1] == \"Tk\"} " + "{\n\t\t$c eval {set argv {-geometry +0+0}}\n\t\tload [lindex $pkg 0] Tk" + " $c\n\t\tbreak\n\t }\n\t}\n\t$c eval [list set file $file]\n\tif [catch {" + "\n\t $c eval {\n\t\tproc dummy args {}\n\t\tpackage unknown dummy\n\t\tse" + "t origCmds [info commands]\n\t\tset dir \"\"\t\t;# in case file is pkgIn" + "dex.tcl\n\t\tset pkgs \"\"\n\n\t\t# Try to load the file if it has the sha" + "red library extension,\n\t\t# otherwise source it. It's important n" + "ot to try to load\n\t\t# files that aren't shared libraries, because" + " on some systems\n\t\t# (like SunOS) the loader will abort the whole" + " application\n\t\t# when it gets an error.\n\n\t\tif {[string compare [f" + "ile extension $file] \\\n\t\t\t[info sharedlibextension]] == 0} {\n\n\t\t " + " # The \"file join .\" command below is necessary. Without\n\t\t " + " # it, if the file name has no \\'s and we're on UNIX, the\n\t\t #" + " load command will invoke the LD_LIBRARY_PATH search\n\t\t # mech" + "anism, which could cause the wrong file to be used.\n\n\t\t load [" + "file join . $file]\n\t\t set type load\n\t\t} else {\n\t\t source $f" + "ile\n\t\t set type source\n\t\t}\n\t\tforeach i [info commands] {\n\t\t " + " set cmds($i) 1\n\t\t}\n\t\tforeach i $origCmds {\n\t\t catch {unset cm" + "ds($i)}\n\t\t}\n\t\tforeach i [package names] {\n\t\t if {([string comp" + "are [package provide $i] \"\"] != 0)\n\t\t\t && ([string compare $i " + "Tcl] != 0)\n\t\t\t && ([string compare $i Tk] != 0)} {\n\t\t\tlappend " + "pkgs [list $i [package provide $i]]\n\t\t }\n\t\t}\n\t }\n\t} msg] {\n" + "\t puts \"error while loading or sourcing $file: $msg\"\n\t}\n\tforea" + "ch pkg [$c eval set pkgs] {\n\t lappend files($pkg) [list $file " + "[$c eval set type] \\\n\t\t [lsort [$c eval array names cmds]]]\n\t}" + "\n\tinterp delete $c\n }\n foreach pkg [lsort [array names file" + "s]] {\n\tappend index \"\\npackage ifneeded $pkg\\\n\t\t\\[list tclPkgSetu" + "p \\$dir [lrange $pkg 0 0] [lrange $pkg 1 1]\\\n\t\t[list $files($pkg)" + "]\\]\"\n }\n set f [open pkgIndex.tcl w]\n puts $f $index\n " + " close $f\n cd $oldDir\n}\n\n# tclPkgSetup --\n# This is a utility " + "procedure use by pkgIndex.tcl files. It is invoked\n# as part of " + "a \"package ifneeded\" script. It calls \"package provide\"\n# to ind" + "icate that a package is available, then sets entries in the\n# aut" + "o_index array so that the package's files will be auto-loaded whe" + "n\n# the commands are used.\n#\n# Arguments:\n# dir -\t\t\tDirectory con" + "taining all the files for this package.\n# pkg -\t\t\tName of the pac" + "kage (no version number).\n# version -\t\tVersion number for the pac" + "kage, such as 2.1.3.\n# files -\t\tList of files that constitute the" + " package. Each\n#\t\t\telement is a sub-list with three elements. T" + "he first\n#\t\t\tis the name of a file relative to $dir, the second i" + "s\n#\t\t\t\"load\" or \"source\", indicating whether the file is a\n#\t\t\tlo" + "adable binary or a script to source, and the third\n#\t\t\tis a list " + "of commands defined by this file.\n\nproc tclPkgSetup {dir pkg vers" + "ion files} {\n global auto_index\n\n package provide $pkg $ver" + "sion\n foreach fileInfo $files {\n\tset f [lindex $fileInfo 0]\n\ts" + "et type [lindex $fileInfo 1]\n\tforeach cmd [lindex $fileInfo 2] {\n" + "\t if {$type == \"load\"} {\n\t\tset auto_index($cmd) [list load [fi" + "le join $dir $f] $pkg]\n\t } else {\n\t\tset auto_index($cmd) [list" + " source [file join $dir $f]]\n\t } \n\t}\n }\n}\n\n# tclMacPkgSearc" + "h --\n# The procedure is used on the Macintosh to search a given d" + "irectory for files\n# with a TEXT resource named \"pkgIndex\". If i" + "t exists it is sourced in to the\n# interpreter to setup the packa" + "ge database.\n\nproc tclMacPkgSearch {dir} {\n foreach x [glob -n" + "ocomplain [file join $dir *.shlb]] {\n\tif [file isfile $x] {\n\t " + "set res [resource open $x]\n\t foreach y [resource list TEXT $re" + "s] {\n\t\tif {$y == \"pkgIndex\"} {source -rsrc pkgIndex}\n\t }\n\t " + "resource close $res\n\t}\n }\n}\n\n# tclPkgUnknown --\n# This procedu" + "re provides the default for the \"package unknown\" function.\n# It " + "is invoked when a package that's needed can't be found. It scans" + "\n# the auto_path directories and their immediate children looking" + " for\n# pkgIndex.tcl files and sources any such files that are fou" + "nd to setup\n# the package database. (On the Macintosh we also se" + "arch for pkgIndex\n# TEXT resources in all files.)\n#\n# Arguments:\n" + "# name -\t\tName of desired package. Not used.\n# version -\t\tVersio" + "n of desired package. Not used.\n# exact -\t\tEither \"-exact\" or om" + "itted. Not used.\n\nproc tclPkgUnknown {name version {exact {}}} {" + "\n global auto_path tcl_platform env\n\n if ![info exists auto" + "_path] {\n\treturn\n }\n for {set i [expr [llength $auto_path] " + "- 1]} {$i >= 0} {incr i -1} {\n\tset dir [lindex $auto_path $i]\n\tse" + "t file [file join $dir pkgIndex.tcl]\n\tif [file readable $file] {\n" + "\t source $file\n\t}\n\tforeach file [glob -nocomplain [file join $" + "dir * pkgIndex.tcl]] {\n\t if [file readable $file] {\n\t\tset dir " + "[file dirname $file]\n\t\tsource $file\n\t }\n\t}\n\t# On the Macintosh" + " we also look in the resource fork \n\t# of shared libraries\n\tif {$" + "tcl_platform(platform) == \"macintosh\"} {\n\t set dir [lindex $au" + "to_path $i]\n\t tclMacPkgSearch $dir\n\t foreach x [glob -nocom" + "plain [file join $dir *]] {\n\t\tif [file isdirectory $x] {\n\t\t se" + "t dir $x\n\t\t tclMacPkgSearch $dir\n\t\t}\n\t }\n\t}\n }\n}\n"; +int initcl_Init(Tcl_Interp * interp) { - Tcl_SetVar(interp, "package_name", "initcl", TCL_GLOBAL_ONLY); - if (Tcl_GlobalEval(interp, init_tcl) != TCL_OK) return TCL_ERROR; - Tcl_UnsetVar(interp, "package_name", TCL_GLOBAL_ONLY); - return TCL_OK; + Tcl_SetVar(interp, "package_name", "initcl", TCL_GLOBAL_ONLY); + if (Tcl_GlobalEval(interp, init_tcl) != TCL_OK) + return TCL_ERROR; + Tcl_UnsetVar(interp, "package_name", TCL_GLOBAL_ONLY); + return TCL_OK; } diff --git a/initializer.c b/initializer.c index 4c8ee024..9d47ed99 100644 --- a/initializer.c +++ b/initializer.c @@ -13,9 +13,9 @@ Markus Zolliker, March 2005 typedef struct Item { struct Item *next; - char *type; /* "Object" for all commands created by makeobject, else something more general */ - char *name; /* the name for identifying an initializer */ - char *desc; /* a description of the initializer. not the same as pObjectDescriptor->name */ + char *type; /* "Object" for all commands created by makeobject, else something more general */ + char *name; /* the name for identifying an initializer */ + char *desc; /* a description of the initializer. not the same as pObjectDescriptor->name */ Initializer maker; int startupOnly; } Item; @@ -24,9 +24,10 @@ static Item *list = NULL; static int startup = 1; void MakeInitializer(const char *type, const char *name, Initializer maker, - int startupOnly, const char *desc) { + int startupOnly, const char *desc) +{ Item *item; - + item = calloc(1, sizeof *item); assert(item); item->maker = maker; @@ -38,9 +39,10 @@ void MakeInitializer(const char *type, const char *name, Initializer maker, list = item; } -Initializer GetInitializer(const char *type, const char *name) { +Initializer GetInitializer(const char *type, const char *name) +{ Item *p, **last; - + if (startup && !ServerIsStarting(pServ)) { /* pServ->pReader exists: startup finished */ startup = 0; @@ -59,42 +61,45 @@ Initializer GetInitializer(const char *type, const char *name) { } } for (p = list; p != NULL; p = p->next) { - if (strcasecmp(p->name, name) == 0 && strcasecmp(p->type, type) == 0) { + if (strcasecmp(p->name, name) == 0 && strcasecmp(p->type, type) == 0) { return p->maker; } } return NULL; } -static int MakeObject(SConnection *con, SicsInterp *sics, - void *data, int argc, char *argv[]) { +static int MakeObject(SConnection * con, SicsInterp * sics, + void *data, int argc, char *argv[]) +{ CmdInitializer cmdin; - + if (argc < 3) { - SCPrintf(con, eError, "ERROR: should be: %s ...", argv[0]); + SCPrintf(con, eError, "ERROR: should be: %s ...", + argv[0]); return 0; } - - cmdin = (CmdInitializer)GetInitializer("Object", argv[2]); + + cmdin = (CmdInitializer) GetInitializer("Object", argv[2]); if (cmdin) { - return cmdin(con, argc, argv, strcasecmp(argv[0],"makeobject") == 0); + return cmdin(con, argc, argv, strcasecmp(argv[0], "makeobject") == 0); } else { SCPrintf(con, eError, "do not know how to make a %s object", argv[2]); return 0; } } -static int DriverList(SConnection *con, SicsInterp *sics, - void *data, int argc, char *argv[]) { +static int DriverList(SConnection * con, SicsInterp * sics, + void *data, int argc, char *argv[]) +{ Item *p; char *name, *type; - + if (argc < 2 || strcasecmp(argv[1], "list") == 0) { for (p = list; p != NULL; p = p->next) { if (argc < 3) { - SCPrintf(con, eStatus, "%s %s %s", p->type, p->name, p->desc); + SCPrintf(con, eValue, "%s %s %s", p->type, p->name, p->desc); } else if (strcasecmp(argv[2], p->type) == 0) { - SCPrintf(con, eStatus, "%s %s", p->name, p->desc); + SCPrintf(con, eValue, "%s %s", p->name, p->desc); } } } else { @@ -106,7 +111,9 @@ static int DriverList(SConnection *con, SicsInterp *sics, type = argv[1]; } p = list; - while (p != NULL && (strcasecmp(p->type, type) != 0 || strcasecmp(p->name, name) != 0)) { + while (p != NULL + && (strcasecmp(p->type, type) != 0 + || strcasecmp(p->name, name) != 0)) { p = p->next; } if (p) { @@ -118,8 +125,9 @@ static int DriverList(SConnection *con, SicsInterp *sics, return 1; } -static int RemoveObject(SConnection *con, SicsInterp *sics, - void *data, int argc, char *argv[]) { +static int RemoveObject(SConnection * con, SicsInterp * sics, + void *data, int argc, char *argv[]) +{ CmdInitializer cmdin; ObjectDescriptor *desc; char *className; @@ -127,18 +135,18 @@ static int RemoveObject(SConnection *con, SicsInterp *sics, char *p; int removeAllowed; char *creationCommand; - + if (argc != 2) { SCPrintf(con, eError, "ERROR: should be: %s ", argv[0]); return 0; } - + desc = FindCommandDescriptor(sics, argv[1]); if (!desc) { SCPrintf(con, eError, "ERROR: %s not found", argv[1]); return 0; } - + creationCommand = GetDescriptorKey(desc, "creationCommand"); if (creationCommand != NULL) { /* if there is a creationCommand, we are allowed to remove */ @@ -146,20 +154,22 @@ static int RemoveObject(SConnection *con, SicsInterp *sics, } else { /* if we have an initializer: we are also allowed to remove */ className = desc->name; - cmdin = (CmdInitializer)GetInitializer("Object", className); + cmdin = (CmdInitializer) GetInitializer("Object", className); if (cmdin == 0) { /* allow also a longer descriptor starting with the initializer name and a blank */ p = strchr(className, ' '); if (p) { - snprintf(shortClassName, sizeof shortClassName, "%.*s", p - className, className); - cmdin = (CmdInitializer)GetInitializer("Object", shortClassName); + snprintf(shortClassName, sizeof shortClassName, "%.*s", + p - className, className); + cmdin = (CmdInitializer) GetInitializer("Object", shortClassName); } } removeAllowed = (cmdin != NULL); } if (removeAllowed) { if (pServ->pExecutor && isInRunMode(pServ->pExecutor)) { - SCPrintf(con, eError, "ERROR: cannot remove %s while running", argv[1]); + SCPrintf(con, eError, "ERROR: cannot remove %s while running", + argv[1]); return 0; } SCPrintf(con, eValue, "remove %s", argv[1]); @@ -176,11 +186,13 @@ typedef struct { FILE *fil; } SaveData; -static int SaveCreationCommand(char *name, pDummy object, void *userData) { +static int SaveCreationCommand(char *name, pDummy object, void *userData) +{ SaveData *saveData = userData; char *creationCommand; - - creationCommand = GetDescriptorKey(object->pDescriptor, "creationCommand"); + + creationCommand = + GetDescriptorKey(object->pDescriptor, "creationCommand"); if (creationCommand && strcmp(creationCommand, "0") != 0) { if (saveData->printHeader == 0) { saveData->printHeader = 1; @@ -191,9 +203,10 @@ static int SaveCreationCommand(char *name, pDummy object, void *userData) { return 1; } -static int SaveCreationCommands(void *object, char *name, FILE *fil) { +static int SaveCreationCommands(void *object, char *name, FILE * fil) +{ SaveData saveData; - + saveData.fil = fil; saveData.printHeader = 0; ForEachCommand(SaveCreationCommand, &saveData); @@ -203,8 +216,9 @@ static int SaveCreationCommands(void *object, char *name, FILE *fil) { return 1; } -static int CreationCommand(SConnection *con, SicsInterp *sics, - void *data, int argc, char *argv[]) { +static int CreationCommand(SConnection * con, SicsInterp * sics, + void *data, int argc, char *argv[]) +{ CmdInitializer cmdin; char *className; char shortClassName[32]; @@ -213,12 +227,14 @@ static int CreationCommand(SConnection *con, SicsInterp *sics, ObjectDescriptor *desc; char *creationCommand; char buf[256]; - + if (argc < 2) { - SCPrintf(con, eError, "ERROR: should be: %s []", argv[0]); + SCPrintf(con, eError, + "ERROR: should be: %s []", + argv[0]); return 0; } - + desc = FindCommandDescriptor(sics, argv[1]); if (!desc) { SCPrintf(con, eError, "ERROR: %s not found", argv[1]); @@ -239,7 +255,8 @@ static int CreationCommand(SConnection *con, SicsInterp *sics, creationCommand = Arg2Tcl(argc - 2, argv + 2, buf, sizeof buf); if (creationCommand) { SetDescriptorKey(desc, "creationCommand", creationCommand); - if (creationCommand != buf) free(creationCommand); + if (creationCommand != buf) + free(creationCommand); } else { SetDescriptorKey(desc, "creationCommand", "0"); } @@ -247,34 +264,46 @@ static int CreationCommand(SConnection *con, SicsInterp *sics, return 1; } -static void KillInitializers(void *data) { +static void KillInitializers(void *data) +{ KillDummy(data); Item *item, *next; - + item = list; while (item) { next = item->next; - if (item->name) free(item->name); - if (item->type) free(item->type); - if (item->desc) free(item->desc); + if (item->name) + free(item->name); + if (item->type) + free(item->type); + if (item->desc) + free(item->desc); free(item); item = next; } list = NULL; } -void MakeDriver(const char *driver, CmdInitializer maker, int startupOnly, const char *desc) { - MakeInitializer("Object", driver, (Initializer)maker, startupOnly, desc); +void MakeDriver(const char *driver, CmdInitializer maker, int startupOnly, + const char *desc) +{ + MakeInitializer("Object", driver, (Initializer) maker, startupOnly, + desc); } -void InitializerInit(void) { +void InitializerInit(void) +{ pDummy cc = NULL; - AddCommandWithFlag(pServ->pSics, "MakeObject", MakeObject, KillInitializers, NULL, 0); - AddCommandWithFlag(pServ->pSics, "MakeStaticObject", MakeObject, NULL, NULL, 0); - AddCommandWithFlag(pServ->pSics, "RemoveObject", RemoveObject, NULL, NULL, 0); - AddCommandWithFlag(pServ->pSics, "DriverList", DriverList, NULL, NULL, 0); + AddCommandWithFlag(pServ->pSics, "MakeObject", MakeObject, + KillInitializers, NULL, 0); + AddCommandWithFlag(pServ->pSics, "MakeStaticObject", MakeObject, NULL, + NULL, 0); + AddCommandWithFlag(pServ->pSics, "RemoveObject", RemoveObject, NULL, + NULL, 0); + AddCommandWithFlag(pServ->pSics, "DriverList", DriverList, NULL, NULL, + 0); cc = CreateDummy("creation commands"); cc->pDescriptor->SaveStatus = SaveCreationCommands; AddCommandWithFlag(pServ->pSics, "CreationCommand", CreationCommand, - KillDummy, cc, 0); + KillDummy, cc, 0); } diff --git a/initializer.h b/initializer.h index 036a15a6..85d4136f 100644 --- a/initializer.h +++ b/initializer.h @@ -10,10 +10,10 @@ Markus Zolliker, March 2005 #ifndef SICSINIT_H #define SICSINIT_H -typedef void (*Initializer)(void); +typedef void (*Initializer) (void); -void MakeInitializer(const char *type, const char *name, Initializer maker, int startupOnly, - const char *desc); +void MakeInitializer(const char *type, const char *name, Initializer maker, + int startupOnly, const char *desc); /* install an initializer @@ -49,7 +49,8 @@ static int MakeObject(SConnection *con, SicsInterp *sics, */ -typedef int (*CmdInitializer) (SConnection *pCon, int argc, char *argv[], int dynamic); +typedef int (*CmdInitializer) (SConnection * pCon, int argc, char *argv[], + int dynamic); /* The initalizer prototype for the type "Object". - pCon: the sics connection calling this initializer diff --git a/intcli.c b/intcli.c index ca781e54..f26a5607 100644 --- a/intcli.c +++ b/intcli.c @@ -43,41 +43,37 @@ #include "network.h" #include "interrupt.h" - static mkChannel *pChannel = NULL; - +static mkChannel *pChannel = NULL; + /*---------------------------------------------------------------------------*/ - int ClientSetupInterrupt(char *host, int iPort) - { - pChannel = UDPConnect(host,iPort); - if(pChannel == NULL) - { - return 0; - } - else - { - return 1; - } - } -/*---------------------------------------------------------------------------*/ - void ClientStopInterrupt(void) - { - if(pChannel) - { - NETClosePort(pChannel); - free(pChannel); - } +int ClientSetupInterrupt(char *host, int iPort) +{ + pChannel = UDPConnect(host, iPort); + if (pChannel == NULL) { + return 0; + } else { + return 1; } +} + /*---------------------------------------------------------------------------*/ - void SendInterrupt(int iCode) - { - char pBueffel[132]; - - if( (iCode <0) ) - { - return; - } - - sprintf(pBueffel,"SICSINT %d",iCode); - UDPWrite(pChannel,pBueffel,strlen(pBueffel)); +void ClientStopInterrupt(void) +{ + if (pChannel) { + NETClosePort(pChannel); + free(pChannel); + } +} + +/*---------------------------------------------------------------------------*/ +void SendInterrupt(int iCode) +{ + char pBueffel[132]; + + if ((iCode < 0)) { + return; } + snprintf(pBueffel,sizeof(pBueffel)-1, "SICSINT %d", iCode); + UDPWrite(pChannel, pBueffel, strlen(pBueffel)); +} diff --git a/integrate.c b/integrate.c index 292a1d78..c9a8751d 100644 --- a/integrate.c +++ b/integrate.c @@ -25,35 +25,34 @@ in between #define LEFT -1 #define RIGHT 1 -#define ABS(x) (x < 0 ? -(x) : (x)) +#define ABS(x) (x < 0 ? -(x) : (x)) /*----------------- a private data structure to keep track of things ----*/ - typedef struct { - long *lCounts; - int iCounts; - int m; - int iLeft; - int iMaxCount; - int iRight; - } IntegData, *pIntegData; - +typedef struct { + long *lCounts; + int iCounts; + int m; + int iLeft; + int iMaxCount; + int iRight; +} IntegData, *pIntegData; + /*-------------------------------------------------------------------------*/ - static int FindMaxCount(long lCounts[], int iCounts) - { - int i, iPtr; - long l = -100000; - - for(i = 0, iPtr = 0; i < iCounts;i++) - { - if(lCounts[i] > l) - { - l = lCounts[i]; - iPtr = i; - } - } - return iPtr; - } +static int FindMaxCount(long lCounts[], int iCounts) +{ + int i, iPtr; + long l = -100000; + + for (i = 0, iPtr = 0; i < iCounts; i++) { + if (lCounts[i] > l) { + l = lCounts[i]; + iPtr = i; + } + } + return iPtr; +} + /*------------------------------------------------------------------------ Finds the index where the counts are less then half peak height. Assumes that iMaxCount has been set to a proper value beforehand. This helps to @@ -63,291 +62,262 @@ in between from there. Saves calculation time as well. FindHalf returns an index on success, else - 1 if it goes beyond limits! -----------------------------------------------------------------------*/ - static int FindHalf(pIntegData self, int iSign) - { - int i; - long lHalf; - - assert(self); - - lHalf = self->lCounts[self->iMaxCount]/2; - i = self->iMaxCount; - while(self->lCounts[i] > lHalf) - { - i += iSign; - if( (i < 0) || (i > self->iCounts) ) - { - return -1; - } - } - return i; - } +static int FindHalf(pIntegData self, int iSign) +{ + int i; + long lHalf; + + assert(self); + + lHalf = self->lCounts[self->iMaxCount] / 2; + i = self->iMaxCount; + while (self->lCounts[i] > lHalf) { + i += iSign; + if ((i < 0) || (i > self->iCounts)) { + return -1; + } + } + return i; +} + /*-------------------------------------------------------------------------- FindWindowHits find the number of hits in the window defined by 0.67 sigma of the value at iPos and m. Returns -1 if insufficient data is available to do the trick. iSign can be -1 for search to left or 1 for search to right. ----------------------------------------------------------------------------*/ - static int FindWindowHits(pIntegData self, int iPos, int iSign) - { - float fWinMin, fWinMax, fVar; - int i, iTest, iCount; - - assert(self); - assert( (iSign == -1) || (iSign == 1) ); - - /* check limits of the show */ - iTest = iPos + iSign * self->m; - if( (iTest < 0) || (iTest >= self->iCounts) ) - { - return -1; - } - - /* calculate limits */ - if(self->lCounts[iPos] > 0) - { - fVar = sqrt((double)self->lCounts[iPos]); - fWinMin = (float)self->lCounts[iPos] - 0.67 * fVar; - fWinMax = (float)self->lCounts[iPos] + 0.67 * fVar; - } - else - { - fWinMin = 0.; - fWinMax = 1.; - } - - /* count the window hits */ - for(i = 0, iCount = 0; i < self->m; i++) - { - iTest = iPos + iSign * i; - if( (self->lCounts[iTest] >= fWinMin) && - (self->lCounts[iTest] <= fWinMax) ) - { - iCount++; - } - } - return iCount; - } +---------------------------------------------------------------------------*/ +static int FindWindowHits(pIntegData self, int iPos, int iSign) +{ + float fWinMin, fWinMax, fVar; + int i, iTest, iCount; + + assert(self); + assert((iSign == -1) || (iSign == 1)); + + /* check limits of the show */ + iTest = iPos + iSign * self->m; + if ((iTest < 0) || (iTest >= self->iCounts)) { + return -1; + } + + /* calculate limits */ + if (self->lCounts[iPos] > 0) { + fVar = sqrt((double) self->lCounts[iPos]); + fWinMin = (float) self->lCounts[iPos] - 0.67 * fVar; + fWinMax = (float) self->lCounts[iPos] + 0.67 * fVar; + } else { + fWinMin = 0.; + fWinMax = 1.; + } + + /* count the window hits */ + for (i = 0, iCount = 0; i < self->m; i++) { + iTest = iPos + iSign * i; + if ((self->lCounts[iTest] >= fWinMin) && + (self->lCounts[iTest] <= fWinMax)) { + iCount++; + } + } + return iCount; +} + /*---------------------------------------------------------------------------- AdvanceBackground advances in the background until the predefined Probability has been reached. The probability is defined at the top of the file. iSign and errors are the same as above. -----------------------------------------------------------------------------*/ - static int AdvanceBackground(pIntegData self, int iPos, int iSign) - { - float fProb; - int iRet, iTest; - - assert(self); - assert( (iSign == 1) || (iSign == -1) ); - - /* initialize, calculate initial Probability */ - iRet = FindWindowHits(self,iPos,iSign); - if(iRet < 0) - { - return iRet; - } - fProb = (self->m - iRet)/self->m; - iTest = iPos; - - /* loop further on */ - while(fProb > PROBABILITY) - { - iTest += iSign; - iRet = FindWindowHits(self,iTest,iSign); - if(iRet < 0) - { - return iRet; - } - fProb *= (self->m - iRet)/self->m; - } - - if( (iTest < 0) || (iTest >= self->iCounts) ) - { - return -1; - } - else - { - return iTest; - } - } +----------------------------------------------------------------------------*/ +static int AdvanceBackground(pIntegData self, int iPos, int iSign) +{ + float fProb; + int iRet, iTest; + + assert(self); + assert((iSign == 1) || (iSign == -1)); + + /* initialize, calculate initial Probability */ + iRet = FindWindowHits(self, iPos, iSign); + if (iRet < 0) { + return iRet; + } + fProb = (self->m - iRet) / self->m; + iTest = iPos; + + /* loop further on */ + while (fProb > PROBABILITY) { + iTest += iSign; + iRet = FindWindowHits(self, iTest, iSign); + if (iRet < 0) { + return iRet; + } + fProb *= (self->m - iRet) / self->m; + } + + if ((iTest < 0) || (iTest >= self->iCounts)) { + return -1; + } else { + return iTest; + } +} + /*-------------------------------------------------------------------------- FindLimit assumes, that iMaxCount has been set to something sensible in advance! ---------------------------------------------------------------------------*/ - static int FindLimit(pIntegData self, int iStart, int iSign) - { - int i, iHalf, iHit, iLeft, iTest; - - assert(self); - assert( (iSign == 1) || (iSign == -1) ); - - iHit = 0; - iHalf = self->m/2; - i = iStart; - - /* loop until iHalf is reached */ - while((iHit = FindWindowHits(self,i,iSign)) < iHalf) - { - i += iSign; - if(iHit < 0) - { - if(iSign == LEFT) - { - return INTEGLEFT; - } - else - { - return INTEGRIGHT; - } - } +--------------------------------------------------------------------------*/ +static int FindLimit(pIntegData self, int iStart, int iSign) +{ + int i, iHalf, iHit, iLeft, iTest; + + assert(self); + assert((iSign == 1) || (iSign == -1)); + + iHit = 0; + iHalf = self->m / 2; + i = iStart; + + /* loop until iHalf is reached */ + while ((iHit = FindWindowHits(self, i, iSign)) < iHalf) { + i += iSign; + if (iHit < 0) { + if (iSign == LEFT) { + return INTEGLEFT; + } else { + return INTEGRIGHT; + } } - - /* step further into the backgound */ - iTest = AdvanceBackground(self,i,iSign); - if(iTest < 0) - { - if(iSign == LEFT) - { - return INTEGLEFT; - } - else - { - return INTEGRIGHT; - } - } - - /* store it away and return success */ - if(iSign == LEFT) - { - self->iLeft = iTest; - } - else - { - self->iRight = iTest; - } - return 1; } + + /* step further into the backgound */ + iTest = AdvanceBackground(self, i, iSign); + if (iTest < 0) { + if (iSign == LEFT) { + return INTEGLEFT; + } else { + return INTEGRIGHT; + } + } + + /* store it away and return success */ + if (iSign == LEFT) { + self->iLeft = iTest; + } else { + self->iRight = iTest; + } + return 1; +} + /*-------------------------------------------------------------------------- This routine does the actual integration once the limits have been determined. - --------------------------------------------------------------------------*/ - static int DoIntegrate(pIntegData self, float *fSum, float *fVariance) - { - long lLeftBack, lRightBack, lBackMean; - int i,iRes = 1; - float fScan, fBackVar,fLeft, fRight, fN, fNP, fNB, fSumm; - float fMLeft, fMRight; - - assert(self); - assert( (self->iLeft != 0) && (self->iRight != 0) ); - - - /* sum the left background */ - for(i = 0, lLeftBack = 0; i < self->iLeft; i++) - { - lLeftBack += self->lCounts[i]; - } - lLeftBack = lLeftBack; - - /* sum the right background */ - for(i = self->iRight, lRightBack = 0; i < self->iCounts; i++) - { - lRightBack += self->lCounts[i]; - } - lRightBack = lRightBack; - - - /* sum all of it */ - fScan = 0.; - for(i = 0; i < self->iCounts; i++) - { - fScan += self->lCounts[i]; - } + --------------------------------------------------------------------------*/ +static int DoIntegrate(pIntegData self, float *fSum, float *fVariance) +{ + long lLeftBack, lRightBack, lBackMean; + int i, iRes = 1; + float fScan, fBackVar, fLeft, fRight, fN, fNP, fNB, fSumm; + float fMLeft, fMRight; - /* sum the peak */ - fSumm = 0.; - for(i = self->iLeft; i < self->iRight +1; i++) - { - fSumm += (float)self->lCounts[i]; - } - - /* calculate the values */ - fLeft = (float)self->iLeft; - fRight = (float)self->iRight; - fN = (float)self->iCounts; - - fNP = fRight - fLeft + 1.; - fNB = fLeft + (fN - fRight); - - *fSum = fSumm - (fNP/fNB)*((float)lLeftBack + (float)lRightBack); - *fVariance = sqrt(fSumm + (fNP/fNB)*(fNP/fNB)*((float)lLeftBack - + (float)lRightBack)); - - /* check the background */ - fMLeft = lLeftBack/fLeft; - fMRight = lRightBack/fRight; - if(ABS(fMLeft - fMRight) > ((fMLeft + fMRight)/2) ) - { - iRes = INTEGFUNNYBACK; - } + assert(self); + assert((self->iLeft != 0) && (self->iRight != 0)); - return iRes; + + /* sum the left background */ + for (i = 0, lLeftBack = 0; i < self->iLeft; i++) { + lLeftBack += self->lCounts[i]; } + lLeftBack = lLeftBack; + + /* sum the right background */ + for (i = self->iRight, lRightBack = 0; i < self->iCounts; i++) { + lRightBack += self->lCounts[i]; + } + lRightBack = lRightBack; + + + /* sum all of it */ + fScan = 0.; + for (i = 0; i < self->iCounts; i++) { + fScan += self->lCounts[i]; + } + + /* sum the peak */ + fSumm = 0.; + for (i = self->iLeft; i < self->iRight + 1; i++) { + fSumm += (float) self->lCounts[i]; + } + + /* calculate the values */ + fLeft = (float) self->iLeft; + fRight = (float) self->iRight; + fN = (float) self->iCounts; + + fNP = fRight - fLeft + 1.; + fNB = fLeft + (fN - fRight); + + *fSum = fSumm - (fNP / fNB) * ((float) lLeftBack + (float) lRightBack); + *fVariance = sqrt(fSumm + (fNP / fNB) * (fNP / fNB) * ((float) lLeftBack + + + (float) + lRightBack)); + + /* check the background */ + fMLeft = lLeftBack / fLeft; + fMRight = lRightBack / fRight; + if (ABS(fMLeft - fMRight) > ((fMLeft + fMRight) / 2)) { + iRes = INTEGFUNNYBACK; + } + + return iRes; +} + /*---------------------------------------------------------------------------*/ - int GabePeakIntegrate(int m, int iCounts, long lCounts[], - float *fIntens, float *fVariance) - { - IntegData self; - int iTest,i, iStart; - - /* check input */ - assert(iCounts > 0); - assert(lCounts); - - - /* initialize Data Structure */ - self.iCounts = iCounts; - self.lCounts = lCounts; /* no need to duplicate data */ - self.iLeft = 0; - self.iRight = 0; - self.iMaxCount = 0; - self.m = m; - - /* find maximum */ - self.iMaxCount = FindMaxCount(self.lCounts, self.iCounts); - - /* find Left Limit */ - iStart = FindHalf(&self,LEFT); - if(iStart < 0) - { - return INTEGLEFT; - } - iTest = FindLimit(&self,iStart,LEFT); - if(iTest < 0) - { - return iTest; - } - - /* find right limit */ - iStart = FindHalf(&self,RIGHT); - if(iStart < 0) - { - return INTEGRIGHT; - } - iTest = FindLimit(&self,iStart,RIGHT); - if(iTest < 0) - { - return iTest; - } +int GabePeakIntegrate(int m, int iCounts, long lCounts[], + float *fIntens, float *fVariance) +{ + IntegData self; + int iTest, i, iStart; + + /* check input */ + assert(iCounts > 0); + assert(lCounts); + + + /* initialize Data Structure */ + self.iCounts = iCounts; + self.lCounts = lCounts; /* no need to duplicate data */ + self.iLeft = 0; + self.iRight = 0; + self.iMaxCount = 0; + self.m = m; + + /* find maximum */ + self.iMaxCount = FindMaxCount(self.lCounts, self.iCounts); + + /* find Left Limit */ + iStart = FindHalf(&self, LEFT); + if (iStart < 0) { + return INTEGLEFT; + } + iTest = FindLimit(&self, iStart, LEFT); + if (iTest < 0) { + return iTest; + } + + /* find right limit */ + iStart = FindHalf(&self, RIGHT); + if (iStart < 0) { + return INTEGRIGHT; + } + iTest = FindLimit(&self, iStart, RIGHT); + if (iTest < 0) { + return iTest; + } #ifdef PRINT - printf("Limits: %d %d\n",self.iLeft, self.iRight); - for(i = self.iLeft; i < self.iRight; i++) - { - printf(" %d\n",self.lCounts[i]); - } + printf("Limits: %d %d\n", self.iLeft, self.iRight); + for (i = self.iLeft; i < self.iRight; i++) { + printf(" %d\n", self.lCounts[i]); + } #endif - /* integrate */ - return DoIntegrate(&self,fIntens, fVariance); - - } + /* integrate */ + return DoIntegrate(&self, fIntens, fVariance); + +} diff --git a/integrate.h b/integrate.h index d03b6421..eb28f1aa 100644 --- a/integrate.h +++ b/integrate.h @@ -16,6 +16,6 @@ #define INTEGNOPEAK -3 #define INTEGFUNNYBACK -4 - int GabePeakIntegrate(int m, int iCounts, long lCounts[], - float *fIntens, float *fVariance); +int GabePeakIntegrate(int m, int iCounts, long lCounts[], + float *fIntens, float *fVariance); #endif diff --git a/interface.c b/interface.c index 6cf6d884..c0f8ebf2 100644 --- a/interface.c +++ b/interface.c @@ -45,132 +45,165 @@ /*========================================================================= Empty driveable interface functions ==========================================================================*/ -static int EmptyHalt(void *self){ +static int EmptyHalt(void *self) +{ return OKOK; } + /*-----------------------------------------------------------------------*/ -static int EmptyLimits(void *self, float fVal, char *error, int errLen){ +static int EmptyLimits(void *self, float fVal, char *error, int errLen) +{ return 1; } + /*-----------------------------------------------------------------------*/ -static long EmptyValue(void *self, SConnection *pCon, float fVal){ - SCWrite(pCon,"WARNING: empty SetValue",eWarning); +static long EmptyValue(void *self, SConnection * pCon, float fVal) +{ + SCWrite(pCon, "WARNING: empty SetValue", eWarning); return OKOK; } + /*-----------------------------------------------------------------------*/ -static int EmptyStatus(void *self, SConnection *pCon){ +static int EmptyStatus(void *self, SConnection * pCon) +{ return HWIdle; } + /*------------------------------------------------------------------------*/ -static float EmptyGet(void *self, SConnection *pCon){ - SCWrite(pCon,"WARNING: empty GetValue",eWarning); +static float EmptyGet(void *self, SConnection * pCon) +{ + SCWrite(pCon, "WARNING: empty GetValue", eWarning); return 555.55; } + /*-------------------------------------------------------------------------*/ - pIDrivable CreateDrivableInterface(void) - { - pIDrivable pRes = NULL; - - pRes = (pIDrivable)malloc(sizeof(IDrivable)); - if(!pRes) - { - return NULL; - } - memset(pRes,0,sizeof(IDrivable)); - pRes->ID = DRIVEID; - pRes->Halt = EmptyHalt; - pRes->CheckLimits = EmptyLimits; - pRes->SetValue = EmptyValue; - pRes->CheckStatus = EmptyStatus; - pRes->GetValue = EmptyGet; - pRes->drivableStatus=HWIdle; - return pRes; +pIDrivable CreateDrivableInterface(void) +{ + pIDrivable pRes = NULL; + + pRes = (pIDrivable) malloc(sizeof(IDrivable)); + if (!pRes) { + return NULL; } + memset(pRes, 0, sizeof(IDrivable)); + pRes->ID = DRIVEID; + pRes->Halt = EmptyHalt; + pRes->CheckLimits = EmptyLimits; + pRes->SetValue = EmptyValue; + pRes->CheckStatus = EmptyStatus; + pRes->GetValue = EmptyGet; + pRes->drivableStatus = HWIdle; + return pRes; +} + /*-------------------------------------------------------------------------*/ - pICountable CreateCountableInterface(void) - { - pICountable pRes = NULL; - - pRes = (pICountable)malloc(sizeof(ICountable)); - if(!pRes) - { - return NULL; - } - memset(pRes,0,sizeof(ICountable)); - pRes->ID = COUNTID; - return pRes; +pICountable CreateCountableInterface(void) +{ + pICountable pRes = NULL; + + pRes = (pICountable) malloc(sizeof(ICountable)); + if (!pRes) { + return NULL; } + memset(pRes, 0, sizeof(ICountable)); + pRes->ID = COUNTID; + return pRes; +} /*---------------------------------------------------------------------------*/ - pEVInterface CreateEVInterface(void) - { - pEVInterface pRes = NULL; - - pRes = (pEVInterface)malloc(sizeof(EVInterface)); - if(!pRes) - { - return NULL; - } - memset(pRes,0,sizeof(EVInterface)); - pRes->iID = ENVIRINTERFACE; - return pRes; +pEVInterface CreateEVInterface(void) +{ + pEVInterface pRes = NULL; + + pRes = (pEVInterface) malloc(sizeof(EVInterface)); + if (!pRes) { + return NULL; } + memset(pRes, 0, sizeof(EVInterface)); + pRes->iID = ENVIRINTERFACE; + return pRes; +} + /*--------------------------------------------------------------------------*/ - static void *FindInterface(void *pObject, int iID) - { - pDummy pDum = NULL; - - pDum = (pDummy)pObject; - if(!pDum) - { - return NULL; - } - if(!pDum->pDescriptor) - { - return NULL; - } - - return pDum->pDescriptor->GetInterface(pDum,iID); +static void *FindInterface(void *pObject, int iID) +{ + pDummy pDum = NULL; + + pDum = (pDummy) pObject; + if (!pDum) { + return NULL; } + if (!pDum->pDescriptor) { + return NULL; + } + + return pDum->pDescriptor->GetInterface(pDum, iID); +} + /*--------------------------------------------------------------------------*/ - pIDrivable GetDrivableInterface(void *pObject) - { - return (pIDrivable)FindInterface(pObject,DRIVEID); - } +pIDrivable GetDrivableInterface(void *pObject) +{ + return (pIDrivable) FindInterface(pObject, DRIVEID); +} + /*-------------------------------------------------------------------------*/ -int GetDrivablePosition(void *pObject, SConnection *pCon, float *fPos) +int GetDrivablePosition(void *pObject, SConnection * pCon, float *fPos) { pIDrivable pDriv = NULL; pMotor pMot = NULL; float value; pDriv = GetDrivableInterface(pObject); - if(pDriv == NULL) - { + if (pDriv == NULL) { return 0; } - if(iHasType(pObject,"Motor")) - { - pMot = (pMotor)pObject; - return MotorGetSoftPosition(pMot,pCon,fPos); + if (iHasType(pObject, "Motor")) { + pMot = (pMotor) pObject; + return MotorGetSoftPosition(pMot, pCon, fPos); } - value = pDriv->GetValue(pObject,pCon); - if(value < -9999.0) - { + value = pDriv->GetValue(pObject, pCon); + if (value < -9999.99) { return 0; } *fPos = value; return 1; } -/*--------------------------------------------------------------------------*/ - pICountable GetCountableInterface(void *pObject) - { - return (pICountable)FindInterface(pObject,COUNTID); - } -/*--------------------------------------------------------------------------*/ - pICallBack GetCallbackInterface(void *pObject) - { - return (pICallBack)FindInterface(pObject,CALLBACKINTERFACE); - } +/*--------------------------------------------------------------------------*/ +pICountable GetCountableInterface(void *pObject) +{ + return (pICountable) FindInterface(pObject, COUNTID); +} +/*--------------------------------------------------------------------------*/ +int GetCountLock(pICountable self, SConnection * pCon) +{ + if (self->running == 1) { + SCWrite(pCon, "ERROR: someone else is already counting!", eError); + /* printf("Countlock denied\n"); */ + return 0; + } else { + /* printf("Countlock aquired\n");*/ + self->running = 1; + return 1; + } +} + +/*--------------------------------------------------------------------------*/ +void ReleaseCountLock(pICountable self) +{ + /* printf("Countlock released\n"); */ + self->running = 0; +} + +/*--------------------------------------------------------------------------*/ +int isRunning(pICountable self) +{ + return self->running; +} + +/*--------------------------------------------------------------------------*/ +pICallBack GetCallbackInterface(void *pObject) +{ + return (pICallBack) FindInterface(pObject, CALLBACKINTERFACE); +} diff --git a/interface.h b/interface.h index 4d6b203e..b3ede689 100644 --- a/interface.h +++ b/interface.h @@ -1,5 +1,5 @@ -#line 379 "interface.w" +#line 399 "interface.w" /*--------------------------------------------------------------------------- I N T E R F A C E S @@ -27,110 +27,110 @@ /* ----------------------- The drivable interface -----------------------*/ -#line 119 "interface.w" +#line 121 "interface.w" - typedef struct { - int ID; - int (*Halt)(void *self); - int (*CheckLimits)(void *self, float fVal, - char *error, int iErrLen); - long (*SetValue)(void *self, SConnection *pCon, - float fVal); - int (*CheckStatus)(void *self, SConnection *pCon); - float (*GetValue)(void *self, SConnection *pCon); - int iErrorCount; - int drivableStatus; - } IDrivable, *pIDrivable; +typedef struct { + int ID; + int (*Halt) (void *self); + int (*CheckLimits) (void *self, float fVal, char *error, int iErrLen); + long (*SetValue) (void *self, SConnection * pCon, float fVal); + int (*CheckStatus) (void *self, SConnection * pCon); + float (*GetValue) (void *self, SConnection * pCon); + int iErrorCount; + int drivableStatus; +} IDrivable, *pIDrivable; - pIDrivable GetDrivableInterface(void *pObject); - int GetDrivablePosition(void *pObject, SConnection *pCon, - float *fPos); +pIDrivable GetDrivableInterface(void *pObject); +int GetDrivablePosition(void *pObject, SConnection * pCon, float *fPos); -#line 405 "interface.w" +#line 425 "interface.w" - pIDrivable CreateDrivableInterface(void); +pIDrivable CreateDrivableInterface(void); /* ------------------------ The countable interface ---------------------*/ -#line 186 "interface.w" +#line 188 "interface.w" - typedef struct { - int ID; - int (*Halt)(void *self); - void (*SetCountParameters)(void *self, float fPreset, - CounterMode eMode);\ - int (*StartCount)(void *self, SConnection *pCon); - int (*CheckCountStatus)(void *self, SConnection *pCon); - int (*Pause)(void *self, SConnection *pCon); - int (*Continue)(void *self, SConnection *pCon); - int (*TransferData)(void *self, SConnection *pCon); - } ICountable, *pICountable; +typedef struct { + int ID; + int running; + int (*Halt) (void *self); + void (*SetCountParameters) (void *self, float fPreset, + CounterMode eMode); + int (*StartCount) (void *self, SConnection * pCon); + int (*CheckCountStatus) (void *self, SConnection * pCon); + int (*Pause) (void *self, SConnection * pCon); + int (*Continue) (void *self, SConnection * pCon); + int (*TransferData) (void *self, SConnection * pCon); +} ICountable, *pICountable; - pICountable GetCountableInterface(void *pObject); +pICountable GetCountableInterface(void *pObject); +int GetCountLock(pICountable self, SConnection * pCon); +void ReleaseCountLock(pICountable self); +int isRunning(pICountable self); + +#line 430 "interface.w" -#line 410 "interface.w" - - - pICountable CreateCountableInterface(void); +pICountable CreateCountableInterface(void); /* ------------------------- The CallBack Interface --------------------*/ -#line 239 "interface.w" +#line 253 "interface.w" - typedef void (*KillFuncIT)(void *pData); - typedef int (*SICSCallBack)(int iEvent, void *pEventData, - void *pUserData, commandContext cc); +typedef void (*KillFuncIT) (void *pData); +typedef int (*SICSCallBack) (int iEvent, void *pEventData, + void *pUserData); -#line 415 "interface.w" +#line 435 "interface.w" -#line 261 "interface.w" +#line 275 "interface.w" + +typedef struct __ICallBack *pICallBack; - typedef struct __ICallBack *pICallBack; - /* event source side */ - pICallBack CreateCallBackInterface(void); - void DeleteCallBackInterface(pICallBack self); - int InvokeCallBack(pICallBack pInterface, int iEvent, void *pEventData); +pICallBack CreateCallBackInterface(void); +void DeleteCallBackInterface(pICallBack self); +int InvokeCallBack(pICallBack pInterface, int iEvent, void *pEventData); /* callback client side */ - long RegisterCallback(pICallBack pInterface, commandContext comCon, - int iEvent, SICSCallBack pFunc, - void *pUserData, KillFuncIT pKill); - int RemoveCallback(pICallBack pInterface, long iID); - int RemoveCallback2(pICallBack pInterface, void *pUserData); - int RemoveCallback3(pICallBack self, SICSCallBack pFunc, int (*func)(const void* context, const void* pUserData), void *context); +long RegisterCallback(pICallBack pInterface, + int iEvent, SICSCallBack pFunc, + void *pUserData, KillFuncIT pKill); +int RemoveCallback(pICallBack pInterface, long iID); +int RemoveCallback2(pICallBack pInterface, void *pUserData); +int RemoveCallbackCon(pICallBack pInterface, SConnection * pCon); - int CallbackScript(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); +int CallbackScript(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); - pICallBack GetCallbackInterface(void *pData); +pICallBack GetCallbackInterface(void *pData); -#line 416 "interface.w" +#line 436 "interface.w" /*---------------------- The Environment Interface --------------------*/ -#line 333 "interface.w" +#line 353 "interface.w" - typedef enum { EVIdle, EVDrive, EVMonitor, EVError } EVMode; - typedef struct { - int iID; - EVMode (*GetMode)(void *self); - int (*IsInTolerance)(void *self); - int (*HandleError)(void *self); - } EVInterface, *pEVInterface; +typedef enum { EVIdle, EVDrive, EVMonitor, EVError } EVMode; +typedef struct { + int iID; + EVMode(*GetMode) (void *self); + int (*IsInTolerance) (void *self); + int (*HandleError) (void *self); +} EVInterface, *pEVInterface; -#line 418 "interface.w" +#line 438 "interface.w" -#line 359 "interface.w" +#line 379 "interface.w" - pEVInterface CreateEVInterface(void); +pEVInterface CreateEVInterface(void); -#line 419 "interface.w" +#line 439 "interface.w" #endif diff --git a/interface.tex b/interface.tex index c1331f38..663fefd9 100644 --- a/interface.tex +++ b/interface.tex @@ -51,12 +51,14 @@ $\langle$obdes {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@#define SICSDESCRIPTOR@\\ \mbox{}\verb@#include @\\ \mbox{}\verb@#include @\\ +\mbox{}\verb@#include @\\ \mbox{}\verb@@\\ \mbox{}\verb@ typedef struct {@\\ \mbox{}\verb@ char *name;@\\ \mbox{}\verb@ int (*SaveStatus)(void *self, char *name,FILE *fd);@\\ \mbox{}\verb@ void *(*GetInterface)(void *self, int iInterfaceID);@\\ \mbox{}\verb@ IPair *pKeys;@\\ +\mbox{}\verb@ pHdb parNode;@\\ \mbox{}\verb@ } ObjectDescriptor, *pObjectDescriptor;@\\ \mbox{}\verb@@\\ \mbox{}\verb@ /*---------------------------------------------------------------------------*/@\\ @@ -81,7 +83,7 @@ $\langle$obdes {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ int iHasType(void *pData, char *Type);@\\ \mbox{}\verb@ @\\ \mbox{}\verb@#endif @\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} @@ -152,7 +154,7 @@ $\langle$driv {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ int GetDrivablePosition(void *pObject, SConnection *pCon,@\\ \mbox{}\verb@ float *fPos);@\\ \mbox{}\verb@@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} @@ -216,6 +218,7 @@ $\langle$count {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@@\\ \mbox{}\verb@ typedef struct {@\\ \mbox{}\verb@ int ID;@\\ +\mbox{}\verb@ int running;@\\ \mbox{}\verb@ int (*Halt)(void *self);@\\ \mbox{}\verb@ void (*SetCountParameters)(void *self, float fPreset,@\\ \mbox{}\verb@ CounterMode eMode);\@\\ @@ -227,8 +230,10 @@ $\langle$count {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ } ICountable, *pICountable;@\\ \mbox{}\verb@@\\ \mbox{}\verb@ pICountable GetCountableInterface(void *pObject); @\\ -\mbox{}\verb@@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@ int GetCountLock(pICountable self, SConnection *pCon);@\\ +\mbox{}\verb@ void ReleaseCountLock(pICountable self);@\\ +\mbox{}\verb@ int isRunning(pICountable self);@\\ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} @@ -237,6 +242,8 @@ $\langle$count {\footnotesize ?}$\rangle\equiv$ \end{list} \end{minipage}\\[4ex] \end{flushleft} +{\bf running } Is a flag which says if the counter is operating or not. + {\bf Halt and StartCount} are self explaining, they just do what they say. Please note, that counting configuration must have happened before usage of this interface. @@ -260,6 +267,13 @@ the existence of a countable interface. If it exists a pointer to it will be returned. NEVER free this pointer. If no countable interface exists, NULL will be returned. +{\bf GetCountLock} will try to set the running flag. If it is already running, an error + is printed to pCon and 0 is returned. + +{\bf ReleaseCountLock} release the count lock. + +{\bf isRunning} returns the running flag. + \subsubsection{The Callback Interface} The Callback Interface is SICS suport for component behaviour for objects. Consider objects A and B. A now is able to generate certain events when it's @@ -281,8 +295,8 @@ $\langle$callfunc {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@@\\ \mbox{}\verb@ typedef void (*KillFuncIT)(void *pData);@\\ \mbox{}\verb@ typedef int (*SICSCallBack)(int iEvent, void *pEventData, @\\ -\mbox{}\verb@ void *pUserData, commandContext cc);@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@ void *pUserData);@\\ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} @@ -321,17 +335,18 @@ $\langle$cifunc {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ int InvokeCallBack(pICallBack pInterface, int iEvent, void *pEventData); @\\ \mbox{}\verb@@\\ \mbox{}\verb@ /* callback client side */@\\ -\mbox{}\verb@ long RegisterCallback(pICallBack pInterface, commandContext comCon, @\\ +\mbox{}\verb@ long RegisterCallback(pICallBack pInterface, @\\ \mbox{}\verb@ int iEvent, SICSCallBack pFunc,@\\ \mbox{}\verb@ void *pUserData, KillFuncIT pKill);@\\ \mbox{}\verb@ int RemoveCallback(pICallBack pInterface, long iID);@\\ \mbox{}\verb@ int RemoveCallback2(pICallBack pInterface, void *pUserData);@\\ +\mbox{}\verb@ int RemoveCallbackCon(pICallBack pInterface, SConnection *pCon);@\\ \mbox{}\verb@@\\ \mbox{}\verb@ int CallbackScript(SConnection *pCon, SicsInterp *pSics, void *pData,@\\ \mbox{}\verb@ int argc, char *argv[]); @\\ \mbox{}\verb@@\\ \mbox{}\verb@ pICallBack GetCallbackInterface(void *pData); @\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} @@ -378,6 +393,11 @@ RegisterCallBack. search key for deletion is the pointer to user data. All callbacks related to this user data in the interface specified will be removed. +{\bf RemoveCallbackCon} is another variant for removing callbacks. This time the +search key for deletion is the pointer to user data which must be a connection object. +All callbacks related to this connection in the interface specified will be removed. This is +a convenience function for removing interest callbacks in SICS. + {\bf CallbackScript} allows to connect callbacks to scripts. Please note, that those scripts will have a dummy connection to clients only and will not be able to write to clients. All output occurring in @@ -404,7 +424,7 @@ $\langle$envir {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ int (*IsInTolerance)(void *self);@\\ \mbox{}\verb@ int (*HandleError)(void *self);@\\ \mbox{}\verb@ } EVInterface, *pEVInterface;@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} @@ -437,7 +457,7 @@ $\langle$envfunc {\footnotesize ?}$\rangle\equiv$ \begin{list}{}{} \item \mbox{}\verb@@\\ \mbox{}\verb@ pEVInterface CreateEVInterface(void);@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} @@ -465,7 +485,7 @@ $\langle$envfunc {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ char * GetDescriptorKey(pObjectDescriptor self, char *keyName);@\\ \mbox{}\verb@ char * GetDescriptorGroup(pObjectDescriptor self);@\\ \mbox{}\verb@ char * GetDescriptorDescription(pObjectDescriptor self);@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-2ex} \end{minipage}\\[4ex] @@ -517,7 +537,7 @@ $\langle$envfunc {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@@$\langle$envir {\footnotesize ?}$\rangle$\verb@@\\ \mbox{}\verb@@$\langle$envfunc {\footnotesize ?}$\rangle$\verb@@\\ \mbox{}\verb@#endif@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-2ex} \end{minipage}\\[4ex] diff --git a/interface.w b/interface.w index 83085a4e..9aa75d36 100644 --- a/interface.w +++ b/interface.w @@ -1,8 +1,8 @@ \subsection{Object interfaces}\label{inter} In order to present themselves to the system SICS objects need to adhere to -certain interfaces. These interfaces are described in this +certyain interfaces. These interfaces are described in this section. Thus this section is one of the most important sections of -this document, read carefully! +theis document, read carefully! A first requirement was that it must be possible to inquire the capabilities of an @@ -32,7 +32,7 @@ Let's start with the objectdescriptor: object is capable of at runtime. If this has been done a general way to access those capabilities is needed. In order to do all this each SICS-object is required to carry an object descriptor - struct as first parameter in its class/object struct. Additionally + struct as first parameter in its class/object struct. Additionslly it is required to initialize this struct to something sensible. This file defines this struct. Additionally a few functions of @@ -40,18 +40,20 @@ Let's start with the objectdescriptor: Mark Koennecke, June, 1997 - copyright: see implementation file + copyrigth: see implementation file ----------------------------------------------------------------------------*/ #ifndef SICSDESCRIPTOR #define SICSDESCRIPTOR #include #include +#include typedef struct { char *name; int (*SaveStatus)(void *self, char *name,FILE *fd); void *(*GetInterface)(void *self, int iInterfaceID); IPair *pKeys; + pHdb parNode; } ObjectDescriptor, *pObjectDescriptor; /*---------------------------------------------------------------------------*/ @@ -102,17 +104,17 @@ It is {\bf important} to note, that the objects themselves are responsible for allocating and freeing memory for the interface structures. Client never should need to worry how to dispose of these structures. Moreover this scheme ensures that changes to the interface due to some command given to -the object are immediately visible through the whole system. +the object are immediatetly visible through the whole system. Additionally this header file defines a few relatively uninteresting -functions for object descriptor maintenance. Slightly more interesting is +functions for object descriptor maintainance. Slightly more interesting is the Dummy structure, which will be used to find the object descriptor in a given objects data structure. \subsubsection{The drivable interface} As first example of an interface the drivable interface will be given. This -interface is implemented by all devices or variables which can be driven to +interface is implemented by all devices or varaibles which can be driven to a value. Most notable example are motors, but composite variables and environment controllers fit this bill as well. @@ -186,6 +188,7 @@ This is an interface for interacting with anything which counts. @d count @{ typedef struct { int ID; + int running; int (*Halt)(void *self); void (*SetCountParameters)(void *self, float fPreset, CounterMode eMode);\ @@ -197,9 +200,13 @@ This is an interface for interacting with anything which counts. } ICountable, *pICountable; pICountable GetCountableInterface(void *pObject); - + int GetCountLock(pICountable self, SConnection *pCon); + void ReleaseCountLock(pICountable self); + int isRunning(pICountable self); @} +{\bf running } Is a flag which says if the counter is operating or not. + {\bf Halt and StartCount} are self explaining, they just do what they say. Please note, that counting configuration must have happened before usage of this interface. @@ -223,12 +230,19 @@ the existence of a countable interface. If it exists a pointer to it will be returned. NEVER free this pointer. If no countable interface exists, NULL will be returned. +{\bf GetCountLock} will try to set the running flag. If it is already running, an error + is printed to pCon and 0 is returned. + +{\bf ReleaseCountLock} release the count lock. + +{\bf isRunning} returns the running flag. + \subsubsection{The Callback Interface} -The Callback Interface is SICS support for component behaviour for objects. +The Callback Interface is SICS suport for component behaviour for objects. Consider objects A and B. A now is able to generate certain events when it's state changes. For instance if A is a variable that its value is changed. B may then choose to register a function with A which gets automatically -called whenever A generates the appropriate event. B is thus automatically +called whenever A generates the apropriate event. B is thus automatically notified about A's status change and can act accordingly to it. In contrast to the interfaces defined above, this interface is defined in terms of a set of functions which manipulate the interface and not as a data structure of @@ -239,11 +253,11 @@ function: @d callfunc @{ typedef void (*KillFuncIT)(void *pData); typedef int (*SICSCallBack)(int iEvent, void *pEventData, - void *pUserData, commandContext cc); + void *pUserData); @} The callback function is meant to return 0 for failure or 1 for success. -This information may be needed by an event invoking object if to continue an +This infomation may be needed by an event invoking object if to continue an operation or not. The first parameter passed to {\bf SICSCallBack} is the id of the generated event. Clearly the communicating objects need to agree on these event. In SICS events types will be held in an header file event.h. @@ -267,13 +281,12 @@ interface: int InvokeCallBack(pICallBack pInterface, int iEvent, void *pEventData); /* callback client side */ - long RegisterCallback(pICallBack pInterface, commandContext comCon, + long RegisterCallback(pICallBack pInterface, int iEvent, SICSCallBack pFunc, void *pUserData, KillFuncIT pKill); int RemoveCallback(pICallBack pInterface, long iID); int RemoveCallback2(pICallBack pInterface, void *pUserData); - int RemoveCallback3(pICallBack self, SICSCallBack pFunc, - int (*func)(const void* context, const void* pUserData), void *context); + int RemoveCallbackCon(pICallBack pInterface, SConnection *pCon); int CallbackScript(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); @@ -319,12 +332,10 @@ RegisterCallBack. search key for deletion is the pointer to user data. All callbacks related to this user data in the interface specified will be removed. -{\bf RemoveCallback3} is another variant for removing callbacks. This time the -search key for deletion is the pointer to user data, qualified by the callback -function and checked by the spuplied check function. If the callback function -matches the one given then the supplied function is called to determine if the -user data matches and return zero if it does. All callbacks related to this -user data in the interface specified will be removed. +{\bf RemoveCallbackCon} is another variant for removing callbacks. This time the +search key for deletion is the pointer to user data which must be a connection object. +All callbacks related to this connection in the interface specified will be removed. This is +a convenience function for removing interest callbacks in SICS. {\bf CallbackScript} allows to connect callbacks to scripts. Please note, that those scripts will have a dummy connection to clients only @@ -360,7 +371,7 @@ controller. EVError is set if the controller is out of tolerances. 0 otherwise. {\bf HandleError} will be automatically called when IsInTolerance returns 0. -Its purpose is to implement the error handling strategy for the controller +Its purpose is to implemnt the error handling startegy for the controller in question. @@ -397,7 +408,7 @@ The environment interface has just one function associated with it: For more documentation see interface.w, interface.tex - copyright: see SICS implementation files + copyright: see SICS impelementation files ---------------------------------------------------------------------------*/ #ifndef SICSINTERFACES diff --git a/interrupt.h b/interrupt.h index 475cb8e2..ed8611c6 100644 --- a/interrupt.h +++ b/interrupt.h @@ -26,24 +26,24 @@ #define eEndServer 6 /* ---------------- server side functions ---------------------------------*/ - void ServerStopInterrupt(void); +void ServerStopInterrupt(void); /* - stops interrupt processing. - */ - - void SetInterrupt(int iCode); + stops interrupt processing. + */ + +void SetInterrupt(int iCode); /* - send an interrupt to everybody - */ + send an interrupt to everybody + */ /*------------------------------ utility ----------------------------------*/ - int Interrupt2Text(int iInterrupt, char *text, int iTextLen); - int Text2Interrupt(char *text); +int Interrupt2Text(int iInterrupt, char *text, int iTextLen); +int Text2Interrupt(char *text); /* --------------------- client side functions ----------------------------*/ - int ClientSetupInterrupt(char *host, int iPort); - void ClientStopInterrupt(void); - void SendInterrupt( int iCode); - - +int ClientSetupInterrupt(char *host, int iPort); +void ClientStopInterrupt(void); +void SendInterrupt(int iCode); + + #endif diff --git a/intserv.c b/intserv.c index 499e29a5..ba6c9bc3 100644 --- a/intserv.c +++ b/intserv.c @@ -19,6 +19,8 @@ #include #include #include +#include + #include "fortify.h" #include "conman.h" #include "SCinter.h" @@ -38,82 +40,80 @@ #define MAXINTERRUPT 7 #define INTERUPTWAIT 5 - static mkChannel *IntPort = NULL; - static pTaskMan pTask = NULL; +static mkChannel *IntPort = NULL; +static pTaskMan pTask = NULL; /*----------------------------------------------------------------------------*/ - static char *pIntText[] = { - "continue", - "abortop", - "abortscan", - "abortbatch", - "halt", - "free", - "end", - NULL }; +static char *pIntText[] = { + "continue", + "abortop", + "abortscan", + "abortbatch", + "halt", + "free", + "end", + NULL +}; + /*---------------------------------------------------------------------------*/ - int ServerSetupInterrupt(int iPort, pNetRead pNet, pTaskMan pTasker) - { - int i; - - - pTask = pTasker; - /* setup interrupt port */ - IntPort = UDPOpen(iPort); - if(IntPort == NULL) - { - return 0; - } - else - { - NetReadRegister(pNet, IntPort,udp,NULL); - return 1; - } - } +int ServerSetupInterrupt(int iPort, pNetRead pNet, pTaskMan pTasker) +{ + int i; + + + pTask = pTasker; + /* setup interrupt port */ + IntPort = UDPOpen(iPort); + if (IntPort == NULL) { + return 0; + } else { + NetReadRegister(pNet, IntPort, udp, NULL); + return 1; + } +} + /*--------------------------------------------------------------------------*/ - void ServerStopInterrupt(void) - { - - /* close the port */ - if(IntPort) - { - NETClosePort(IntPort); - free(IntPort); - } - } +void ServerStopInterrupt(void) +{ + + /* close the port */ + if (IntPort) { + NETClosePort(IntPort); + free(IntPort); + } +} + /*-------------------------------------------------------------------------*/ - void SetInterrupt(int iCode) - { - int iInt; - - iInt = iCode; - - TaskSignal(pTask,SICSINT, &iInt); - } +void SetInterrupt(int iCode) +{ + int iInt; + + iInt = iCode; + + TaskSignal(pTask, SICSINT, &iInt); +} + /*--------------------------------------------------------------------------*/ - int Interrupt2Text(int iInterrupt, char *text, int iTextLen) - { - if( (iInterrupt < 0) || (iInterrupt > MAXINTERRUPT)) - { - return 0; - } - strncpy(text,pIntText[iInterrupt],iTextLen-1); - return 1; - } +int Interrupt2Text(int iInterrupt, char *text, int iTextLen) +{ + if ((iInterrupt < 0) || (iInterrupt > MAXINTERRUPT)) { + return 0; + } + strlcpy(text, pIntText[iInterrupt], iTextLen - 1); + return 1; +} + /*-------------------------------------------------------------------------*/ - int Text2Interrupt(char *text) - { - int i = 0; - while(pIntText[i] != NULL) - { - if(strcmp(pIntText[i],text) == 0) - { - break; - } - i++; - } - if(i >= MAXINTERRUPT) - { - return -1; - } - return i; - } +int Text2Interrupt(char *text) +{ + int i = 0; + while (pIntText[i] != NULL) { + if (strcmp(pIntText[i], text) == 0) { + break; + } + i++; + } + if (i >= MAXINTERRUPT) { + return -1; + } + return i; +} diff --git a/lin2ang.c b/lin2ang.c index 0c6de052..721d6f4d 100644 --- a/lin2ang.c +++ b/lin2ang.c @@ -20,303 +20,290 @@ #include "sics.h" #include "lin2ang.h" - static const float RD = 57.2957795, pi = 3.1415926; +static const float RD = 57.2957795, pi = 3.1415926; /* --------- our very own private data structure ------------------------*/ - typedef struct __LIN2ANG { - pObjectDescriptor pDes; - pIDrivable pDriv; - pMotor lin; - float length; - float zero; - }Lin2Ang, *pLin2Ang; +typedef struct __LIN2ANG { + pObjectDescriptor pDes; + pIDrivable pDriv; + pMotor lin; + float length; + float zero; +} Lin2Ang, *pLin2Ang; /*-------------------------- conversion routines -------------------------*/ - static float ang2x(pLin2Ang self, float fAngle) - { - return self->length*tan((fAngle+self->zero)/RD); - } +static float ang2x(pLin2Ang self, float fAngle) +{ + return self->length * tan((fAngle + self->zero) / RD); +} + /*-----------------------------------------------------------------------*/ - static float x2ang(pLin2Ang self, float fX) - { - double dt; +static float x2ang(pLin2Ang self, float fX) +{ + double dt; - assert(self->length > 0.); + assert(self->length > 0.); + + dt = fX / self->length; + return RD * atan(dt) - self->zero; +} - dt = fX/self->length; - return RD*atan(dt) - self->zero; - } /*============== functions in the interface ============================*/ - static void *Lin2AngGetInterface(void *pData, int iID) - { - pLin2Ang self = NULL; - - self = (pLin2Ang)pData; - assert(self); +static void *Lin2AngGetInterface(void *pData, int iID) +{ + pLin2Ang self = NULL; - if(iID == DRIVEID) - { - return self->pDriv; - } - return NULL; + self = (pLin2Ang) pData; + assert(self); + + if (iID == DRIVEID) { + return self->pDriv; } + return NULL; +} + /*----------------------------------------------------------------------*/ - static int Lin2AngSave(void *pData, char *name, FILE *fd) - { - pLin2Ang self = NULL; - - self = (pLin2Ang)pData; - if(!self) - return 0; +static int Lin2AngSave(void *pData, char *name, FILE * fd) +{ + pLin2Ang self = NULL; + + self = (pLin2Ang) pData; + if (!self) + return 0; + + fprintf(fd, "%s length %f\n", name, self->length); + fprintf(fd, "%s softzero %f\n", name, self->zero); + return 1; + +} - fprintf(fd,"%s length %f\n",name, self->length); - fprintf(fd,"%s softzero %f\n",name, self->zero); - return 1; - - } /*-----------------------------------------------------------------------*/ - static int L2AHalt(void *pData) - { - pLin2Ang self = NULL; +static int L2AHalt(void *pData) +{ + pLin2Ang self = NULL; + + self = (pLin2Ang) pData; + assert(self); + + return self->lin->pDrivInt->Halt(self->lin); +} - self = (pLin2Ang)pData; - assert(self); - - return self->lin->pDrivInt->Halt(self->lin); - } /*------------------------------------------------------------------------*/ - static int L2ALimits(void *pData, float fVal, char *error, int iErrlen) - { - float fX; - pLin2Ang self = NULL; +static int L2ALimits(void *pData, float fVal, char *error, int iErrlen) +{ + float fX; + pLin2Ang self = NULL; - self = (pLin2Ang)pData; - assert(self); + self = (pLin2Ang) pData; + assert(self); + + fX = ang2x(self, fVal); + return self->lin->pDrivInt->CheckLimits(self->lin, fX, error, iErrlen); +} - fX = ang2x(self,fVal); - return self->lin->pDrivInt->CheckLimits(self->lin,fX,error,iErrlen); - } /*-----------------------------------------------------------------------*/ - static float L2AGetValue(void *pData, SConnection *pCon) - { - float fX, zero = 0.; - pLin2Ang self = NULL; +static float L2AGetValue(void *pData, SConnection * pCon) +{ + float fX, zero = 0.; + pLin2Ang self = NULL; + + self = (pLin2Ang) pData; + assert(self); + MotorGetSoftPosition(self->lin, pCon, &fX); + return x2ang(self, fX); +} - self = (pLin2Ang)pData; - assert(self); - MotorGetSoftPosition(self->lin,pCon,&fX); - return x2ang(self,fX); - } /*------------------------------------------------------------------------*/ - static int L2AStatus(void *pData, SConnection *pCon) - { - pLin2Ang self = NULL; +static int L2AStatus(void *pData, SConnection * pCon) +{ + pLin2Ang self = NULL; + + self = (pLin2Ang) pData; + assert(self); + return self->lin->pDrivInt->CheckStatus(self->lin, pCon); +} - self = (pLin2Ang)pData; - assert(self); - return self->lin->pDrivInt->CheckStatus(self->lin,pCon); - } /*------------------------------------------------------------------------*/ - static long L2ASetValue(void *pData, SConnection *pCon, float fValue) - { - float fX; - pLin2Ang self = NULL; +static long L2ASetValue(void *pData, SConnection * pCon, float fValue) +{ + float fX; + pLin2Ang self = NULL; - self = (pLin2Ang)pData; - assert(self); + self = (pLin2Ang) pData; + assert(self); + + fX = ang2x(self, fValue); + return self->lin->pDrivInt->SetValue(self->lin, pCon, fX); +} - fX = ang2x(self,fValue); - return self->lin->pDrivInt->SetValue(self->lin,pCon,fX); - } /*--------------------------------------------------------------------*/ - static void KillL2A(void *pData) - { - pLin2Ang self = NULL; +static void KillL2A(void *pData) +{ + pLin2Ang self = NULL; - self = (pLin2Ang)pData; - if(!self) - return; + self = (pLin2Ang) pData; + if (!self) + return; - if(self->pDes) - { - DeleteDescriptor(self->pDes); - } - if(self->pDriv) - { - free(self->pDriv); - } - free(self); + if (self->pDes) { + DeleteDescriptor(self->pDes); } + if (self->pDriv) { + free(self->pDriv); + } + free(self); +} + /*------------------------------------------------------------------- Syntax: MakeLin2Ang name motor */ - int MakeLin2Ang(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - pLin2Ang pNew = NULL; - char pBueffel[255]; - int iRet; +int MakeLin2Ang(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pLin2Ang pNew = NULL; + char pBueffel[255]; + int iRet; - /* check number of arguments */ - if(argc < 3) - { - SCWrite(pCon,"ERROR: Insufficient arguments to Lin2Arg",eError); - return 0; - } - - /* allocate memory */ - pNew = (pLin2Ang)malloc(sizeof(Lin2Ang)); - if(!pNew) - { - SCWrite(pCon,"ERROR: out of memory in MakeLin2Ang",eError); - return 0; - } - memset(pNew,0,sizeof(Lin2Ang)); - pNew->pDes = CreateDescriptor("Lin2Ang"); - if(!pNew->pDes) - { - SCWrite(pCon,"ERROR: out of memory in MakeLin2Ang",eError); - free(pNew); - return 0; - } - pNew->pDriv = CreateDrivableInterface(); - if(!pNew->pDriv) - { - SCWrite(pCon,"ERROR: out of memory in MakeLin2Ang",eError); - KillL2A(pNew); - return 0; - } - - /* check if we got a motor */ - pNew->lin = FindMotor(pSics,argv[2]); - if(!pNew->lin) - { - sprintf(pBueffel,"ERROR: %s is no motor!",argv[2]); - SCWrite(pCon,pBueffel,eError); - KillL2A(pNew); - return 0; - } - - - /* initialize the data structure */ - pNew->pDes->GetInterface = Lin2AngGetInterface; - pNew->pDes->SaveStatus = Lin2AngSave; - pNew->pDriv->Halt = L2AHalt; - pNew->pDriv->CheckLimits = L2ALimits; - pNew->pDriv->SetValue = L2ASetValue; - pNew->pDriv->CheckStatus = L2AStatus; - pNew->pDriv->GetValue = L2AGetValue; - pNew->length = 80.; - - /* install command */ - iRet = AddCommand(pSics, argv[1],Lin2AngAction,KillL2A,pNew); - if(!iRet) - { - sprintf(pBueffel, - "ERROR: duplicate Lin2Ang command %s NOT created", - argv[1]); - SCWrite(pCon,pBueffel,eError); - KillL2A(pNew); - return 0; - } - return 1; + /* check number of arguments */ + if (argc < 3) { + SCWrite(pCon, "ERROR: Insufficient arguments to Lin2Arg", eError); + return 0; } + + /* allocate memory */ + pNew = (pLin2Ang) malloc(sizeof(Lin2Ang)); + if (!pNew) { + SCWrite(pCon, "ERROR: out of memory in MakeLin2Ang", eError); + return 0; + } + memset(pNew, 0, sizeof(Lin2Ang)); + pNew->pDes = CreateDescriptor("Lin2Ang"); + if (!pNew->pDes) { + SCWrite(pCon, "ERROR: out of memory in MakeLin2Ang", eError); + free(pNew); + return 0; + } + pNew->pDriv = CreateDrivableInterface(); + if (!pNew->pDriv) { + SCWrite(pCon, "ERROR: out of memory in MakeLin2Ang", eError); + KillL2A(pNew); + return 0; + } + + /* check if we got a motor */ + pNew->lin = FindMotor(pSics, argv[2]); + if (!pNew->lin) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s is no motor!", argv[2]); + SCWrite(pCon, pBueffel, eError); + KillL2A(pNew); + return 0; + } + + + /* initialize the data structure */ + pNew->pDes->GetInterface = Lin2AngGetInterface; + pNew->pDes->SaveStatus = Lin2AngSave; + pNew->pDriv->Halt = L2AHalt; + pNew->pDriv->CheckLimits = L2ALimits; + pNew->pDriv->SetValue = L2ASetValue; + pNew->pDriv->CheckStatus = L2AStatus; + pNew->pDriv->GetValue = L2AGetValue; + pNew->length = 80.; + + /* install command */ + iRet = AddCommand(pSics, argv[1], Lin2AngAction, KillL2A, pNew); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: duplicate Lin2Ang command %s NOT created", argv[1]); + SCWrite(pCon, pBueffel, eError); + KillL2A(pNew); + return 0; + } + return 1; +} + /*--------------------------------------------------------------------*/ - int Lin2AngAction(SConnection *pCon, SicsInterp *pSics, void *pData, +int Lin2AngAction(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]) - { - pLin2Ang self = NULL; - char pBueffel[255]; - float fVal, fLow, fHigh; - double dVal; - int iRet; +{ + pLin2Ang self = NULL; + char pBueffel[255]; + float fVal, fLow, fHigh; + double dVal; + int iRet; - self = (pLin2Ang)pData; - assert(self); - assert(pCon); + self = (pLin2Ang) pData; + assert(self); + assert(pCon); - /* without parameter: give value */ - if(argc < 2) - { - fVal = L2AGetValue(self,pCon); - sprintf(pBueffel,"%s = %f",argv[0],fVal); - SCWrite(pCon,pBueffel,eError); - return 1; - } - - /* interpret commands */ - strtolower(argv[1]); - if(strcmp(argv[1],"length") == 0) - { - if(argc >= 3) - { - iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&dVal); - if(iRet != TCL_OK) - { - SCWrite(pCon,"ERROR: length parameter not recognised as number", - eError); - return 0; - } - if(!SCMatchRights(pCon,usUser)) - { - SCWrite(pCon,"ERROR: Insufficient privilege to change length", - eError); - return 0; - } - self->length = dVal; - SCSendOK(pCon); - return 1; - } - else - { - sprintf(pBueffel,"%s.length = %f",argv[0],self->length); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - } -/* zero point */ - if(strcmp(argv[1],"softzero") == 0) - { - if(argc >= 3) - { - iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&dVal); - if(iRet != TCL_OK) - { - SCWrite(pCon,"ERROR: softzero parameter not recognised as number", - eError); - return 0; - } - if(!SCMatchRights(pCon,usUser)) - { - SCWrite(pCon,"ERROR: Insufficient privilege to change softzero point", - eError); - return 0; - } - self->zero = dVal; - SCSendOK(pCon); - return 1; - } - else - { - sprintf(pBueffel,"%s.softzero = %f",argv[0],self->zero); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - } -/* limits */ - if(strstr(argv[1],"lim") != NULL) - { - MotorGetPar(self->lin,"softupperlim",&fHigh); - MotorGetPar(self->lin,"softlowerlim",&fLow); - fHigh = x2ang(self,fHigh); - fLow = x2ang(self,fLow); - sprintf(pBueffel,"%s.limits: %f %f\n change through motor limits ", - argv[0],fLow,fHigh); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - sprintf(pBueffel,"ERROR: method %s not found!",argv[1]); - SCWrite(pCon, pBueffel,eError); - return 0; + /* without parameter: give value */ + if (argc < 2) { + fVal = L2AGetValue(self, pCon); + snprintf(pBueffel,sizeof(pBueffel)-1, "%s = %f", argv[0], fVal); + SCWrite(pCon, pBueffel, eError); + return 1; } + /* interpret commands */ + strtolower(argv[1]); + if (strcmp(argv[1], "length") == 0) { + if (argc >= 3) { + iRet = Tcl_GetDouble(pSics->pTcl, argv[2], &dVal); + if (iRet != TCL_OK) { + SCWrite(pCon, "ERROR: length parameter not recognised as number", + eError); + return 0; + } + if (!SCMatchRights(pCon, usUser)) { + SCWrite(pCon, "ERROR: Insufficient privilege to change length", + eError); + return 0; + } + self->length = dVal; + SCSendOK(pCon); + return 1; + } else { + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.length = %f", argv[0], self->length); + SCWrite(pCon, pBueffel, eValue); + return 1; + } + } +/* zero point */ + if (strcmp(argv[1], "softzero") == 0) { + if (argc >= 3) { + iRet = Tcl_GetDouble(pSics->pTcl, argv[2], &dVal); + if (iRet != TCL_OK) { + SCWrite(pCon, "ERROR: softzero parameter not recognised as number", + eError); + return 0; + } + if (!SCMatchRights(pCon, usUser)) { + SCWrite(pCon, + "ERROR: Insufficient privilege to change softzero point", + eError); + return 0; + } + self->zero = dVal; + SCSendOK(pCon); + return 1; + } else { + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.softzero = %f", argv[0], self->zero); + SCWrite(pCon, pBueffel, eValue); + return 1; + } + } +/* limits */ + if (strstr(argv[1], "lim") != NULL) { + MotorGetPar(self->lin, "softupperlim", &fHigh); + MotorGetPar(self->lin, "softlowerlim", &fLow); + fHigh = x2ang(self, fHigh); + fLow = x2ang(self, fLow); + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.limits: %f %f\n change through motor limits ", + argv[0], fLow, fHigh); + SCWrite(pCon, pBueffel, eValue); + return 1; + } + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: method %s not found!", argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; +} diff --git a/lin2ang.h b/lin2ang.h index fcd2c5a3..8541d829 100644 --- a/lin2ang.h +++ b/lin2ang.h @@ -13,11 +13,10 @@ #define LIN2ANG #include "motor.h" - int MakeLin2Ang(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - int Lin2AngAction(SConnection *pCon, SicsInterp *pSics, void *pData, +int MakeLin2Ang(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); +int Lin2AngAction(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]); #endif - diff --git a/linux_def b/linux_def index 4feb8a3b..45815958 100644 --- a/linux_def +++ b/linux_def @@ -10,3 +10,4 @@ MFLAGS=-f makefile_linux$(DUMMY) HDFROOT=/usr/local +TCLINC=/usr/include/tcl8.3 \ No newline at end of file diff --git a/lld.c b/lld.c index c66db0f3..c5e7f3dd 100644 --- a/lld.c +++ b/lld.c @@ -22,30 +22,36 @@ - Node deletion via first and/or last node pointers. (as for access functions, then simplify ...) + ** Comment by Mark Koennecke ** + This implementation has problems when being accessed + concurrently in any form. The reason is the single + current pointer in the list data stucture. A improvement + would be to have a function to get an iterator which holds + this crucial value and functions to iterate on the iterator + *************** end of comment ********* + _____ This version is Public Domain. /_|__| A.Reitsma, Delft, The Netherlands. / | \ --------------------------------------------------------------- */ -#include /* variable arg handling */ -#include /* debugging */ -#include "defines.h" /* debugging incl MALLOC (re-) definition */ -#include "lld.h" /* also includes portable.h if necessary */ +#include /* variable arg handling */ +#include /* debugging */ +#include "defines.h" /* debugging incl MALLOC (re-) definition */ +#include "lld.h" /* also includes portable.h if necessary */ -#define NO_PROBLEMS LIST_NO_PROBLEMS /* local redefinition */ +#define NO_PROBLEMS LIST_NO_PROBLEMS /* local redefinition */ -struct Node -{ - struct Node * next; - struct Node * prev; - int data; /* also place-holder for larger items. */ -}; /* actual nodes have various sizes, */ +struct Node { + struct Node *next; + struct Node *prev; + int data; /* also place-holder for larger items. */ +}; /* actual nodes have various sizes, */ /* but a fixed size within a list. */ -struct ListHead -{ - struct Node * current; /* points to the actual current node */ - struct Node * first; /* always points to dummy head node */ - struct Node * last; /* always points to dummy tail node */ - int itemsize ; /* zero value: used as 'list not used' flag */ +struct ListHead { + struct Node *current; /* points to the actual current node */ + struct Node *first; /* always points to dummy head node */ + struct Node *last; /* always points to dummy tail node */ + int itemsize; /* zero value: used as 'list not used' flag */ }; #define ERR_MEMORY -1 @@ -59,643 +65,603 @@ struct ListHead /* ---- Local data ---------------------------------------------------- */ -static struct ListHead * ListControl = NULL; +static struct ListHead *ListControl = NULL; static unsigned int ListCount = 0; /* ---- LL system mangement ------------------------------------------- */ -static int ListInit( int List, int ItemSize ) +static int ListInit(int List, int ItemSize) { - struct Node * Tmp ; + struct Node *Tmp; - if( 0 != ItemSize ) - { - /* create dummy head node - */ - Fortify_CheckAllMemory(); - Tmp = NODE_MALLOC( List ); - if( NULL == Tmp ) - { - return ERR_MEMORY ; - } - Tmp->prev = NULL ; /* NULL identifies it as dummy head node */ - Tmp->data = 0xA709 ; /* dummy value */ - ListControl[ List ].first = Tmp ; - - /* create dummy tail node - */ - Tmp = NODE_MALLOC( List ); - if( NULL == Tmp ) - { - Tmp = ListControl[ List ].first; - NODE_FREE( Tmp ); /* no need to cause memory leaks */ - ListControl[ List ].first = NULL ; /* or other errors */ - return ERR_MEMORY ; /* even if we're in trouble ... */ - } - Tmp->next = NULL ; /* NULL identifies it as dummy tail node */ - Tmp->data = 0xA725 ; /* dummy value */ - Tmp->prev = ListControl[ List ].first ; - - ListControl[ List ].current = - ListControl[ List ].last = - ListControl[ List ].first->next = Tmp ; - } - else - { - ListControl[ List ].current = - ListControl[ List ].first = - ListControl[ List ].last = NULL ; + if (0 != ItemSize) { + /* create dummy head node + */ + Tmp = NODE_MALLOC(List); + if (NULL == Tmp) { + return ERR_MEMORY; } + Tmp->prev = NULL; /* NULL identifies it as dummy head node */ + Tmp->data = 0xA709; /* dummy value */ + ListControl[List].first = Tmp; - ListControl[ List ].itemsize = ItemSize ; /* zero: list not used */ - return NO_PROBLEMS ; + /* create dummy tail node + */ + Tmp = NODE_MALLOC(List); + if (NULL == Tmp) { + NODE_FREE(Tmp); /* no need to cause memory leaks */ + ListControl[List].first = NULL; /* or other errors */ + return ERR_MEMORY; /* even if we're in trouble ... */ + } + Tmp->next = NULL; /* NULL identifies it as dummy tail node */ + Tmp->data = 0xA725; /* dummy value */ + Tmp->prev = ListControl[List].first; + + ListControl[List].current = + ListControl[List].last = ListControl[List].first->next = Tmp; + } else { + ListControl[List].current = + ListControl[List].first = ListControl[List].last = NULL; + } + + ListControl[List].itemsize = ItemSize; /* zero: list not used */ + return NO_PROBLEMS; } -int LLDsystemInit( int ListCountInit ) +int LLDsystemInit(int ListCountInit) { - assert( (unsigned) ( ListCountInit -1 ) <= 20 -1 ); - /* negative is logic error (cast => neg. is large int) */ - /* higher than 20 is ridiculous for an initial setup */ - /* zero is useless */ + assert((unsigned) (ListCountInit - 1) <= 20 - 1); + /* negative is logic error (cast => neg. is large int) */ + /* higher than 20 is ridiculous for an initial setup */ + /* zero is useless */ - if( NULL != ListControl ) - { - return NO_PROBLEMS ; /* LL system already initialized */ - } + if (NULL != ListControl) { + return NO_PROBLEMS; /* LL system already initialized */ + } - ListControl = MALLOC( ListCountInit, struct ListHead ); - if( NULL == ListControl ) - { - return ERR_MEMORY ; - } - /* MK */ - memset(ListControl,0,ListCountInit*sizeof(struct ListHead)); + ListControl = MALLOC(ListCountInit, struct ListHead); + if (NULL == ListControl) { + return ERR_MEMORY; + } + /* MK */ + memset(ListControl, 0, ListCountInit * sizeof(struct ListHead)); - for( ListCount = 0 ; ListCount < (unsigned)ListCountInit ; ListCount++ ) - ListInit( ListCount, 0 ); /* just mark it as usable ... */ + for (ListCount = 0; ListCount < (unsigned) ListCountInit; ListCount++) + ListInit(ListCount, 0); /* just mark it as usable ... */ - /* ListCount is now ListCountInit */ - assert( ListCount == (unsigned)ListCountInit ); + /* ListCount is now ListCountInit */ + assert(ListCount == (unsigned) ListCountInit); - return NO_PROBLEMS; + return NO_PROBLEMS; } int LLDsystemClose(void) { - if(ListControl) - { + if (ListControl) { free(ListControl); } ListControl = NULL; return 1; } -int LLDcreate( int ItemSize ) +int LLDcreate(int ItemSize) { - int List ; + int List; - assert( (unsigned) ( ItemSize -1 ) < 1024 -1 ) ; - /* limit to 1kB. A size of 0 is ridiculous */ + assert((unsigned) (ItemSize - 1) < 1024 - 1); + /* limit to 1kB. A size of 0 is ridiculous */ - /* trigger automatic system initialisation if neccesary - */ - if( NULL == ListControl && 0 != LLDsystemInit( 1 )) - { - return ERR_MEMORY ; + /* trigger automatic system initialisation if neccesary + */ + if (NULL == ListControl && 0 != LLDsystemInit(1)) { + return ERR_MEMORY; + } + + /* Look for empty slot + */ + for (List = 0; List < (int) ListCount; List++) { + if (0 == ListControl[List].itemsize) + break; + } + + /* What if NO EMPTY slot ??? + */ + if (List == (int) ListCount) { + struct ListHead *tmp; /* ListControl expansion needed */ + + tmp = MALLOC(ListCount + 1, struct ListHead); + if (NULL == tmp) { + return ERR_MEMORY; } + /* MK */ + memset(tmp, 0, (ListCount + 1) * sizeof(struct ListHead)); - /* Look for empty slot - */ - for( List = 0; List < (int)ListCount; List++ ) - { - if( 0 == ListControl[ List ].itemsize ) - break; - } + memcpy(tmp, ListControl, ListCount * sizeof(struct ListHead)); + /* MK */ + free(ListControl); + ListControl = tmp; + ListCount++; + } - /* What if NO EMPTY slot ??? - */ - if( List == (int)ListCount ) - { - struct ListHead * tmp ; /* ListControl expansion needed */ + /* create dummy head node and set up ListControl for the list. + */ + if (ERR_MEMORY == ListInit(List, ItemSize)) { + return ERR_MEMORY; + } - tmp = MALLOC( ListCount + 1, struct ListHead ); - if( NULL == tmp ) - { - return ERR_MEMORY ; - } - /* MK */ - memset(tmp,0,(ListCount+1)*sizeof(struct ListHead)); - - memcpy( tmp, ListControl, ListCount * sizeof( struct ListHead )); - /* MK */ - free(ListControl); - ListControl = tmp ; - ListCount++ ; - } - - /* create dummy head node and set up ListControl for the list. - */ - if( ERR_MEMORY == ListInit( List, ItemSize )) - { - return ERR_MEMORY ; - } - - return List ; + return List; } -void LLDdelete( int List ) +void LLDdelete(int List) { - struct Node * Tmp ; - struct Node * Old ; + struct Node *Tmp; + struct Node *Old; - assert( (unsigned) List < ListCount ); + assert((unsigned) List < ListCount); - if(ListControl == NULL) - { - return; - } - Tmp = ListControl[ List ].first ; /* dummies are also deleted !!! */ - while( NULL != Tmp ) /* still assuming last node has */ - { /* a NULL next pointer ... */ - Old = Tmp ; - Tmp = Old->next; - NODE_FREE( Old ); /* data already presumed to be deleted */ - } + if (ListControl == NULL) { + return; + } + Tmp = ListControl[List].first; /* dummies are also deleted !!! */ + while (NULL != Tmp) { /* still assuming last node has *//* a NULL next pointer ... */ + Old = Tmp; + Tmp = Old->next; + NODE_FREE(Old); /* data already presumed to be deleted */ + } - ListInit( List, 0 ); /* 0: mark list as not used. */ + ListInit(List, 0); /* 0: mark list as not used. */ - return ; + return; } /* ---- LL system maintenance ----------------------------------------- */ -int LLDcheck( int List ) +int LLDcheck(int List) { - if( NULL == ListControl ) - { - return LIST_SYSTEM_NULL ; + if (NULL == ListControl) { + return LIST_SYSTEM_NULL; + } + + if ((unsigned) List >= ListCount) { + return LIST_INV_NUMBER; + } + + if (0 == ListControl[List].itemsize) { + return LIST_NOT_CREATED; + } + + if (NULL == ListControl[List].first || NULL == ListControl[List].first->next /* missing tail ? */ + || NULL != ListControl[List].first->prev) { + return LIST_ERR_HEAD; + } + + /* Validate current pointer + */ + if (NULL == ListControl[List].current) { + return LIST_CORRUPT7; /* shouldn't be NULL with a good head */ + } + + if (NULL != ListControl[List].first->next->next) { /* empty list ? *//* not empty. */ + struct Node *tmp = ListControl[List].first; + + if (NULL == ListControl[List].current->next) { + return LIST_CORRUPT6; /* a NULL next pointer is only valid */ } - if( (unsigned) List >= ListCount ) - { - return LIST_INV_NUMBER ; + /* for an empty list. */ + /* look for .current in list, + checking the .prev links along the way + */ + do { + tmp = tmp->next; + + if (NULL == tmp || NULL == tmp->prev || tmp != tmp->prev->next) { + return LIST_CORRUPT5; /* current not found in list */ + } + /* or link to/from next node */ + /* invalid */ + } while (tmp != ListControl[List].current); + + /* Found .current in list. Also without link errors. + Now look for valid last node pointer in the list, + checking the .prev links along the way + Note that .current itself is never supposed to be equal + to .last (which points to the dummy tail) ! + */ + if (NULL == ListControl[List].last) { + return LIST_ERR_LAST; } - if( 0 == ListControl[ List ].itemsize ) - { - return LIST_NOT_CREATED ; + do { + tmp = tmp->next; + if (NULL == tmp || NULL == tmp->prev || tmp != tmp->prev->next) { + return LIST_CORRUPT4; /* last not found in list */ + } + /* or link to/from prev node */ + /* invalid */ + } while (tmp != ListControl[List].last); + + /* Found .last in list but is it really a valid last pointer? + Note: tmp == .last + */ + if (NULL != tmp->next) { + return LIST_CORRUPT3; } - if( NULL == ListControl[ List ].first - || NULL == ListControl[ List ].first->next /* missing tail ? */ - || NULL != ListControl[ List ].first->prev ) - { - return LIST_ERR_HEAD ; - } + return NO_PROBLEMS; + } - /* Validate current pointer - */ - if( NULL == ListControl[ List ].current ) - { - return LIST_CORRUPT7 ; /* shouldn't be NULL with a good head */ - } + /* .first->next->next == NULL => list is empty + */ + if (ListControl[List].current != ListControl[List].first->next) { + return LIST_CORRUPT2; + } - if( NULL != ListControl[ List ].first->next->next ) /* empty list ? */ - { /* not empty. */ - struct Node * tmp = ListControl[ List ].first ; + if (ListControl[List].last != ListControl[List].first->next + || ListControl[List].last != ListControl[List].current->prev->next) { + return LIST_CORRUPT1; + } - if( NULL == ListControl[ List ].current->next ) - { - return LIST_CORRUPT6 ; /* a NULL next pointer is only valid */ - } /* for an empty list. */ - - /* look for .current in list, - checking the .prev links along the way - */ - do - { - tmp = tmp->next ; - - if( NULL == tmp || NULL == tmp->prev - || tmp != tmp->prev->next ) - { - return LIST_CORRUPT5 ; /* current not found in list */ - } /* or link to/from next node */ - /* invalid */ - }while( tmp != ListControl[ List ].current ); - - /* Found .current in list. Also without link errors. - Now look for valid last node pointer in the list, - checking the .prev links along the way - Note that .current itself is never supposed to be equal - to .last (which points to the dummy tail) ! - */ - if( NULL == ListControl[ List ].last ) - { - return LIST_ERR_LAST ; - } - - do - { - tmp = tmp->next ; - if( NULL == tmp || NULL == tmp->prev - || tmp != tmp->prev->next ) - { - return LIST_CORRUPT4 ; /* last not found in list */ - } /* or link to/from prev node */ - /* invalid */ - }while( tmp != ListControl[ List ].last ); - - /* Found .last in list but is it really a valid last pointer? - Note: tmp == .last - */ - if( NULL != tmp->next ) - { - return LIST_CORRUPT3 ; - } - - return NO_PROBLEMS ; - } - - /* .first->next->next == NULL => list is empty - */ - if( ListControl[ List ].current != ListControl[ List ].first->next ) - { - return LIST_CORRUPT2 ; - } - - if( ListControl[ List ].last != ListControl[ List ].first->next - || ListControl[ List ].last - != ListControl[ List ].current->prev->next ) - { - return LIST_CORRUPT1 ; - } - - return LIST_EMPTY ; + return LIST_EMPTY; } /* ---- node management ----------------------------------------------- */ -int LLDnodeInsert( int List, ... ) /* insert _BEFORE_ current node */ +int LLDnodeInsert(int List, ...) +{ /* insert _BEFORE_ current node */ + va_list DataPtr; + int Retval; + + /* set DataPtr to the address of "..." + then action, cleanup and return. + */ + va_start(DataPtr, List); + + Retval = LLDnodeInsertFrom(List, (void *) va_arg(DataPtr, void *)); + + va_end(DataPtr); + return Retval; +} + +int LLDnodeAdd(int List, ...) +{ /* insert _AFTER_ current node */ + va_list DataPtr; + int Retval; + + /* set DataPtr to the address of "..." + then action, cleanup and return. + */ + va_start(DataPtr, List); + + Retval = LLDnodeAddFrom(List, (void *) va_arg(DataPtr, void *)); + + va_end(DataPtr); + return Retval; +} + +int LLDnodePrepend(int List, ...) +{ /* insert as first node */ + va_list DataPtr; + int Retval; + + /* set DataPtr to the address of "..." + then action, cleanup and return. + */ + va_start(DataPtr, List); + + Retval = LLDnodePrependFrom(List, (void *) va_arg(DataPtr, void *)); + + va_end(DataPtr); + return Retval; +} + +int LLDnodeAppend(int List, ...) +{ /* insert as last node */ + va_list DataPtr; + int Retval; + + /* set DataPtr to the address of "..." + then action, cleanup and return. + */ + va_start(DataPtr, List); + + Retval = LLDnodeAppendFrom(List, (void *) va_arg(DataPtr, void *)); + + va_end(DataPtr); + return Retval; +} + +int LLDnodeInsertFrom(int List, void *Source) +{ /* insert _BEFORE_ current node */ + struct Node *New; + + assert((unsigned) List < ListCount); + + /* create new node if possible + */ + New = NODE_MALLOC(List); + if (NULL == New) { + return ERR_MEMORY; + } + + /* fill node with data, link to next and previous nodes + and adjust current node pointer + */ + memcpy(&New->data, Source, ListControl[List].itemsize); + New->next = ListControl[List].current; + New->prev = ListControl[List].current->prev; + + ListControl[List].current->prev = New; + New->prev->next = New; + + ListControl[List].current = New; + + return NO_PROBLEMS; +} + +int LLDnodeAddFrom(int List, void *Source) +{ /* insert _AFTER_ current node */ + struct Node *New; + + assert((unsigned) List < ListCount); + + /* create new node if possible + */ + New = NODE_MALLOC(List); + if (NULL == New) { + return ERR_MEMORY; + } + + /* fill node with data and link to next and previous nodes + with special handling when the current node pointer points + to the dummy tail node: i.e it is an empty list. + (the same case in a non-empty list is made not to occur.) + */ + memcpy(&New->data, Source, ListControl[List].itemsize); + + if (NULL != ListControl[List].current->next) + ListControl[List].current = ListControl[List].current->next; + + New->next = ListControl[List].current; + New->prev = ListControl[List].current->prev; + + ListControl[List].current->prev = New; + New->prev->next = New; + + ListControl[List].current = New; + + return NO_PROBLEMS; +} + +int LLDnodePrependFrom(int List, void *Source) +{ /* insert as first node */ + struct Node *New; + + assert((unsigned) List < ListCount); + + /* create new node if possible + */ + New = NODE_MALLOC(List); + if (NULL == New) { + return ERR_MEMORY; + } + + /* fill node with data and link to dummy head and actual first nodes + */ + memcpy(&New->data, Source, ListControl[List].itemsize); + New->prev = ListControl[List].first; /* == .first->next->prev */ + New->next = ListControl[List].first->next; + + ListControl[List].first->next = New; + New->next->prev = New; + + /* Prevent .current from pointing at the dummy tail + (New is the only normal node...) + */ + if (NULL == ListControl[List].current->next) + ListControl[List].current = New; + + return NO_PROBLEMS; +} + +int LLDnodeAppendFrom(int List, void *Source) +{ /* insert as last node */ + struct Node *New; + + assert((unsigned) List < ListCount); + + /* create new node if possible + */ + New = NODE_MALLOC(List); + if (NULL == New) { + return ERR_MEMORY; + } + + /* fill node with data and link to dummy tail and actual last nodes + */ + memcpy(&New->data, Source, ListControl[List].itemsize); + New->next = ListControl[List].last; /* == .last->prev->next */ + New->prev = ListControl[List].last->prev; + + ListControl[List].last->prev = New; + New->prev->next = New; + + /* Prevent .current from pointing at the dummy tail + (New is the only normal node...) + */ + if (NULL == ListControl[List].current->next) + ListControl[List].current = New; + + return NO_PROBLEMS; +} + +void LLDnodeDelete(int List) { - va_list DataPtr ; - int Retval ; + struct Node *Old = ListControl[List].current; - /* set DataPtr to the address of "..." - then action, cleanup and return. - */ - va_start( DataPtr, List ); + assert((unsigned) List < ListCount); - Retval = LLDnodeInsertFrom( List, (void *)va_arg(DataPtr,void *) ); + if (NULL == ListControl[List].current->next) { + return; /* don't delete dummy tail node (list is empty) */ + } - va_end( DataPtr ); - return Retval ; + /* adjust links + */ + if(Old->prev != NULL){ + Old->prev->next = Old->next; + } + if(Old->next != NULL){ + Old->next->prev = Old->prev; + } + + /* adjust current node pointer + prevent it from pointing to the dummy tail node + */ + if (NULL != Old->next->next) + ListControl[List].current = Old->next; + else + ListControl[List].current = Old->prev; + + NODE_FREE(Old); + + return; } -int LLDnodeAdd( int List, ... ) /* insert _AFTER_ current node */ -{ - va_list DataPtr ; - int Retval ; +int LLDnodeFind(int List, CompFunPtr Compare, void *DataPtr) +{ /* FindFirst/FindNext format may be needed ... */ + int RetVal; - /* set DataPtr to the address of "..." - then action, cleanup and return. - */ - va_start( DataPtr, List ); + assert((unsigned) List < ListCount); - Retval = LLDnodeAddFrom( List, (void *)va_arg(DataPtr,void *) ); + if (NULL == ListControl[List].first->next->next) { /* empty list ? */ + return 2; /* a compare usually returns just -1, 0 or 1 !!! */ + } - va_end( DataPtr ); - return Retval ; -} + /* note: current->next will never be NULL in a non-empty list */ -int LLDnodePrepend( int List, ... ) /* insert as first node */ -{ - va_list DataPtr ; - int Retval ; - - /* set DataPtr to the address of "..." - then action, cleanup and return. - */ - va_start( DataPtr, List ); - - Retval = LLDnodePrependFrom( List, (void *)va_arg(DataPtr,void *) ); - - va_end( DataPtr ); - return Retval ; -} - -int LLDnodeAppend( int List, ... ) /* insert as last node */ -{ - va_list DataPtr ; - int Retval ; - - /* set DataPtr to the address of "..." - then action, cleanup and return. - */ - va_start( DataPtr, List ); - - Retval = LLDnodeAppendFrom( List, (void *)va_arg(DataPtr,void *) ); - - va_end( DataPtr ); - return Retval ; -} - -int LLDnodeInsertFrom( int List, void * Source ) -{ /* insert _BEFORE_ current node */ - struct Node * New ; - - assert( (unsigned) List < ListCount ); - - /* create new node if possible - */ - New = NODE_MALLOC( List ); - if( NULL == New ) - { - return ERR_MEMORY ; + if (NULL == Compare) { /* default to memcmp with .itemsize */ + while (0 != (RetVal = memcmp(DataPtr, + &ListControl[List].current->data, + ListControl[List].itemsize)) + && NULL != ListControl[List].current->next->next) { + ListControl[List].current = ListControl[List].current->next; } - - /* fill node with data, link to next and previous nodes - and adjust current node pointer - */ - memcpy( & New->data, Source, ListControl[ List ].itemsize ); - New->next = ListControl[ List ].current; - New->prev = ListControl[ List ].current->prev; - - ListControl[ List ].current->prev = New ; - New->prev->next = New ; - - ListControl[ List ].current = New ; - - return NO_PROBLEMS; -} - -int LLDnodeAddFrom( int List, void * Source ) -{ /* insert _AFTER_ current node */ - struct Node * New ; - - assert( (unsigned) List < ListCount ); - - /* create new node if possible - */ - New = NODE_MALLOC( List ); - if( NULL == New ) - { - return ERR_MEMORY ; - } - - /* fill node with data and link to next and previous nodes - with special handling when the current node pointer points - to the dummy tail node: i.e it is an empty list. - (the same case in a non-empty list is made not to occur.) - */ - memcpy( & New->data, Source, ListControl[ List ].itemsize ); - - if( NULL != ListControl[ List ].current->next ) - ListControl[ List ].current = ListControl[ List ].current->next ; - - New->next = ListControl[ List ].current; - New->prev = ListControl[ List ].current->prev; - - ListControl[ List ].current->prev = New ; - New->prev->next = New ; - - ListControl[ List ].current = New ; - - return NO_PROBLEMS; -} - -int LLDnodePrependFrom( int List, void * Source ) -{ /* insert as first node */ - struct Node * New ; - - assert( (unsigned) List < ListCount ); - - /* create new node if possible - */ - New = NODE_MALLOC( List ); - if( NULL == New ) - { - return ERR_MEMORY ; - } - - /* fill node with data and link to dummy head and actual first nodes - */ - memcpy( & New->data, Source, ListControl[ List ].itemsize ); - New->prev = ListControl[ List ].first; /* == .first->next->prev */ - New->next = ListControl[ List ].first->next; - - ListControl[ List ].first->next = New; - New->next->prev = New ; - - /* Prevent .current from pointing at the dummy tail - (New is the only normal node...) - */ - if( NULL == ListControl[ List ].current->next ) - ListControl[ List ].current = New; - - return NO_PROBLEMS; -} - -int LLDnodeAppendFrom( int List, void * Source ) -{ /* insert as last node */ - struct Node * New ; - - assert( (unsigned) List < ListCount ); - - /* create new node if possible - */ - New = NODE_MALLOC( List ); - if( NULL == New ) - { - return ERR_MEMORY ; - } - - /* fill node with data and link to dummy tail and actual last nodes - */ - memcpy( & New->data, Source, ListControl[ List ].itemsize ); - New->next = ListControl[ List ].last ; /* == .last->prev->next */ - New->prev = ListControl[ List ].last->prev; - - ListControl[ List ].last->prev = New ; - New->prev->next = New ; - - /* Prevent .current from pointing at the dummy tail - (New is the only normal node...) - */ - if( NULL == ListControl[ List ].current->next ) - ListControl[ List ].current = New; - - return NO_PROBLEMS; -} - -void LLDnodeDelete( int List ) -{ - struct Node * Old = ListControl[ List ].current ; - - assert( (unsigned) List < ListCount ); - - if( NULL == ListControl[ List ].current->next ) - { - return ; /* don't delete dummy tail node (list is empty) */ - } - - /* adjust links - */ - Old->prev->next = Old->next ; - Old->next->prev = Old->prev ; - - /* adjust current node pointer - prevent it from pointing to the dummy tail node - */ - if( NULL != Old->next->next ) - ListControl[ List ].current = Old->next ; - else - ListControl[ List ].current = Old->prev ; - - NODE_FREE( Old ); - - return ; -} - -int LLDnodeFind( int List, CompFunPtr Compare, void * DataPtr ) -{ /* FindFirst/FindNext format may be needed ... */ - int RetVal ; - - assert( (unsigned) List < ListCount ); - - if( NULL == ListControl[ List ].first->next->next ) /* empty list ? */ - { - return 2; /* a compare usually returns just -1, 0 or 1 !!! */ - } - - /* note: current->next will never be NULL in a non-empty list */ - - if( NULL == Compare ) /* default to memcmp with .itemsize */ - { - while( 0 != (RetVal = memcmp( DataPtr, - & ListControl[ List ].current->data, - ListControl[ List ].itemsize )) - && NULL != ListControl[ List ].current->next->next ) - { - ListControl[ List ].current=ListControl[ List ].current->next; - } - return RetVal ; - } - else - { - while( 0 != (RetVal = (*Compare)( DataPtr, - & ListControl[ List ].current->data )) - && NULL != ListControl[ List ].current->next->next ) - { - ListControl[ List ].current=ListControl[ List ].current->next; - } - return RetVal ; + return RetVal; + } else { + while (0 != (RetVal = (*Compare) (DataPtr, + &ListControl[List].current->data)) + && NULL != ListControl[List].current->next->next) { + ListControl[List].current = ListControl[List].current->next; } + return RetVal; + } } /* ---- current node pointer management ------------------------------- */ -int LLDnodePtr2First( int List ) +int LLDnodePtr2First(int List) { - assert( (unsigned) List < ListCount ); + assert((unsigned) List < ListCount); - ListControl[ List ].current = ListControl[ List ].first->next ; + ListControl[List].current = ListControl[List].first->next; - if(ListControl[List].first->next == NULL) - { - return 0; - } + if (ListControl[List].first->next == NULL) { + return 0; + } - return NULL != ListControl[ List ].first->next->next ; + return NULL != ListControl[List].first->next->next; } -int LLDnodePtr2Last( int List ) +int LLDnodePtr2Last(int List) { - assert( (unsigned) List < ListCount ); + assert((unsigned) List < ListCount); - ListControl[ List ].current = ListControl[ List ].last->prev ; + ListControl[List].current = ListControl[List].last->prev; - return NULL != ListControl[ List ].last->prev->prev ; + return NULL != ListControl[List].last->prev->prev; } -int LLDnodePtr2Next( int List ) +int LLDnodePtr2Next(int List) { - assert( (unsigned) List < ListCount ); + assert((unsigned) List < ListCount); - if( NULL == ListControl[ List ].current->next /* empty list ? */ - || NULL == ListControl[ List ].current->next->next ) /* at end ?*/ - { - return 0 ; /* do not allow the current node pointer */ - } /* to point at the dummy tail node ... */ - - ListControl[ List ].current = ListControl[ List ].current->next ; - return 1 ; + if (NULL == ListControl[List].current->next /* empty list ? */ + || NULL == ListControl[List].current->next->next) { /* at end ? */ + return 0; /* do not allow the current node pointer */ + } + /* to point at the dummy tail node ... */ + ListControl[List].current = ListControl[List].current->next; + return 1; } -int LLDnodePtr2Prev( int List ) +int LLDnodePtr2Prev(int List) { - assert( (unsigned) List < ListCount ); + assert((unsigned) List < ListCount); - if( NULL == ListControl[ List ].current->prev /* empty list ? */ - || NULL == ListControl[ List ].current->prev->prev ) /* begin ? */ - { - return 0 ; /* do not allow the current node pointer */ - } /* to point at the dummy head node ... */ - - ListControl[ List ].current = ListControl[ List ].current->prev ; - return 1 ; + if (NULL == ListControl[List].current->prev /* empty list ? */ + || NULL == ListControl[List].current->prev->prev) { /* begin ? */ + return 0; /* do not allow the current node pointer */ + } + /* to point at the dummy head node ... */ + ListControl[List].current = ListControl[List].current->prev; + return 1; } /* ---- stored data management ---------------------------------------- */ -int LLDnodeInt( int List ) +int LLDnodeInt(int List) { - return ListControl[ List ].current->data; + return ListControl[List].current->data; } -long LLDnodeLong( int List ) +long LLDnodeLong(int List) { - return *((long *) &ListControl[ List ].current->data ); + return *((long *) &ListControl[List].current->data); } -float LLDnodeFloat( int List ) +float LLDnodeFloat(int List) { - return *((float *) &ListControl[ List ].current->data ); + return *((float *) &ListControl[List].current->data); } -void * LLDnodePtr( int List ) +void *LLDnodePtr(int List) { - return *((void **) &ListControl[ List ].current->data ); + return *((void **) &ListControl[List].current->data); } -void FAR * LLDnodeFptr( int List ) +void FAR *LLDnodeFptr(int List) { - return *((void FAR **) &ListControl[ List ].current->data ); + return *((void FAR **) &ListControl[List].current->data); } -int LLDnodeDataTo( int List, void * Destination ) +int LLDnodeDataTo(int List, void *Destination) { - if( NULL != Destination ) - { - memcpy( Destination, - & ListControl[ List ].current->data, - ListControl[ List ].itemsize ); - } + if (NULL != Destination) { + memcpy(Destination, + &ListControl[List].current->data, ListControl[List].itemsize); + } - return ListControl[ List ].itemsize ; /* size needed for blob */ + return ListControl[List].itemsize; /* size needed for blob */ } /* added: Mark Koennecke, 7.4.1997 */ -int LLDnodeDataFrom( int List, void *source ) +int LLDnodeDataFrom(int List, void *source) { - if( NULL != source ) - { - memcpy( - & ListControl[ List ].current->data, - source, - ListControl[ List ].itemsize ); - } + if (NULL != source) { + memcpy(&ListControl[List].current->data, + source, ListControl[List].itemsize); + } - return ListControl[ List ].itemsize ; /* size needed for blob */ + return ListControl[List].itemsize; /* size needed for blob */ } /* ==== LLD.c end ==================================================== */ +/** + * These two functions help me implement a solution for a race condition + * in devexec.c, especially in DevexecLevelRunning. + */ +void *LLDgetCurrent(int List){ + return ListControl[List].current; +} +void LLDsetCurrent(int List, void *pointer){ + ListControl[List].current = (struct Node*)pointer; +} diff --git a/lld.h b/lld.h index c6c6d535..645c39c4 100644 --- a/lld.h +++ b/lld.h @@ -14,54 +14,52 @@ #endif #ifndef LL__ERR_H -#define LL__ERR_H /* same values used in LLS ... */ +#define LL__ERR_H /* same values used in LLS ... */ -enum ListErrors /* return values for LLDcheck() */ -{ /* The highest value is returned */ - - LIST_NO_PROBLEMS, /* All is OK (multiple use) */ - LIST_EMPTY, /* No data available */ - LIST_ERRORS, /* Dummy to separate warnings from */ - /* ---- REAL errors --------------------------- */ - LIST_CORRUPT1, /* invalid last node pointer: != first->next */ - /* (empty list) or link error */ - LIST_CORRUPT2, /* invalid current node pointer: != first->next */ - /* (empty list) */ - LIST_CORRUPT3, /* invalid last node pointer: Not really last. */ - LIST_CORRUPT4, /* invalid last node pointer: Not in list, */ - /* or link error after current node */ - LIST_ERR_LAST, /* invalid last node pointer: NULL */ - LIST_CORRUPT5, /* invalid current node pointer: Not in list, */ - /* or link error before current node */ - LIST_CORRUPT6, /* invalid current->next node pointer: NULL */ - /* although the list is not empty */ - LIST_CORRUPT7, /* NULL current node pointer */ - LIST_ERR_HEAD, /* NULL first node pointer */ - /* or error in head node */ - LIST_NOT_CREATED, /* List deleted or not created */ - LIST_INV_NUMBER, /* List number out of range */ - LIST_SYSTEM_NULL /* List system not intialized */ +enum ListErrors { /* return values for LLDcheck() *//* The highest value is returned */ + LIST_NO_PROBLEMS, /* All is OK (multiple use) */ + LIST_EMPTY, /* No data available */ + LIST_ERRORS, /* Dummy to separate warnings from */ + /* ---- REAL errors --------------------------- */ + LIST_CORRUPT1, /* invalid last node pointer: != first->next */ + /* (empty list) or link error */ + LIST_CORRUPT2, /* invalid current node pointer: != first->next */ + /* (empty list) */ + LIST_CORRUPT3, /* invalid last node pointer: Not really last. */ + LIST_CORRUPT4, /* invalid last node pointer: Not in list, */ + /* or link error after current node */ + LIST_ERR_LAST, /* invalid last node pointer: NULL */ + LIST_CORRUPT5, /* invalid current node pointer: Not in list, */ + /* or link error before current node */ + LIST_CORRUPT6, /* invalid current->next node pointer: NULL */ + /* although the list is not empty */ + LIST_CORRUPT7, /* NULL current node pointer */ + LIST_ERR_HEAD, /* NULL first node pointer */ + /* or error in head node */ + LIST_NOT_CREATED, /* List deleted or not created */ + LIST_INV_NUMBER, /* List number out of range */ + LIST_SYSTEM_NULL /* List system not intialized */ }; -typedef int (*CompFunPtr)( const void *, const void * ); +typedef int (*CompFunPtr) (const void *, const void *); /* simplifies declarations */ #endif #ifndef LLD_H #define LLD_H /* ---- LL system management and maintenance -------------------------- */ -int LLDsystemInit( int ListCount ); +int LLDsystemInit(int ListCount); /* returns -1 on failure. It is not required to call it. */ /* A second call does nothing: ListCount is ignored. */ -int LLDcreate( int ItemSize ); +int LLDcreate(int ItemSize); /* returns list number to use or -1 on failure. */ /* MUST be called before using a list. */ /* Calls LLsystemInit if necessary. */ -void LLDdelete( int List ); /* delete entire list, data is NOT free()'d */ +void LLDdelete(int List); /* delete entire list, data is NOT free()'d */ -int LLDcheck( int List ); /* returns enum ListErrors value */ +int LLDcheck(int List); /* returns enum ListErrors value */ /* its primary purpose is debugging. */ int LLDsystemClose(void); @@ -71,30 +69,30 @@ int LLDsystemClose(void); Each created list has its own -- fixed -- datasize. See LLcreate(). An ellipsis "..." indicates the data to insert. */ -int LLDnodeInsert( int List, ... ); /* insert BEFORE current node */ -int LLDnodeAdd( int List, ... ); /* insert AFTER current node */ +int LLDnodeInsert(int List, ...); /* insert BEFORE current node */ +int LLDnodeAdd(int List, ...); /* insert AFTER current node */ /* a return value of -1 indicates a memory allocation problem. */ /* Functions NOT changing the current node pointer. Especially intended for implementation of Queue's and Stacks. */ -int LLDnodePrepend( int List, ... ); /* insert as first node */ -int LLDnodeAppend( int List, ... ); /* insert as last node */ +int LLDnodePrepend(int List, ...); /* insert as first node */ +int LLDnodeAppend(int List, ...); /* insert as last node */ /* a return value of -1 indicates a memory allocation problem. */ /* The following four functions are essentially the same as the preceeding four. The data is however not passed by value but by reference. */ -int LLDnodeInsertFrom( int List, void * Source ); -int LLDnodeAddFrom( int List, void * Source ); -int LLDnodePrependFrom( int List, void * Source ); -int LLDnodeAppendFrom( int List, void * Source ); +int LLDnodeInsertFrom(int List, void *Source); +int LLDnodeAddFrom(int List, void *Source); +int LLDnodePrependFrom(int List, void *Source); +int LLDnodeAppendFrom(int List, void *Source); -void LLDnodeDelete( int List ); /* remove current node */ +void LLDnodeDelete(int List); /* remove current node */ /* current node ptr moved to next node. UNLESS the deleted node */ /* was the last node: then current ptr moved to previous node */ -int LLDnodeFind( int List, CompFunPtr Compare, void * DataPtr ); +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. */ @@ -110,25 +108,25 @@ int LLDnodeFind( int List, CompFunPtr Compare, void * DataPtr ); the end of the list, or an empty list. The return value is intended for iteration purposes. I.e. stopping a scan through a list. */ -int LLDnodePtr2First( int List ); -int LLDnodePtr2Last( int List ); -int LLDnodePtr2Next( int List ); -int LLDnodePtr2Prev( int List ); +int LLDnodePtr2First(int List); +int LLDnodePtr2Last(int List); +int LLDnodePtr2Next(int List); +int LLDnodePtr2Prev(int List); /* ---- stored data management ------------------------------------------- return typed data: */ -int LLDnodeInt( int List ); -long LLDnodeLong( int List ); -float LLDnodeFloat( int List ); -void * LLDnodePtr( int List ); -void FAR * LLDnodeFptr( int List ); +int LLDnodeInt(int List); +long LLDnodeLong(int List); +float LLDnodeFloat(int List); +void *LLDnodePtr(int List); +void FAR *LLDnodeFptr(int List); /* 'return' typeless data. The return value is the size of the data. The data is transferred to Destination. If 'Destination' is NULL, the only action is returning the size. */ -int LLDnodeDataTo( int List, void * Destination ); +int LLDnodeDataTo(int List, void *Destination); /* replaces typeless data with source diff --git a/lld_blob.c b/lld_blob.c index 99e560bb..12e0a410 100644 --- a/lld_blob.c +++ b/lld_blob.c @@ -9,138 +9,134 @@ /_|__| A.Reitsma, Delft, The Netherlands. / | \ --------------------------------------------------------------- */ -#include /* for malloc() */ -#include "lld.h" /* the generic LLD functions ... */ -#include "lld_blob.h" /* also includes portable.h if necessary */ +#include /* for malloc() */ +#include "lld.h" /* the generic LLD functions ... */ +#include "lld_blob.h" /* also includes portable.h if necessary */ -struct BlobDesc -{ - void * data ; /* 'data' can be obtained by LLDnodePtr() ! */ - unsigned size ; +struct BlobDesc { + void *data; /* 'data' can be obtained by LLDnodePtr() ! */ + unsigned size; }; #define ERR_MEMORY -1 /* ---- LL blob system mangement -------------------------------------- */ -int LLDblobCreate( void ) +int LLDblobCreate(void) { - return LLDcreate( sizeof( struct BlobDesc )); + return LLDcreate(sizeof(struct BlobDesc)); } /*---------------------------------------------------------------------*/ int LLDdeleteBlob(int List) { - struct BlobDesc Blob ; - int status; - - status = LLDnodePtr2First(List); - while(status == 1){ - LLDnodeDataTo( List, & Blob ); - free(Blob.data); - status = LLDnodePtr2Next(List); - } - LLDdelete(List); - return 1; + struct BlobDesc Blob; + int status; + + status = LLDnodePtr2First(List); + while (status == 1) { + LLDnodeDataTo(List, &Blob); + free(Blob.data); + status = LLDnodePtr2Next(List); + } + LLDdelete(List); + return 1; } + /* ---- LL blob node mangement ---------------------------------------- */ -int LLDblobInsert( int List, void * Source, unsigned Size ) -{ /* insert _BEFORE_ current node */ - struct BlobDesc Blob ; +int LLDblobInsert(int List, void *Source, unsigned Size) +{ /* insert _BEFORE_ current node */ + struct BlobDesc Blob; - Blob.size = Size ; - Blob.data = malloc( Size ); + Blob.size = Size; + Blob.data = malloc(Size); - if( NULL == Blob.data ) - { - return ERR_MEMORY ; - } + if (NULL == Blob.data) { + return ERR_MEMORY; + } - memcpy( Blob.data, Source, Size ); - LLDnodeInsertFrom( List, & Blob ); + memcpy(Blob.data, Source, Size); + LLDnodeInsertFrom(List, &Blob); - return LIST_NO_PROBLEMS ; + return LIST_NO_PROBLEMS; } -int LLDblobAdd( int List, void * Source, unsigned Size ) -{ /* insert _AFTER_ current node */ - struct BlobDesc Blob ; +int LLDblobAdd(int List, void *Source, unsigned Size) +{ /* insert _AFTER_ current node */ + struct BlobDesc Blob; - Blob.size = Size ; - Blob.data = malloc( Size ); + Blob.size = Size; + Blob.data = malloc(Size); - if( NULL == Blob.data ) - { - return ERR_MEMORY ; - } + if (NULL == Blob.data) { + return ERR_MEMORY; + } - memcpy( Blob.data, Source, Size ); - LLDnodeAddFrom( List, & Blob ); + memcpy(Blob.data, Source, Size); + LLDnodeAddFrom(List, &Blob); - return LIST_NO_PROBLEMS ; + return LIST_NO_PROBLEMS; } -int LLDblobPrepend( int List, void * Source, unsigned Size ) -{ /* insert as first node */ - struct BlobDesc Blob ; +int LLDblobPrepend(int List, void *Source, unsigned Size) +{ /* insert as first node */ + struct BlobDesc Blob; - Blob.size = Size ; - Blob.data = malloc( Size ); + Blob.size = Size; + Blob.data = malloc(Size); - if( NULL == Blob.data ) - { - return ERR_MEMORY ; - } + if (NULL == Blob.data) { + return ERR_MEMORY; + } - memcpy( Blob.data, Source, Size ); - LLDnodePrependFrom( List, & Blob ); + memcpy(Blob.data, Source, Size); + LLDnodePrependFrom(List, &Blob); - return LIST_NO_PROBLEMS ; + return LIST_NO_PROBLEMS; } -int LLDblobAppend( int List, void * Source, unsigned Size ) -{ /* insert as last node */ - struct BlobDesc Blob ; +int LLDblobAppend(int List, void *Source, unsigned Size) +{ /* insert as last node */ + struct BlobDesc Blob; - Blob.size = Size ; - Blob.data = malloc( Size ); + Blob.size = Size; + Blob.data = malloc(Size); - if( NULL == Blob.data ) - { - return ERR_MEMORY ; - } + if (NULL == Blob.data) { + return ERR_MEMORY; + } - memcpy( Blob.data, Source, Size ); - LLDnodeAppendFrom( List, & Blob ); + memcpy(Blob.data, Source, Size); + LLDnodeAppendFrom(List, &Blob); - return LIST_NO_PROBLEMS ; + return LIST_NO_PROBLEMS; } -void LLDblobDelete( int List ) +void LLDblobDelete(int List) { - struct BlobDesc Blob ; + struct BlobDesc Blob; - LLDnodeDataTo( List, & Blob ); - free( Blob.data ); + LLDnodeDataTo(List, &Blob); + free(Blob.data); - LLDnodeDelete( List ); + LLDnodeDelete(List); - return ; + return; } /* ---- stored data management ---------------------------------------- */ -unsigned LLDblobData( int List, void * Destination ) +unsigned LLDblobData(int List, void *Destination) { - struct BlobDesc Blob ; + struct BlobDesc Blob; - LLDnodeDataTo( List, & Blob ); + LLDnodeDataTo(List, &Blob); - if( NULL != Destination ) - memcpy( Destination, Blob.data, Blob.size ); + if (NULL != Destination) + memcpy(Destination, Blob.data, Blob.size); - return Blob.size ; /* size needed for blob */ + return Blob.size; /* size needed for blob */ } /* ==== LLD_BLOB.c end =============================================== */ diff --git a/lld_blob.h b/lld_blob.h index 56ceab06..1663e394 100644 --- a/lld_blob.h +++ b/lld_blob.h @@ -17,7 +17,7 @@ /* ---- LL blob system management and maintenance --------------------- */ -int LLDblobCreate( void ); +int LLDblobCreate(void); /* returns list number to use or -1 on failure. */ /* MUST be called before using a list of blobs. */ int LLDdeleteBlob(int List); @@ -26,20 +26,20 @@ int LLDdeleteBlob(int List); Functions changing current node pointer to the new node. A return value of -1 indicates a memory allocation problem. */ -int LLDblobInsert( int List, void * Source, unsigned Size ); +int LLDblobInsert(int List, void *Source, unsigned Size); /* insert BEFORE current node */ -int LLDblobAdd( int List, void * Source, unsigned Size ); +int LLDblobAdd(int List, void *Source, unsigned Size); /* insert AFTER current node */ /* Functions NOT changing the current node pointer. Especially intended for implementation of Queue's and Stacks. */ -int LLDblobPrepend( int List, void * Source, unsigned Size ); +int LLDblobPrepend(int List, void *Source, unsigned Size); /* insert as first node */ -int LLDblobAppend( int List, void * Source, unsigned Size ); +int LLDblobAppend(int List, void *Source, unsigned Size); /* insert as last node */ -void LLDblobDelete( int List ); +void LLDblobDelete(int List); /* remove current node and free() the data. */ /* current node ptr moved to next node. UNLESS the deleted node */ /* was the last node: then current ptr moved to previous node */ @@ -49,6 +49,6 @@ void LLDblobDelete( int List ); The data is transferred to Destination. If 'Destination' is NULL, the only action is returning the size. */ -unsigned LLDblobData( int List, void * Destination ); +unsigned LLDblobData(int List, void *Destination); /* ==== LLD_BLOB.h end =============================================== */ diff --git a/logger.c b/logger.c index 1f9eed5f..37d0d631 100644 --- a/logger.c +++ b/logger.c @@ -20,8 +20,9 @@ struct Logger { char *old; int oldsize; int period; - time_t last, lastWrite; + time_t last, lastWrite, omitTime; int numeric; + float omitValue; int exact; Logger *next; }; @@ -30,48 +31,57 @@ static char *dir = NULL; static Logger *list; static time_t lastLife = 0; static time_t lastWritten = 0; +static time_t omitCheck = 0; /*--------------------------------------------------------------------------*/ -char *LoggerName(Logger *log) { +char *LoggerName(Logger * log) +{ return log->name; } + /*--------------------------------------------------------------------------*/ -void LoggerSetNumeric(Logger *log, int numeric) { +void LoggerSetNumeric(Logger * log, int numeric) +{ if (log) { log->numeric = numeric; } } + /*--------------------------------------------------------------------------*/ -Logger *LoggerFind(const char *name) { +Logger *LoggerFind(const char *name) +{ Logger *p; p = list; while (p != NULL) { - if (0==strcasecmp(name, p->name)) { + if (0 == strcasecmp(name, p->name)) { return p; } p = p->next; } return NULL; } + /*--------------------------------------------------------------------------*/ #define LASTLOGTXT "#last logging entry at:\n" -time_t LoggerGetLastLife(char *dirarg) { +time_t LoggerGetLastLife(char *dirarg) +{ char path[256], line[32]; FILE *fil; time_t t = 0; - + if (dirarg == NULL) { return lastWritten; } snprintf(path, sizeof path, "%s/lastlife.dat", dirarg); fil = fopen(path, "r"); if (fil) { + line[0]='\0'; fgets(line, sizeof line, fil); if (strcmp(line, LASTLOGTXT) == 0) { fgets(line, sizeof line, fil); t = atol(line); if (t < 1000000000) { - printf("bad lastLife %ld\n", (long)t); + printf("bad lastLife %ld\n", (long) t); } } fclose(fil); @@ -82,23 +92,26 @@ time_t LoggerGetLastLife(char *dirarg) { } /*--------------------------------------------------------------------------*/ -time_t LoggerSetDir(char *dirarg) { +time_t LoggerSetDir(char *dirarg) +{ dir = dirarg; lastLife = LoggerGetLastLife(dir); return lastLife; } + /*--------------------------------------------------------------------------*/ -char *LoggerGetDir(void) { +char *LoggerGetDir(void) +{ char path[256]; FILE *fil; static time_t last; lastWritten = time(NULL); - if (lastWritten != last) { /* do not write more than once per second */ + if (lastWritten != last) { /* do not write more than once per second */ snprintf(path, sizeof path, "%s/lastlife.dat", dir); fil = fopen(path, "w"); if (fil) { - fprintf(fil, "%s%ld\n", LASTLOGTXT, (long)lastWritten); + fprintf(fil, "%s%ld\n", LASTLOGTXT, (long) lastWritten); fclose(fil); } else { printf("can not write %s\n", path); @@ -107,35 +120,44 @@ char *LoggerGetDir(void) { } return dir; } + /*--------------------------------------------------------------------------*/ -int LoggerVarPath(char *dir, char *path, int pathLen, char *name, struct tm *t) { +int LoggerVarPath(char *dir, char *path, int pathLen, char *name, + struct tm *t) +{ int l; - + l = strlen(dir); if (l + strlen(name) + 8 >= pathLen) { - path[0]='\0'; + path[0] = '\0'; return 0; } strcpy(path, dir); strftime(path + l, pathLen - l, "/%Y/", t); l += 6; - for (;*name != '\0'; name++, l++) { + for (; *name != '\0'; name++, l++) { path[l] = tolower(*name); } - path[l] = '/'; l++; + path[l] = '/'; + l++; path[l] = '\0'; return l; } + /*--------------------------------------------------------------------------*/ -int LoggerWrite0(Logger *log, time_t now, int period, char *value) { +int LoggerWrite0(Logger * log, time_t now, int period, char *value) +{ char path[256], stim[32], buf[32]; struct tm tm, lasttm; int l, ext, writeInfo; FILE *fil; time_t beforenow; - + + if (log->name[0] == '\0') + return 0; LoggerGetDir(); - if (dir == NULL) return 0; + if (dir == NULL) + return 0; if (now == 0) { printf("now==0\n"); } @@ -146,35 +168,41 @@ int LoggerWrite0(Logger *log, time_t now, int period, char *value) { strftime(path + l, sizeof path - l, "%m-%d.log", &tm); strftime(stim, sizeof stim, "#%Y-%m-%d %H:%M:%S", &tm); - if (period <= 0) period = 1; + if (period <= 0) + period = 1; writeInfo = (tm.tm_isdst != lasttm.tm_isdst || tm.tm_yday != lasttm.tm_yday || (period != log->period && log->numeric)); if (strcmp(value, log->old) != 0 || writeInfo) { - + fil = fopen(path, "r+"); - if (fil == NULL) { /* create new file */ + if (fil == NULL) { /* create new file */ fil = fopen(path, "w+"); - if (fil == NULL) return 0; - fprintf(fil, "%s isdst %d period %d exact %d\n", stim, tm.tm_isdst, period, log->exact); - } else { /* check if file is from today */ + if (fil == NULL) + return 0; + fprintf(fil, "%s isdst %d period %d exact %d\n", stim, tm.tm_isdst, + period, log->exact); + } else { /* check if file is from today */ fgets(buf, sizeof buf, fil); if (0 != strncmp(buf, stim, 11)) { - fclose(fil); /* it was file from an earlier year */ - fil=fopen(path, "w+"); /* overwrite old logfile */ - if (fil == NULL) return 0; - fprintf(fil, "%s isdst %d period %d exact %d\n", stim, tm.tm_isdst, period, log->exact); + fclose(fil); /* it was file from an earlier year */ + fil = fopen(path, "w+"); /* overwrite old logfile */ + if (fil == NULL) + return 0; + fprintf(fil, "%s isdst %d period %d exact %d\n", stim, tm.tm_isdst, + period, log->exact); } else { - fseek(fil, 0, SEEK_END); /* set position to end */ + fseek(fil, 0, SEEK_END); /* set position to end */ if (writeInfo) { - fprintf(fil, "#isdst %d period %d exact %d\n", tm.tm_isdst, period, log->exact); + fprintf(fil, "#isdst %d period %d exact %d\n", tm.tm_isdst, + period, log->exact); } if (log->lastWrite != 0 && now >= log->lastWrite + 2 * period) { /* this is only useful for direct access of the log files */ beforenow = now - period; lasttm = *localtime(&beforenow); if (lasttm.tm_yday == tm.tm_yday) { - strftime(stim, sizeof stim,"%H:%M:%S", &lasttm); + strftime(stim, sizeof stim, "%H:%M:%S", &lasttm); } else { snprintf(stim, sizeof stim, "00:00:00"); } @@ -182,43 +210,52 @@ int LoggerWrite0(Logger *log, time_t now, int period, char *value) { } } } - strftime(stim, sizeof stim,"%H:%M:%S", &tm); + strftime(stim, sizeof stim, "%H:%M:%S", &tm); fprintf(fil, "%s\t%s\n", stim, value); log->lastWrite = now; fclose(fil); - + } log->period = period; l = strlen(value); - if (l >= log->oldsize) { /* increase log->old size, optimized for linux/i386 */ - ext = ((l - log->oldsize)/16 + 1) * 16; - if (ext < log->oldsize / 4) ext += (log->oldsize / 64) * 16; + if (l >= log->oldsize) { /* increase log->old size, optimized for linux/i386 */ + ext = ((l - log->oldsize) / 16 + 1) * 16; + if (ext < log->oldsize / 4) + ext += (log->oldsize / 64) * 16; log->oldsize += ext; free(log->old); log->old = calloc(1, log->oldsize); } assert(log->old); assert(l < log->oldsize); - strcpy(log->old, value); + if (log->old != value) { + strcpy(log->old, value); + } assert(log->old[l] == '\0'); log->last = now; return 1; } + /*--------------------------------------------------------------------------*/ -int LoggerWrite(Logger *log, time_t now, int period, char *value) { +int LoggerWrite(Logger * log, time_t now, int period, char *value) +{ Logger *p; time_t h0; static int yday = -1; struct tm *tm; + char *valp; + char buf[32]; int l; FILE *fil; char path[256]; char tim[256]; + if (log->name[0] == '\0') + return 0; tm = localtime(&now); - if (tm->tm_yday != yday) { + if (tm->tm_yday != yday) { /* new day */ tm->tm_hour = 0; tm->tm_min = 0; tm->tm_sec = 0; @@ -229,7 +266,7 @@ int LoggerWrite(Logger *log, time_t now, int period, char *value) { /* -- debug logging if dir/debug exists */ l = LoggerVarPath(dir, path, sizeof path, "debug", tm); strftime(path + l, sizeof path - l, "%m-%d.log", tm); - fil=fopen(path, "a"); + fil = fopen(path, "a"); if (fil) { strftime(tim, sizeof tim, "h0 %m-%d %H:%M:%S\n", localtime(&h0)); fputs(tim, fil); @@ -238,99 +275,168 @@ int LoggerWrite(Logger *log, time_t now, int period, char *value) { /* log old values (forced midnight log) */ p = list; while (p != NULL) { - - if (fil) { /* debug logging */ - strftime(tim, sizeof tim, "last %m-%d %H:%M:%S, ", localtime(&p->last)); + + if (fil) { /* debug logging */ + strftime(tim, sizeof tim, "last %m-%d %H:%M:%S, ", + localtime(&p->last)); fputs(tim, fil); - fprintf(fil, "period %d, name %s, old %s\n", p->period, p->name, p->old); + fprintf(fil, "period %d, name %s, old %s\n", p->period, p->name, + p->old); } - + if (p->last < h0 && p->last != 0 && p->period >= 0 && p->old[0] != '\0') { LoggerWrite0(p, h0, p->period, p->old); } p = p->next; } - if (fil) fclose(fil); + if (fil) + fclose(fil); + } + if (now < log->last + log->period && strcmp(log->old, value) != 0) { + log->omitValue = strtod(value, &valp); + if (value != valp && valp[0] == '\0') { /* value was a plain number */ + log->omitTime = now; + return 1; + } + } else { + log->omitTime = 0; + } + if (now > omitCheck + 5) { /* check for omitted values only every 5 seconds */ + for (p = list; p != NULL; p = p->next) { + if (p->omitTime > 0 && now > p->omitTime + p->period) { + snprintf(buf, sizeof buf, "%.7g", p->omitValue); + LoggerWrite0(p, p->omitTime, p->period, buf); + p->omitTime = 0; + } + } + omitCheck = now; } return LoggerWrite0(log, now, period, value); } + /*--------------------------------------------------------------------------*/ -time_t LoggerLastTime(Logger *log) { +time_t LoggerLastTime(Logger * log) +{ if (log->last != 0 && log->period > 0) { return log->last; } return 0; } + /*--------------------------------------------------------------------------*/ -int LoggerPeriod(Logger *log) { +int LoggerPeriod(Logger * log) +{ return log->period; } + /*--------------------------------------------------------------------------*/ -void LoggerSetPeriod(Logger *log, int period) { - LoggerWrite0(log, time(NULL), period, log->old); +void LoggerChange(Logger * log, int period, char *newname) +{ + Logger *other; + time_t t; + + if (period < 0) { + period = log->period; + } + if (strcasecmp(newname, log->name) != 0) { + if (log->name[0] != '\0') { /* was not defunct */ + LoggerWrite0(log, time(NULL), log->period, log->old); + LoggerWrite0(log, time(NULL), log->period, ""); + } + + other = LoggerFind(newname); /* look if logger with new name already exists */ + if (other) { + /* make defunct */ + LoggerWrite0(other, time(NULL), other->period, other->old); + LoggerWrite0(other, time(NULL), other->period, ""); + other->name[0] = '\0'; + } + free(log->name); + log->name = strdup(newname); + t = time(NULL) - 1; + if (lastLife != 0 && lastLife + period < t) { + t = lastLife + period; + } + LoggerWrite(log, t, period, ""); /* value was undefined since last life of server */ + } else { + LoggerWrite0(log, time(NULL), period, log->old); + } + } + /*--------------------------------------------------------------------------*/ -void LoggerKill(Logger *log) { +void LoggerKill(Logger * log) +{ /* we do not really free the logger, it might be reused for the same variable later. We set the value to undefined */ - - if (list != NULL) { /* LoggerFreeAll not yet called */ + + if (list != NULL) { /* LoggerFreeAll not yet called */ LoggerWrite(log, time(NULL), 0, ""); } } + /*--------------------------------------------------------------------------*/ -static int LoggerMakeDir(char *path) { +static int LoggerMakeDir(char *path) +{ static char buffer[4096]; struct stat st; int i, lpath, l; char *slash; - + i = stat(path, &st); if (i >= 0) { - if (((st.st_mode >> 12) & 15) != 4) { /* exists, but is no directory */ + if (((st.st_mode >> 12) & 15) != 4) { /* exists, but is no directory */ return 0; } return 1; } - i = mkdir(path, S_IRWXU+S_IRGRP+S_IXGRP+S_IROTH+S_IXOTH); + i = mkdir(path, S_IRWXU + S_IRGRP + S_IXGRP + S_IROTH + S_IXOTH); if (i < 0) { - if (errno != ENOENT) return 0; /* mkdir failed */ + if (errno != ENOENT) + return 0; /* mkdir failed */ snprintf(buffer, sizeof buffer, "%s", path); lpath = strlen(buffer); do { slash = strrchr(buffer, '/'); - if (!slash) return 0; - *slash='\0'; - i = mkdir(buffer, S_IRWXU+S_IRGRP+S_IXGRP+S_IROTH+S_IXOTH); + if (!slash) + return 0; + *slash = '\0'; + i = mkdir(buffer, S_IRWXU + S_IRGRP + S_IXGRP + S_IROTH + S_IXOTH); } while (i < 0 && errno == ENOENT); l = strlen(buffer); - while (lname = strdup(name); if (log->name == NULL) { free(log); @@ -338,30 +444,36 @@ Logger *LoggerMake(char *name, int period, int exact) { } log->period = -1; log->exact = exact; - log->old = calloc(1,12); + log->old = calloc(1, 12); log->oldsize = 12; log->last = 0; log->lastWrite = 0; log->numeric = 1; log->next = list; list = log; - t = time(NULL) -1; + t = time(NULL) - 1; if (lastLife != 0 && lastLife + period < t) { t = lastLife + period; - } - LoggerWrite(log, t, period, ""); /* value was undefined since last life of server */ + } + LoggerWrite(log, t, period, ""); /* value was undefined since last life of server */ + } else { + LoggerWrite0(log, time(NULL), period, log->old); } return log; } + /*--------------------------------------------------------------------------*/ -void LoggerFreeAll(void) { +void LoggerFreeAll(void) +{ Logger *p, *next; - + p = list; while (p != NULL) { next = p->next; - if (p->name) free(p->name); - if (p->old) free(p->old); + if (p->name) + free(p->name); + if (p->old) + free(p->old); free(p); p = next; } diff --git a/logger.h b/logger.h index 276a5494..a8404c4e 100644 --- a/logger.h +++ b/logger.h @@ -13,17 +13,18 @@ Markus Zolliker, Sept 2004 typedef struct Logger Logger; Logger *LoggerMake(char *name, int period, int exact); -void LoggerKill(Logger *log); -int LoggerWrite(Logger *log, time_t now, int period, char *value); -char *LoggerName(Logger *log); -void LoggerSetNumeric(Logger *log, int numeric); +void LoggerKill(Logger * log); +int LoggerWrite(Logger * log, time_t now, int period, char *value); +char *LoggerName(Logger * log); +void LoggerSetNumeric(Logger * log, int numeric); time_t LoggerSetDir(char *dirarg); time_t LoggerGetLastLife(char *dirarg); -void LoggerWriteOld(Logger *log, time_t now); -time_t LoggerLastTime(Logger *log); -int LoggerPeriod(Logger *log); -void LoggerSetPeriod(Logger *log, int period); -int LoggerVarPath(char *dir, char *path, int pathLen, char *name, struct tm *t); +void LoggerWriteOld(Logger * log, time_t now); +time_t LoggerLastTime(Logger * log); +int LoggerPeriod(Logger * log); +void LoggerChange(Logger * log, int period, char *newname); +int LoggerVarPath(char *dir, char *path, int pathLen, char *name, + struct tm *t); void LoggerFreeAll(void); #endif diff --git a/logreader.c b/logreader.c index cfa8b618..f5cd6f03 100644 --- a/logreader.c +++ b/logreader.c @@ -26,10 +26,10 @@ typedef struct { int exact; CompType type; time_t step; - time_t tlim; /* 0: initial state */ - Point best; /* best point, to be written if tlim > 0 */ - Point written; /* last written point */ - Point last; /* last point */ + time_t tlim; /* 0: initial state */ + Point best; /* best point, to be written if tlim > 0 */ + Point written; /* last written point */ + Point last; /* last point */ char buf[LLEN]; int np; char *none; @@ -38,62 +38,105 @@ typedef struct { int omitEqual; } Compressor; -static char *dirs[MAX_DIRS] = {NULL}; -static int ndirs=0; +static char *dirs[MAX_DIRS] = { NULL }; +static int ndirs = 0; -static void InitCompressor(Compressor *c, SConnection *pCon, time_t step) { +static float decodeWithPrefix(char *text, int *ok) { + static char *prefixes = "yzafpnumkMGTPEZY"; + static float multiplier[] = { + 1e-24, 1e-21, 1e-18, 1e-15, 1e-12, 1e-9, 1e-6, 1e-3, + 1e3, 1e6, 1e9, 1e12, 1e15, 1e18, 1e21, 1e24}; + char *pos, *unit; + float result; + float eps; + + result = strtod(text, &unit); + if (unit == text) { + if (ok) { + *ok = 0; + } + return 0.0; + } + while (*unit == ' ') { + unit++; + } + if (unit[0] != '\0' && unit[1] > ' ') { + /* do not allow prefixes without unit (like "m" - might be meter instead of milli) */ + pos = strchr(prefixes, *unit); + if (pos != NULL) { + result *= multiplier[pos-prefixes]; + } + } + if (ok) { + *ok = 1; + } + return result; +} + +static void InitCompressor(Compressor * c, SConnection * pCon, time_t step) +{ c->pCon = pCon; c->step = step; c->tlim = 0; c->last.y = LOGGER_NAN; c->last.t = 0; - c->buf[0]='\0'; + c->buf[0] = '\0'; c->written.t = 0; c->written.y = LOGGER_NAN; c->omitEqual = 1; } -static void OutFloat(Compressor *c, Point p) { +static void OutFloat(Compressor * c, Point p) +{ char *value; - + if (p.y == LOGGER_NAN) { - if (c->omitEqual && c->written.y == LOGGER_NAN) return; + if (c->omitEqual && c->written.y == LOGGER_NAN) + return; if (c->none) { value = c->none; } else { value = ""; } } else { - if (c->omitEqual && c->written.y == p.y) return; - snprintf(c->buf, sizeof(c->buf), "%g", p.y); + if (c->omitEqual && c->written.y == p.y) + return; + snprintf(c->buf, sizeof(c->buf), "%.7g", p.y); value = c->buf; } - SCPrintf(c->pCon, eWarning, "%ld %s", (long)(p.t - c->written.t), value); + SCPrintf(c->pCon, eWarning, "%ld %s", (long) (p.t - c->written.t), + value); c->written = p; c->np--; } -static void WriteHeader(Compressor *c) { +static void WriteHeader(Compressor * c) +{ if (c->header) { SCPrintf(c->pCon, eWarning, "*%s period %ld\n", c->header, c->period); c->header = NULL; } } -static void PutValue(Compressor *c, time_t t, char *value) { +static void PutValue(Compressor * c, time_t t, char *value) +{ char *p; Point new; + char unitPrefix; + int ok; WriteHeader(c); if (c->type == NUMERIC) { - new.y = strtod(value, &p); - if (p == value) { - new.y = LOGGER_NAN; + new.y = decodeWithPrefix(value, &ok); + if (ok) { + if (new.y == LOGGER_NAN) { + new.y *= 1.0000002; + } } else { - if (new.y == LOGGER_NAN) new.y *= 1.0000002; + new.y = LOGGER_NAN; } new.t = t; - if (t >= c->tlim) { /* a new interval starts */ + if (t >= c->tlim) { /* a new interval starts */ if (c->tlim == 0) { c->tlim = t; } else if (c->best.y != c->written.y) { @@ -107,47 +150,52 @@ static void PutValue(Compressor *c, time_t t, char *value) { } c->tlim = t + c->step; } - } else { /* not the first point */ + } else { /* not the first point */ if (fabs(new.y - c->best.y) > fabs(c->written.y - c->best.y)) { c->best = new; } } c->last = new; } else if (c->type == TEXT) { - if (0 != strncmp(value, c->buf, sizeof(c->buf)-1)) { + if (0 != strncmp(value, c->buf, sizeof(c->buf) - 1)) { snprintf(c->buf, sizeof(c->buf), "%s", value); - SCPrintf(c->pCon, eWarning, "%ld %s\n", (long)(t - c->written.t), value); + SCPrintf(c->pCon, eWarning, "%ld %s\n", (long) (t - c->written.t), + value); c->written.t = t; c->np--; } } } -static void PutFinish(Compressor *c, time_t now) { +static void PutFinish(Compressor * c, time_t now) +{ char value[32]; - - if (c->tlim != 0) { /* there is data already */ + + if (c->tlim != 0) { /* there is data already */ c->omitEqual = 0; if (c->type == NUMERIC) { - if (now > c->last.t + c->period) { /* copy last value to the actual time */ + if (now > c->last.t + c->period) { /* copy last value to the actual time */ if (c->last.y != LOGGER_NAN) { - snprintf(value, sizeof value, "%g", c->last.y); + snprintf(value, sizeof value, "%.7g", c->last.y); PutValue(c, now, value); } if (c->best.t > c->written.t) { OutFloat(c, c->best); /* write last buffered value */ } } - } if (now > c->last.t) { + } + if (now > c->last.t) { PutValue(c, now, c->buf); } } } + /*--------------------------------------------------------------------------*/ -static long getOpt(char *line, int *isdst, int *exact) { +static long getOpt(char *line, int *isdst, int *exact) +{ long lxs; char *opt; - + opt = strstr(line, "isdst"); if (opt) { sscanf(opt, "isdst %d", isdst); @@ -164,67 +212,69 @@ static long getOpt(char *line, int *isdst, int *exact) { return -1; } } + /*--------------------------------------------------------------------------*/ -static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) { +static int LogReader(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ /* Usage: - graph [ none ] np [ ...] - graph text - graph [ ...] - - and are seconds since epoch (unix time) or, if the value - is below one day, a time relative to the actual time - - The is optional. if not given, unknown values are returned as empty strings - - is the maximal number of points to be returned. If more values - are present and the values are numeric, the data is reduced. If the data is not - numeric, the last values may be skipped in order to avoid overflow. - - is the name of a variable (several vaiables may be given). - Note that slashes are converted to dots, and that the first slash is ignored. - - The seconds variant is for text values, which can not be reduced. In any case, all values - are returned. - - The third variant is old style and can be replaced by the first variant, where - = ( - ) / + 2 - - + graph [ none ] np [ ...] + graph text + graph [ ...] + + and are seconds since epoch (unix time) or, if the value + is below one day, a time relative to the actual time + + The is optional. if not given, unknown values are returned as empty strings + + is the maximal number of points to be returned. If more values + are present and the values are numeric, the data is reduced. If the data is not + numeric, the last values may be skipped in order to avoid overflow. + + is the name of a variable (several vaiables may be given). + Note that slashes are converted to dots, and that the first slash is ignored. + + The seconds variant is for text values, which can not be reduced. In any case, all values + are returned. + + The third variant is old style and can be replaced by the first variant, where + = ( - ) / + 2 + + Output format: - First line: returning the actual time on the server (this time is used for relative times) - - For each variable which has data in the given interval, - the variable name is returned preceeded by a '*', followed by some infos* separated with - blanks. - After the header line for every data point a line follows with - a time relative to the last point and the value. - The first time value relative to zero, e.g. absolute. - The data value is valid until the next datapoint. Empty values are returned as an - empty string or as the . - - At the very end * is returned. - is 1, when the data had to be reduced, 0 else - is 1, when overflow occured, 0 else. Overflow may happen only - when np is given and a text variable was demanded. - - *actually only one info exists: period . This is the update rate in seconds. - As equal values are not transmitted, two points (t1,y1) and (t2,y2) with a distance - (t2 - t1) > period should not be connected directly. The plot software should generate - an intermediate point at (t2-period,y1). - - */ + First line: returning the actual time on the server (this time is used for relative times) + + For each variable which has data in the given interval, + the variable name is returned preceeded by a '*', followed by some infos* separated with + blanks. + After the header line for every data point a line follows with + a time relative to the last point and the value. + The first time value relative to zero, e.g. absolute. + The data value is valid until the next datapoint. Empty values are returned as an + empty string or as the . + + At the very end * is returned. + is 1, when the data had to be reduced, 0 else + is 1, when overflow occured, 0 else. Overflow may happen only + when np is given and a text variable was demanded. + + *actually only one info exists: period . This is the update rate in seconds. + As equal values are not transmitted, two points (t1,y1) and (t2,y2) with a distance + (t2 - t1) > period should not be connected directly. The plot software should generate + an intermediate point at (t2-period,y1). + + */ time_t from, to, step, xs, lastt; char *p, *varp; int i, j, iarg, pathLen, iret, loss, np; int inRange; - int yday=0; + int yday = 0; time_t t, startim; struct tm tm; char stim[32], path[LLEN], line[LLEN], lastval[LLEN]; char *lin, *val, *stp; FILE *fil; - Compressor c={0}; + Compressor c = { 0 }; float yy, lasty; CompType type0; DIR *dr; @@ -237,15 +287,21 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData, char *dirPath; int idir; char *colon; - + +static Statistics *stat; +Statistics *old; + /* argtolower(argc, argv); */ - if (argc < 4) goto illarg; + if (argc < 4) + goto illarg; now = time(NULL); - from = strtol(argv[1], &p, 0); /* unix time, not year 2038 safe */ - if (p == argv[1]) goto illarg; + from = strtol(argv[1], &p, 0); /* unix time, not year 2038 safe */ + if (p == argv[1]) + goto illarg; to = strtol(argv[2], &p, 0); - if (p == argv[2]) goto illarg; - if (from < ONE_YEAR) { + if (p == argv[2]) + goto illarg; + if (from < ONE_YEAR) { from += now; } if (to < ONE_YEAR) { @@ -253,24 +309,28 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData, } iarg = 3; while (1) { - if (iarg>=argc) goto illarg; - if (strcasecmp(argv[iarg],"text") == 0) { /* non-numeric values */ + if (iarg >= argc) + goto illarg; + if (strcasecmp(argv[iarg], "text") == 0) { /* non-numeric values */ iarg++; step = 1; type0 = TEXT; np = to - from + 2; break; - } else if (strcasecmp(argv[iarg],"none") == 0) { /* none */ + } else if (strcasecmp(argv[iarg], "none") == 0) { /* none */ iarg++; - if (iarg >= argc) goto illarg; + if (iarg >= argc) + goto illarg; c.none = argv[iarg]; iarg++; - } else if (strcasecmp(argv[iarg],"np") == 0) { /* max. number of points */ + } else if (strcasecmp(argv[iarg], "np") == 0) { /* max. number of points */ iarg++; - if (iarg >= argc) goto illarg; + if (iarg >= argc) + goto illarg; type0 = NUMERIC; np = strtol(argv[iarg], &p, 0); - if (p == argv[iarg]) goto illarg; + if (p == argv[iarg]) + goto illarg; iarg++; if (to <= from) { step = 1; @@ -282,26 +342,32 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData, break; } else { step = strtol(argv[iarg], &p, 0); - if (p == argv[iarg]) goto illarg; + if (p == argv[iarg]) + goto illarg; iarg++; - if (step <= 0) step = 1; + if (step <= 0) + step = 1; type0 = NUMERIC; np = (from - to) / step + 2; } } - if (step <= 0) step = 1; - - snprintf(line, sizeof line, "%ld\n", (long)now); + if (step <= 0) + step = 1; + + snprintf(line, sizeof line, "%ld\n", (long) now); SCWrite(pCon, line, eWarning); dirPath = IFindOption(pSICSOptions, "LogReaderPath"); - if (dirPath == NULL) { /* for compatibility, check */ + if (dirPath == NULL) { /* for compatibility, check */ dirs[0] = IFindOption(pSICSOptions, "LoggerDir"); if (dirs[0] == NULL) { SCWrite(pCon, "ERROR: LoggerPath not found", eError); return 0; } nows[0] = LoggerGetLastLife(NULL); + if (nows[0] == 0) { + nows[0] = LoggerGetLastLife(dirs[0]); + } if (dirs[1] == NULL) { dirs[1] = IFindOption(pSICSOptions, "LoggerDir2"); nows[1] = LoggerGetLastLife(dirs[1]); @@ -316,7 +382,10 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData, *colon = '\0'; } if (ndirs == 0) { - nows[0] = LoggerGetLastLife(NULL); + nows[0] = LoggerGetLastLife(NULL); /* get from internal variable instead of file */ + if (nows[0] == 0) { // internal value not available + nows[0] = LoggerGetLastLife(dirPath); + } } else { nows[ndirs] = LoggerGetLastLife(dirPath); } @@ -327,22 +396,27 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData, dirPath = colon + 1; } } - + loss = 0; overflow = 0; - for (i=iarg; i= 0) { @@ -425,10 +502,14 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData, xs = step; } } - lin[0]='\0'; + lin[0] = '\0'; } else { - p = strchr(line, '\n'); if (p) *p='\0'; - p = strchr(line, '#'); if (p) *p='\0'; + p = strchr(line, '\n'); + if (p) + *p = '\0'; + p = strchr(line, '#'); + if (p) + *p = '\0'; } } while (lin[0] == '\0'); } @@ -436,15 +517,15 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData, /* printf(" %s\n", line); */ p = strchr(line, '\t'); if (p) { - *p='\0'; - val = p+1; + *p = '\0'; + val = p + 1; } else { val = ""; } p = strchr(val, '\t'); if (p) { - stp = p+1; - *p='\0'; + stp = p + 1; + *p = '\0'; iret = sscanf(stp, "%ld", &c.period); if (iret == 1) { if (c.period == 0) { @@ -459,19 +540,20 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData, } } } - iret = sscanf(line, "%d:%d:%d", &tm.tm_hour, &tm.tm_min, &tm.tm_sec); + iret = + sscanf(line, "%d:%d:%d", &tm.tm_hour, &tm.tm_min, &tm.tm_sec); if (iret != 3) { lin = NULL; } else { tm.tm_isdst = isdst; - t=mktime(&tm); + t = mktime(&tm); if (!inRange) { if (t < startim) { - lastval[0]='\0'; + lastval[0] = '\0'; strncat(lastval, val, sizeof lastval - 1); lastt = t; } else { - inRange=1; + inRange = 1; if (lastt != 0) { PutValue(&c, lastt, lastval); } @@ -483,11 +565,11 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData, } } if (lin == NULL) { - tm.tm_hour = 24; /* try next day */ + tm.tm_hour = 24; /* try next day */ tm.tm_min = 0; tm.tm_sec = 0; tm.tm_isdst = -1; - startim=mktime(&tm); + startim = mktime(&tm); continue; } } @@ -496,13 +578,15 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData, PutValue(&c, lastt, lastval); } } - WriteHeader(&c); /* write header, if not already done */ + WriteHeader(&c); /* write header, if not already done */ PutFinish(&c, nowi); if (fil) { fclose(fil); fil = NULL; } - if (c.np < 0) overflow = 1; + if (c.np < 0) + overflow = 1; +StatisticsEnd(old); } snprintf(line, sizeof line, "*%d %d\n", loss, overflow); SCWrite(pCon, line, eWarning); @@ -511,14 +595,18 @@ illarg: SCWrite(pCon, "illegal argument(s)", eError); return 0; } + /*--------------------------------------------------------------------------*/ -static void KillLogReader(void *data) { +static void KillLogReader(void *data) +{ Logger *p, *next; - + KillDummy(data); LoggerFreeAll(); } + /*--------------------------------------------------------------------------*/ -void LogReaderInit(void) { - AddCommand(pServ->pSics,"Graph",LogReader,KillLogReader,NULL); +void LogReaderInit(void) +{ + AddCommand(pServ->pSics, "Graph", LogReader, KillLogReader, NULL); } diff --git a/logsetup.c b/logsetup.c index 46059917..a8394b97 100644 --- a/logsetup.c +++ b/logsetup.c @@ -5,13 +5,16 @@ static char *loggerID = "loggerID"; static hdbCallbackReturn LoggerUpdateCallback(pHdb node, - void *userData, pHdbMessage message) { + void *userData, + pHdbMessage message) +{ Logger *logger = userData; pDynString str; SConnection *conn = NULL; hdbValue value; pHdbDataMessage mm = NULL; pHdbDataSearch dsm = NULL; + time_t now; if ((dsm = GetHdbDataSearchMessage(message)) != NULL) { if (dsm->testPtr == loggerID) { @@ -20,32 +23,42 @@ static hdbCallbackReturn LoggerUpdateCallback(pHdb node, } return hdbContinue; } - - if((mm = GetHdbUpdateMessage(message)) == NULL){ + + if ((mm = GetHdbUpdateMessage(message)) == NULL) { return hdbContinue; } - + value = *(mm->v); - - str = formatValue(value, node); - LoggerWrite(logger, time(NULL), LoggerPeriod(logger), GetCharArray(str)); - DeleteDynString(str); + + time(&now); + if (now > LoggerLastTime(logger)) { /* never write more than once per second */ + if (GetHdbProp(node, "geterror") == NULL) { + str = formatValue(value, node); + LoggerWrite(logger, time(NULL), LoggerPeriod(logger), GetCharArray(str)); + DeleteDynString(str); + } else { + LoggerWrite(logger, time(NULL), LoggerPeriod(logger), ""); + } + } return hdbContinue; } -static int LogSetup(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) { +static int LogSetup(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ pHdb node; pHdbCallback cb; - static char basepath[1024]="/"; + static char basepath[1024] = "/"; char buf[1024]; char *p, *name; - static char *loggerDir=NULL; + static char *loggerDir = NULL; int numeric, period; Logger *logger; - + if (argc < 2) { - SCPrintf(pCon, eError, "ERROR: should be: logsetup [ []]"); + SCPrintf(pCon, eError, + "ERROR: should be: logsetup [ []]"); + /* or logsetup clear */ return 0; } if (strcasecmp(argv[1], "basepath") == 0) { @@ -57,7 +70,8 @@ static int LogSetup(SConnection *pCon, SicsInterp *pSics, void *pData, } if (loggerDir == NULL) { loggerDir = IFindOption(pSICSOptions, "LoggerDir"); - if (loggerDir == NULL) loggerDir="./"; + if (loggerDir == NULL) + loggerDir = "./"; LoggerSetDir(loggerDir); } if (strcasecmp(argv[1], "directory") == 0) { @@ -72,20 +86,17 @@ static int LogSetup(SConnection *pCon, SicsInterp *pSics, void *pData, SCPrintf(pCon, eError, "ERROR: %s not found", argv[1]); return 0; } - period = 0; - if (argc > 2) { - period = atoi(argv[2]); - } if (argc > 3) { snprintf(buf, sizeof buf, "%s", argv[3]); } else { snprintf(buf, sizeof buf, "%s", argv[1]); } for (p = buf; *p != '\0'; p++) { - if (*p =='/') *p = '.'; + if (*p == '/') + *p = '.'; } if (buf[0] == '.') { - name = buf+1; + name = buf + 1; } else { name = buf; } @@ -95,19 +106,30 @@ static int LogSetup(SConnection *pCon, SicsInterp *pSics, void *pData, numeric = 0; } logger = FindHdbCallbackData(node, loggerID); - if (logger != 0) { /* logger exists already, changed only period */ - LoggerSetPeriod(logger, period); + period = 0; + if (argc > 2) { + if (logger != NULL && strcasecmp(argv[2], "clear") == 0) { + LoggerWrite(logger, time(NULL), LoggerPeriod(logger), ""); + return 1; + } + period = atoi(argv[2]); + } + if (logger != 0) { /* logger exists already */ + LoggerChange(logger, period, name); } else { logger = LoggerMake(name, period, !numeric); LoggerSetNumeric(logger, numeric); - cb = MakeHipadabaCallback(LoggerUpdateCallback, logger, (void (*)(void *))LoggerKill); + SetHdbProperty(node, "logger_name", name); + cb = MakeHipadabaCallback(LoggerUpdateCallback, logger, + (void (*)(void *)) LoggerKill); assert(cb); AppendHipadabaCallback(node, cb); } - + return 1; } -void LogSetupInit(void) { - AddCmd("LogSetup",LogSetup); +void LogSetupInit(void) +{ + AddCmd("LogSetup", LogSetup); } diff --git a/lomax.c b/lomax.c index 57721a6a..5ca7999a 100644 --- a/lomax.c +++ b/lomax.c @@ -27,265 +27,253 @@ extern float nintf(float f); /*-------------------------------------------------------------------*/ -static int testBoundaries(int xsize, int ysize, int window, - int i, int j) +static int testBoundaries(int xsize, int ysize, int window, int i, int j) { int half; /* - if the window touches the data boundary the result is probably not - very useful. Discarding these cases early on also protects us - against data array overrun problems. - */ + if the window touches the data boundary the result is probably not + very useful. Discarding these cases early on also protects us + against data array overrun problems. + */ - half = window/2; + half = window / 2; - if( i - half < 0 || i + half > xsize) + if (i - half < 0 || i + half > xsize) return 0; - if( j - half < 0 || j + half > ysize) + if (j - half < 0 || j + half > ysize) return 0; return 1; } + /*-------------------------------------------------------------------*/ static int testSteepness(int *iData, int xsize, int ysize, - int i, int j, int window, int steepness) + int i, int j, int window, int steepness) { int testValue, x, y, half; int *iPtr; - + testValue = iData[j * xsize + i] - steepness; - half = window/2; + half = window / 2; /* - test upper row - */ + test upper row + */ iPtr = iData + (j - half) * xsize + i - half; - for(x = 0; x < window; x++) - { - if(iPtr[x] > testValue) + for (x = 0; x < window; x++) { + if (iPtr[x] > testValue) return 0; } /* - test lower row - */ + test lower row + */ iPtr = iData + (j + half) * xsize + i - half; - for(x = 0; x < window; x++) - { - if(iPtr[x] > testValue) + for (x = 0; x < window; x++) { + if (iPtr[x] > testValue) return 0; } /* - test columns - */ - for(y = j - half; y < j + half; y++) - { + test columns + */ + for (y = j - half; y < j + half; y++) { /* - left - */ - if(iData[y*xsize + i - half] > testValue) + left + */ + if (iData[y * xsize + i - half] > testValue) return 0; /* - right - */ - if(iData[y*xsize + i + half] > testValue) + right + */ + if (iData[y * xsize + i + half] > testValue) return 0; } - + return 1; } /*--------------------------------------------------------------------*/ -static int testMaximum(int *iData, int xsize, int ysize, - int i, int j, int window) +static int testMaximum(int *iData, int xsize, int ysize, + int i, int j, int window) { int testValue, x, y, half; int *iPtr; int equalCount = 0; testValue = iData[j * xsize + i]; - half = window/2; + half = window / 2; - for(y = j - half; y < j + half; y++) - { + for (y = j - half; y < j + half; y++) { iPtr = iData + y * xsize + i - half; - for(x = 0; x < window; x++) - { - if(iPtr[x] > testValue) - return 0; - if(iPtr[x] == testValue) - equalCount++; + for (x = 0; x < window; x++) { + if (iPtr[x] > testValue) + return 0; + if (iPtr[x] == testValue) + equalCount++; } } /* - if(equalCount > 3) - { - return 0; - } - */ + if(equalCount > 3) + { + return 0; + } + */ return 1; -} +} + /*--------------------------------------------------------------------*/ -int testLocalMaximum(int *iData, int xsize, int ysize, - int i, int j, - int window, int steepness, int threshold, +int testLocalMaximum(int *iData, int xsize, int ysize, + int i, int j, + int window, int steepness, int threshold, int *intensity) { - if(!testBoundaries(xsize,ysize,window,i,j)) + if (!testBoundaries(xsize, ysize, window, i, j)) return 0; - if(!testMaximum(iData,xsize,ysize,i,j,window)) + if (!testMaximum(iData, xsize, ysize, i, j, window)) return 0; - if(iData[j * xsize + i] < threshold) + if (iData[j * xsize + i] < threshold) return 0; - if(!testSteepness(iData,xsize,ysize,i,j,window, steepness)) + if (!testSteepness(iData, xsize, ysize, i, j, window, steepness)) return 0; *intensity = iData[j * xsize + i]; return 1; -} +} + /*-------------------------------------------------------------------*/ int calculateCOG(int *iData, int xsize, int ysize, - int *i, int *j, int *intensity,int *nCount, - int cogWindow, - float contour) + int *i, int *j, int *intensity, int *nCount, + int cogWindow, float contour) { int x, xLow, xMax, y, yLow, yMax; int threshold; float cogTotal, cogX, cogY; int *iPtr; - if(!testBoundaries(xsize,ysize,cogWindow,*i,*j)) + if (!testBoundaries(xsize, ysize, cogWindow, *i, *j)) return 0; /* - preparations - */ - xLow = *i - cogWindow/2; - if(xLow < 0) + preparations + */ + xLow = *i - cogWindow / 2; + if (xLow < 0) xLow = 0; - xMax = *i + cogWindow/2; - if(xLow >= xsize) - xMax = xsize-1; + xMax = *i + cogWindow / 2; + if (xLow >= xsize) + xMax = xsize - 1; - yLow = *j - cogWindow/2; - if(yLow < 0) + yLow = *j - cogWindow / 2; + if (yLow < 0) yLow = 0; - yMax = *j + cogWindow/2; - if(yLow >= ysize) - yMax = ysize-1; + yMax = *j + cogWindow / 2; + if (yLow >= ysize) + yMax = ysize - 1; - threshold = (int)(float)iData[*j * xsize + *i] * contour; + threshold = (int) (float) iData[*j * xsize + *i] * contour; /* - build the sums - */ + build the sums + */ *nCount = 0; cogTotal = cogY = cogX = .0; - for(y = yLow; y < yMax; y++) - { - iPtr = iData + y *xsize; - for(x = xLow; x < xMax; x++) - { - if(iPtr[x] > threshold) - { - *nCount++; - cogTotal += iPtr[x]; - cogY += y * iPtr[x]; + for (y = yLow; y < yMax; y++) { + iPtr = iData + y * xsize; + for (x = xLow; x < xMax; x++) { + if (iPtr[x] > threshold) { + (void)*nCount++; + cogTotal += iPtr[x]; + cogY += y * iPtr[x]; cogX += x * iPtr[x]; } } } - if(cogTotal <= .0) - { + if (cogTotal <= .0) { return 0; } - *i = (int)nintf(cogX/cogTotal); - *j = (int)nintf(cogY/cogTotal); - *intensity = (int)cogTotal; + *i = (int) nintf(cogX / cogTotal); + *j = (int) nintf(cogY / cogTotal); + *intensity = (int) cogTotal; return 1; } + /*-------------------------------------------------------------------*/ void calculateStatistics(int *iData, int xsize, int ysize, - float *average, float *maximum) + float *average, float *maximum) { int i, iLength; int max = -999999999; long sum = 0; - iLength = xsize*ysize; - for(i = 0; i < iLength; i++) - { + iLength = xsize * ysize; + for (i = 0; i < iLength; i++) { sum += iData[i]; - if(iData[i] > max) + if (iData[i] > max) max = iData[i]; } - *average = (float)sum/(float)iLength; - *maximum = (float)max; + *average = (float) sum / (float) iLength; + *maximum = (float) max; } + /*-------------------------------------------------------------------*/ int wellFormed(int *iData, int xsize, int ysize, - int i, int j, int window, float contour, - int maxBad) + int i, int j, int window, float contour, int maxBad) { int testValue, x, y, half; int *iPtr; - int badCount = 0; + int badCount = 0; - testValue = (int)((float)iData[j * xsize + i]*contour); - half = window/2; + testValue = (int) ((float) iData[j * xsize + i] * contour); + half = window / 2; /* - test upper row - */ + test upper row + */ iPtr = iData + (j - half) * xsize + i - half; - for(x = 0; x < window; x++) - { - if(iPtr[x] > testValue) + for (x = 0; x < window; x++) { + if (iPtr[x] > testValue) badCount++; } /* - test lower row - */ + test lower row + */ iPtr = iData + (j + half) * xsize + i - half; - for(x = 0; x < window; x++) - { - if(iPtr[x] > testValue) + for (x = 0; x < window; x++) { + if (iPtr[x] > testValue) badCount++; } /* - test columns - */ - for(y = j - half; y < j + half; y++) - { + test columns + */ + for (y = j - half; y < j + half; y++) { /* - left - */ - if(iData[y*xsize + i - half] > testValue) + left + */ + if (iData[y * xsize + i - half] > testValue) badCount++; /* - right - */ - if(iData[y*xsize + i + half] > testValue) + right + */ + if (iData[y * xsize + i + half] > testValue) badCount++; } - - if(badCount > maxBad) - { + + if (badCount > maxBad) { return 0; } @@ -293,49 +281,46 @@ int wellFormed(int *iData, int xsize, int ysize, } /*-------------------------------------------------------------------*/ -static int checkHM(pHistMem *pHM, SicsInterp *pSics, SConnection *pCon, +static int checkHM(pHistMem * pHM, SicsInterp * pSics, SConnection * pCon, char *name, int *iDim) { - CommandList *pCom = NULL; - char pBueffel[256]; - int nDim; + CommandList *pCom = NULL; + char pBueffel[256]; + int nDim; - pCom = FindCommand(pSics, name); - if(!pCom) - { - sprintf(pBueffel,"ERROR: histogram memory %s not found", name); - SCWrite(pCon,pBueffel,eError); - return 0; - } - if(!pCom->pData) - { - sprintf(pBueffel,"ERROR: histogram memory %s not found", name); - SCWrite(pCon,pBueffel,eError); - return 0; - } - *pHM = (pHistMem)pCom->pData; - if(!iHasType(*pHM, "HistMem")) - { - sprintf(pBueffel,"ERROR: %s is no histogram memory!", name); - SCWrite(pCon,pBueffel,eError); - return 0; - } - /* - we now know that we have a histogram memory, now check Sizes - */ - GetHistDim(*pHM,iDim,&nDim); - if(nDim < 2) - { - sprintf(pBueffel,"ERROR: %s is not 2 dimensional!", name); - SCWrite(pCon,pBueffel,eError); - return 0; - } + pCom = FindCommand(pSics, name); + if (!pCom) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: histogram memory %s not found", name); + SCWrite(pCon, pBueffel, eError); + return 0; + } + if (!pCom->pData) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: histogram memory %s not found", name); + SCWrite(pCon, pBueffel, eError); + return 0; + } + *pHM = (pHistMem) pCom->pData; + if (!iHasType(*pHM, "HistMem")) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s is no histogram memory!", name); + SCWrite(pCon, pBueffel, eError); + return 0; + } + /* + we now know that we have a histogram memory, now check Sizes + */ + GetHistDim(*pHM, iDim, &nDim); + if (nDim < 2) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s is not 2 dimensional!", name); + SCWrite(pCon, pBueffel, eError); + return 0; + } - return 1; + return 1; } + /*--------------------------------------------------------------------*/ -int LoMaxAction(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]) +int LoMaxAction(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]) { pLoMax self = NULL; char pBueffel[256], pNum[20]; @@ -347,285 +332,250 @@ int LoMaxAction(SConnection *pCon, SicsInterp *pSics, int window; int *iData; double dVal; - ObPar *ob = NULL; + ObPar *ob = NULL; float average, maximum; - self = (pLoMax)pData; + self = (pLoMax) pData; assert(pCon); assert(pSics); assert(self); /* - we need arguments - */ - if(argc < 2) - { - sprintf(pBueffel,"ERROR: insufficient number of arguments to %s", - argv[0]); - SCWrite(pCon,pBueffel,eError); + we need arguments + */ + if (argc < 2) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: insufficient number of arguments to %s", + argv[0]); + SCWrite(pCon, pBueffel, eError); return 0; } /* - interpret arguments - */ + interpret arguments + */ strtolower(argv[1]); - if(strcmp(argv[1],"search") == 0) - { - if(argc < 3) - { - sprintf(pBueffel,"ERROR: insufficient number of arguments to %s.search", - argv[0]); - SCWrite(pCon,pBueffel,eError); + if (strcmp(argv[1], "search") == 0) { + if (argc < 3) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: insufficient number of arguments to %s.search", + argv[0]); + SCWrite(pCon, pBueffel, eError); return 0; } - if(!checkHM(&pHM, pSics,pCon, argv[2],iDim)) - { + if (!checkHM(&pHM, pSics, pCon, argv[2], iDim)) { return 0; } Tcl_DStringInit(&result); - iData = GetHistogramPointer(pHM,pCon); - window = (int)ObVal(self->pParam,WINDOW); + iData = GetHistogramPointer(pHM, pCon); + window = (int) ObVal(self->pParam, WINDOW); count = 0; - for(i = 0 + window/2; i < iDim[0] - window/2; i++) - { - for(j = 0 + window/2; j < iDim[1] - window/2; j++) - { - if(testLocalMaximum(iData,iDim[0], iDim[1], - i,j, - (int)ObVal(self->pParam,WINDOW), - (int)ObVal(self->pParam,STEEPNESS), - (int)ObVal(self->pParam,THRESHOLD), - &intensity)) - { - if(count != 0) - { - Tcl_DStringAppend(&result,"@",strlen("@")); + for (i = 0 + window / 2; i < iDim[0] - window / 2; i++) { + for (j = 0 + window / 2; j < iDim[1] - window / 2; j++) { + if (testLocalMaximum(iData, iDim[0], iDim[1], + i, j, + (int) ObVal(self->pParam, WINDOW), + (int) ObVal(self->pParam, STEEPNESS), + (int) ObVal(self->pParam, THRESHOLD), + &intensity)) { + if (count != 0) { + Tcl_DStringAppend(&result, "@", strlen("@")); } - sprintf(pNum,"%d ", i); - Tcl_DStringAppend(&result,pNum,strlen(pNum)); - sprintf(pNum,"%d ", j); - Tcl_DStringAppend(&result,pNum,strlen(pNum)); - sprintf(pNum,"%d", intensity); - Tcl_DStringAppend(&result,pNum,strlen(pNum)); + snprintf(pNum,sizeof(pNum)-1, "%d ", i); + Tcl_DStringAppend(&result, pNum, strlen(pNum)); + snprintf(pNum,sizeof(pNum)-1, "%d ", j); + Tcl_DStringAppend(&result, pNum, strlen(pNum)); + snprintf(pNum,sizeof(pNum)-1, "%d", intensity); + Tcl_DStringAppend(&result, pNum, strlen(pNum)); count++; } - } + } } - SCWrite(pCon,Tcl_DStringValue(&result),eValue); + SCWrite(pCon, Tcl_DStringValue(&result), eValue); Tcl_DStringFree(&result); return 1; - } - else if(strcmp(argv[1],"cog") == 0) /* COG calculation */ - { - if(argc < 5) - { - sprintf(pBueffel,"ERROR: insufficient number of arguments to %s.cog", - argv[0]); - SCWrite(pCon,pBueffel,eError); + } else if (strcmp(argv[1], "cog") == 0) { /* COG calculation */ + if (argc < 5) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: insufficient number of arguments to %s.cog", + argv[0]); + SCWrite(pCon, pBueffel, eError); return 0; } - if(!checkHM(&pHM, pSics,pCon, argv[2],iDim)) - { + if (!checkHM(&pHM, pSics, pCon, argv[2], iDim)) { return 0; } - if(Tcl_GetInt(pSics->pTcl,argv[3],&i)!= TCL_OK) - { - sprintf(pBueffel,"ERROR: expected number, got %s",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; + if (Tcl_GetInt(pSics->pTcl, argv[3], &i) != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; } - if(Tcl_GetInt(pSics->pTcl,argv[4],&j)!= TCL_OK) - { - sprintf(pBueffel,"ERROR: expected number, got %s",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; + if (Tcl_GetInt(pSics->pTcl, argv[4], &j) != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; } Tcl_DStringInit(&result); - iData = GetHistogramPointer(pHM,pCon); - window = (int)ObVal(self->pParam,COGWINDOW); - iRet = calculateCOG(iData,iDim[0], iDim[1], &i, &j, &intensity,&count, - window, ObVal(self->pParam,COGCONTOUR)); - if(!iRet) - { - SCWrite(pCon,"ERROR: no intensity in data",eError); + iData = GetHistogramPointer(pHM, pCon); + window = (int) ObVal(self->pParam, COGWINDOW); + iRet = + calculateCOG(iData, iDim[0], iDim[1], &i, &j, &intensity, &count, + window, ObVal(self->pParam, COGCONTOUR)); + if (!iRet) { + SCWrite(pCon, "ERROR: no intensity in data", eError); return 0; } - sprintf(pNum,"%d ", i); - Tcl_DStringAppend(&result,pNum,strlen(pNum)); - sprintf(pNum,"%d ", j); - Tcl_DStringAppend(&result,pNum,strlen(pNum)); - sprintf(pNum,"%d ", intensity); - Tcl_DStringAppend(&result,pNum,strlen(pNum)); - sprintf(pNum,"%d ", count); - Tcl_DStringAppend(&result,pNum,strlen(pNum)); - SCWrite(pCon,Tcl_DStringValue(&result),eValue); + snprintf(pNum,sizeof(pNum)-1, "%d ", i); + Tcl_DStringAppend(&result, pNum, strlen(pNum)); + snprintf(pNum,sizeof(pNum)-1, "%d ", j); + Tcl_DStringAppend(&result, pNum, strlen(pNum)); + snprintf(pNum,sizeof(pNum)-1, "%d ", intensity); + Tcl_DStringAppend(&result, pNum, strlen(pNum)); + snprintf(pNum,sizeof(pNum)-1, "%d ", count); + Tcl_DStringAppend(&result, pNum, strlen(pNum)); + SCWrite(pCon, Tcl_DStringValue(&result), eValue); Tcl_DStringFree(&result); return 1; - } - else if(strcmp(argv[1],"wellformed") == 0) /* test for wellformedness */ - { - if(argc < 6) - { - sprintf(pBueffel, - "ERROR: insufficient number of arguments to %s.wellformed", - argv[0]); - SCWrite(pCon,pBueffel,eError); + } else if (strcmp(argv[1], "wellformed") == 0) { /* test for wellformedness */ + if (argc < 6) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: insufficient number of arguments to %s.wellformed", + argv[0]); + SCWrite(pCon, pBueffel, eError); return 0; } - if(!checkHM(&pHM, pSics,pCon, argv[2],iDim)) - { + if (!checkHM(&pHM, pSics, pCon, argv[2], iDim)) { return 0; } - if(Tcl_GetInt(pSics->pTcl,argv[3],&i)!= TCL_OK) - { - sprintf(pBueffel,"ERROR: expected number, got %s",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; + if (Tcl_GetInt(pSics->pTcl, argv[3], &i) != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; } - if(Tcl_GetInt(pSics->pTcl,argv[4],&j)!= TCL_OK) - { - sprintf(pBueffel,"ERROR: expected number, got %s",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; + if (Tcl_GetInt(pSics->pTcl, argv[4], &j) != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; } - if(Tcl_GetInt(pSics->pTcl,argv[5],&badMax)!= TCL_OK) - { - sprintf(pBueffel,"ERROR: expected number, got %s",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; + if (Tcl_GetInt(pSics->pTcl, argv[5], &badMax) != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; } - iData = GetHistogramPointer(pHM,pCon); - window = (int)ObVal(self->pParam,COGWINDOW); - iRet = wellFormed(iData,iDim[0], iDim[1], i, j, - window, ObVal(self->pParam,COGCONTOUR), - badMax); - sprintf(pBueffel,"%5d", iRet); - SCWrite(pCon,pBueffel,eValue); + iData = GetHistogramPointer(pHM, pCon); + window = (int) ObVal(self->pParam, COGWINDOW); + iRet = wellFormed(iData, iDim[0], iDim[1], i, j, + window, ObVal(self->pParam, COGCONTOUR), badMax); + snprintf(pBueffel,sizeof(pBueffel)-1, "%5d", iRet); + SCWrite(pCon, pBueffel, eValue); return 1; - } - else if(strcmp(argv[1],"stat") == 0) - { - if(argc < 3) - { - sprintf(pBueffel,"ERROR: insufficient number of arguments to %s.search", - argv[0]); - SCWrite(pCon,pBueffel,eError); + } else if (strcmp(argv[1], "stat") == 0) { + if (argc < 3) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: insufficient number of arguments to %s.search", + argv[0]); + SCWrite(pCon, pBueffel, eError); return 0; } - if(!checkHM(&pHM, pSics,pCon, argv[2],iDim)) - { + if (!checkHM(&pHM, pSics, pCon, argv[2], iDim)) { return 0; } - iData = GetHistogramPointer(pHM,pCon); - calculateStatistics(iData,iDim[0],iDim[1],&average,&maximum); - sprintf(pBueffel," %f %f", average, maximum); - SCWrite(pCon,pBueffel,eValue); + iData = GetHistogramPointer(pHM, pCon); + calculateStatistics(iData, iDim[0], iDim[1], &average, &maximum); + snprintf(pBueffel,sizeof(pBueffel)-1, " %f %f", average, maximum); + SCWrite(pCon, pBueffel, eValue); return 1; - } - else - { + } else { /* we are handling one of the parameter commands */ - if(argc > 2) /* set case */ - { - if(Tcl_GetDouble(pSics->pTcl,argv[2],&dVal) != TCL_OK) - { - sprintf(pBueffel,"ERROR: expected number, got %s",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - return ObParSet(self->pParam,argv[0],argv[1],(float)dVal,pCon); - } - else /* read case */ - { - ob = ObParFind(self->pParam,argv[1]); - if(!ob) - { - sprintf(pBueffel,"ERROR: parameter %s not found or wrong command", - argv[1]); - SCWrite(pCon,pBueffel,eError); + if (argc > 2) { /* set case */ + if (Tcl_GetDouble(pSics->pTcl, argv[2], &dVal) != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[2]); + SCWrite(pCon, pBueffel, eError); return 0; } - sprintf(pBueffel,"%s.%s = %f",argv[0],argv[1],ob->fVal); - SCWrite(pCon,pBueffel,eError); + return ObParSet(self->pParam, argv[0], argv[1], (float) dVal, pCon); + } else { /* read case */ + + ob = ObParFind(self->pParam, argv[1]); + if (!ob) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: parameter %s not found or wrong command", + argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.%s = %f", argv[0], argv[1], ob->fVal); + SCWrite(pCon, pBueffel, eError); return 1; } } /* - not reached - */ + not reached + */ assert(0); return 0; } + /*-------------------------------------------------------------------*/ static void KillLoMax(void *pData) { - pLoMax self = (pLoMax)pData; - if(!self) + pLoMax self = (pLoMax) pData; + if (!self) return; - if(self->pDes) + if (self->pDes) DeleteDescriptor(self->pDes); - if(self->pParam) + if (self->pParam) ObParDelete(self->pParam); free(self); } + /*-------------------------------------------------------------------*/ -int LoMaxFactory(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]) +int LoMaxFactory(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]) { pLoMax pNew = NULL; - if(argc < 2) - { - SCWrite(pCon,"ERROR: Insufficient number of arguments to LoMaxfactory", - eError); - return 0; - } - - pNew = (pLoMax)malloc(sizeof(LoMax)); - if(!pNew) - { - SCWrite(pCon,"ERROR: out of memory creating local maximum searcher", + if (argc < 2) { + SCWrite(pCon, + "ERROR: Insufficient number of arguments to LoMaxfactory", eError); return 0; } - memset(pNew,0,sizeof(LoMax)); + + pNew = (pLoMax) malloc(sizeof(LoMax)); + if (!pNew) { + SCWrite(pCon, "ERROR: out of memory creating local maximum searcher", + eError); + return 0; + } + memset(pNew, 0, sizeof(LoMax)); /* - create Descriptor - */ + create Descriptor + */ pNew->pDes = CreateDescriptor("Local Maximum Detector"); - if(!pNew->pDes) - { + if (!pNew->pDes) { KillLoMax(pNew); - SCWrite(pCon,"ERROR: out of memory creating local maximum searcher", + SCWrite(pCon, "ERROR: out of memory creating local maximum searcher", eError); return 0; } /* - create and install parameters - */ + create and install parameters + */ pNew->pParam = ObParCreate(5); - if(!pNew->pParam) - { + if (!pNew->pParam) { KillLoMax(pNew); - SCWrite(pCon,"ERROR: out of memory creating local maximum searcher", + SCWrite(pCon, "ERROR: out of memory creating local maximum searcher", eError); return 0; } - ObParInit(pNew->pParam,WINDOW,"window",10,usUser); - ObParInit(pNew->pParam,THRESHOLD,"threshold",30,usUser); - ObParInit(pNew->pParam,STEEPNESS,"steepness",5,usUser); - ObParInit(pNew->pParam,COGWINDOW,"cogwindow",50,usUser); - ObParInit(pNew->pParam,COGCONTOUR,"cogcontour",.2,usUser); + ObParInit(pNew->pParam, WINDOW, "window", 10, usUser); + ObParInit(pNew->pParam, THRESHOLD, "threshold", 30, usUser); + ObParInit(pNew->pParam, STEEPNESS, "steepness", 5, usUser); + ObParInit(pNew->pParam, COGWINDOW, "cogwindow", 50, usUser); + ObParInit(pNew->pParam, COGCONTOUR, "cogcontour", .2, usUser); - return AddCommand(pSics, - argv[1], - LoMaxAction, - KillLoMax, - pNew); + return AddCommand(pSics, argv[1], LoMaxAction, KillLoMax, pNew); } - diff --git a/lomax.h b/lomax.h index 823a1b3a..43c3eba7 100644 --- a/lomax.h +++ b/lomax.h @@ -13,28 +13,26 @@ #define LOCALMAXIMUM #include "obpar.h" - typedef struct __LOMAX *pLoMax; +typedef struct __LOMAX *pLoMax; - int LoMaxAction(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]); +int LoMaxAction(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]); - int LoMaxFactory(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]); +int LoMaxFactory(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]); - int testLocalMaximum(int *iData, int xsize, int ysize, - int i, int j, - int window, int threshold, int steepness, - int *intensity); - int calculateCOG(int *iData, int xsize, int ysize, - int *i, int *j, int *intensity, int *count, - int cogWindow, - float contour); - void calculateStatistics(int *iData, int xsize, int ysize, - float *average, float *maximum); - int wellFormed(int *iData, int xsize, int ysize, - int x, int y, int window, float contour, - int maxBad); +int testLocalMaximum(int *iData, int xsize, int ysize, + int i, int j, + int window, int threshold, int steepness, + int *intensity); +int calculateCOG(int *iData, int xsize, int ysize, + int *i, int *j, int *intensity, int *count, + int cogWindow, float contour); +void calculateStatistics(int *iData, int xsize, int ysize, + float *average, float *maximum); +int wellFormed(int *iData, int xsize, int ysize, + int x, int y, int window, float contour, int maxBad); diff --git a/macro.c b/macro.c index 82ea66e7..b3a3e03a 100644 --- a/macro.c +++ b/macro.c @@ -71,6 +71,7 @@ #include "stringdict.h" #include "exeman.h" #include "nxcopy.h" +#include "commandlog.h" #define SICSERROR "005567SICS" /*---------------------------------------------------------------------------- @@ -86,517 +87,494 @@ #define MAXSTACK 50 - struct __SicsUnknown { - SConnection *pCon[MAXSTACK]; - char *lastUnknown[MAXSTACK]; - int iStack; - SicsInterp *pInter; - }; - - static struct __SicsUnknown *pUnbekannt = NULL; +struct __SicsUnknown { + SConnection *pCon[MAXSTACK]; + char *lastUnknown[MAXSTACK]; + int iStack; + SicsInterp *pInter; +}; + +static struct __SicsUnknown *pUnbekannt = NULL; /*---------------------------------------------------------------------------*/ - int MacroPush(SConnection *pCon) - { - assert(pUnbekannt); - pUnbekannt->iStack++; - if(pUnbekannt->iStack >= MAXSTACK) - { - SCWrite(pCon,"ERROR: Out of Stack in macro.c",eError); - return 0; - } - pUnbekannt->pCon[pUnbekannt->iStack] = pCon; - return 1; +int MacroPush(SConnection * pCon) +{ + assert(pUnbekannt); + pUnbekannt->iStack++; + if (pUnbekannt->iStack >= MAXSTACK) { + SCWrite(pCon, "ERROR: Out of Stack in macro.c", eError); + return 0; } -/*-------------------------------------------------------------------------*/ - int MacroPop(void) - { - assert(pUnbekannt); - pUnbekannt->iStack--; - if(pUnbekannt->iStack < 1) - { - pUnbekannt->iStack = 0; + pUnbekannt->pCon[pUnbekannt->iStack] = pCon; + return 1; +} + +/*-------------------------------------------------------------------------*/ +int MacroPop(void) +{ + assert(pUnbekannt); + pUnbekannt->iStack--; + if (pUnbekannt->iStack < 1) { + pUnbekannt->iStack = 0; + } + return 1; +} +/*---------------------------------------------------------------------------*/ +SConnection *MacroPeek(void) +{ + assert(pUnbekannt); + return pUnbekannt->pCon[pUnbekannt->iStack]; +} +/*---------------------------------------------------------------------------*/ +static int SicsUnknownProc(ClientData pData, Tcl_Interp * pInter, + int argc, char *argv[]) +{ + struct __SicsUnknown *pSics = NULL; + char **myarg = NULL; + int margc; + SicsInterp *pSinter = NULL; + SConnection *pCon = NULL; + CommandList *pCommand = NULL; + char *lastCommand = NULL, comBuffer[132]; + int iRet = 0, i; + int iMacro; + Statistics *old; + + /* get the datastructures */ + pSics = (struct __SicsUnknown *) pData; + assert(pSics); + + if(pSics->iStack >= MAXSTACK -1) { + Tcl_SetResult(pInter,"ERROR: cyclic call or to deep a nesting of SICSUnknown", + TCL_VOLATILE); + return 0; + } + pSinter = pSics->pInter; + pCon = pSics->pCon[pSics->iStack]; + lastCommand = pSics->lastUnknown[pSics->iStack]; + + assert(pSinter); + assert(pCon); + + + /* shorten the argc, argv by one and invoke */ + margc = argc - 1; + myarg = &argv[1]; + + /* find object */ + if (margc < 1) { + Tcl_SetResult(pInter, "No command found", TCL_VOLATILE); + return TCL_ERROR; + } + pCommand = FindCommand(pSinter, myarg[0]); + if (!pCommand) { + Tcl_AppendResult(pInter, "Object ", myarg[0], " not found", NULL); + return TCL_ERROR; + } + + /* check for endless loop */ + Arg2Text(margc, myarg, comBuffer, 131); + if (lastCommand != NULL) { + if (strcmp(lastCommand, comBuffer) == 0) { + Tcl_AppendResult(pInter, "ERROR: Never ending loop in unknown\n", + "Offending command: ", comBuffer, + " Probably Tcl command not found", NULL); + SCSetInterrupt(pCon, eAbortBatch); + return TCL_ERROR; } - return 1; } -/*---------------------------------------------------------------------------*/ - static int SicsUnknownProc(ClientData pData, Tcl_Interp *pInter, - int argc, char *argv[]) - { - struct __SicsUnknown *pSics = NULL; - char **myarg = NULL; - int margc; - SicsInterp *pSinter = NULL; - SConnection *pCon = NULL; - CommandList *pCommand = NULL; - char *lastCommand = NULL, comBuffer[132]; - int iRet = 0,i; - int iMacro; - Statistics *old; + if (pSics->lastUnknown[pSics->iStack]) + free(pSics->lastUnknown[pSics->iStack]); + pSics->lastUnknown[pSics->iStack] = strdup(comBuffer); - /* get the datastructures */ - pSics = (struct __SicsUnknown *)pData; - assert(pSics); - pSinter = pSics->pInter; - pCon = pSics->pCon[pSics->iStack]; - lastCommand = pSics->lastUnknown[pSics->iStack]; - pCon->sicsError = 0; + /* invoke */ + pCon->sicsError = 0; + iMacro = SCinMacro(pCon); + SCsetMacro(pCon, 1); + old = StatisticsBegin(pCommand->stat); + iRet = pCommand->OFunc(pCon, pSinter, pCommand->pData, margc, myarg); + StatisticsEnd(old); + SCsetMacro(pCon, iMacro); - assert(pSinter); - assert(pCon); - - - /* shorten the argc, argv by one and invoke */ - margc = argc -1; - myarg = &argv[1]; - - /* find object */ - if(margc < 1) - { - Tcl_SetResult(pInter,"No command found",TCL_VOLATILE); - return TCL_ERROR; - } - pCommand = FindCommand(pSinter,myarg[0]); - if(!pCommand) - { - Tcl_AppendResult(pInter,"Object ",myarg[0]," not found",NULL); - return TCL_ERROR; - } - - /* check for endless loop */ - Arg2Text(margc, myarg, comBuffer,131); - if(lastCommand != NULL) - { - if(strcmp(lastCommand,comBuffer) == 0) - { - Tcl_AppendResult(pInter,"ERROR: Never ending loop in unknown\n", - "Offending command: ",comBuffer, - " Probably Tcl command not found",NULL); - SCSetInterrupt(pCon,eAbortBatch); - return TCL_ERROR; - } - } - if (pSics->lastUnknown[pSics->iStack]) free(pSics->lastUnknown[pSics->iStack]); - pSics->lastUnknown[pSics->iStack] = strdup(comBuffer); - - /* invoke */ - iMacro = SCinMacro(pCon); - SCsetMacro(pCon,1); - old=StatisticsBegin(pCommand->stat); - iRet = pCommand->OFunc(pCon,pSinter,pCommand->pData,margc, myarg); - StatisticsEnd(old); - SCsetMacro(pCon,iMacro); - /* - lastUnkown gets deeply stacked with each SICS command exec'd. - This is not reflected in code. However, lastUnknown has already - done its job here, so it is safe to do it the way it is done - */ - if(pSics->lastUnknown[pSics->iStack] != NULL) - { - free(pSics->lastUnknown[pSics->iStack]); - pSics->lastUnknown[pSics->iStack] = NULL; - } - - /* finish */ - if(iRet == 1) - { - return TCL_OK; - } - else - { - Tcl_SetVar(pInter,SICSERROR,"yes",TCL_GLOBAL_ONLY); - pCon->sicsError = 1; - return TCL_ERROR; - } + /* + lastUnkown gets deeply stacked with each SICS command exec'd. + This is not reflected in code. However, lastUnknown has already + done its job here, so it is safe to do it the way it is done + */ + if (pSics->lastUnknown[pSics->iStack] != NULL) { + free(pSics->lastUnknown[pSics->iStack]); + pSics->lastUnknown[pSics->iStack] = NULL; } + + /* finish */ + if (iRet == 1) { + WriteCommandHistory(comBuffer); + return TCL_OK; + } else { + Tcl_SetVar(pInter, SICSERROR, "yes", TCL_GLOBAL_ONLY); + pCon->sicsError = 1; + return TCL_ERROR; + } +} + /*-----------------------------------------------------------------------*/ - static void UnknownKill(ClientData pData) - { - struct __SicsUnknown *pU = NULL; - - pU = (struct __SicsUnknown *)pData; - if(pU->pCon[0]) - { - SCDeleteConnection(pU->pCon[0]); - } - free(pData); - pUnbekannt = NULL; - } - /*-----------------------------------------------------------------------*/ - void KillSicsUnknown(void) { - if (pUnbekannt) { - UnknownKill(pUnbekannt); - pUnbekannt = NULL; - } +static void UnknownKill(ClientData pData) +{ + struct __SicsUnknown *pU = NULL; + + pU = (struct __SicsUnknown *) pData; + if (pU->pCon[0]) { + SCDeleteConnection(pU->pCon[0]); } + free(pData); + pUnbekannt = NULL; +} + + /*-----------------------------------------------------------------------*/ +void KillSicsUnknown(void) +{ + if (pUnbekannt) { + UnknownKill(pUnbekannt); + pUnbekannt = NULL; + } +} + /*------------------------------------------------------------------------ Implementation of a protected exec command --------------------------------------------------------------------------*/ static pStringDict allowedCommands = NULL; /*----------------------------------------------------------------------*/ -int AllowExec(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) +int AllowExec(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) { - if(argc < 2) - { - SCWrite(pCon,"ERROR: not enough arguments to allowexec",eError); + if (argc < 2) { + SCWrite(pCon, "ERROR: not enough arguments to allowexec", eError); return 0; } - if(!SCMatchRights(pCon,usInternal)) - { + if (!SCMatchRights(pCon, usInternal)) { return 0; } - if(allowedCommands == NULL) - { + if (allowedCommands == NULL) { allowedCommands = CreateStringDict(); - if(allowedCommands == NULL) - { + if (allowedCommands == NULL) { SCWrite(pCon, - "ERROR: not enough memory for list of allowed system commands", - eError); + "ERROR: not enough memory for list of allowed system commands", + eError); return 0; } } - StringDictAddPair(allowedCommands,argv[1],"Allowed!"); + StringDictAddPair(allowedCommands, argv[1], "Allowed!"); return 1; } + /*--------------------------------------------------------------------*/ static void KillExec(ClientData data) { - if(allowedCommands != NULL) - { - DeleteStringDict(allowedCommands); - allowedCommands = NULL; + if (allowedCommands != NULL) { + DeleteStringDict(allowedCommands); + allowedCommands = NULL; } } -/*------------------------------------------------------------------------ - This is in the Tcl sources -*/ -Tcl_CmdInfo cmd_info; + /*-----------------------------------------------------------------------*/ -static int ProtectedExec(ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *CONST objv[]) +/* static Tcl_ObjCmdProc oldExec = NULL; */ +static int (*oldExec)(ClientData clientData,Tcl_Interp *interp, + int objc,Tcl_Obj *const objv[] ) = NULL; +/*-----------------------------------------------------------------------*/ +static int ProtectedExec(ClientData clientData, Tcl_Interp * interp, + int objc, Tcl_Obj * CONST objv[]) { char *test = NULL; - if(objc < 2) - { - return (cmd_info.objProc) (cmd_info.objClientData, interp, objc, objv); + if (objc < 2) { + return oldExec(clientData, interp, objc, objv); } - test = Tcl_GetStringFromObj(objv[1],NULL); - if(allowedCommands != NULL) - { - if(StringDictExists(allowedCommands,test)) - { - return (cmd_info.objProc) (cmd_info.objClientData, interp, objc, objv); + test = Tcl_GetStringFromObj(objv[1], NULL); + if (allowedCommands != NULL) { + if (StringDictExists(allowedCommands, test)) { + return oldExec(clientData, interp, objc, objv); } } - + /* - if we are here, we are not allowed to invoke this command - */ - Tcl_AppendResult(interp,"System command NOT allowed!",NULL); + if we are here, we are not allowed to invoke this command + */ + Tcl_AppendResult(interp, "System command NOT allowed!", NULL); return TCL_ERROR; } + /*-------------------------------------------------------------------------- initialises a Tcl-Interpreter, installs SICS unknown mechanism and kills a few dangerous commands from the normal Tcl command set ----------------------------------------------------------------------------*/ -extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface */ +extern int Nxinter_SafeInit(Tcl_Interp * pTcl); /* from Swig NeXus Tcl interface */ - Tcl_Interp *MacroInit(SicsInterp *pSics) - { - Tcl_Interp *pInter = NULL; - struct __SicsUnknown *pUnknown = NULL; - char *pPtr = NULL; - char *pPtr2 = NULL; - FILE *fp = NULL; - char pBueffel[512]; - int iRet; - - assert(pSics); - - /* create interpreter and unknown */ - pInter = Tcl_CreateInterp(); - pUnknown = (struct __SicsUnknown *)malloc(sizeof(struct __SicsUnknown)); - if( (!pInter) || (!pUnknown) ) - { - return NULL; - } - - /* install unknown command */ - memset(pUnknown,0,sizeof(struct __SicsUnknown)); - pUnknown->pCon[0] = SCCreateDummyConnection(pSics); - pUnknown->iStack = 0; - pUnknown->pInter = pSics; - pUnbekannt = pUnknown; - /* the cast before SicsUnknwonProc is to avoid a warning - Tcl_CmdProc has a const char instead of char as argument M.Z. */ - Tcl_CreateCommand(pInter,"unknown",(Tcl_CmdProc *)SicsUnknownProc, - pUnknown, UnknownKill); +Tcl_Interp *MacroInit(SicsInterp * pSics) +{ + Tcl_Interp *pInter = NULL; + struct __SicsUnknown *pUnknown = NULL; + char *pPtr = NULL; + char *pPtr2 = NULL; + FILE *fp = NULL; + char pBueffel[512]; + int iRet; + Tcl_CmdInfo execInfo; - /* hide dangers */ - Tcl_HideCommand(pInter,"exit", "hidden_exit"); - Tcl_HideCommand(pInter,"socket", "hidden_socket"); - Tcl_HideCommand(pInter,"vwait", "hidden_vwait"); - { - int retval = Tcl_GetCommandInfo(pInter, "exec", &cmd_info); - assert (retval != 0); - } - Tcl_HideCommand(pInter,"exec", "hidden_exec"); + assert(pSics); - /* - install protected exec command - */ - Tcl_CreateObjCommand(pInter,"exec",ProtectedExec,NULL,KillExec); - - Nxinter_SafeInit(pInter); - NXcopy_Init(pInter); - - return pInter; + /* create interpreter and unknown */ + pInter = Tcl_CreateInterp(); + pUnknown = (struct __SicsUnknown *) malloc(sizeof(struct __SicsUnknown)); + if ((!pInter) || (!pUnknown)) { + return NULL; } + + /* install unknown command */ + memset(pUnknown, 0, sizeof(struct __SicsUnknown)); + pUnknown->pCon[0] = SCCreateDummyConnection(pSics); + pUnknown->iStack = 0; + pUnknown->pInter = pSics; + pUnbekannt = pUnknown; + /* the cast before SicsUnknwonProc is to avoid a warning + Tcl_CmdProc has a const char instead of char as argument M.Z. */ + Tcl_CreateCommand(pInter, "unknown", (Tcl_CmdProc *) SicsUnknownProc, + pUnknown, UnknownKill); + + /* delete dangers */ + Tcl_DeleteCommand(pInter, "exit"); + Tcl_DeleteCommand(pInter, "socket"); + Tcl_DeleteCommand(pInter, "vwait"); + Tcl_GetCommandInfo(pInter,"exec",&execInfo); + oldExec = execInfo.objProc; + Tcl_DeleteCommand(pInter, "exec"); + + /* + install protected exec command + */ + Tcl_CreateObjCommand(pInter, "exec", ProtectedExec, NULL, KillExec); + + Nxinter_SafeInit(pInter); + NXcopy_Init(pInter); + + return pInter; +} + /*--------------------------------------------------------------------------*/ - void MacroDelete(Tcl_Interp *pInter) - { - Tcl_DeleteInterp(pInter); - } +void MacroDelete(Tcl_Interp * pInter) +{ + Tcl_DeleteInterp(pInter); +} + /*------------------------------------------------------------------------- Find the first word of a command string */ - static void FirstWord(char *pSource, char *pTarget) - { - int i, iLength, iStart, iPos; - - iLength = strlen(pSource); +static void FirstWord(char *pSource, char *pTarget) +{ + int i, iLength, iStart, iPos; - /* find start */ - for(i = 0, iStart = 0; i < iLength; i++) - { - if(pSource[i] != ' ') - { - break; - } - else - { - iStart++; - } - } + iLength = strlen(pSource); - /* do a quick check */ - if(iStart >= iLength - 2) - { - pTarget[0] = '\0'; - return; - } - - /* do the copy */ - for(i = iStart, iPos = 0; i < iLength; i++) - { - if(pSource[i] != ' ') - { - pTarget[iPos] = pSource[i]; - iPos++; - } - else - { - pTarget[iPos] = '\0'; - return; - } - } - pTarget[iPos] = '\0'; - return; + /* find start */ + for (i = 0, iStart = 0; i < iLength; i++) { + if (pSource[i] != ' ') { + break; + } else { + iStart++; } + } + + /* do a quick check */ + if (iStart >= iLength - 2) { + pTarget[0] = '\0'; + return; + } + + /* do the copy */ + for (i = iStart, iPos = 0; i < iLength; i++) { + if (pSource[i] != ' ') { + pTarget[iPos] = pSource[i]; + iPos++; + } else { + pTarget[iPos] = '\0'; + return; + } + } + pTarget[iPos] = '\0'; + return; +} + /*-------------------------------------------------------------------------*/ - static char *pWhere = NULL; - static char *pFile = NULL; +static char *pWhere = NULL; +static char *pFile = NULL; - int MacroWhere(SConnection *pCon, SicsInterp *pInter, void *pData, - int argc, char *argv[]) - { - assert(pCon); +int MacroWhere(SConnection * pCon, SicsInterp * pInter, void *pData, + int argc, char *argv[]) +{ + assert(pCon); + + if (pWhere) { + SCWrite(pCon, pWhere, eValue); + } + return 1; +} - if(pWhere) - { - SCWrite(pCon,pWhere,eValue); - } - return 1; - } /*-------------------------------------------------------------------------*/ - void WhereKill(void *pData) - { +void WhereKill(void *pData) +{ - if(pWhere) - { - free(pWhere); - pWhere = NULL; - } - if(pFile) - { - free(pFile); - pFile = NULL; - } + if (pWhere) { + free(pWhere); + pWhere = NULL; + } + if (pFile) { + free(pFile); + pFile = NULL; + } - if(pData) - KillDummy(pData); + if (pData) + KillDummy(pData); + +} - } /*--------------------------------------------------------------------------*/ - int MacroFileEvalNew(SConnection *pCon, SicsInterp *pInter, void *pData, - int argc, char *argv[]) - { - void *pCom = NULL; - pCom = FindCommandData(pInter,"exe","ExeManager"); - assert(pCom != NULL); - - if(argc < 2){ - SCWrite(pCon,"ERROR: no batch buffer to execute specified", - eError); - return 0; - } - return runExeBatchBuffer(pCom,pCon,pInter,argv[1]); - } -/*----------------------------------------------------------------------*/ - int MacroFileEval(SConnection *pCon, SicsInterp *pInter, void *pData, - int argc, char *argv[]) - { - FILE *fp = NULL; - char pBueffel[512]; - int iChar; - int i, iRun; - Tcl_DString command; - char *pCom = NULL; - int iRet; - Status eOld; - Tcl_Interp *pTcl = NULL; - int iLine = 0; +int MacroFileEvalNew(SConnection * pCon, SicsInterp * pInter, void *pData, + int argc, char *argv[]) +{ + void *pCom = NULL; + pCom = FindCommandData(pInter, "exe", "ExeManager"); + assert(pCom != NULL); - assert(pCon); - assert(pInter); - pTcl = InterpGetTcl(pInter); + if (argc < 2) { + SCWrite(pCon, "ERROR: no batch buffer to execute specified", eError); + return 0; + } + return runExeBatchBuffer(pCom, pCon, pInter, argv[1]); +} - /* check authorisation: only users permitted here */ - if(!SCMatchRights(pCon,usUser)) - { - SCWrite(pCon,"ERROR: Insufficient Privilege to do FileEval",eError); - return 0; - } +/*----------------------------------------------------------------------*/ +int MacroFileEval(SConnection * pCon, SicsInterp * pInter, void *pData, + int argc, char *argv[]) +{ + FILE *fp = NULL; + char pBueffel[512]; + int iChar; + int i, iRun; + Tcl_DString command; + char *pCom = NULL; + int iRet; + Status eOld; + Tcl_Interp *pTcl = NULL; + int iLine = 0; - /* open filename */ - if( argc < 2) - { - SCWrite(pCon,"ERROR: No filename specified ",eError); - return 0; - } - fp = fopen(argv[1],"r"); - if(!fp) - { - sprintf(pBueffel," Failed to open file -> %s <- ",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* handle status first */ - eOld = GetStatus(); - SetStatus(eBatch); - - SICSLogWrite("Evaluating in MacroFileEval",eValue); - SICSLogWrite(argv[1],eValue); - if(pFile) - { - free(pFile); - } - pFile = strdup(argv[1]); + assert(pCon); + assert(pInter); + pTcl = InterpGetTcl(pInter); - /* cycle through file and execute complete commands */ - i = 0; - Tcl_DStringInit(&command); - iRun = 1; - while(iRun) - { - iChar = fgetc(fp); - if(iChar == EOF) - { - iChar = (int)'\n'; - iRun = 0; - } - if( iChar == (int)'\n' ) - { - pBueffel[i] = (char)iChar; - pBueffel[i+1] = '\0'; - Tcl_DStringAppend(&command,pBueffel,-1); - pCom = Tcl_DStringValue(&command); - if(Tcl_CommandComplete(pCom)) - { - SetStatus(eEager); - FirstWord(pCom,pBueffel); - if(FindCommand(pInter,pBueffel) != NULL) - { - sprintf(pBueffel,"%s:%d>> %s",pFile,iLine,pCom); - SCWrite(pCon,pBueffel,eValue); - if(pWhere != NULL) - { - free(pWhere); - } - pWhere = strdup(pBueffel); - iLine++; - } - iRet = Tcl_Eval(pTcl,pCom); - SetStatus(eBatch); - if(iRet != TCL_OK) - { - /* write TCL error and check for total interrupt */ - if(Tcl_GetVar(pTcl,SICSERROR,TCL_GLOBAL_ONLY) == NULL) - { /* Tcl error */ - if(strlen(pTcl->result) > 2) - { - /* - local copy in order to resolve a valgrind error - */ - strncpy(pBueffel,pTcl->result,511); - SCWrite(pCon,pBueffel,eError); - } - pCom = Tcl_DStringValue(&command); - SCWrite(pCon,"ERROR: in Tcl block:",eError); - SCWrite(pCon,pCom,eError); - SCWrite(pCon,"ERROR: end of Tcl error block",eError); - } - else /* SICS error */ - { - Tcl_UnsetVar(pTcl,SICSERROR,TCL_GLOBAL_ONLY); - /* SCWrite(pCon,pTcl->result,eError); */ - } - } - if(SCGetInterrupt(pCon) >= eAbortBatch) - { - fclose(fp); - Tcl_DStringFree(&command); - SCWrite(pCon,"ERROR: batch processing interrupted",eError); + /* check authorisation: only users permitted here */ + if (!SCMatchRights(pCon, usUser)) { + SCWrite(pCon, "ERROR: Insufficient Privilege to do FileEval", eError); + return 0; + } + + /* open filename */ + if (argc < 2) { + SCWrite(pCon, "ERROR: No filename specified ", eError); + return 0; + } + fp = fopen(argv[1], "r"); + if (!fp) { + snprintf(pBueffel,sizeof(pBueffel)-1, " Failed to open file -> %s <- ", argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* handle status first */ + eOld = GetStatus(); + SetStatus(eBatch); + + SICSLogWrite("Evaluating in MacroFileEval", eValue); + SICSLogWrite(argv[1], eValue); + if (pFile) { + free(pFile); + } + pFile = strdup(argv[1]); + + /* cycle through file and execute complete commands */ + i = 0; + Tcl_DStringInit(&command); + iRun = 1; + while (iRun) { + iChar = fgetc(fp); + if (iChar == EOF) { + iChar = (int) '\n'; + iRun = 0; + } + if (iChar == (int) '\n') { + pBueffel[i] = (char) iChar; + pBueffel[i + 1] = '\0'; + Tcl_DStringAppend(&command, pBueffel, -1); + pCom = Tcl_DStringValue(&command); + if (Tcl_CommandComplete(pCom)) { SetStatus(eEager); - return 0; - } - else - { - SCSetInterrupt(pCon,eContinue); - } - Tcl_DStringFree(&command); - } - i = 0; - } - else - { - pBueffel[i] = (char)iChar; - i++; - } - } /* end while */ - - - /* clean up */ - fclose(fp); - Tcl_DStringFree(&command); - SetStatus(eOld); - SCSendOK(pCon); - return 1; - } + FirstWord(pCom, pBueffel); + if (FindCommand(pInter, pBueffel) != NULL) { + snprintf(pBueffel,sizeof(pBueffel)-1, "%s:%d>> %s", pFile, iLine, pCom); + SCWrite(pCon, pBueffel, eLog); + if (pWhere != NULL) { + free(pWhere); + } + pWhere = strdup(pBueffel); + iLine++; + } + iRet = Tcl_Eval(pTcl, pCom); + SetStatus(eBatch); + if (iRet != TCL_OK) { + /* write TCL error and check for total interrupt */ + if (Tcl_GetVar(pTcl, SICSERROR, TCL_GLOBAL_ONLY) == NULL) { /* Tcl error */ + if (strlen(pTcl->result) > 2) { + /* + local copy in order to resolve a valgrind error + */ + strlcpy(pBueffel, pTcl->result, 511); + SCWrite(pCon, pBueffel, eError); + } + pCom = Tcl_DStringValue(&command); + SCWrite(pCon, "ERROR: in Tcl block:", eError); + SCWrite(pCon, pCom, eError); + SCWrite(pCon, "ERROR: end of Tcl error block", eError); + } else { /* SICS error */ + + Tcl_UnsetVar(pTcl, SICSERROR, TCL_GLOBAL_ONLY); + /* SCWrite(pCon,pTcl->result,eError); */ + } + } + if (SCGetInterrupt(pCon) >= eAbortBatch) { + fclose(fp); + Tcl_DStringFree(&command); + SCWrite(pCon, "ERROR: batch processing interrupted", eError); + SetStatus(eEager); + return 0; + } else { + SCSetInterrupt(pCon, eContinue); + } + Tcl_DStringFree(&command); + } + i = 0; + } else { + pBueffel[i] = (char) iChar; + i++; + } + } /* end while */ + + + /* clean up */ + fclose(fp); + Tcl_DStringFree(&command); + SetStatus(eOld); + SCSendOK(pCon); + return 1; +} + /*---------------------------------------------------------------------- InternalFileEval evaluates a file but on a dummy connection which only writes log files. It also configures a log file for output @@ -604,328 +582,329 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface This is here in order to support the evaluation of command files generated in a specific directory from the WWW-interface. If the latter does not get through, this can safely be deleted. -*/ +*/ - int InternalFileEval(SConnection *pCon, SicsInterp *pInter, void *pData, - int argc, char *argv[]) - { - SConnection *pIntern = NULL; - int iRet; - char *pFil = NULL, *pExt = NULL; +int InternalFileEval(SConnection * pCon, SicsInterp * pInter, void *pData, + int argc, char *argv[]) +{ + SConnection *pIntern = NULL; + int iRet; + char *pFil = NULL, *pExt = NULL; - /* we need a filename */ - if( argc < 2) - { - SCWrite(pCon,"ERROR: No filename specified ",eError); - return 0; - } + /* we need a filename */ + if (argc < 2) { + SCWrite(pCon, "ERROR: No filename specified ", eError); + return 0; + } - /* allocate a dummy connection for this */ - pIntern = SCCreateDummyConnection(pInter); - if(!pInter) - { - SCWrite(pCon,"ERROR: out of memory in InternalFileEval",eError); - return 0; - } - SCnoSock(pIntern); - - /* configure the log file */ - pFil = strdup(argv[1]); - pExt = strrchr(pFil,(int)'.'); - if(!pExt) - { - SCWrite(pCon,"ERROR: no extension found in InternalFileEval", - eError); - return 0; - } - else - { - strcpy(pExt,".log"); - SCAddLogFile(pIntern,pFil); - free(pFil); - } - - /* invoke the fileeval */ - MacroPush(pIntern); - iRet = MacroFileEval(pIntern,pInter,pData,argc,argv); - MacroPop(); + /* allocate a dummy connection for this */ + pIntern = SCCreateDummyConnection(pInter); + if (!pInter) { + SCWrite(pCon, "ERROR: out of memory in InternalFileEval", eError); + return 0; + } + SCnoSock(pIntern); + + + /* invoke the fileeval */ + MacroPush(pIntern); + iRet = MacroFileEval(pIntern, pInter, pData, argc, argv); + MacroPop(); + + /* remove our internal connection */ + SCDeleteConnection(pIntern); + return iRet; +} - /* remove our internal connection */ - SCDeleteConnection(pIntern); - return iRet; - } /*-------------------------------------------------------------------------- ClientPut is installed as a command to write data to the client from a server script. Syntax: ClientPut text outputcode The output code is optional and and defaults to eStatus. ----------------------------------------------------------------------------*/ +---------------------------------------------------------------------------*/ #include "outcode.c" - int ClientPut(SConnection *pCon, SicsInterp *pInter, void *pData, - int argc, char *argv[]) - { - OutCode eOut = eWarning; - int i = 0, iCode, iLen; - int iMacro; - char *ppCode; - char *pMessage = NULL; - - assert(pCon); - assert(pInter); - - if(argc < 2) - { - SCWrite(pCon,"Insufficient arguments to ClientPut",eError); - return 0; - } - - /* handle optional I/O codes */ - if(argc > 2) - { - /* the last one must be the code */ - iCode = argc - 1; - ppCode = strdup(argv[iCode]); - strtolower(ppCode); - while(pCode[i] != NULL) - { - if(strcmp(pCode[i],ppCode) == 0) - { - break; - } - i++; - } - if(ppCode) - { - free(ppCode); - } - } - else - { - i = 10; - iCode = argc; - } - - switch(i) - { - case 0: - eOut = eInternal; - break; - case 1: - eOut = eCommand; - break; - case 2: - eOut = eHWError; - break; - case 3: - eOut = eInError; - break; - case 4: - eOut = eStatus; - break; - case 5: - eOut = eValue; - break; - case 6: - eOut = eWarning; - break; - case 7: - eOut = eFinish; - break; - case 8: - eOut = eEvent; - break; - case 9: - eOut = eWarning; - break; - case 10: - eOut = eError; - break; - default: - eOut = eWarning; - iCode = argc; - break; - } +int ClientPut(SConnection * pCon, SicsInterp * pInter, void *pData, + int argc, char *argv[]) +{ + OutCode eOut = eLog; + int i = 0, iCode, iLen; + char *ppCode; + char *pMessage = NULL; - /* recombine the message */ - /* find length */ - iLen = 0; - for(i = 1; i < iCode; i++) - { - iLen += strlen(argv[i]); - } - pMessage = (char *)malloc((iLen+100)*sizeof(char)); - if(!pMessage) - { - SCWrite(pCon,"ERROR: out of memory in clientput",eError); - return 0; - } - memset(pMessage,0,(iLen+100)*sizeof(char)); - Arg2Text(iCode-1,&argv[1],pMessage,(iLen+100)*sizeof(char)); + assert(pCon); + assert(pInter); - /* now write, thereby tunneling macro flag in order to get proper - write to client and not into interpreter - */ - iMacro = SCinMacro(pCon); - SCsetMacro(pCon,0); - SCWrite(pCon,pMessage,eOut); - SCsetMacro(pCon,iMacro); - if(pMessage) - { - free(pMessage); - } - return 1; + if (argc < 2) { + SCWrite(pCon, "Insufficient arguments to ClientPut", eError); + return 0; + } + + /* handle optional I/O codes */ + if (argc > 2) { + /* the last one must be the code */ + iCode = argc - 1; + ppCode = strdup(argv[iCode]); + strtolower(ppCode); + while (pCode[i] != NULL) { + if (strcmp(pCode[i], ppCode) == 0) { + break; + } + i++; } + if (ppCode) { + free(ppCode); + } + } else { + i = eLog; + iCode = argc; + } + + switch (i) { + case 0: + eOut = eInternal; + break; + case 1: + eOut = eCommand; + break; + case 2: + eOut = eHWError; + break; + case 3: + eOut = eInError; + break; + case 4: + eOut = eStatus; + break; + case 5: + eOut = eValue; + break; + case 6: + eOut = eWarning; + break; + case 7: + eOut = eFinish; + break; + case 8: + eOut = eEvent; + break; + case 9: + eOut = eWarning; + break; + case 10: + eOut = eError; + break; + case 11: + eOut = eLog; + break; + case 12: + eOut = eLogError; + break; + default: + eOut = eLog; + iCode = argc; + break; + } + + /* recombine the message */ + /* find length */ + iLen = 0; + for (i = 1; i < iCode; i++) { + iLen += strlen(argv[i]); + } + pMessage = (char *) malloc((iLen + 100) * sizeof(char)); + if (!pMessage) { + SCWrite(pCon, "ERROR: out of memory in clientput", eLogError); + return 0; + } + memset(pMessage, 0, (iLen + 100) * sizeof(char)); + Arg2Text(iCode - 1, &argv[1], pMessage, (iLen + 100) * sizeof(char)); + + SCWrite(pCon, pMessage, eOut); + if (pMessage) { + free(pMessage); + } + return 1; +} +/*----------------------------------------------------------------- + ClientLog writes to the socket and the command log only + -------------------------------------------------------------------*/ +int ClientLog(SConnection * pCon, SicsInterp * pInter, void *pData, + int argc, char *argv[]) +{ + OutCode eOut = eLog; + int i = 0, iLen; + char *pMessage = NULL; + + assert(pCon); + assert(pInter); + + if (argc < 2) { + SCWrite(pCon, "Insufficient arguments to ClientLog", eError); + return 0; + } + + + /* recombine the message */ + /* find length */ + iLen = 0; + for (i = 1; i < argc; i++) { + iLen += strlen(argv[i]); + } + pMessage = (char *) malloc((iLen + 100) * sizeof(char)); + if (!pMessage) { + SCWrite(pCon, "ERROR: out of memory in clientlo", eLogError); + return 0; + } + memset(pMessage, 0, (iLen + 100) * sizeof(char)); + Arg2Text(argc - 1, &argv[1], pMessage, (iLen + 100) * sizeof(char)); + + SCLogWrite(pCon,pMessage, eError); + free(pMessage); + return 1; +} /*-----------------------------------------------------------------------*/ - int GumPut(SConnection *pCon, SicsInterp *pInter, void *pData, - int argc, char *argv[]) - { - OutCode eOut = eWarning; - int i = 0, iCode, iLen; - int iMacro; - char *ppCode; - char *pMessage = NULL; - commandContext cc; - - assert(pCon); - assert(pInter); - - if(argc < 2) - { - SCWrite(pCon,"Insufficient arguments to ClientPut",eError); - return 0; - } - - /* handle optional I/O codes */ - if(argc > 2) - { - /* the last one must be the code */ - iCode = argc - 1; - ppCode = strdup(argv[iCode]); - strtolower(ppCode); - while(pCode[i] != NULL) - { - if(strcmp(pCode[i],ppCode) == 0) - { - break; - } - i++; - } - if(ppCode) - { - free(ppCode); - } - } - else - { - i = 10; - iCode = argc; - } - - switch(i) - { - case 0: - eOut = eInternal; - break; - case 1: - eOut = eCommand; - break; - case 2: - eOut = eHWError; - break; - case 3: - eOut = eInError; - break; - case 4: - eOut = eStatus; - break; - case 5: - eOut = eValue; - break; - case 6: - eOut = eWarning; - break; - case 7: - eOut = eFinish; - break; - case 8: - eOut = eEvent; - break; - case 9: - eOut = eWarning; - break; - case 10: - eOut = eError; - break; - default: - eOut = eWarning; - iCode = argc; - break; - } +int GumPut(SConnection * pCon, SicsInterp * pInter, void *pData, + int argc, char *argv[]) +{ + OutCode eOut = eWarning; + int i = 0, iCode, iLen; + int iMacro; + char *ppCode; + char *pMessage = NULL; + SConnection *conCon = NULL; - /* recombine the message */ - /* find length */ - iLen = 0; - for(i = 1; i < iCode; i++) - { - iLen += strlen(argv[i]); - } - pMessage = (char *)malloc((iLen+100)*sizeof(char)); - if(!pMessage) - { - SCWrite(pCon,"ERROR: out of memory in clientput",eError); - return 0; - } - memset(pMessage,0,(iLen+100)*sizeof(char)); - Arg2Text(iCode-1,&argv[1],pMessage,(iLen+100)*sizeof(char)); + assert(pCon); + assert(pInter); - /* now write, thereby tunneling macro flag in order to get proper - write to client and not into interpreter. We also make sure that the device - is gumput - */ - iMacro = SCinMacro(pCon); - SCsetMacro(pCon,0); - cc = SCGetContext(pCon); - strcpy(cc.deviceID,"gumput"); - SCPushContext2(pCon,cc); - SCWrite(pCon,pMessage,eOut); - SCPopContext(pCon); - SCsetMacro(pCon,iMacro); - if(pMessage) - { - free(pMessage); - } - return 1; + if (argc < 2) { + SCWrite(pCon, "Insufficient arguments to ClientPut", eLogError); + return 0; + } + + /* handle optional I/O codes */ + if (argc > 2) { + /* the last one must be the code */ + iCode = argc - 1; + ppCode = strdup(argv[iCode]); + strtolower(ppCode); + while (pCode[i] != NULL) { + if (strcmp(pCode[i], ppCode) == 0) { + break; + } + i++; } + if (ppCode) { + free(ppCode); + } + } else { + i = 10; + iCode = argc; + } + + switch (i) { + case 0: + eOut = eInternal; + break; + case 1: + eOut = eCommand; + break; + case 2: + eOut = eHWError; + break; + case 3: + eOut = eInError; + break; + case 4: + eOut = eStatus; + break; + case 5: + eOut = eValue; + break; + case 6: + eOut = eWarning; + break; + case 7: + eOut = eFinish; + break; + case 8: + eOut = eEvent; + break; + case 9: + eOut = eWarning; + break; + case 10: + eOut = eError; + break; + case 11: + eOut = eLog; + break; + case 12: + eOut = eLogError; + break; + default: + eOut = eLog; + iCode = argc; + break; + } + + /* recombine the message */ + /* find length */ + iLen = 0; + for (i = 1; i < iCode; i++) { + iLen += strlen(argv[i]); + } + pMessage = (char *) malloc((iLen + 100) * sizeof(char)); + if (!pMessage) { + SCWrite(pCon, "ERROR: out of memory in clientput", eError); + return 0; + } + memset(pMessage, 0, (iLen + 100) * sizeof(char)); + Arg2Text(iCode - 1, &argv[1], pMessage, (iLen + 100) * sizeof(char)); + + /* now write, thereby tunneling macro flag in order to get proper + write to client and not into interpreter. We also make sure that the device + is gumput + */ + conCon = SCCopyConnection(pCon); + if (conCon == NULL) { + SCWrite(pCon, "ERROR: out of memory in gumput", eError); + } + strcpy(conCon->deviceID, "gumput"); + SCWrite(conCon, pMessage, eOut); + SCDeleteConnection(conCon); + if (pMessage) { + free(pMessage); + } + return 1; +} + /*----------------------------------------------------------------------*/ - int Broadcast(SConnection *pCon, SicsInterp *pInter, void *pData, - int argc, char *argv[]) - { - int iMacro; - char pBueffel[256]; +int Broadcast(SConnection * pCon, SicsInterp * pInter, void *pData, + int argc, char *argv[]) +{ + int iMacro; + char pBueffel[256]; - assert(pCon); - assert(pInter); - - if(argc < 2) - { - SCWrite(pCon,"Insufficient arguments to Broadcast",eError); - return 0; - } - + assert(pCon); + assert(pInter); + + if (argc < 2) { + SCWrite(pCon, "Insufficient arguments to Broadcast", eLog); + return 0; + } + + + /* now write, thereby tunneling macro flag in order to get proper + write to client and not into interpreter + */ + Arg2Text(argc - 1, &argv[1], pBueffel, 255); + ServerWriteGlobal(pBueffel, eLog); + return 1; +} - /* now write, thereby tunneling macro flag in order to get proper - write to client and not into interpreter - */ - Arg2Text(argc-1, &argv[1],pBueffel,255); - iMacro = SCinMacro(pCon); - SCsetMacro(pCon,0); - ServerWriteGlobal(pBueffel,eWarning); - SCsetMacro(pCon,iMacro); - return 1; - } /*--------------------------------------------------------------------------- This implements a scheme to provide Tcl commands to Tcl. The Tcl commands (either procedures or objects) must be defined in a separate file. Than @@ -935,169 +914,178 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface the rights initialized may use it. Below the datastructure to hold for each command -----------------------------------------------------------------------------*/ - typedef struct { - pObjectDescriptor pDes; - char *command; - int iUser; - } PubTcl, *pPubTcl; -/*--------------------------------------------------------------------------*/ - static pPubTcl CreatePublish(char *name, int iUser) - { - pPubTcl pRes = NULL; - - pRes = (pPubTcl)malloc(sizeof(PubTcl)); - if(!pRes) - { - return NULL; - } - - pRes->pDes = CreateDescriptor("Macro"); - if(!pRes->pDes) - { - free(pRes); - return NULL; - } - - pRes->command = strdup(name); - pRes->iUser = iUser; - return pRes; - } +----------------------------------------------------------------------------*/ +typedef struct { + pObjectDescriptor pDes; + char *command; + int iUser; +} PubTcl, *pPubTcl; +/*--------------------------------------------------------------------------*/ +static pPubTcl CreatePublish(char *name, int iUser) +{ + pPubTcl pRes = NULL; + + pRes = (pPubTcl) malloc(sizeof(PubTcl)); + if (!pRes) { + return NULL; + } + + pRes->pDes = CreateDescriptor("Macro"); + if (!pRes->pDes) { + free(pRes); + return NULL; + } + + pRes->command = strdup(name); + pRes->iUser = iUser; + return pRes; +} + /*-------------------------------------------------------------------------*/ - static void DeletePublish(void *pData) - { - pPubTcl self = NULL; - - self = (pPubTcl)pData; - assert(self); - - if(self->pDes) - { - DeleteDescriptor(self->pDes); - } - if(self->command) - { - free(self->command); - } - free(self); - } +static void DeletePublish(void *pData) +{ + pPubTcl self = NULL; + + self = (pPubTcl) pData; + assert(self); + + if (self->pDes) { + DeleteDescriptor(self->pDes); + } + if (self->command) { + free(self->command); + } + free(self); +} + /*-------------------------------------------------------------------------- TclAction checks the user rights and than invokes the arguments as a Tcl command */ - - static int TclAction(SConnection *pCon,SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - char pBueffel[1024]; - char *pCommand; - pPubTcl self = NULL; - int iRet, length; - char *pPtr; - Tcl_Interp *pTcl = NULL; - - self = (pPubTcl)pData; - assert(pCon); - assert(pSics); - assert(self); - pTcl = InterpGetTcl(pSics); - - if(!SCMatchRights(pCon,self->iUser)) - { - sprintf(pBueffel,"ERROR: you are not authorised to invoke %s", - argv[0]); - SCWrite(pCon,pBueffel,eError); - return 1; - } - /* make a string */ - pCommand = Arg2Tcl0(argc-1,argv+1,pBueffel,sizeof(pBueffel),self->command); - if (!pCommand) { - SCWrite(pCon, "ERROR: no more memory", eError); - return 0; - } - iRet = Tcl_Eval(pTcl,pCommand); - if (pCommand != pBueffel) free(pCommand); - if(iRet == TCL_OK) - { - if(strlen(pTcl->result) > 0){ - SCPrintf(pCon, eStatus, "%s", pTcl->result); - } - return 1; - } - else - { - if(Tcl_GetVar(pTcl,SICSERROR,TCL_GLOBAL_ONLY) != NULL) - { - Tcl_UnsetVar(pTcl,SICSERROR,TCL_GLOBAL_ONLY); - } - SCPrintf(pCon,eError,"%s",pTcl->result); - return 0; - } - return 1; /* not reached */ - } +static int TclAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + char pBueffel[1024]; + char *pCommand; + pPubTcl self = NULL; + int iRet, length; + char *pPtr; + Tcl_Interp *pTcl = NULL; + + self = (pPubTcl) pData; + assert(pCon); + assert(pSics); + assert(self); + pTcl = InterpGetTcl(pSics); + + if (!SCMatchRights(pCon, self->iUser)) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: you are not authorised to invoke %s", + argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* make a string */ + pCommand = + Arg2Tcl0(argc - 1, argv + 1, pBueffel, sizeof(pBueffel), + self->command); + if (!pCommand) { + SCWrite(pCon, "ERROR: no more memory", eError); + return 0; + } + Tcl_ResetResult(pTcl); + SetWriteHistory(0); + iRet = Tcl_Eval(pTcl, pCommand); + SetWriteHistory(1); + if (iRet == TCL_OK) { + if (strlen(pTcl->result) > 0) { + SCPrintf(pCon, eValue, "%s", pTcl->result); + } + if (pCommand != pBueffel) + free(pCommand); + return 1; + } else { + if (Tcl_GetVar(pTcl, SICSERROR, TCL_GLOBAL_ONLY) != NULL) { + Tcl_UnsetVar(pTcl, SICSERROR, TCL_GLOBAL_ONLY); + } + if (strlen(pTcl->result) > 0) { + SCPrintf(pCon, eError, "ERROR: Tcl reported %s in %s", pTcl->result, + pCommand); + } + if (pCommand != pBueffel) + free(pCommand); + return 0; + } + return 1; /* not reached */ +} + /*--------------------------------------------------------------------------*/ - int TclPublish(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - pPubTcl pNew = NULL; - char pBueffel[132]; - int iUser, i, iRet; - - /* check no of args */ - if(argc < 3) - { - sprintf(pBueffel,"ERROR: Insufficient no of arguments to %s", - argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* check user rights */ - if(!SCMatchRights(pCon,usMugger)) - { - sprintf(pBueffel,"ERROR: you are not authorised to use %s", - argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - - /* try convert last parameter to user code */ - iUser = decodeSICSPriv(argv[2]); - if(iUser < 0) - { - sprintf(pBueffel,"ERROR: cannot identify %s as a valid user code", - argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* check if the macro already exists */ - pNew = FindCommandData(pSics, argv[1], "Macro"); - if (pNew) - { /* yes -> overwrite access code */ - pNew->iUser = iUser; +int TclPublish(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pPubTcl pNew = NULL; + char pBueffel[132]; + int iUser, i, iRet; + + /* check no of args */ + if (argc < 3) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Insufficient no of arguments to %s", + argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* try convert last parameter to user code */ + iUser = decodeSICSPriv(argv[2]); + if (iUser < 0) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: cannot identify %s as a valid user code", + argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* check if the macro already exists */ + pNew = FindCommandData(pSics, argv[1], "Macro"); + if (pNew) { /* yes -> overwrite access code */ + if (pNew->iUser == iUser) { return 1; } - /* do a job !*/ - pNew = CreatePublish(argv[1],iUser); - if(!pNew) - { - sprintf(pBueffel,"ERROR: memory error in %s",argv[0]); - SCWrite(pCon,pBueffel,eError); + /* check user rights */ + if (!SCMatchRights(pCon, usMugger)) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: you are not authorised to use %s", argv[0]); + SCWrite(pCon, pBueffel, eError); return 0; } - iRet = AddCommand(pSics,argv[1],TclAction,DeletePublish,(void *)pNew); - if(!iRet) - { - sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } + pNew->iUser = iUser; return 1; - - } + } + + /* check user rights */ + if (!SCMatchRights(pCon, usMugger)) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: you are not authorised to use %s", argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* do a job ! */ + pNew = CreatePublish(argv[1], iUser); + if (!pNew) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: memory error in %s", argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + iRet = + AddCommand(pSics, argv[1], TclAction, DeletePublish, (void *) pNew); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: duplicate command %s not created", argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + return 1; + +} + /*------------------------------------------------------------------------- Transact executes a command and sends a TRANSACTIONFINISHED string at the end. This is to permit clients to search for this string in @@ -1106,34 +1094,66 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface - int TransactAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - char pBuffer[1024]; - char *pCommand; - int iRet; - - pCommand = Arg2Tcl(argc-1,&argv[1],pBuffer, sizeof(pBuffer)); - if (!pCommand) { - SCWrite(pCon,"ERROR: no memory", eError); - return 0; - } - strtolower(argv[0]); - if(strcmp(argv[0],"fulltransact") == 0){ - SCPrintf(pCon,eError, "TRANSACTIONSTART %s",pCommand); - } - iRet = InterpExecute(pSics,pCon,pCommand); - if (pCommand != pBuffer) free(pCommand); - SCWrite(pCon,"TRANSACTIONFINISHED",eError); - return iRet; - } - - - - - - - +int TransactAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + char pBuffer[1024]; + char *pCommand; + int iRet; + pCommand = Arg2Tcl(argc - 1, &argv[1], pBuffer, sizeof(pBuffer)); + if (!pCommand) { + SCWrite(pCon, "ERROR: no memory", eError); + return 0; + } + strtolower(argv[0]); + if (strcmp(argv[0], "fulltransact") == 0) { + SCPrintf(pCon, eLog, "TRANSACTIONSTART %s", pCommand); + } + iRet = InterpExecute(pSics, pCon, pCommand); + if (pCommand != pBuffer) + free(pCommand); + SCWrite(pCon, "TRANSACTIONFINISHED", eLog); + return iRet; +} +/*-----------------------------------------------------------------------------*/ +int CaptureAction(SConnection *pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + SConnection *comCon = NULL; + char buffer[1024]; + char *command; + int status; + pDynString reply = NULL; + + if (argc < 2) { + SCWrite(pCon, "ERROR: insufficient arguments to capture", eError); + return 0; + } + comCon = SCCopyConnection(pCon); + if (comCon == NULL) { + SCWrite(pCon, "ERROR: out of memory in capture", eError); + return 0; + } + /* + * This line is required to support nested captures + */ + comCon->data = NULL; + memset(buffer, 0, sizeof(buffer)); + command = Arg2Tcl(argc - 1, &argv[1], buffer, sizeof buffer); + if (!command) { + SCWrite(pCon, "ERROR: no more memory", eError); + return 0; + } + SCStartBuffering(comCon); + status = InterpExecute(pSics, comCon, command); + if (command != buffer) + free(command); + reply = SCEndBuffering(comCon); + SCWrite(pCon,GetCharArray(reply), eValue); + SCDeleteConnection(comCon); + return status; + +} diff --git a/macro.h b/macro.h index 2bd8fa78..166e25c0 100644 --- a/macro.h +++ b/macro.h @@ -17,41 +17,41 @@ #include "sics.h" #include "SCinter.h" - Tcl_Interp *MacroInit(SicsInterp *pInter); - void MacroDelete(Tcl_Interp *pInter); - void WhereKill(void *pData); - - int MacroEval(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - int MacroFileEval(SConnection *pCon, SicsInterp *pInter, void *pData, +Tcl_Interp *MacroInit(SicsInterp * pInter); +void MacroDelete(Tcl_Interp * pInter); +void WhereKill(void *pData); + +int MacroEval(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); +int MacroFileEval(SConnection * pCon, SicsInterp * pInter, void *pData, + int argc, char *argv[]); +int InternalFileEval(SConnection * pCon, SicsInterp * pInter, void *pData, int argc, char *argv[]); - int InternalFileEval(SConnection *pCon, SicsInterp *pInter, void *pData, - int argc, char *argv[]); - int MacroWhere(SConnection *pCon, SicsInterp *pInter, void *pData, - int argc, char *argv[]); - int ClientPut(SConnection *pCon, SicsInterp *pInter, void *pData, - int argc, char *argv[]); - int GumPut(SConnection *pCon, SicsInterp *pInter, void *pData, - int argc, char *argv[]); - int Broadcast(SConnection *pCon, SicsInterp *pInter, void *pData, - int argc, char *argv[]); - int TransactAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - - int TclPublish(SConnection *pCon, SicsInterp *pInter, void *pData, - int argc, char *argv[]); - int AllowExec(SConnection *pCon, SicsInterp *pInter, void *pData, - int argc, char *argv[]); - +int MacroWhere(SConnection * pCon, SicsInterp * pInter, void *pData, + int argc, char *argv[]); +int ClientPut(SConnection * pCon, SicsInterp * pInter, void *pData, + int argc, char *argv[]); +int GumPut(SConnection * pCon, SicsInterp * pInter, void *pData, + int argc, char *argv[]); +int Broadcast(SConnection * pCon, SicsInterp * pInter, void *pData, + int argc, char *argv[]); +int TransactAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); +int CaptureAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); + +int TclPublish(SConnection * pCon, SicsInterp * pInter, void *pData, + int argc, char *argv[]); +int AllowExec(SConnection * pCon, SicsInterp * pInter, void *pData, + int argc, char *argv[]); + /* for maintaining the Connection stack at Unknown. Should only be used by SicsInterp module - */ - int MacroPush(SConnection *pCon); - int MacroPop(void); - - void KillSicsUnknown(void); + */ +int MacroPush(SConnection * pCon); +int MacroPop(void); +SConnection *MacroPeek(void); + +void KillSicsUnknown(void); #endif - - - diff --git a/make_gen b/make_gen index 75a9edf4..7c710e42 100644 --- a/make_gen +++ b/make_gen @@ -8,20 +8,20 @@ COBJ = Sclient.o network.o ifile.o intcli.o $(FORTIFYOBJ) SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \ servlog.o sicvar.o nserver.o SICSmain.o motorlist.o\ - sicsexit.o costa.o task.o $(FORTIFYOBJ) access.o\ + sicsexit.o costa.o task.o $(FORTIFYOBJ) testprot.o\ macro.o ofac.o obpar.o obdes.o drive.o status.o intserv.o \ devexec.o mumo.o mumoconf.o selector.o selvar.o fupa.o lld.o \ lld_blob.o strrepl.o lin2ang.o fomerge.o napi5.o napi4.o\ - script.o o2t.o alias.o napi.o nxdata.o stringdict.o sdynar.o \ + script.o o2t.o alias.o napi.o stringdict.o sdynar.o \ histmem.o histdriv.o histsim.o interface.o callback.o nxio.o \ event.o emon.o evcontroller.o evdriver.o simev.o perfmon.o \ danu.o nxdict.o varlog.o stptok.o nread.o trigd.o cell.o\ scan.o fitcenter.o telnet.o token.o wwildcard.o hklmot.o\ tclev.o hkl.o integrate.o optimise.o dynstring.o nxutil.o \ - mesure.o uubuffer.o commandlog.o udpquieck.o fourtable.o\ + uubuffer.o commandlog.o udpquieck.o fourtable.o\ rmtrail.o help.o nxupdate.o confvirtualmot.o vector.o\ simchop.o choco.o chadapter.o trim.o scaldate.o tasub.o\ - hklscan.o xytable.o exebuf.o exeman.o ubfour.o ubcalc.o\ + xytable.o exebuf.o exeman.o ubfour.o ubcalc.o\ circular.o maximize.o sicscron.o scanvar.o tasublib.o\ d_sign.o d_mod.o tcldrivable.o stdscan.o diffscan.o nxxml.o\ synchronize.o definealias.o oscillate.o tasdrive.o \ @@ -29,20 +29,27 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \ fourlib.o motreg.o motreglist.o anticollider.o nxdataset.o \ s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) mcreader.o mccontrol.o\ hmdata.o nxscript.o tclintimpl.o sicsdata.o mcstascounter.o \ - mcstashm.o initializer.o remob.o protocol.o \ + mcstashm.o initializer.o remob.o tclmotdriv.o protocol.o \ sinfox.o sicslist.o cone.o hipadaba.o sicshipadaba.o statistics.o \ - ascon.o errormsg.o scriptcontext.o logger.o logreader.o logsetup.o \ + ascon.o scriptcontext.o logger.o logreader.o logsetup.o \ savehdb.o statusfile.o sicshdbfactory.o proxy.o devser.o \ moregress.o multicounter.o regresscter.o histregress.o \ sicshdbadapter.o polldriv.o sicspoll.o statemon.o hmslave.o \ - nwatch.o asyncqueue.o asyncprotocol.o sicsobj.o \ - nxcopy.o nxinterhelper.o nxinter_wrap.o genericcontroller.o nxstack.o \ - sctdriveadapter.o sctdriveobj.o + nwatch.o asyncqueue.o asyncprotocol.o sicsobj.o frame.o syncedprot.o\ + nxcopy.o nxinterhelper.o nxinter_wrap.o nxstack.o arrayutil.o \ + sctdriveadapter.o sctdriveobj.o reflist.o singlex.o fourmess.o \ + sgclib.o sgfind.o sgio.o sgsi.o sghkl.o singlediff.o singlebi.o \ + singlenb.o simindex.o simidx.o uselect.o singletas.o motorsec.o \ + rwpuffer.o asynnet.o background.o countersec.o hdbtable.o velosec.o \ + histmemsec.o sansbc.o sicsutil.o strlutil.o genbinprot.o trace.o\ + singlebinb.o MOTOROBJ = motor.o simdriv.o COUNTEROBJ = countdriv.o simcter.o counter.o VELOOBJ = velo.o velosim.o +OBJ = $(SOBJ) $(MOTOROBJ) $(COUNTEROBJ) $(VELOOBJ) $(DIFIL) $(EXTRA) + .SUFFIXES: .SUFFIXES: .tcl .htm .c .o .tc @@ -57,12 +64,8 @@ all: libmat libhlib libtecsl libpsi SICServer # use this target when some of the libraries SUBLIBS might be incomplete full: purge all -SICServer: $(SOBJ) $(MOTOROBJ) $(COUNTEROBJ) \ - $(VELOOBJ) $(DIFIL) $(EXTRA) \ - $(SUBLIBS) - $(CC) -g -pg -o SICServer \ - $(SOBJ) $(MOTOROBJ) $(COUNTEROBJ) \ - $(VELOOBJ) $(DIFOBJ) $(EXTRA) $(LIBS) +SICServer: $(OBJ) $(SUBLIBS) + $(CC) -g -o SICServer $(OBJ) $(LIBS) matrix/libmatrix.a: libmat @@ -88,7 +91,7 @@ purge: rm -f SICServer $(SUBLIBS) clean: - rm -f *.o SICServer + rm -f *.o *.d SICServer cd psi/hardsup; make $(MFLAGS) clean cd matrix; make $(MFLAGS) clean cd psi/tecs; make $(MFLAGS) clean diff --git a/makefile b/makefile index 03dfa3af..adc02ada 100644 --- a/makefile +++ b/makefile @@ -19,3 +19,4 @@ usage: @ ls -1 makefile_* | pr -t -o 4 +# DO NOT DELETE diff --git a/makefile_linux b/makefile_linux index 33944cd7..059317ff 100644 --- a/makefile_linux +++ b/makefile_linux @@ -1,32 +1,32 @@ #--------------------------------------------------------------------------- # Makefile for SICS -# machine-dependent part for Redhat Linux with AFS at PSI +# This one is to use when all additional libraries have been +# installed under /usr/local # # Mark Koennecke 1996-2001 # Markus Zolliker, March 2003 +# Mark Koennecke, December 2009 #========================================================================== # assign if the National Instrument GPIB driver is available SINQDIR=/usr/local -#NI= -NI= -DHAVENI -NIOBJ= nigpib.o -NILIB=$(SINQDIR)/lib/cib.o +NI= +#NI= -DHAVENI +#NIOBJ= nigpib.o +#NILIB=$(SINQDIR)/lib/cib.o include linux_def CC = gcc -CFLAGS = -I$(HDFROOT)/include -DHDF4 -DHDF5 -DNXXML $(NI) \ - -Ipsi/hardsup -I. \ - -fwritable-strings -DCYGNUS -DNONINTF -g $(DFORTIFY) +CFLAGS = -I$(HDFROOT)/include -I/usr/include/hdf -I$(TCLINC) -DHDF4 -DHDF5 \ + -DNXXML $(NI) -Ipsi/hardsup -I. -DCYGNUS -DNONINTF -g $(DFORTIFY) BINTARGET = bin EXTRA=nintf.o SUBLIBS = psi/libpsi.a psi/hardsup/libhlib.a matrix/libmatrix.a \ psi/tecs/libtecsl.a LIBS = -L$(HDFROOT)/lib $(SUBLIBS) $(NILIB)\ - -ltcl8.4 -lmxml $(HDFROOT)/lib/libhdf5.a \ - $(HDFROOT)/lib/libmfhdf.a $(HDFROOT)/lib/libdf.a \ - -lmxml -lghttp -ljpeg -ljson -ldl -lz -lsz -lm -lc + -ltcl8.3 -lhdf5 -lmfhdf -ldf \ + -lmxml -lghttp -ljpeg -ljson -ldl -lz -lm -lc include make_gen diff --git a/makefile_slinux b/makefile_slinux index f5955672..3602a289 100644 --- a/makefile_slinux +++ b/makefile_slinux @@ -9,30 +9,29 @@ SINQDIR=/afs/psi.ch/project/sinq NI= -DHAVENI NIOBJ= nigpib.o -NILIB=$(SINQDIR)/sl5/lib/cib.o +NILIB=$(SINQDIR)/sl6/lib/cib.o include sllinux_def CC = gcc -CFLAGS = -I$(HDFROOT)/include -DNXXML -DHDF4 -DHDF5 $(NI) \ - -Ipsi/hardsup -I. \ +CFLAGS = -I$(HDFROOT)/include -DNXXML -DHDF5 $(NI) \ + -Ipsi/hardsup -I. -MMD \ -Werror -DCYGNUS -DNONINTF -g $(DFORTIFY) \ - -Wall -Wno-unused -Wno-comment -Wno-switch + -Wall -Wno-unused -Wunused-value -Wno-comment -Wno-switch BINTARGET = bin EXTRA=nintf.o SUBLIBS = psi/libpsi.a psi/hardsup/libhlib.a matrix/libmatrix.a \ psi/tecs/libtecsl.a -LIBS = -L$(HDFROOT)/lib $(SUBLIBS) $(NILIB)\ +LIBS = -L$(HDFROOT)/lib $(SUBLIBS) $(NILIB)\ -ltcl $(HDFROOT)/lib/libhdf5.a \ - $(HDFROOT)/lib/libmfhdf.a $(HDFROOT)/lib/libdf.a \ - $(HDFROOT)/lib/libjpeg.a $(HDFROOT)/lib/libsz.a \ + $(HDFROOT)/lib/libsz.a \ $(HDFROOT)/lib/libjson.a \ - -ldl -lz -lmxml $(HDFROOT)/lib/libghttp.a -lm -lc + -ldl -lz $(HDFROOT)/lib/libmxml.a $(HDFROOT)/lib/libghttp.a -lm -lc -lpthread include make_gen - +-include $(OBJ:.o=.d) diff --git a/matrix/make_gen b/matrix/make_gen index 992e1d54..4d142e12 100644 --- a/matrix/make_gen +++ b/matrix/make_gen @@ -14,5 +14,4 @@ libmatrix.a: $(OBJ) ranlib libmatrix.a clean: - rm -f *.o - rm -f *.a + rm -f *.o *.a *.d diff --git a/matrix/makefile_linux b/matrix/makefile_linux index addaf48b..ba158810 100644 --- a/matrix/makefile_linux +++ b/matrix/makefile_linux @@ -1,6 +1,5 @@ #--------------------------------------------------------------------------- # Makefile for the Matrix library -# machine-dependent part for Redhat Linux with AFS at PSI # # Mark Koennecke, November 1996 # Markus Zolliker, March 2003 @@ -9,6 +8,9 @@ include ../linux_def CC = gcc -CFLAGS = -g $(DFORTIFY) +CFLAGS = -g $(DFORTIFY) -MMD include make_gen + +-include $(OBJ:.o=.d) + diff --git a/maximize.c b/maximize.c index a8b8affa..8be3b4ec 100644 --- a/maximize.c +++ b/maximize.c @@ -50,520 +50,451 @@ #include "motor.h" #define MAXPTS 100 -#define DEBUG 1 +#define DEBUG 0 - typedef struct __MAXIMIZE { - pObjectDescriptor pDes; - pCounter pCount; - int i360; - int maxpts; - }Maxxii; +typedef struct __MAXIMIZE { + pObjectDescriptor pDes; + pCounter pCount; + int i360; + int maxpts; +} Maxxii; /*----------------------------------------------------------------------- put into 360 degree range if 360 degree flag is active. */ - static float in360(pMax self, float fVal) - { - if(self->i360) - { - if(fVal < 0.) - fVal = 360. + fVal; - if(fVal > 360.) - fVal = fVal - 360.; - } - return fVal; - } +static float in360(pMax self, float fVal) +{ + if (self->i360) { + if (fVal < 0.) + fVal = 360. + fVal; + if (fVal > 360.) + fVal = fVal - 360.; + } + return fVal; +} + /*---------------------------------------------------------------------*/ - static int maxDrive(void *pObject, char *pVarName, - float fPos, SConnection *pCon) - { - pDummy pDum; - int status; - char pBueffel[132]; - long lTask; +static int maxDrive(void *pObject, char *pVarName, + float fPos, SConnection * pCon) +{ + pDummy pDum; + int status; + char pBueffel[132]; - /* start */ - pDum = (pDummy)pObject; - status = StartDevice(pServ->pExecutor, - pVarName, - pDum->pDescriptor, - pObject, - pCon, - fPos); - if(!status) - { - sprintf(pBueffel,"ERROR: failed to start %s",pVarName); - SCWrite(pCon,pBueffel,eError); - return 0; - } + /* start */ + pDum = (pDummy) pObject; + status = StartDevice(pServ->pExecutor, + pVarName, pDum->pDescriptor, pObject, pCon, + RUNDRIVE, fPos); + if (!status) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: failed to start %s", pVarName); + SCWrite(pCon, pBueffel, eError); + return 0; + } - /* wait */ - lTask = GetDevexecID(pServ->pExecutor); - if(lTask > 0) - { - TaskWait(pServ->pTasker,lTask); - } - else - { - return 0; - } + /* wait */ + while(DevExecLevelRunning(pServ->pExecutor,RUNDRIVE)){ + TaskYield(pServ->pTasker); + } + + /* check interrupts */ + if (SCGetInterrupt(pCon) >= eAbortScan) { + SCWrite(pCon, "ERROR: Maximizing interrupted", eError); + return 0; + } + return 1; +} - /* check interrupts */ - if(SCGetInterrupt(pCon) >= eAbortScan) - { - SCWrite(pCon,"ERROR: Maximizing interrupted",eError); - return 0; - } - return 1; - } /*----------------------------------------------------------------------*/ - static int maxCount(void *pCount, CounterMode eMode, - float fPreset, long *lCts, SConnection *pCon) - { - int iRet; +static int maxCount(void *pCount, CounterMode eMode, + float fPreset, long *lCts, SConnection * pCon) +{ + int iRet; + + SetCounterMode((pCounter) pCount, eMode); + iRet = DoCount((pCounter) pCount, fPreset, pCon, 1); + if (!iRet) { + return 0; + } + *lCts = GetCounts((pCounter) pCount, pCon); + if (SCGetInterrupt(pCon) >= eAbortScan) { + SCWrite(pCon, "ERROR: maximizing aborted", eError); + return 0; + } + return 1; +} - SetCounterMode((pCounter)pCount,eMode); - iRet = DoCount((pCounter)pCount, fPreset, pCon,1); - if(!iRet) - { - return 0; - } - *lCts = GetCounts((pCounter)pCount,pCon); - if(SCGetInterrupt(pCon) >= eAbortScan) - { - SCWrite(pCon,"ERROR: maximizing aborted",eError); - return 0; - } - return 1; - } /*----------------------------------------------------------------------*/ - static float readMPDrivable(void *pVar, SConnection *pCon) - { - float value = -999.99; - pIDrivable pDriv = NULL; - pDummy pDum = (pDummy)pVar; +static float readMPDrivable(void *pVar, SConnection * pCon) +{ + float value = -999.99; + pIDrivable pDriv = NULL; + pDummy pDum = (pDummy) pVar; + + pDriv = GetDrivableInterface(pVar); + assert(pDriv != NULL); + value = pDriv->GetValue(pVar, pCon); + return value; +} - pDriv = GetDrivableInterface(pVar); - assert(pDriv != NULL); - value = pDriv->GetValue(pVar,pCon); - return value; - } /*-----------------------------------------------------------------------*/ - int MaximizePeak(pMax self, void *pVar, char *pVarName, - float fStep, CounterMode eMode, - float fPreset, SConnection *pCon) - { - float x[MAXPTS], y[MAXPTS]; - float fMax, fCent, fS, fArea, fStart, fPos, fDA, fDisc; - int iBot, iTop, iMax, i, iRet, iSkip, iTMin, iTMax; - pIDrivable pDriv = NULL; - long lCts, lMax, lMin; - char pBueffel[132]; +int MaximizePeak(pMax self, void *pVar, char *pVarName, + float fStep, CounterMode eMode, + float fPreset, SConnection * pCon) +{ + float x[MAXPTS], y[MAXPTS]; + float fMax, fCent, fS, fArea, fStart, fPos, fDA, fDisc; + int iBot, iTop, iMax, i, iRet, iSkip, iTMin, iTMax; + pIDrivable pDriv = NULL; + long lCts, lMax, lMin; + char pBueffel[132]; - /* get drivable interface */ - pDriv = GetDrivableInterface(pVar); - if(!pDriv) - { - SCWrite(pCon,"ERROR: variable is NOT drivable, cannot maximize", - eError); - return 0; + /* get drivable interface */ + pDriv = GetDrivableInterface(pVar); + if (!pDriv) { + SCWrite(pCon, "ERROR: variable is NOT drivable, cannot maximize", + eError); + return 0; + } + +start: + lMax = 0; + lMin = 0x7fffffff; + fStart = readMPDrivable(pVar, pCon); + if (fStart < -999999.) { + return 0; + } + + /* search to the left until out of space or lCts < lMax/2. */ + SCWrite(pCon, "Searching for low angle boundary..", eLog); + for (i = self->maxpts / 2; i >= 0; i--) { + /* drive motor */ + fPos = fStart - (self->maxpts / 2 - i) * fStep; + fPos = in360(self, fPos); + if (maxDrive(pVar, pVarName, fPos, pCon) != 1) { + return 0; + } + x[i] = readMPDrivable(pVar, pCon); + /* count */ + if (maxCount(self->pCount, eMode, fPreset, &lCts, pCon) != 1) { + return 0; + } + /* print a message */ + snprintf(pBueffel,sizeof(pBueffel)-1, "%5d %8.2f %ld", i, x[i], lCts); + SCWrite(pCon, pBueffel, eLog); + + /* store counts and some logic */ + if (lCts < 1) { + y[i] = 0.; + } else { + y[i] = (float) lCts; + } + if (lCts > lMax) { + lMax = lCts; + iMax = i; + } + if (lCts < lMin) { + lMin = lCts; + } + if (lCts < lMax / 2) { + break; + } + } + /* some logic: the four cases */ + iSkip = 0; + iBot = i; + /* first case: peak out of range: do again */ + if ((iMax == 0) && (lMax / 2 > lMin)) { + goto start; + } + /* no peak found or normal peak: continue at other side */ + if ((i < 1) || (y[self->maxpts / 2] > lMax / 2)) { + iSkip = 0; + } else { + /* next case: all of the peak in measured half: + find max value and skip the right half + */ + for (i = self->maxpts / 2; i > 0; i--) { + if (y[i] > lMax / 2) { + iTop = i + 1; + break; } + } + iSkip = 1; + } - start: - lMax = 0; - lMin = 0x7fffffff; - fStart = readMPDrivable(pVar,pCon); - if(fStart < -999999.) - { - return 0; - } + /* + do the same to the right hand side, but only if required + */ + if (iSkip == 0) { + lMin = 100000; + lMax = -100000; + SCWrite(pCon, "Searching for high angle boundary..", eLog); + for (i = self->maxpts / 2; i < self->maxpts; i++) { + /* drive motor */ + fPos = fStart + (i - self->maxpts / 2) * fStep; + fPos = in360(self, fPos); + if (maxDrive(pVar, pVarName, fPos, pCon) != 1) { + return 0; + } + x[i] = readMPDrivable(pVar, pCon); + /* count */ + if (maxCount(self->pCount, eMode, fPreset, &lCts, pCon) != 1) { + return 0; + } + /* print a message */ + snprintf(pBueffel,sizeof(pBueffel)-1, "%5d %8.2f %ld", i, x[i], lCts); + SCWrite(pCon, pBueffel, eLog); - /* search to the left until out of space or lCts < lMax/2. */ - SCWrite(pCon,"Searching for low angle boundary..",eWarning); - for(i = self->maxpts/2; i >= 0; i--) - { - /* drive motor */ - fPos = fStart - (self->maxpts/2 - i)*fStep; - fPos = in360(self,fPos); - if(maxDrive(pVar,pVarName,fPos,pCon) != 1) - { - return 0; - } - x[i] = readMPDrivable(pVar,pCon); - /* count */ - if(maxCount(self->pCount,eMode,fPreset, &lCts,pCon) != 1) - { - return 0; - } - /* print a message */ - sprintf(pBueffel,"%5d %8.2f %ld",i,x[i],lCts); - SCWrite(pCon,pBueffel,eWarning); - - /* store counts and some logic */ - if(lCts < 1) - { - y[i] = 0.; - } - else - { - y[i] = (float)lCts; - } - if(lCts > lMax) - { - lMax = lCts; - iMax = i; - } - if(lCts < lMin) - { - lMin = lCts; - } - if(lCts < lMax/2) - { - break; - } - } - /* some logic: the four cases */ - iSkip = 0; - iBot = i; - /* first case: peak out of range: do again */ - if( (iMax == 0) && (lMax/2 > lMin) ) - { - goto start; - } - /* no peak found or normal peak: continue at other side */ - if( (i < 1) || (y[self->maxpts/2] > lMax/2) ) - { - iSkip = 0; - } - else - { - /* next case: all of the peak in measured half: - find max value and skip the right half - */ - for(i = self->maxpts/2; i > 0; i--) - { - if(y[i] > lMax/2) - { - iTop = i + 1; - break; - } - } - iSkip = 1; - } - - /* - do the same to the right hand side, but only if required - */ - if(iSkip == 0) - { - lMin = 100000; - lMax = -100000; - SCWrite(pCon,"Searching for high angle boundary..",eWarning); - for(i = self->maxpts/2; i < self->maxpts; i++) - { - /* drive motor */ - fPos = fStart + (i - self->maxpts/2) * fStep; - fPos = in360(self,fPos); - if(maxDrive(pVar,pVarName,fPos,pCon) != 1) - { - return 0; - } - x[i] = readMPDrivable(pVar,pCon); - /* count */ - if(maxCount(self->pCount,eMode,fPreset, &lCts,pCon) != 1) - { - return 0; - } - /* print a message */ - sprintf(pBueffel,"%5d %8.2f %ld",i,x[i],lCts); - SCWrite(pCon,pBueffel,eWarning); - - /* store counts and some logic */ - if(lCts < 1) - { - y[i] = 0.; - } - else - { - y[i] = (float)lCts; - } - if(lCts > lMax) - { - lMax = lCts; - iMax = i; - } - if(lCts < lMin) - { - lMin = lCts; - } - if(lCts < lMax/2) - { - break; - } - } - /* some logic again: four cases */ - iTop = i; - iTop++; - /* first case: peak is at high angle side */ - if( (i > self->maxpts-2) && (lMax*0.5 > lMin) ) - { - goto start; - } - /* second case: no peak */ - if( (iTop > self->maxpts-2) ) - { - SCWrite(pCon,"ERROR: no peak found!",eError); - return 0; - } - /* third case: normal peak */ - if(y[self->maxpts/2] >= 0.5*lMax) - { - iTop--; - } - /* - fourth case: the peak is completely at the high angle - side - */ - else - { - for(i = self->maxpts/2; i < self->maxpts; i++) - { - if(y[i] > lMax/2) - { - iBot = i - 1; - break; - } - } - iTop--; - } - } /* end of iSkip */ - - if( (iBot < 2) || (iTop > self->maxpts-2) || (lMax < lMin*2) ) - { - SCWrite(pCon,"ERROR: no peak found!",eError); - return 0; - } + /* store counts and some logic */ + if (lCts < 1) { + y[i] = 0.; + } else { + y[i] = (float) lCts; + } + if (lCts > lMax) { + lMax = lCts; + iMax = i; + } + if (lCts < lMin) { + lMin = lCts; + } + if (lCts < lMax / 2) { + break; + } + } + /* some logic again: four cases */ + iTop = i; + iTop++; + /* first case: peak is at high angle side */ + if ((i > self->maxpts - 2) && (lMax * 0.5 > lMin)) { + goto start; + } + /* second case: no peak */ + if ((iTop > self->maxpts - 2)) { + SCWrite(pCon, "ERROR: no peak found!", eError); + return 0; + } + /* third case: normal peak */ + if (y[self->maxpts / 2] >= 0.5 * lMax) { + iTop--; + } + /* + fourth case: the peak is completely at the high angle + side + */ + else { + for (i = self->maxpts / 2; i < self->maxpts; i++) { + if (y[i] > lMax / 2) { + iBot = i - 1; + break; + } + } + iTop--; + } + } + /* end of iSkip */ + if ((iBot < 2) || (iTop > self->maxpts - 2) || (lMax < lMin * 2)) { + SCWrite(pCon, "ERROR: no peak found!", eError); + return 0; + } #ifdef DEBUG - sprintf(pBueffel,"iBot = %d, iTop = %d, lMax = %ld", - iBot, iTop, lMax); - SCWrite(pCon,pBueffel,eWarning); -#endif - - /* calculate median */ - fArea = 0.; - for(i = iBot; i < iTop; i++) - { - fArea += (x[i+1] - x[i])*(y[i+1] + y[i])*.25; - } - fS = 0.; - for(i = iBot; i < iTop; i++) - { - fS += (x[i+1] -x[i])*(y[i+1] +y[i]) *.5; - if(fS > fArea) - { - break; - } - } - fS -= .5*(x[i+1] - x[i])*(y[i+1] + y[i]); - fDA = fArea - fS; - if(y[i+1] == y[i]) - { - fCent = x[i] + fDA/y[i]; - } - else - { - fS = (y[i+1] - y[i])/(x[i+1] -x[i]); - if( (y[i]*y[i] + 2. * fS * fDA) < 0.) - { - SCWrite(pCon,"ERROR calculating median",eError); - return 0; - } - fDisc = sqrt(y[i]*y[i] + 2.* fS * fDA); - fCent = x[i] +(fDisc -y[i])/fS; - } - /* finished ! */ - maxDrive(pVar,pVarName,fCent,pCon); - sprintf(pBueffel,"Found peak center at %8.2f", fCent); - SCWrite(pCon,pBueffel,eValue); - return 1; - } + snprintf(pBueffel,sizeof(pBueffel)-1, "iBot = %d, iTop = %d, lMax = %ld", iBot, iTop, lMax); + SCWrite(pCon, pBueffel, eWarning); +#endif + + /* calculate median */ + fArea = 0.; + for (i = iBot; i < iTop; i++) { + fArea += (x[i + 1] - x[i]) * (y[i + 1] + y[i]) * .25; + } + fS = 0.; + for (i = iBot; i < iTop; i++) { + fS += (x[i + 1] - x[i]) * (y[i + 1] + y[i]) * .5; + if (fS > fArea) { + break; + } + } + fS -= .5 * (x[i + 1] - x[i]) * (y[i + 1] + y[i]); + fDA = fArea - fS; + if (y[i + 1] == y[i]) { + fCent = x[i] + fDA / y[i]; + } else { + fS = (y[i + 1] - y[i]) / (x[i + 1] - x[i]); + if ((y[i] * y[i] + 2. * fS * fDA) < 0.) { + SCWrite(pCon, "ERROR calculating median", eError); + return 0; + } + fDisc = sqrt(y[i] * y[i] + 2. * fS * fDA); + fCent = x[i] + (fDisc - y[i]) / fS; + } + /* finished ! */ + for (i = 0; i < iTop - 1; i++) { + if (fCent >= x[i] && fCent < x[i + 1]) { + lCts = y[i]; + break; + } + } + maxDrive(pVar, pVarName, fCent, pCon); + snprintf(pBueffel,sizeof(pBueffel)-1, "Found peak center at %8.2f, Count = %ld", fCent, + lCts); + SCWrite(pCon, pBueffel, eValue); + return 1; +} + /*------------------------------------------------------------------*/ - static void MaxKill(void *pData) - { - pMax self = (pMax)pData; - if(self == NULL) - return; +static void MaxKill(void *pData) +{ + pMax self = (pMax) pData; + if (self == NULL) + return; + + if (self->pDes) + DeleteDescriptor(self->pDes); + free(self); +} - if(self->pDes) - DeleteDescriptor(self->pDes); - free(self); - } /*-------------------- wrap-i-wrap ----------------------------------*/ - int MaximizeFactory(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - pMax pNew = NULL; - CommandList *pCom = NULL; - pICountable pCts = NULL; +int MaximizeFactory(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pMax pNew = NULL; + CommandList *pCom = NULL; + pICountable pCts = NULL; - if(argc < 2) - { - SCWrite(pCon, - "ERROR: insufficient number of arguments to MaximizeFactory", - eError); - return 0; - } + if (argc < 2) { + SCWrite(pCon, + "ERROR: insufficient number of arguments to MaximizeFactory", + eError); + return 0; + } - /* find a countable */ - pCom = FindCommand(pSics,argv[1]); - if(pCom == NULL) - { - SCWrite(pCon,"ERROR: counter not found in MaximizeFactory", - eError); - return 0; - } - pCts = GetCountableInterface(pCom->pData); - if(!pCts) - { - SCWrite(pCon,"ERROR: argument to MaximizeFactory is no counter", - eError); - return 0; - } - pNew = (pMax)malloc(sizeof(Maxxii)); - pNew->pDes = CreateDescriptor("Maximizer"); - pNew->pCount = pCom->pData; - pNew->i360 = 0; - pNew->maxpts = 100; + /* find a countable */ + pCom = FindCommand(pSics, argv[1]); + if (pCom == NULL) { + SCWrite(pCon, "ERROR: counter not found in MaximizeFactory", eError); + return 0; + } + pCts = GetCountableInterface(pCom->pData); + if (!pCts) { + SCWrite(pCon, "ERROR: argument to MaximizeFactory is no counter", + eError); + return 0; + } + pNew = (pMax) malloc(sizeof(Maxxii)); + pNew->pDes = CreateDescriptor("Maximizer"); + pNew->pCount = pCom->pData; + pNew->i360 = 0; + pNew->maxpts = 100; + + AddCommand(pSics, "max", MaximizeAction, MaxKill, pNew); + return 1; +} - AddCommand(pSics,"max",MaximizeAction,MaxKill,pNew); - return 1; - } /*------------------------------------------------------------------ * max motor step preset mode * ---------------------------------------------------------------------*/ - int MaximizeAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - pMax self = NULL; - CommandList *pCom = NULL; - char pBueffel[256]; - double dVal; - float fStep, fPreset; - CounterMode eCount; - int iRet, iVal; +int MaximizeAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pMax self = NULL; + CommandList *pCom = NULL; + char pBueffel[256]; + double dVal; + float fStep, fPreset; + CounterMode eCount; + int iRet, iVal; - self = (pMax)pData; - assert(self); - assert(pCon); + self = (pMax) pData; + assert(self); + assert(pCon); - /* check privilege */ - if(!SCMatchRights(pCon,usUser)) - { - return 1; - } + /* check privilege */ + if (!SCMatchRights(pCon, usUser)) { + return 1; + } - /* enough arguments ?*/ - if(argc < 5) - { - if(argc > 1) - { - strtolower(argv[1]); - if(strcmp(argv[1],"in360") == 0) - { - if(argc > 2) - { - iVal = atoi(argv[2]); - if(iVal != 0 && iVal != 1) { - SCWrite(pCon,"ERROR: only 0, 1 allowed for in360",eError); - return 0; - } - self->i360 = iVal; - SCSendOK(pCon); - return 1; - } - else - { - snprintf(pBueffel,255,"max.in360 = %d", self->i360); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - } - if(strcmp(argv[1],"maxpts") == 0) - { - if(argc > 2) - { - iVal = atoi(argv[2]); - if(iVal < 10 || iVal > 100) { - SCWrite(pCon,"ERROR: maxpst must be between 10 and 100", - eError); - return 0; - } - self->maxpts = iVal; - SCSendOK(pCon); - return 1; - } - else - { - snprintf(pBueffel,255,"max.maxpts = %d", self->maxpts); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - } - + /* enough arguments ? */ + if (argc < 5) { + if (argc > 1) { + strtolower(argv[1]); + if (strcmp(argv[1], "in360") == 0) { + if (argc > 2) { + iVal = atoi(argv[2]); + if (iVal != 0 && iVal != 1) { + SCWrite(pCon, "ERROR: only 0, 1 allowed for in360", eError); + return 0; + } + self->i360 = iVal; + SCSendOK(pCon); + return 1; + } else { + snprintf(pBueffel, 255, "max.in360 = %d", self->i360); + SCWrite(pCon, pBueffel, eValue); + return 1; + } + } + if (strcmp(argv[1], "maxpts") == 0) { + if (argc > 2) { + iVal = atoi(argv[2]); + if (iVal < 10 || iVal > 100) { + SCWrite(pCon, "ERROR: maxpst must be between 10 and 100", + eError); + return 0; + } + self->maxpts = iVal; + SCSendOK(pCon); + return 1; + } else { + snprintf(pBueffel, 255, "max.maxpts = %d", self->maxpts); + SCWrite(pCon, pBueffel, eValue); + return 1; } - SCWrite(pCon,"ERROR: Insufficient number of arguments to max", - eError); - return 0; - } - - /* decode arguments */ - pCom = FindCommand(pSics,argv[1]); - if(!pCom) - { - sprintf(pBueffel,"ERROR: object %s NOT found!", - argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - if(!pCom->pData) - { - sprintf(pBueffel,"ERROR: object %s Invalid!!", - argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - iRet = Tcl_GetDouble(pSics->pTcl,argv[2], &dVal); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: failed to convert %s to number", - argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; } - fStep = (float)dVal; - iRet = Tcl_GetDouble(pSics->pTcl,argv[4], &dVal); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: failed to convert %s to number", - argv[4]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - fPreset = (float)dVal; + } + SCWrite(pCon, "ERROR: Insufficient number of arguments to max", + eError); + return 0; + } - /* convert countmode */ - strtolower(argv[3]); - if(strcmp(argv[3],"timer") == 0) - { - eCount = eTimer; - } - else - { - eCount = ePreset; - } - return MaximizePeak(self,pCom->pData, argv[1],fStep,eCount, - fPreset, pCon); - } + /* decode arguments */ + pCom = FindCommand(pSics, argv[1]); + if (!pCom) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: object %s NOT found!", argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + if (!pCom->pData) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: object %s Invalid!!", argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + iRet = Tcl_GetDouble(pSics->pTcl, argv[2], &dVal); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: failed to convert %s to number", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + fStep = (float) dVal; + + iRet = Tcl_GetDouble(pSics->pTcl, argv[4], &dVal); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: failed to convert %s to number", argv[4]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + fPreset = (float) dVal; + + /* convert countmode */ + strtolower(argv[3]); + if (strcmp(argv[3], "timer") == 0) { + eCount = eTimer; + } else { + eCount = ePreset; + } + return MaximizePeak(self, pCom->pData, argv[1], fStep, eCount, + fPreset, pCon); +} diff --git a/maximize.h b/maximize.h index 06fd64c2..c38abd7b 100644 --- a/maximize.h +++ b/maximize.h @@ -12,11 +12,11 @@ #ifndef SICSMAXIMIZE #define SICSMAXIMIZE - typedef struct __MAXIMIZE *pMax; +typedef struct __MAXIMIZE *pMax; - int MaximizePeak(pMax self, void *pVar, char *pVarName, - float fStep, CounterMode eMode, - float fPreset, SConnection *pCon); +int MaximizePeak(pMax self, void *pVar, char *pVarName, + float fStep, CounterMode eMode, + float fPreset, SConnection * pCon); /* * Locates the maximum of a peak with respect to the motor or virtual @@ -26,10 +26,8 @@ * reported. */ /*------------------------ Wrapper functions ----------------------------*/ - int MaximizeFactory(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - int MaximizeAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); +int MaximizeFactory(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); +int MaximizeAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); #endif - - diff --git a/mccontrol.c b/mccontrol.c index 1927259e..f89ba5ce 100644 --- a/mccontrol.c +++ b/mccontrol.c @@ -17,435 +17,466 @@ #include "stringdict.h" #include "mccontrol.h" /*========================= life and death ==================================*/ -static void KillMcStasController(void *pData){ - pMcStasController self = (pMcStasController)pData; - if(self == NULL){ - return; - } - if(self->pDes != NULL){ - DeleteDescriptor(self->pDes); - } - if(self->scripts != NULL){ - DeleteStringDict(self->scripts); - } - free(self); +static void KillMcStasController(void *pData) +{ + pMcStasController self = (pMcStasController) pData; + if (self == NULL) { + return; + } + if (self->pDes != NULL) { + DeleteDescriptor(self->pDes); + } + if (self->scripts != NULL) { + DeleteStringDict(self->scripts); + } + free(self); } + /*---------------------------------------------------------------------------*/ -int McStasControllerFactory(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]){ - pMcStasController pNew = NULL; - - pNew = (pMcStasController)malloc(sizeof(McStasController)); - if(pNew == NULL){ - SCWrite(pCon,"ERROR: out of memory creating McStasController", - eError); - return 0; - } - memset(pNew,0,sizeof(McStasController)); - - pNew->pDes = CreateDescriptor("McStasController"); - pNew->scripts = CreateStringDict(); - if(pNew->pDes == NULL || pNew->scripts == NULL){ - SCWrite(pCon,"ERROR: out of memory creating McStasController", - eError); - free(pNew); - return 0; - } - StringDictAddPair(pNew->scripts,"mcstart","UNDEFINED"); - StringDictAddPair(pNew->scripts,"mcisrunning","UNDEFINED"); - StringDictAddPair(pNew->scripts,"mcdump","UNDEFINED"); - StringDictAddPair(pNew->scripts,"mckill","UNDEFINED"); - StringDictAddPair(pNew->scripts,"mccopydata","UNDEFINED"); - StringDictAddPair(pNew->scripts,"mcmonfile","UNDEFINED"); - pNew->pid = -1; - pNew->monitorScale = 1; - - return AddCommand(pSics,"mccontrol", - McStasControllerWrapper, - KillMcStasController, - pNew); -} -/*====================== interpreter interface ============================*/ -static int configureController(pMcStasController self, SConnection *pCon, - int argc, char *argv[]){ - char pBueffel[256]; - - if(argc < 4){ - SCWrite(pCon, - "ERRROR: insufficient number of arguments to mccontrol configure", - eError); - return 0; - } - strtolower(argv[2]); - if(strcmp(argv[2],"update") == 0){ - self->updateIntervall = atoi(argv[3]); - SCSendOK(pCon); - return 1; - } - if(strcmp(argv[2],"monitorscale") == 0){ - self->monitorScale = atof(argv[3]); - if(self->monitorScale <= 0){ - SCWrite(pCon,"ERROR: invalid monitor scale",eError); - self->monitorScale = 1; - return 0; - } - SCSendOK(pCon); - return 1; - } - if(!StringDictExists(self->scripts,argv[2])){ - snprintf(pBueffel,255,"ERROR: scriptkey %s does not exist",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - StringDictUpdate(self->scripts,argv[2],argv[3]); - SCSendOK(pCon); - return 1; -} -/*------------------------------------------------------------------------*/ -static void listConfiguration(pMcStasController self, SConnection *pCon){ - Tcl_DString txt; - char pLine[256]; - char pScript[131]; - - Tcl_DStringInit(&txt); - StringDictGet(self->scripts,"mcstart",pScript,131); - snprintf(pLine,255,"mccontrol.mcstart = %s\n",pScript); - Tcl_DStringAppend(&txt,pLine,-1); - StringDictGet(self->scripts,"mcisrunning",pScript,131); - snprintf(pLine,255,"mccontrol.mcisrunning = %s\n",pScript); - Tcl_DStringAppend(&txt,pLine,-1); - StringDictGet(self->scripts,"mcdump",pScript,131); - snprintf(pLine,255,"mccontrol.mcdump = %s\n",pScript); - Tcl_DStringAppend(&txt,pLine,-1); - StringDictGet(self->scripts,"mckill",pScript,131); - snprintf(pLine,255,"mccontrol.mckill = %s\n",pScript); - Tcl_DStringAppend(&txt,pLine,-1); - StringDictGet(self->scripts,"mccopydata",pScript,131); - snprintf(pLine,255,"mccontrol.mccopydata = %s\n",pScript); - Tcl_DStringAppend(&txt,pLine,-1); - StringDictGet(self->scripts,"mcmonfile",pScript,131); - snprintf(pLine,255,"mccontrol.mcmonfile = %s\n",pScript); - Tcl_DStringAppend(&txt,pLine,-1); - snprintf(pLine,255,"mccontrol.updateintervall = %d\n", - self->updateIntervall); - Tcl_DStringAppend(&txt,pLine,-1); - snprintf(pLine,255,"mccontrol.monitorscale = %f\n", - self->monitorScale); - Tcl_DStringAppend(&txt,pLine,-1); - snprintf(pLine,255,"mccontrol.pid = %d", self->pid); - Tcl_DStringAppend(&txt,pLine,-1); +int McStasControllerFactory(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]) +{ + pMcStasController pNew = NULL; - SCWrite(pCon,Tcl_DStringValue(&txt),eValue); - Tcl_DStringFree(&txt); + pNew = (pMcStasController) malloc(sizeof(McStasController)); + if (pNew == NULL) { + SCWrite(pCon, "ERROR: out of memory creating McStasController", + eError); + return 0; + } + memset(pNew, 0, sizeof(McStasController)); + + pNew->pDes = CreateDescriptor("McStasController"); + pNew->scripts = CreateStringDict(); + if (pNew->pDes == NULL || pNew->scripts == NULL) { + SCWrite(pCon, "ERROR: out of memory creating McStasController", + eError); + free(pNew); + return 0; + } + StringDictAddPair(pNew->scripts, "mcstart", "UNDEFINED"); + StringDictAddPair(pNew->scripts, "mcisrunning", "UNDEFINED"); + StringDictAddPair(pNew->scripts, "mcdump", "UNDEFINED"); + StringDictAddPair(pNew->scripts, "mckill", "UNDEFINED"); + StringDictAddPair(pNew->scripts, "mccopydata", "UNDEFINED"); + StringDictAddPair(pNew->scripts, "mcmonfile", "UNDEFINED"); + pNew->pid = -1; + pNew->monitorScale = 1; + + return AddCommand(pSics, "mccontrol", + McStasControllerWrapper, KillMcStasController, pNew); } + +/*====================== interpreter interface ============================*/ +static int configureController(pMcStasController self, SConnection * pCon, + int argc, char *argv[]) +{ + char pBueffel[256]; + + if (argc < 4) { + SCWrite(pCon, + "ERRROR: insufficient number of arguments to mccontrol configure", + eError); + return 0; + } + strtolower(argv[2]); + if (strcmp(argv[2], "update") == 0) { + self->updateIntervall = atoi(argv[3]); + SCSendOK(pCon); + return 1; + } + if (strcmp(argv[2], "monitorscale") == 0) { + self->monitorScale = atof(argv[3]); + if (self->monitorScale <= 0) { + SCWrite(pCon, "ERROR: invalid monitor scale", eError); + self->monitorScale = 1; + return 0; + } + SCSendOK(pCon); + return 1; + } + if (!StringDictExists(self->scripts, argv[2])) { + snprintf(pBueffel, 255, "ERROR: scriptkey %s does not exist", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + StringDictUpdate(self->scripts, argv[2], argv[3]); + SCSendOK(pCon); + return 1; +} + +/*------------------------------------------------------------------------*/ +static void listConfiguration(pMcStasController self, SConnection * pCon) +{ + Tcl_DString txt; + char pLine[256]; + char pScript[131]; + + Tcl_DStringInit(&txt); + StringDictGet(self->scripts, "mcstart", pScript, 131); + snprintf(pLine, 255, "mccontrol.mcstart = %s\n", pScript); + Tcl_DStringAppend(&txt, pLine, -1); + StringDictGet(self->scripts, "mcisrunning", pScript, 131); + snprintf(pLine, 255, "mccontrol.mcisrunning = %s\n", pScript); + Tcl_DStringAppend(&txt, pLine, -1); + StringDictGet(self->scripts, "mcdump", pScript, 131); + snprintf(pLine, 255, "mccontrol.mcdump = %s\n", pScript); + Tcl_DStringAppend(&txt, pLine, -1); + StringDictGet(self->scripts, "mckill", pScript, 131); + snprintf(pLine, 255, "mccontrol.mckill = %s\n", pScript); + Tcl_DStringAppend(&txt, pLine, -1); + StringDictGet(self->scripts, "mccopydata", pScript, 131); + snprintf(pLine, 255, "mccontrol.mccopydata = %s\n", pScript); + Tcl_DStringAppend(&txt, pLine, -1); + StringDictGet(self->scripts, "mcmonfile", pScript, 131); + snprintf(pLine, 255, "mccontrol.mcmonfile = %s\n", pScript); + Tcl_DStringAppend(&txt, pLine, -1); + snprintf(pLine, 255, "mccontrol.updateintervall = %d\n", + self->updateIntervall); + Tcl_DStringAppend(&txt, pLine, -1); + snprintf(pLine, 255, "mccontrol.monitorscale = %f\n", + self->monitorScale); + Tcl_DStringAppend(&txt, pLine, -1); + snprintf(pLine, 255, "mccontrol.pid = %d", self->pid); + Tcl_DStringAppend(&txt, pLine, -1); + + SCWrite(pCon, Tcl_DStringValue(&txt), eValue); + Tcl_DStringFree(&txt); +} + /*--------------------------------------------------------------------------*/ -static int invokeScript(pMcStasController self, char *name, SicsInterp *pSics, - char *result, int resultLen){ - char pCommand[256], pScript[132], pMode[10]; - Tcl_Interp *pTcl; - int status; - - if(!StringDictGet(self->scripts,name,pScript,131)){ - strncpy(result,"ERROR: script not found",resultLen); - return 0; - } - - if(strcmp(name,"mccopydata") == 0){ - snprintf(pCommand,255,"%s",pScript); - }else if(strcmp(name,"mcstart") == 0){ - if(self->mode == eTimer){ - strcpy(pMode,"timer"); - }else { - strcpy(pMode,"monitor"); - } - snprintf(pCommand,255,"%s %s %f", pScript,pMode,self->fPreset); - } else { - snprintf(pCommand,255,"%s %d",pScript,self->pid); - } - - pTcl = InterpGetTcl(pSics); - status = Tcl_Eval(pTcl,pCommand); - strncpy(result, pTcl->result, resultLen); - if(status == TCL_OK){ - return 1; - } else { - return 0; - } -} -/*------------------------------------------------------------------------*/ -static int runScript(pMcStasController self, SConnection *pCon, - SicsInterp *pSics, int argc, char *argv[]){ - char pResult[256]; - int status; - - if(argc < 3){ - SCWrite(pCon, - "ERRROR: insufficient number of arguments to mccontrol run", - eError); - return 0; - } - status = invokeScript(self,argv[2],pSics,pResult,255); - if(status == 1){ - SCWrite(pCon,pResult,eValue); - return 1; - } else { - SCWrite(pCon,pResult,eError); - return 0; - } -} -/*------------------------------------------------------------------------*/ -static int start(pMcStasController self, SConnection *pCon){ - int status; +static int invokeScript(pMcStasController self, char *name, + SicsInterp * pSics, char *result, int resultLen) +{ + char pCommand[256], pScript[132], pMode[10]; + Tcl_Interp *pTcl; + int status; - status = McStasStart(self,eTimer,1000.); - if(status != OKOK){ - SCWrite(pCon,self->errorText,eError); - return 0; - } - SCSendOK(pCon); - return 1; -} -/*-----------------------------------------------------------------------*/ -static void wait4Finish(pMcStasController self){ - int status; - - if(self->pid > 0){ - status = waitpid(self->pid,NULL,WNOHANG); - if(status >= 0){ - self->pid = -1; - } - } -} -/*-------------------------------------------------------------------------*/ -int McStasControllerWrapper(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]){ - pMcStasController self = NULL; - char pBueffel[255], pFile[132]; - - self = (pMcStasController)pData; - assert(self); - if(argc < 2) { - SCWrite(pCon,"ERROR: insufficient number of arguments to mccontrol", - eError); - return 0; - } - strtolower(argv[1]); - if(strcmp(argv[1],"configure") == 0){ - return configureController(self,pCon,argc,argv); - } else if(strcmp(argv[1],"list") == 0){ - listConfiguration(self,pCon); - return 1; - } else if(strcmp(argv[1],"run") == 0){ - return runScript(self,pCon,pSics,argc,argv); - } else if(strcmp(argv[1],"start") == 0){ - return start(self,pCon); - } else if(strcmp(argv[1],"finish") == 0){ - wait4Finish(self); - SCSendOK(pCon); - return 1; + if (!StringDictGet(self->scripts, name, pScript, 131)) { + strlcpy(result, "ERROR: script not found", resultLen); + return 0; + } + + if (strcmp(name, "mccopydata") == 0) { + snprintf(pCommand, 255, "%s", pScript); + } else if (strcmp(name, "mcstart") == 0) { + if (self->mode == eTimer) { + strcpy(pMode, "timer"); } else { - snprintf(pBueffel,255,"ERROR: subcommand %s to mccontrol unknown", - argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; + strcpy(pMode, "monitor"); } - return 0; + snprintf(pCommand, 255, "%s %s %f", pScript, pMode, self->fPreset); + } else { + snprintf(pCommand, 255, "%s %d", pScript, self->pid); + } + + pTcl = InterpGetTcl(pSics); + status = Tcl_Eval(pTcl, pCommand); + strlcpy(result, pTcl->result, resultLen); + if (status == TCL_OK) { + return 1; + } else { + return 0; + } } + +/*------------------------------------------------------------------------*/ +static int runScript(pMcStasController self, SConnection * pCon, + SicsInterp * pSics, int argc, char *argv[]) +{ + char pResult[256]; + int status; + + if (argc < 3) { + SCWrite(pCon, + "ERRROR: insufficient number of arguments to mccontrol run", + eError); + return 0; + } + status = invokeScript(self, argv[2], pSics, pResult, 255); + if (status == 1) { + SCWrite(pCon, pResult, eValue); + return 1; + } else { + SCWrite(pCon, pResult, eError); + return 0; + } +} + +/*------------------------------------------------------------------------*/ +static int start(pMcStasController self, SConnection * pCon) +{ + int status; + + status = McStasStart(self, eTimer, 1000.); + if (status != OKOK) { + SCWrite(pCon, self->errorText, eError); + return 0; + } + SCSendOK(pCon); + return 1; +} + +/*-----------------------------------------------------------------------*/ +static void wait4Finish(pMcStasController self) +{ + int status; + + if (self->pid > 0) { + status = waitpid(self->pid, NULL, WNOHANG); + if (status >= 0) { + self->pid = -1; + } + } +} + +/*-------------------------------------------------------------------------*/ +int McStasControllerWrapper(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]) +{ + pMcStasController self = NULL; + char pBueffel[255], pFile[132]; + + self = (pMcStasController) pData; + assert(self); + if (argc < 2) { + SCWrite(pCon, "ERROR: insufficient number of arguments to mccontrol", + eError); + return 0; + } + strtolower(argv[1]); + if (strcmp(argv[1], "configure") == 0) { + return configureController(self, pCon, argc, argv); + } else if (strcmp(argv[1], "list") == 0) { + listConfiguration(self, pCon); + return 1; + } else if (strcmp(argv[1], "run") == 0) { + return runScript(self, pCon, pSics, argc, argv); + } else if (strcmp(argv[1], "start") == 0) { + return start(self, pCon); + } else if (strcmp(argv[1], "finish") == 0) { + wait4Finish(self); + SCSendOK(pCon); + return 1; + } else { + snprintf(pBueffel, 255, "ERROR: subcommand %s to mccontrol unknown", + argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + return 0; +} + /*========================== the actual action functions =================*/ -int McStasStart(pMcStasController self, CounterMode mode, float fPreset){ - char pResult[256]; - int status; - FILE *fd = NULL; - - self->fPreset = fPreset; - self->mode = mode; - /** +int McStasStart(pMcStasController self, CounterMode mode, float fPreset) +{ + char pResult[256]; + int status; + FILE *fd = NULL; + + self->fPreset = fPreset; + self->mode = mode; + /** * make sure that the monitor file has only a 0 in it... */ - if(!StringDictGet(self->scripts,"mcmonfile",pResult,255)){ - strncpy(self->errorText,"Misconfiguration: no monfile",255); - return HWFault; - } - fd = fopen(pResult,"w"); - if(fd == NULL){ - strncpy(self->errorText,"Failed to access monitor file",255); - return HWFault; - } - fprintf(fd,"0\n"); - fclose(fd); - - /* - * invoke start script - */ - status = invokeScript(self,"mcstart",pServ->pSics,pResult,255); - if(status == 0){ - strncpy(self->errorText,pResult,255); - return HWFault; - } - - /* - * some general initializations .. - */ - self->pid = atoi(pResult); - self->startTime = time(NULL); - self->lastUpdate = self->startTime - self->updateIntervall; - self->lastMonitorRead = self->startTime; - return OKOK; + if (!StringDictGet(self->scripts, "mcmonfile", pResult, 255)) { + strlcpy(self->errorText, "Misconfiguration: no monfile", 255); + return HWFault; + } + fd = fopen(pResult, "w"); + if (fd == NULL) { + strlcpy(self->errorText, "Failed to access monitor file", 255); + return HWFault; + } + fprintf(fd, "0\n"); + fclose(fd); + + /* + * invoke start script + */ + status = invokeScript(self, "mcstart", pServ->pSics, pResult, 255); + if (status == 0) { + strlcpy(self->errorText, pResult, 255); + return HWFault; + } + + /* + * some general initializations .. + */ + self->pid = atoi(pResult); + self->startTime = time(NULL); + self->lastUpdate = self->startTime - self->updateIntervall; + self->lastMonitorRead = self->startTime; + return OKOK; } + /*------------------------------------------------------------------------*/ -static long readMonFile(pMcStasController self){ - char pResult[256]; - FILE *fd = NULL; - long monValue = -1; - int i; - - if(!StringDictGet(self->scripts,"mcmonfile",pResult,255)){ - return -1; - } +static long readMonFile(pMcStasController self) +{ + char pResult[256]; + FILE *fd = NULL; + long monValue = -1; + int i; - fd = fopen(pResult,"r"); - if(fd != NULL){ - fscanf(fd,"%ld", &monValue); - fclose(fd); - } - return monValue; + if (!StringDictGet(self->scripts, "mcmonfile", pResult, 255)) { + return -1; + } + + fd = fopen(pResult, "r"); + if (fd != NULL) { + fscanf(fd, "%ld", &monValue); + fclose(fd); + } + return monValue; } + /*------------------------------------------------------------------------*/ -int McStasStatus(pMcStasController self, float *fControl){ - char pResult[256]; - float monValue; - int status, i; +int McStasStatus(pMcStasController self, float *fControl) +{ + char pResult[256]; + float monValue; + int status, i; - /* - * check at max any second, else SICS keeps the system busy and - * there is no CPU left for McStas - */ - SicsWait(1); - status = invokeScript(self,"mcisrunning",pServ->pSics,pResult, 255); - if(status == 0){ - strncpy(self->errorText,pResult,255); - return HWFault; - } - status = atoi(pResult); - /* - * handle timer mode - */ - if(status == 1 && self->mode == eTimer && - time(NULL) >= self->startTime + (int)self->fPreset){ - McStasStop(self); - return HWBusy; - } else { - *fControl = time(NULL) - self->startTime; - } - /* - * handle monitor mode - */ - if(status == 1 && self->mode == ePreset){ - /* - * check only any three seconds, else SICS uses up all the CPU time - * and the simulation has no chance. - */ - *fControl = self->lastMon; - if(time(NULL) < self->lastMonitorRead + 3) { - return HWBusy; - } - monValue = -1; - /* - * try to read the monfile up to three times. Problems reading it - * can be synchronisation problems with McStas - */ - for(i = 0, monValue = -1; i < 7; i++){ - monValue = (float)readMonFile(self); - if(monValue >= 0){ - break; - } - } - if(monValue < 0){ - return HWBusy; - } - self->lastMonitorRead = time(NULL); - monValue *= self->monitorScale; - *fControl = monValue; - self->lastMon = monValue; - if(monValue >= self->fPreset){ - McStasStop(self); - } - } - - if(status == 1){ - return HWBusy; - } else { - self->stopTime = time(NULL); - self->pid = -1; - return HWIdle; - } -} -/*-------------------------------------------------------------------------*/ -int McStasStop(pMcStasController self){ - char pResult[256]; - invokeScript(self,"mckill",pServ->pSics,pResult, 255); - self->lastUpdate = time(NULL) - 3*self->updateIntervall; - return 1; -} -/*-------------------------------------------------------------------------*/ -int McStasTransferData(pMcStasController self){ - char pResult[256]; - int status; - - /* - * prevent to frequent requests - */ - if(self->lastUpdate + self->updateIntervall > time(NULL)){ - return OKOK; - } + /* + * check at max any second, else SICS keeps the system busy and + * there is no CPU left for McStas + */ + SicsWait(1); + status = invokeScript(self, "mcisrunning", pServ->pSics, pResult, 255); + if (status == 0) { + strlcpy(self->errorText, pResult, 255); + return HWFault; + } + status = atoi(pResult); + /* + * handle timer mode + */ + if (status == 1 && self->mode == eTimer && + time(NULL) >= self->startTime + (int) self->fPreset) { + McStasStop(self); + return HWBusy; + } else { + *fControl = time(NULL) - self->startTime; + } + /* + * handle monitor mode + */ + if (status == 1 && self->mode == ePreset) { + /* + * check only any three seconds, else SICS uses up all the CPU time + * and the simulation has no chance. + */ + *fControl = self->lastMon; + if (time(NULL) < self->lastMonitorRead + 3) { + return HWBusy; + } + monValue = -1; + /* + * try to read the monfile up to three times. Problems reading it + * can be synchronisation problems with McStas + */ + for (i = 0, monValue = -1; i < 7; i++) { + monValue = (float) readMonFile(self); + if (monValue >= 0) { + break; + } + } + if (monValue < 0) { + return HWBusy; + } + self->lastMonitorRead = time(NULL); + monValue *= self->monitorScale; + *fControl = monValue; + self->lastMon = monValue; + if (monValue >= self->fPreset) { + McStasStop(self); + } + } - self->lastUpdate = time(NULL); - if(self->pid >= 0){ - status = invokeScript(self,"mcdump",pServ->pSics,pResult, 255); - if(status == 0){ - strncpy(self->errorText,pResult,255); - self->lastUpdate = time(NULL) - self->updateIntervall; - return HWFault; - } - } - - status = invokeScript(self,"mccopydata",pServ->pSics,pResult, 255); - if(status == 0){ - strncpy(self->errorText,pResult,255); - self->lastUpdate = time(NULL) - self->updateIntervall; - return HWFault; - } - return OKOK; + if (status == 1) { + return HWBusy; + } else { + self->stopTime = time(NULL); + self->pid = -1; + return HWIdle; + } } + /*-------------------------------------------------------------------------*/ -int McStasGetError(pMcStasController self, char *error, int errLen){ - strncpy(error,self->errorText,errLen); - return 1; -} -/*-------------------------------------------------------------------------*/ -int McStasFix(pMcStasController self){ - /* - * if the monitor file cannot be read, this may be caused by - * a conflict of mCstas writing while we are reading. let us - * retry... - */ - if(strstr(self->errorText,"monitor") != NULL){ - return COREDO; - } - /* - * you have to edit the scripts to fix anything which is going wrong here. - * But make sure the simulation is stopped. - */ - McStasStop(self); - self->stopTime = time(NULL); - self->pid = -1; - return COTERM; +int McStasStop(pMcStasController self) +{ + char pResult[256]; + invokeScript(self, "mckill", pServ->pSics, pResult, 255); + self->lastUpdate = time(NULL) - 3 * self->updateIntervall; + return 1; } + /*-------------------------------------------------------------------------*/ -float McStasGetTime(pMcStasController self){ - if(self->pid < 0){ - return (float)(self->stopTime - self->startTime); - } else { - return (float)time(NULL) - self->startTime; - } +int McStasTransferData(pMcStasController self) +{ + char pResult[256]; + int status; + + /* + * prevent to frequent requests + */ + if (self->lastUpdate + self->updateIntervall > time(NULL)) { + return OKOK; + } + + self->lastUpdate = time(NULL); + if (self->pid >= 0) { + status = invokeScript(self, "mcdump", pServ->pSics, pResult, 255); + if (status == 0) { + strlcpy(self->errorText, pResult, 255); + self->lastUpdate = time(NULL) - self->updateIntervall; + return HWFault; + } + } + + status = invokeScript(self, "mccopydata", pServ->pSics, pResult, 255); + if (status == 0) { + strlcpy(self->errorText, pResult, 255); + self->lastUpdate = time(NULL) - self->updateIntervall; + return HWFault; + } + return OKOK; +} + +/*-------------------------------------------------------------------------*/ +int McStasGetError(pMcStasController self, char *error, int errLen) +{ + strlcpy(error, self->errorText, errLen); + return 1; +} + +/*-------------------------------------------------------------------------*/ +int McStasFix(pMcStasController self) +{ + /* + * if the monitor file cannot be read, this may be caused by + * a conflict of mCstas writing while we are reading. let us + * retry... + */ + if (strstr(self->errorText, "monitor") != NULL) { + return COREDO; + } + /* + * you have to edit the scripts to fix anything which is going wrong here. + * But make sure the simulation is stopped. + */ + McStasStop(self); + self->stopTime = time(NULL); + self->pid = -1; + return COTERM; +} + +/*-------------------------------------------------------------------------*/ +float McStasGetTime(pMcStasController self) +{ + if (self->pid < 0) { + return (float) (self->stopTime - self->startTime); + } else { + return (float) time(NULL) - self->startTime; + } } diff --git a/mccontrol.h b/mccontrol.h index 43d611f5..d9ea74ab 100644 --- a/mccontrol.h +++ b/mccontrol.h @@ -14,37 +14,36 @@ #include "stringdict.h" /*--------------------- data structure -------------------------------------------------*/ - typedef struct{ - pObjectDescriptor pDes; - pStringDict scripts; - int updateIntervall; - int pid; - float monitorScale; - int lastError; - char errorText[256]; - CounterMode mode; - float fPreset; - time_t lastUpdate; - time_t startTime; - time_t stopTime; - time_t lastMonitorRead; - float lastMon; - }McStasController, *pMcStasController; - +typedef struct { + pObjectDescriptor pDes; + pStringDict scripts; + int updateIntervall; + int pid; + float monitorScale; + int lastError; + char errorText[256]; + CounterMode mode; + float fPreset; + time_t lastUpdate; + time_t startTime; + time_t stopTime; + time_t lastMonitorRead; + float lastMon; +} McStasController, *pMcStasController; + /*---------------------- function prototypes -------------------------------------------*/ - int McStasControllerFactory(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]); - int McStasControllerWrapper(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]); +int McStasControllerFactory(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]); +int McStasControllerWrapper(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]); + +int McStasStart(pMcStasController self, CounterMode mode, float fPreset); +int McStasStatus(pMcStasController self, float *fControl); +int McStasStop(pMcStasController self); +int McStasTransferData(pMcStasController self); +int McStasGetError(pMcStasController self, char *error, int errLen); +int McStasFix(pMcStasController self); +float McStasGetTime(pMcStasController self); - int McStasStart(pMcStasController self, CounterMode mode, float fPreset); - int McStasStatus(pMcStasController self,float *fControl); - int McStasStop(pMcStasController self); - int McStasTransferData(pMcStasController self); - int McStasGetError(pMcStasController self, char *error, int errLen); - int McStasFix(pMcStasController self); - float McStasGetTime(pMcStasController self); - #endif - diff --git a/mclist.c b/mclist.c index f67badf0..df354ac6 100644 --- a/mclist.c +++ b/mclist.c @@ -28,20 +28,23 @@ #define MC_NEXT next #endif -MC_TYPE MC_First_FUN(MC_List_TYPE *list) { +MC_TYPE MC_First_FUN(MC_List_TYPE * list) +{ list->ptr = &list->head; return list->head; } -MC_TYPE MC_This_FUN(MC_List_TYPE *list) { +MC_TYPE MC_This_FUN(MC_List_TYPE * list) +{ if (list->head == NULL) { list->ptr = &list->head; return NULL; } return *list->ptr; - } +} -MC_TYPE MC_Next_FUN(MC_List_TYPE *list) { +MC_TYPE MC_Next_FUN(MC_List_TYPE * list) +{ MC_TYPE node; if (list->head == NULL) { list->ptr = &list->head; @@ -54,7 +57,8 @@ MC_TYPE MC_Next_FUN(MC_List_TYPE *list) { return *list->ptr; } -void MC_End_FUN(MC_List_TYPE *list) { +void MC_End_FUN(MC_List_TYPE * list) +{ MC_TYPE node; if (list->head == NULL) { list->ptr = &list->head; @@ -68,7 +72,8 @@ void MC_End_FUN(MC_List_TYPE *list) { } } -void MC_Insert_FUN(MC_List_TYPE *list, MC_TYPE node) { +void MC_Insert_FUN(MC_List_TYPE * list, MC_TYPE node) +{ if (list->head == NULL) { list->ptr = &list->head; } @@ -76,7 +81,8 @@ void MC_Insert_FUN(MC_List_TYPE *list, MC_TYPE node) { *list->ptr = node; } -void MC_Add_FUN(MC_List_TYPE *list, MC_TYPE node) { +void MC_Add_FUN(MC_List_TYPE * list, MC_TYPE node) +{ node->MC_NEXT = NULL; if (list->head == NULL) { list->head = node; @@ -89,7 +95,8 @@ void MC_Add_FUN(MC_List_TYPE *list, MC_TYPE node) { } } -MC_TYPE MC_Take_FUN(MC_List_TYPE *list) { +MC_TYPE MC_Take_FUN(MC_List_TYPE * list) +{ MC_TYPE node; node = *list->ptr; if (node != NULL) { @@ -98,7 +105,8 @@ MC_TYPE MC_Take_FUN(MC_List_TYPE *list) { return node; } -void MC_Delete_FUN(MC_List_TYPE *list, void (*deleteFunc)(MC_TYPE n)) { +void MC_Delete_FUN(MC_List_TYPE * list, void (*deleteFunc) (MC_TYPE n)) +{ MC_TYPE node; MC_TYPE victim; node = list->head; diff --git a/mclist.h b/mclist.h index 889a6737..6dbf7553 100644 --- a/mclist.h +++ b/mclist.h @@ -110,7 +110,7 @@ typedef struct MC_List_TYPE { * * Actual position on return: at the first node */ -MC_TYPE MC_First_FUN(MC_List_TYPE *list); +MC_TYPE MC_First_FUN(MC_List_TYPE * list); /** \brief get the node at the current position * \param list the list @@ -118,7 +118,7 @@ MC_TYPE MC_First_FUN(MC_List_TYPE *list); * * Actual position on return: not changed (= at the returned node) */ -MC_TYPE MC_This_FUN(MC_List_TYPE *list); +MC_TYPE MC_This_FUN(MC_List_TYPE * list); /** \brief get the node after the current node * \param list the list @@ -126,14 +126,14 @@ MC_TYPE MC_This_FUN(MC_List_TYPE *list); * * Actual position on return: incremented (= at the returned node or at end) */ -MC_TYPE MC_Next_FUN(MC_List_TYPE *list); +MC_TYPE MC_Next_FUN(MC_List_TYPE * list); /** \brief move the position to the end * \param list the list * * Actual position on return: at end */ -void MC_End_FUN(MC_List_TYPE *list); +void MC_End_FUN(MC_List_TYPE * list); /** \brief insert at the current position, i.e. before the current node * \param list the list @@ -141,7 +141,7 @@ void MC_End_FUN(MC_List_TYPE *list); * * Actual position on return: at the inserted node */ -void MC_Insert_FUN(MC_List_TYPE *list, MC_TYPE node); +void MC_Insert_FUN(MC_List_TYPE * list, MC_TYPE node); /** \brief add at the end of the list * \param list the list @@ -149,7 +149,7 @@ void MC_Insert_FUN(MC_List_TYPE *list, MC_TYPE node); * * Actual position on return: at the inserted node (before the last node, not at end!) */ -void MC_Add_FUN(MC_List_TYPE *list, MC_TYPE node); +void MC_Add_FUN(MC_List_TYPE * list, MC_TYPE node); /** \brief remove the node at the current position * \param list the list @@ -160,7 +160,7 @@ void MC_Add_FUN(MC_List_TYPE *list, MC_TYPE node); * Note: it is the responsibility of the caller to free the node if it is not used * anymore */ -MC_TYPE MC_Take_FUN(MC_List_TYPE *list); +MC_TYPE MC_Take_FUN(MC_List_TYPE * list); /** \brief remove and delete all nodes * \param list the list @@ -169,7 +169,7 @@ MC_TYPE MC_Take_FUN(MC_List_TYPE *list); * Calls the kill function for every node. The list is * empty on return. */ -void MC_Delete_FUN(MC_List_TYPE *list, void (*deleteFunc)(MC_TYPE node)); +void MC_Delete_FUN(MC_List_TYPE * list, void (*deleteFunc) (MC_TYPE node)); #ifndef MC_DO_NOT_UNDEF #undef MC_NAME diff --git a/mcreader.c b/mcreader.c index d2d6c48d..02ea848d 100644 --- a/mcreader.c +++ b/mcreader.c @@ -13,110 +13,118 @@ #include "HistMem.h" #include "sicsdata.h" /*-------------------------------------------------------------------------*/ -static void KillMcReader(void *pData){ - pMcStasReader self = (pMcStasReader)pData; - if(self == NULL){ - return; - } - if(self->pDes){ - DeleteDescriptor(self->pDes); - } - if(self->handle != NULL){ - NXclose(&self->handle); - } - free(self); +static void KillMcReader(void *pData) +{ + pMcStasReader self = (pMcStasReader) pData; + if (self == NULL) { + return; + } + if (self->pDes) { + DeleteDescriptor(self->pDes); + } + if (self->handle != NULL) { + NXclose(&self->handle); + } + free(self); } + /*--------------------------------------------------------------------------*/ -int McStasReaderFactory(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]){ - pMcStasReader pNew = NULL; - - pNew = (pMcStasReader)malloc(sizeof(McStasReader)); - if(pNew == NULL){ - SCWrite(pCon,"ERROR: out of memory creating McStasReader",eError); - return 0; - } - memset(pNew,0,sizeof(McStasReader)); - - pNew->pDes = CreateDescriptor("McStasReader"); - if(pNew->pDes == NULL){ - SCWrite(pCon,"ERROR: out of memory creating McStasReader",eError); - free(pNew); - return 0; - } - return AddCommand(pSics,"mcreader", - McStasReaderWrapper, - KillMcReader, - pNew); +int McStasReaderFactory(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]) +{ + pMcStasReader pNew = NULL; + + pNew = (pMcStasReader) malloc(sizeof(McStasReader)); + if (pNew == NULL) { + SCWrite(pCon, "ERROR: out of memory creating McStasReader", eError); + return 0; + } + memset(pNew, 0, sizeof(McStasReader)); + + pNew->pDes = CreateDescriptor("McStasReader"); + if (pNew->pDes == NULL) { + SCWrite(pCon, "ERROR: out of memory creating McStasReader", eError); + free(pNew); + return 0; + } + return AddCommand(pSics, "mcreader", + McStasReaderWrapper, KillMcReader, pNew); } + /*==================== interpreter interface ===============================*/ -static void MCReportError(void *pData, char *txt){ - pMcStasReader self = NULL; - - self = (pMcStasReader)pData; - if(self != NULL){ - strncpy(self->nexusError,txt,1024); - } else { - printf( -"ERROR: NeXus error in McStasReader without McStasReader data structure: %s\n", - txt); - } +static void MCReportError(void *pData, char *txt) +{ + pMcStasReader self = NULL; + + self = (pMcStasReader) pData; + if (self != NULL) { + strlcpy(self->nexusError, txt, 1024); + } else { + printf + ("ERROR: NeXus error in McStasReader without McStasReader data structure: %s\n", + txt); + } } + /*-------------------------------------------------------------------------*/ -static int openMcStasFile(pMcStasReader self, SConnection *pCon, - int argc, char *argv[]){ - int status; - char pBueffel[512]; - - if(argc < 3){ - SCWrite(pCon,"ERROR: need filename argument for opening file", - eError); - } - /* - * be nice to users: if file still open, close it - */ - if(self->handle != NULL){ - NXclose(&self->handle); - self->handle = NULL; - } - /** +static int openMcStasFile(pMcStasReader self, SConnection * pCon, + int argc, char *argv[]) +{ + int status; + char pBueffel[512]; + + if (argc < 3) { + SCWrite(pCon, "ERROR: need filename argument for opening file", + eError); + } + /* + * be nice to users: if file still open, close it + */ + if (self->handle != NULL) { + NXclose(&self->handle); + self->handle = NULL; + } + /** * open the file */ - NXMSetError(self,MCReportError); - status = NXopen((const char*)argv[2],NXACC_READ,&self->handle); - if(status != NX_OK){ - snprintf(pBueffel,511,"ERROR: NeXus reported %s", - self->nexusError); - SCWrite(pCon,pBueffel,eError); - return 0; - } - SCSendOK(pCon); - return 1; + NXMSetError(self, MCReportError); + status = NXopen((const char *) argv[2], NXACC_READ, &self->handle); + if (status != NX_OK) { + snprintf(pBueffel, 511, "ERROR: NeXus reported %s", self->nexusError); + SCWrite(pCon, pBueffel, eError); + return 0; + } + SCSendOK(pCon); + return 1; } + /*--------------------------------------------------------------------------*/ -static int closeMcStasFile(pMcStasReader self, SConnection *pCon){ - if(self->handle != NULL){ - NXclose(&self->handle); - self->handle = NULL; - } - SCSendOK(pCon); - return 1; +static int closeMcStasFile(pMcStasReader self, SConnection * pCon) +{ + if (self->handle != NULL) { + NXclose(&self->handle); + self->handle = NULL; + } + SCSendOK(pCon); + return 1; } + /*-------------------------------------------------------------------*/ -static char *getNextMCNumber(char *pStart, char pNumber[80]){ +static char *getNextMCNumber(char *pStart, char pNumber[80]) +{ int charCount = 0; pNumber[0] = '\0'; /* advance to first digit */ - while(isspace(*pStart) && *pStart != '\0'){ + while (isspace(*pStart) && *pStart != '\0') { pStart++; } - if(*pStart == '\0'){ + if (*pStart == '\0') { return NULL; } /* copy */ - while(!isspace(*pStart) && *pStart != '\0' && charCount < 78){ + while (!isspace(*pStart) && *pStart != '\0' && charCount < 78) { pNumber[charCount] = *pStart; pStart++; charCount++; @@ -124,345 +132,348 @@ static char *getNextMCNumber(char *pStart, char pNumber[80]){ pNumber[charCount] = '\0'; return pStart; } + /*--------------------------------------------------------------------------*/ -static int insertMonitor(pMcStasReader self, SConnection *pCon, - SicsInterp *pSics, int argc, char *argv[]){ - char pBueffel[512], *pPtr, pNumber[80]; - pCounter pCount = NULL; - int status, mon, type, rank, iDim[NX_MAXRANK]; - float monValue, scale = 1.; - - if(argc < 5){ - SCWrite(pCon,\ - "ERROR: insufficient number of arguments to mcreader insertmon", - eError); - return 0; - } - if(self->handle == NULL){ - SCWrite(pCon,"ERROR: no file open to read data from",eError); - return 0; - } - pCount = FindCommandData(pSics,argv[3],"SingleCounter"); - if(pCount == NULL){ - snprintf(pBueffel,511, - "ERROR: %s is no counter object", - argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - mon = atoi(argv[4]); - - status = NXopenpath(self->handle,argv[2]); - if(status != NX_OK){ - snprintf(pBueffel,511,"ERROR: Nexus error %s while opening %s", - self->nexusError, argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - if(argc > 5) { - scale = atof(argv[5]); - } - - status = NXgetinfo(self->handle,&rank,iDim,&type); - if(status != NX_OK){ - snprintf(pBueffel,511,"ERROR: Nexus error %s while reading %s", - self->nexusError, argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - if(rank != 1 || type != NX_CHAR || iDim[0] > 511){ - snprintf(pBueffel,511,"ERROR: %s is no valid monitor data", - argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - memset(pBueffel,0,512); - status = NXgetdata(self->handle,pBueffel); - if(status != NX_OK){ - snprintf(pBueffel,511,"ERROR: Nexus error %s while reading %s", - self->nexusError, argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } +static int insertMonitor(pMcStasReader self, SConnection * pCon, + SicsInterp * pSics, int argc, char *argv[]) +{ + char pBueffel[512], *pPtr, pNumber[80]; + pCounter pCount = NULL; + int status, mon, type, rank, iDim[NX_MAXRANK]; + float monValue, scale = 1.; + + if (argc < 5) { + SCWrite(pCon, + "ERROR: insufficient number of arguments to mcreader insertmon", + eError); + return 0; + } + if (self->handle == NULL) { + SCWrite(pCon, "ERROR: no file open to read data from", eError); + return 0; + } + pCount = FindCommandData(pSics, argv[3], "SingleCounter"); + if (pCount == NULL) { + snprintf(pBueffel, 511, "ERROR: %s is no counter object", argv[3]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + mon = atoi(argv[4]); + + status = NXopenpath(self->handle, argv[2]); + if (status != NX_OK) { + snprintf(pBueffel, 511, "ERROR: Nexus error %s while opening %s", + self->nexusError, argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + if (argc > 5) { + scale = atof(argv[5]); + } + + status = NXgetinfo(self->handle, &rank, iDim, &type); + if (status != NX_OK) { + snprintf(pBueffel, 511, "ERROR: Nexus error %s while reading %s", + self->nexusError, argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + if (rank != 1 || type != NX_CHAR || iDim[0] > 511) { + snprintf(pBueffel, 511, "ERROR: %s is no valid monitor data", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + memset(pBueffel, 0, 512); + status = NXgetdata(self->handle, pBueffel); + if (status != NX_OK) { + snprintf(pBueffel, 511, "ERROR: Nexus error %s while reading %s", + self->nexusError, argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* + * the monitor value we want is the third value in the values field + */ + pPtr = pBueffel; + memset(pNumber, 0, 80 * sizeof(char)); + pPtr = getNextMCNumber(pPtr, pNumber); + pPtr = getNextMCNumber(pPtr, pNumber); + pPtr = getNextMCNumber(pPtr, pNumber); + monValue = atof(pNumber); + monValue *= scale; + + if (pCount != NULL) { + SetMonitorValue(pCount, mon, (long) monValue); + } + SCSendOK(pCon); + return 1; +} - /* - * the monitor value we want is the third value in the values field - */ - pPtr = pBueffel; - memset(pNumber,0,80*sizeof(char)); - pPtr = getNextMCNumber(pPtr,pNumber); - pPtr = getNextMCNumber(pPtr,pNumber); - pPtr = getNextMCNumber(pPtr,pNumber); - monValue = atof(pNumber); - monValue *= scale; - - if(pCount != NULL){ - SetMonitorValue(pCount,mon,(long)monValue); - } - SCSendOK(pCon); - return 1; -} /*--------------------------------------------------------------------------*/ -static int insertMonitorDirect(pMcStasReader self, SConnection *pCon, - SicsInterp *pSics, int argc, char *argv[]){ - char pBueffel[512], *pPtr, pNumber[80]; - pCounter pCount = NULL; - int status, mon; - float monValue; - - if(argc < 5){ - SCWrite(pCon,\ - "ERROR: insufficient number of arguments to mcreader insertmondirect", - eError); - return 0; - } +static int insertMonitorDirect(pMcStasReader self, SConnection * pCon, + SicsInterp * pSics, int argc, char *argv[]) +{ + char pBueffel[512], *pPtr, pNumber[80]; + pCounter pCount = NULL; + int status, mon; + float monValue; - pCount = FindCommandData(pSics,argv[2],"SingleCounter"); - if(pCount == NULL){ - snprintf(pBueffel,511, - "ERROR: %s is no counter object", - argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - mon = atoi(argv[3]); - monValue = atof(argv[4]); - - if(pCount != NULL){ - SetMonitorValue(pCount,mon,(long)monValue); - } - SCSendOK(pCon); - return 1; -} -/*--------------------------------------------------------------------------*/ -static int insertHM(pMcStasReader self, SConnection *pCon, - SicsInterp *pSics, int argc, char *argv[]){ - char pBueffel[512], *pPtr, pNumber[80], *pData = NULL; - pHistMem pHM = NULL; - int status, type, rank, iDim[NX_MAXRANK]; - int length, i; - HistInt *lData = NULL; - float scale = 1.; - double val; - - if(argc < 4){ - SCWrite(pCon,\ - "ERROR: insufficient number of arguments to mcreader inserthm", - eError); - return 0; - } - if(self->handle == NULL){ - SCWrite(pCon,"ERROR: no file open to read data from",eError); - return 0; - } - pHM = FindCommandData(pSics,argv[3],"HistMem"); - if(pHM == NULL){ - snprintf(pBueffel,511, - "ERROR: %s is no histogram memory object", - argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - status = NXopenpath(self->handle,argv[2]); - if(status != NX_OK){ - snprintf(pBueffel,511,"ERROR: Nexus error %s while opening %s", - self->nexusError, argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - if(argc > 4){ - scale = atof(argv[4]); - } - - status = NXgetinfo(self->handle,&rank,iDim,&type); - if(status != NX_OK){ - snprintf(pBueffel,511,"ERROR: Nexus error %s while reading %s", - self->nexusError, argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - pData = (char *)malloc((iDim[0]+1)*sizeof(char)); - if(pData == NULL){ - SCWrite(pCon,"ERROR: out of memory in mcreader inserthm",eError); - return 0; - } - memset(pData,0,(iDim[0]+1)*sizeof(char)); + if (argc < 5) { + SCWrite(pCon, + "ERROR: insufficient number of arguments to mcreader insertmondirect", + eError); + return 0; + } - status = NXgetdata(self->handle,pData); - if(status != NX_OK){ - snprintf(pBueffel,511,"ERROR: Nexus error %s while reading %s", - self->nexusError, argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - length = GetHistLength(pHM); - lData = (HistInt *)malloc(length*sizeof(HistInt)); - if(lData== NULL){ - SCWrite(pCon,"ERROR: out of memory in mcreader inserthm",eError); - free(pData); - return 0; - } - memset(lData,0,length*sizeof(HistInt)); - - pPtr = pData; - for(i = 0; i < length && pPtr != NULL; i++){ - pPtr = getNextMCNumber(pPtr,pNumber); - val = atof(pNumber); - val *= scale; - lData[i] = (HistInt)val; - } + pCount = FindCommandData(pSics, argv[2], "SingleCounter"); + if (pCount == NULL) { + snprintf(pBueffel, 511, "ERROR: %s is no counter object", argv[3]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + mon = atoi(argv[3]); + monValue = atof(argv[4]); - SetHistogram(pHM,pCon,0,0,length,lData); - free(pData); - free(lData); - SCSendOK(pCon); - return 1; + if (pCount != NULL) { + SetMonitorValue(pCount, mon, (long) monValue); + } + SCSendOK(pCon); + return 1; } -/*--------------------------------------------------------------------------*/ -static int getField(pMcStasReader self, SConnection *pCon, - SicsInterp *pSics, int argc, char *argv[]){ - char pBueffel[512], *pPtr, pNumber[80], *pData = NULL; - int status, type, rank, iDim[NX_MAXRANK]; - - if(argc < 2){ - SCWrite(pCon,\ - "ERROR: insufficient number of arguments to mcreader getfield", - eError); - return 0; - } - if(self->handle == NULL){ - SCWrite(pCon,"ERROR: no file open to read data from",eError); - return 0; - } - status = NXopenpath(self->handle,argv[2]); - if(status != NX_OK){ - snprintf(pBueffel,511,"ERROR: Nexus error %s while opening %s", - self->nexusError, argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - status = NXgetinfo(self->handle,&rank,iDim,&type); - if(status != NX_OK){ - snprintf(pBueffel,511,"ERROR: Nexus error %s while reading %s", - self->nexusError, argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - pData = (char *)malloc((iDim[0]+1)*sizeof(char)); - if(pData == NULL){ - SCWrite(pCon,"ERROR: out of memory in mcreader getfield",eError); - return 0; - } - memset(pData,0,(iDim[0]+1)*sizeof(char)); - - status = NXgetdata(self->handle,pData); - if(status != NX_OK){ - snprintf(pBueffel,511,"ERROR: Nexus error %s while reading %s", - self->nexusError, argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - SCWrite(pCon,pData,eValue); - free(pData); - return 1; -} -/*--------------------------------------------------------------------------*/ -static int insertHMFromData(pMcStasReader self, SConnection *pCon, - SicsInterp *pSics, int argc, char *argv[]){ - char pBueffel[512]; - pHistMem pHM = NULL; - int length, i; - HistInt *lData = NULL; - pSICSData data = NULL; - - if(argc < 4){ - SCWrite(pCon,\ - "ERROR: insufficient number of arguments to mcreader inserthmfromdata", - eError); - return 0; - } - pHM = FindCommandData(pSics,argv[2],"HistMem"); - if(pHM == NULL){ - snprintf(pBueffel,511, - "ERROR: %s is no histogram memory object", - argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - data = FindCommandData(pSics,argv[3],"SICSData"); - if(data == NULL){ - snprintf(pBueffel,511, - "ERROR: %s is no SICSData object", - argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - length = GetHistLength(pHM); - if(data->currentDataSize < length){ - snprintf(pBueffel,511,"WARNING: data in %s to short for HM %s", - argv[3],argv[2]); - SCWrite(pCon,pBueffel,eWarning); - } - lData = (HistInt *)malloc(length*sizeof(HistInt)); - if(lData== NULL){ - SCWrite(pCon,"ERROR: out of memory in mcreader inserthm",eError); - return 0; - } - memset(lData,0,length*sizeof(HistInt)); - if(data->currentDataSize < length){ - length = data->currentDataSize; - } - for(i = 0; i < length; i++){ - lData[i] = (HistInt)data->data[i]; - } - SetHistogram(pHM,pCon,0,0,length,lData); - free(lData); - SCSendOK(pCon); - return 1; -} /*--------------------------------------------------------------------------*/ -int McStasReaderWrapper(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]){ - pMcStasReader self = NULL; - char pBueffel[512]; - - self = (pMcStasReader)pData; - assert(self != NULL); - - if(argc < 2){ - SCWrite(pCon,"ERROR: insufficient number of arguments to mcreader", - eError); - return 0; - } - strtolower(argv[1]); - if(strcmp(argv[1],"open") == 0){ - return openMcStasFile(self, pCon, argc, argv); - } else if(strcmp(argv[1],"close") == 0){ - return closeMcStasFile(self,pCon); - } else if(strcmp(argv[1],"insertmon") == 0){ - return insertMonitor(self,pCon, pSics,argc,argv); - } else if(strcmp(argv[1],"insertmondirect") == 0){ - return insertMonitorDirect(self,pCon, pSics,argc,argv); - } else if(strcmp(argv[1],"inserthm") == 0){ - return insertHM(self,pCon, pSics,argc,argv); - } else if(strcmp(argv[1],"inserthmfromdata") == 0){ - return insertHMFromData(self,pCon, pSics,argc,argv); - } else if(strcmp(argv[1],"getfield") == 0){ - return getField(self,pCon, pSics,argc,argv); - } else { - snprintf(pBueffel,511,"ERROR: invalid subcommand %s to %s", - argv[1],argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - return 1; +static int insertHM(pMcStasReader self, SConnection * pCon, + SicsInterp * pSics, int argc, char *argv[]) +{ + char pBueffel[512], *pPtr, pNumber[80], *pData = NULL; + pHistMem pHM = NULL; + int status, type, rank, iDim[NX_MAXRANK]; + int length, i; + HistInt *lData = NULL; + float scale = 1.; + double val; + + if (argc < 4) { + SCWrite(pCon, + "ERROR: insufficient number of arguments to mcreader inserthm", + eError); + return 0; + } + if (self->handle == NULL) { + SCWrite(pCon, "ERROR: no file open to read data from", eError); + return 0; + } + pHM = FindCommandData(pSics, argv[3], "HistMem"); + if (pHM == NULL) { + snprintf(pBueffel, 511, + "ERROR: %s is no histogram memory object", argv[3]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + status = NXopenpath(self->handle, argv[2]); + if (status != NX_OK) { + snprintf(pBueffel, 511, "ERROR: Nexus error %s while opening %s", + self->nexusError, argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + if (argc > 4) { + scale = atof(argv[4]); + } + + status = NXgetinfo(self->handle, &rank, iDim, &type); + if (status != NX_OK) { + snprintf(pBueffel, 511, "ERROR: Nexus error %s while reading %s", + self->nexusError, argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + pData = (char *) malloc((iDim[0] + 1) * sizeof(char)); + if (pData == NULL) { + SCWrite(pCon, "ERROR: out of memory in mcreader inserthm", eError); + return 0; + } + memset(pData, 0, (iDim[0] + 1) * sizeof(char)); + + status = NXgetdata(self->handle, pData); + if (status != NX_OK) { + snprintf(pBueffel, 511, "ERROR: Nexus error %s while reading %s", + self->nexusError, argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + length = GetHistLength(pHM); + lData = (HistInt *) malloc(length * sizeof(HistInt)); + if (lData == NULL) { + SCWrite(pCon, "ERROR: out of memory in mcreader inserthm", eError); + free(pData); + return 0; + } + memset(lData, 0, length * sizeof(HistInt)); + + pPtr = pData; + for (i = 0; i < length && pPtr != NULL; i++) { + pPtr = getNextMCNumber(pPtr, pNumber); + val = atof(pNumber); + val *= scale; + lData[i] = (HistInt) val; + } + + SetHistogram(pHM, pCon, 0, 0, length, lData); + free(pData); + free(lData); + SCSendOK(pCon); + return 1; +} + +/*--------------------------------------------------------------------------*/ +static int getField(pMcStasReader self, SConnection * pCon, + SicsInterp * pSics, int argc, char *argv[]) +{ + char pBueffel[512], *pPtr, pNumber[80], *pData = NULL; + int status, type, rank, iDim[NX_MAXRANK]; + + if (argc < 2) { + SCWrite(pCon, + "ERROR: insufficient number of arguments to mcreader getfield", + eError); + return 0; + } + if (self->handle == NULL) { + SCWrite(pCon, "ERROR: no file open to read data from", eError); + return 0; + } + + status = NXopenpath(self->handle, argv[2]); + if (status != NX_OK) { + snprintf(pBueffel, 511, "ERROR: Nexus error %s while opening %s", + self->nexusError, argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + status = NXgetinfo(self->handle, &rank, iDim, &type); + if (status != NX_OK) { + snprintf(pBueffel, 511, "ERROR: Nexus error %s while reading %s", + self->nexusError, argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + pData = (char *) malloc((iDim[0] + 1) * sizeof(char)); + if (pData == NULL) { + SCWrite(pCon, "ERROR: out of memory in mcreader getfield", eError); + return 0; + } + memset(pData, 0, (iDim[0] + 1) * sizeof(char)); + + status = NXgetdata(self->handle, pData); + if (status != NX_OK) { + snprintf(pBueffel, 511, "ERROR: Nexus error %s while reading %s", + self->nexusError, argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + SCWrite(pCon, pData, eValue); + free(pData); + return 1; +} + +/*--------------------------------------------------------------------------*/ +static int insertHMFromData(pMcStasReader self, SConnection * pCon, + SicsInterp * pSics, int argc, char *argv[]) +{ + char pBueffel[512]; + pHistMem pHM = NULL; + int length, i; + HistInt *lData = NULL; + pSICSData data = NULL; + + if (argc < 4) { + SCWrite(pCon, + "ERROR: insufficient number of arguments to mcreader inserthmfromdata", + eError); + return 0; + } + pHM = FindCommandData(pSics, argv[2], "HistMem"); + if (pHM == NULL) { + snprintf(pBueffel, 511, + "ERROR: %s is no histogram memory object", argv[3]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + data = FindCommandData(pSics, argv[3], "SICSData"); + if (data == NULL) { + snprintf(pBueffel, 511, "ERROR: %s is no SICSData object", argv[3]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + length = GetHistLength(pHM); + if (data->currentDataSize < length) { + snprintf(pBueffel, 511, "WARNING: data in %s to short for HM %s", + argv[3], argv[2]); + SCWrite(pCon, pBueffel, eWarning); + } + lData = (HistInt *) malloc(length * sizeof(HistInt)); + if (lData == NULL) { + SCWrite(pCon, "ERROR: out of memory in mcreader inserthm", eError); + return 0; + } + memset(lData, 0, length * sizeof(HistInt)); + if (data->currentDataSize < length) { + length = data->currentDataSize; + } + for (i = 0; i < length; i++) { + lData[i] = (HistInt) data->data[i]; + } + SetHistogram(pHM, pCon, 0, 0, length, lData); + free(lData); + SCSendOK(pCon); + return 1; +} + +/*--------------------------------------------------------------------------*/ +int McStasReaderWrapper(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]) +{ + pMcStasReader self = NULL; + char pBueffel[512]; + + self = (pMcStasReader) pData; + assert(self != NULL); + + if (argc < 2) { + SCWrite(pCon, "ERROR: insufficient number of arguments to mcreader", + eError); + return 0; + } + strtolower(argv[1]); + if (strcmp(argv[1], "open") == 0) { + return openMcStasFile(self, pCon, argc, argv); + } else if (strcmp(argv[1], "close") == 0) { + return closeMcStasFile(self, pCon); + } else if (strcmp(argv[1], "insertmon") == 0) { + return insertMonitor(self, pCon, pSics, argc, argv); + } else if (strcmp(argv[1], "insertmondirect") == 0) { + return insertMonitorDirect(self, pCon, pSics, argc, argv); + } else if (strcmp(argv[1], "inserthm") == 0) { + return insertHM(self, pCon, pSics, argc, argv); + } else if (strcmp(argv[1], "inserthmfromdata") == 0) { + return insertHMFromData(self, pCon, pSics, argc, argv); + } else if (strcmp(argv[1], "getfield") == 0) { + return getField(self, pCon, pSics, argc, argv); + } else { + snprintf(pBueffel, 511, "ERROR: invalid subcommand %s to %s", + argv[1], argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + return 1; } diff --git a/mcreader.h b/mcreader.h index 6bd627b0..154e15d2 100644 --- a/mcreader.h +++ b/mcreader.h @@ -7,22 +7,20 @@ Mark Koennecke, June 2005 -------------------------------------------------------------------------------------*/ -#ifndef MCSTASREADER +#ifndef MCSTASREADER #define MCSTASREADER #include "sics.h" #include "napi.h" typedef struct { - pObjectDescriptor pDes; - NXhandle handle; - char nexusError[1024]; - }McStasReader, *pMcStasReader; + pObjectDescriptor pDes; + NXhandle handle; + char nexusError[1024]; +} McStasReader, *pMcStasReader; /*-----------------------------------------------------------------------------*/ - int McStasReaderFactory(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]); - int McStasReaderWrapper(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]); - +int McStasReaderFactory(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]); +int McStasReaderWrapper(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]); + #endif - - diff --git a/mcstas/dmc/DataNumber b/mcstas/dmc/DataNumber index b4495070..984e0a6f 100644 --- a/mcstas/dmc/DataNumber +++ b/mcstas/dmc/DataNumber @@ -1,3 +1,3 @@ - 230 + 232 NEVER, EVER modify or delete this file You'll risk eternal damnation and a reincarnation as a cockroach!|n \ No newline at end of file diff --git a/mcstas/dmc/MKMonitor.comp b/mcstas/dmc/MKMonitor.comp index 79eb2803..8927f61c 100644 --- a/mcstas/dmc/MKMonitor.comp +++ b/mcstas/dmc/MKMonitor.comp @@ -10,7 +10,7 @@ * %I * Written by: Kim Lefmann * Date: October 4, 1997 -* Version: $Revision: 1.19 $ +* Version: $Revision$ * Origin: Risoe * Release: McStas 1.6 * Modified to write monitor file for SICS: Mark Koennecke, June 2005 diff --git a/mcstas/dmc/PSD_monitor.comp b/mcstas/dmc/PSD_monitor.comp index 8ae68401..0103aaa8 100644 --- a/mcstas/dmc/PSD_monitor.comp +++ b/mcstas/dmc/PSD_monitor.comp @@ -10,7 +10,7 @@ * %I * Written by: Kim Lefmann * Date: Feb 3, 1998 -* Version: $Revision: 1.2 $ +* Version: $Revision$ * Origin: Risoe * Release: McStas 1.6 * diff --git a/mcstas/dmc/dmcafter.c b/mcstas/dmc/dmcafter.c index cbfbd1ee..9579fd0b 100644 --- a/mcstas/dmc/dmcafter.c +++ b/mcstas/dmc/dmcafter.c @@ -30,12 +30,9 @@ * * Usage: Automatically embbeded in the c code. * -* $Id: dmcafter.c,v 1.2 2007-02-12 01:19:07 ffr Exp $ +* $Id$ * -* $Log: not supported by cvs2svn $ -* Revision 1.1.2.1 2007/02/06 04:03:21 ffr -* PSI Update -* +* $Log$ * Revision 1.1 2007/01/30 03:19:43 koennecke * - Fixed state monitor eclipse commit problems. Siiiiiiiggggghhhhhh! * @@ -90,7 +87,7 @@ *******************************************************************************/ #ifndef MCSTAS_R_H -#define MCSTAS_R_H "$Revision: 1.2 $" +#define MCSTAS_R_H "$Revision$" #include #include @@ -572,12 +569,9 @@ void mcsiminfo_close(void); * * Usage: Automatically embbeded in the c code whenever required. * -* $Id: dmcafter.c,v 1.2 2007-02-12 01:19:07 ffr Exp $ -* -* $Log: not supported by cvs2svn $ -* Revision 1.1.2.1 2007/02/06 04:03:21 ffr -* PSI Update +* $Id$ * +* $Log$ * Revision 1.1 2007/01/30 03:19:43 koennecke * - Fixed state monitor eclipse commit problems. Siiiiiiiggggghhhhhh! * @@ -4362,12 +4356,9 @@ MCNUM mccDet9_zmax; * %include "read_table-lib" * * -* $Id: dmcafter.c,v 1.2 2007-02-12 01:19:07 ffr Exp $ +* $Id$ * -* $Log: not supported by cvs2svn $ -* Revision 1.1.2.1 2007/02/06 04:03:21 ffr -* PSI Update -* +* $Log$ * Revision 1.1 2007/01/30 03:19:43 koennecke * - Fixed state monitor eclipse commit problems. Siiiiiiiggggghhhhhh! * @@ -4442,12 +4433,9 @@ static void Table_Stat(t_Table *mc_rt_Table); * Usage: within SHARE * %include "read_table-lib" * -* $Id: dmcafter.c,v 1.2 2007-02-12 01:19:07 ffr Exp $ +* $Id$ * -* $Log: not supported by cvs2svn $ -* Revision 1.1.2.1 2007/02/06 04:03:21 ffr -* PSI Update -* +* $Log$ * Revision 1.1 2007/01/30 03:19:43 koennecke * - Fixed state monitor eclipse commit problems. Siiiiiiiggggghhhhhh! * @@ -5296,12 +5284,9 @@ long Virtual_input_Read_Input(char *aFile, char *aType, t_Table *aTable, long *a * Usage: within SHARE * %include "monitor_nd-lib" * -* $Id: dmcafter.c,v 1.2 2007-02-12 01:19:07 ffr Exp $ +* $Id$ * -* $Log: not supported by cvs2svn $ -* Revision 1.1.2.1 2007/02/06 04:03:21 ffr -* PSI Update -* +* $Log$ * Revision 1.1 2007/01/30 03:19:43 koennecke * - Fixed state monitor eclipse commit problems. Siiiiiiiggggghhhhhh! * @@ -5475,12 +5460,9 @@ void Monitor_nD_McDisplay(MonitornD_Defines_type *, * Usage: within SHARE * %include "monitor_nd-lib" * -* $Id: dmcafter.c,v 1.2 2007-02-12 01:19:07 ffr Exp $ +* $Id$ * -* $Log: not supported by cvs2svn $ -* Revision 1.1.2.1 2007/02/06 04:03:21 ffr -* PSI Update -* +* $Log$ * Revision 1.1 2007/01/30 03:19:43 koennecke * - Fixed state monitor eclipse commit problems. Siiiiiiiggggghhhhhh! * diff --git a/mcstas/dmc/samenv/tomato/07-20.log b/mcstas/dmc/samenv/tomato/07-20.log new file mode 100644 index 00000000..da845dd1 --- /dev/null +++ b/mcstas/dmc/samenv/tomato/07-20.log @@ -0,0 +1,11390 @@ +#2006-07-20 00:00:00 isdst 1 period 5 exact 1 +00:00:00 4.4220 +00:00:05 4.6817 +00:00:10 4.8740 +00:00:15 4.5413 +00:00:20 4.8290 +00:00:25 4.6405 +00:00:30 4.7156 +00:00:35 4.7455 +00:00:40 4.6929 +00:00:45 4.9565 +00:00:50 4.6585 +00:00:55 4.7447 +00:01:00 4.8010 +00:01:05 4.6188 +00:01:10 4.8519 +00:01:15 4.7247 +00:01:20 4.7355 +00:01:25 4.7258 +00:01:30 4.7237 +00:01:35 4.7483 +00:01:40 4.7082 +00:01:45 4.8206 +00:01:50 4.7051 +00:01:55 4.7323 +00:02:00 4.6824 +00:02:05 4.7419 +00:02:10 4.6984 +00:02:15 4.6150 +00:02:20 4.6714 +00:02:25 4.7849 +00:02:30 4.6965 +00:02:35 4.5760 +00:02:40 4.9699 +00:02:45 4.7526 +00:02:50 4.7628 +00:02:55 4.9419 +00:03:00 4.6565 +00:03:05 4.6991 +00:03:10 4.8350 +00:03:15 4.5047 +00:03:20 4.7496 +00:03:25 4.9007 +00:03:30 4.5065 +00:03:35 4.5825 +00:03:40 4.7890 +00:03:45 4.5428 +00:03:50 4.8036 +00:03:55 4.9926 +00:04:00 4.7839 +00:04:05 4.5629 +00:04:10 4.5483 +00:04:15 4.7965 +00:04:20 4.7145 +00:04:25 4.4598 +00:04:30 4.7563 +00:04:35 4.9160 +00:04:40 4.6162 +00:04:45 4.6842 +00:04:50 4.8263 +00:04:55 4.6060 +00:05:00 4.6326 +00:05:05 4.8250 +00:05:10 4.5465 +00:05:15 4.4622 +00:05:20 4.7847 +00:05:25 5.0117 +00:05:30 4.6701 +00:05:35 4.5193 +00:05:40 4.9961 +00:05:45 4.7811 +00:05:50 4.4906 +00:05:55 4.7368 +00:06:00 4.8617 +00:06:05 4.5488 +00:06:10 4.7841 +00:06:15 4.7002 +00:06:20 4.6989 +00:06:25 4.6631 +00:06:30 4.7193 +00:06:35 4.7415 +00:06:40 4.6767 +00:06:45 4.6453 +00:06:50 4.6289 +00:06:55 4.6962 +00:07:00 4.7160 +00:07:05 4.6867 +00:07:10 4.5543 +00:07:15 4.8891 +00:07:20 4.7052 +00:07:25 4.7904 +00:07:30 4.7234 +00:07:35 4.8186 +00:07:40 4.6969 +00:07:45 4.7239 +00:07:50 4.6745 +00:07:55 4.7484 +00:08:00 4.7717 +00:08:05 4.7169 +00:08:10 4.7550 +00:08:15 4.7468 +00:08:20 4.7159 +00:08:25 4.7103 +00:08:30 4.6670 +00:08:35 4.6043 +00:08:40 4.6312 +00:08:45 4.6176 +00:08:50 4.6648 +00:08:55 4.5711 +00:09:00 4.6102 +00:09:05 4.6890 +00:09:10 4.7265 +00:09:15 4.7744 +00:09:20 4.8012 +00:09:25 4.7519 +00:09:30 4.6055 +00:09:35 4.6143 +00:09:40 4.6462 +00:09:45 4.5684 +00:09:50 4.7042 +00:09:55 4.7895 +00:10:00 4.6858 +00:10:05 4.7278 +00:10:10 4.6530 +00:10:15 4.7561 +00:10:20 4.7606 +00:10:25 4.6972 +00:10:30 4.7211 +00:10:35 4.6725 +00:10:40 4.6632 +00:10:45 4.6419 +00:10:50 4.6491 +00:10:55 4.7272 +00:11:00 4.6261 +00:11:05 4.6826 +00:11:10 4.7016 +00:11:15 4.6607 +00:11:20 4.7134 +00:11:25 4.7481 +00:11:30 4.7713 +00:11:35 4.7040 +00:11:40 4.5523 +00:11:45 4.5043 +00:11:50 4.5869 +00:11:55 4.7134 +00:12:00 4.8288 +00:12:05 4.7514 +00:12:10 4.6918 +00:12:15 4.6551 +00:12:20 4.6139 +00:12:25 4.5990 +00:12:30 4.6124 +00:12:35 4.6045 +00:12:40 4.7286 +00:12:45 4.6947 +00:12:50 4.6556 +00:12:55 4.6186 +00:13:00 4.6898 +00:13:05 4.6398 +00:13:10 4.6271 +00:13:15 4.6729 +00:13:20 4.7055 +00:13:25 4.7354 +00:13:30 4.6922 +00:13:35 4.6496 +00:13:40 4.5600 +00:13:45 4.5622 +00:13:50 4.6482 +00:13:55 4.6778 +00:14:00 4.6985 +00:14:05 4.7838 +00:14:10 4.8014 +00:14:15 4.7729 +00:14:20 4.7496 +00:14:25 4.6716 +00:14:30 4.7095 +00:14:35 4.7489 +00:14:40 4.8078 +00:14:45 4.7304 +00:14:50 4.6622 +00:14:55 4.5774 +00:15:00 4.5783 +00:15:05 4.6438 +00:15:10 4.6234 +00:15:15 4.5829 +00:15:20 4.6076 +00:15:25 4.6770 +00:15:30 4.6758 +00:15:35 4.7493 +00:15:40 4.6859 +00:15:45 4.6512 +00:15:50 4.6163 +00:15:55 4.5922 +00:16:00 4.6821 +00:16:05 4.6786 +00:16:10 4.7159 +00:16:15 4.7040 +00:16:20 4.5776 +00:16:25 4.5723 +00:16:30 4.6434 +00:16:35 4.6034 +00:16:40 4.5789 +00:16:45 4.5967 +00:16:50 4.5976 +00:16:55 4.6045 +00:17:00 4.5067 +00:17:05 4.5015 +00:17:10 4.5918 +00:17:15 4.6710 +00:17:20 4.6784 +00:17:25 4.6811 +00:17:30 4.6865 +00:17:35 4.6031 +00:17:40 4.5319 +00:17:45 4.5924 +00:17:50 4.6342 +00:17:55 4.6277 +00:18:00 4.7354 +00:18:05 4.7905 +00:18:10 4.6982 +00:18:15 4.6340 +00:18:20 4.6698 +00:18:25 4.7368 +00:18:30 4.6674 +00:18:35 4.6634 +00:18:40 4.6390 +00:18:45 4.5669 +00:18:50 4.6421 +00:18:55 4.6479 +00:19:00 4.6485 +00:19:05 4.5901 +00:19:10 4.6362 +00:19:15 4.5978 +00:19:20 4.6604 +00:19:25 4.6522 +00:19:30 4.5403 +00:19:35 4.5121 +00:19:40 4.5020 +00:19:45 4.5524 +00:19:50 4.5470 +00:19:55 4.6470 +00:20:00 4.7540 +00:20:05 4.6294 +00:20:10 4.6719 +00:20:15 4.7052 +00:20:20 4.7341 +00:20:25 4.5804 +00:20:30 4.4892 +00:20:35 4.5266 +00:20:40 4.4486 +00:20:45 4.5381 +00:20:50 4.6343 +00:20:55 4.7059 +00:21:00 4.6584 +00:21:05 4.6118 +00:21:10 4.6244 +00:21:15 4.5285 +00:21:20 4.5853 +00:21:25 4.6887 +00:21:30 4.6226 +00:21:35 4.6477 +00:21:40 4.6974 +00:21:45 4.7163 +00:21:50 4.6072 +00:21:55 4.6236 +00:22:00 4.6290 +00:22:05 4.6181 +00:22:10 4.6448 +00:22:15 4.5960 +00:22:20 4.5376 +00:22:25 4.5801 +00:22:30 4.6342 +00:22:35 4.6794 +00:22:40 4.6625 +00:22:45 4.5974 +00:22:50 4.5335 +00:22:55 4.5006 +00:23:00 4.5708 +00:23:05 4.6173 +00:23:10 4.6414 +00:23:15 4.7294 +00:23:20 4.6904 +00:23:25 4.5300 +00:23:30 4.5055 +00:23:35 4.5294 +00:23:40 4.5644 +00:23:45 4.6120 +00:23:50 4.5459 +00:23:55 4.5728 +00:24:00 4.6435 +00:24:05 4.5234 +00:24:10 4.5409 +00:24:15 4.6420 +00:24:20 4.5347 +00:24:25 4.4408 +00:24:30 4.4648 +00:24:35 4.6354 +00:24:40 4.7121 +00:24:45 4.5644 +00:24:50 4.6285 +00:24:55 4.6569 +00:25:00 4.6329 +00:25:05 4.5035 +00:25:10 4.5827 +00:25:15 4.6283 +00:25:20 4.5210 +00:25:25 4.6864 +00:25:30 4.6783 +00:25:35 4.5636 +00:25:40 4.4468 +00:25:45 4.5108 +00:25:50 4.5875 +00:25:55 4.5955 +00:26:00 4.6033 +00:26:05 4.5904 +00:26:10 4.5635 +00:26:15 4.6481 +00:26:20 4.5530 +00:26:25 4.4963 +00:26:30 4.4125 +00:26:35 4.4791 +00:26:40 4.6544 +00:26:45 4.6642 +00:26:50 4.6169 +00:26:55 4.6023 +00:27:00 4.5304 +00:27:05 4.5282 +00:27:10 4.5902 +00:27:15 4.6882 +00:27:20 4.5866 +00:27:25 4.4517 +00:27:30 4.5170 +00:27:35 4.4722 +00:27:40 4.4385 +00:27:45 4.5143 +00:27:50 4.5300 +00:27:55 4.5571 +00:28:00 4.5760 +00:28:05 4.5816 +00:28:10 4.6103 +00:28:15 4.6614 +00:28:20 4.6084 +00:28:25 4.5492 +00:28:30 4.5768 +00:28:35 4.6348 +00:28:40 4.6360 +00:28:45 4.6178 +00:28:50 4.5579 +00:28:55 4.5451 +00:29:00 4.4516 +00:29:05 4.5316 +00:29:10 4.5465 +00:29:15 4.4857 +00:29:20 4.5358 +00:29:25 4.5520 +00:29:30 4.5424 +00:29:35 4.5882 +00:29:40 4.6289 +00:29:45 4.5276 +00:29:50 4.4803 +00:29:55 4.5501 +00:30:00 4.5949 +00:30:05 4.4963 +00:30:10 4.4566 +00:30:15 4.5125 +00:30:20 4.5830 +00:30:25 4.5704 +00:30:30 4.5960 +00:30:35 4.6502 +00:30:40 4.6714 +00:30:45 4.4935 +00:30:50 4.5360 +00:30:55 4.5935 +00:31:00 4.5341 +00:31:05 4.5745 +00:31:10 4.5400 +00:31:15 4.4936 +00:31:20 4.5170 +00:31:25 4.4749 +00:31:30 4.5411 +00:31:35 4.5790 +00:31:40 4.6014 +00:31:45 4.5899 +00:31:50 4.6218 +00:31:55 4.5692 +00:32:00 4.5669 +00:32:05 4.5436 +00:32:10 4.5633 +00:32:15 4.5415 +00:32:20 4.5203 +00:32:25 4.5493 +00:32:30 4.5474 +00:32:35 4.5792 +00:32:40 4.4826 +00:32:45 4.5856 +00:32:50 4.6930 +00:32:55 4.4555 +00:33:00 4.4590 +00:33:05 4.4742 +00:33:10 4.3939 +00:33:15 4.5159 +00:33:20 4.5537 +00:33:25 4.5368 +00:33:30 4.6501 +00:33:35 4.5147 +00:33:40 4.4638 +00:33:45 4.5270 +00:33:50 4.5219 +00:33:55 4.5862 +00:34:00 4.5359 +00:34:05 4.5661 +00:34:10 4.5016 +00:34:15 4.4848 +00:34:20 4.5342 +00:34:25 4.5615 +00:34:30 4.4712 +00:34:35 4.4322 +00:34:40 4.4936 +00:34:45 4.5149 +00:34:50 4.4938 +00:34:55 4.5250 +00:35:00 4.6035 +00:35:05 4.6155 +00:35:10 4.4953 +00:35:15 4.4337 +00:35:20 4.4871 +00:35:25 4.4752 +00:35:30 4.4806 +00:35:35 4.5323 +00:35:40 4.4637 +00:35:45 4.5142 +00:35:50 4.5820 +00:35:55 4.4824 +00:36:00 4.3943 +00:36:05 4.4192 +00:36:10 4.5344 +00:36:15 4.6162 +00:36:20 4.5492 +00:36:25 4.4987 +00:36:30 4.4474 +00:36:35 4.5160 +00:36:40 4.5782 +00:36:45 4.6402 +00:36:50 4.6382 +00:36:55 4.5542 +00:37:00 4.6179 +00:37:05 4.5565 +00:37:10 4.4886 +00:37:15 4.5097 +00:37:20 4.5766 +00:37:25 4.5297 +00:37:30 4.5245 +00:37:35 4.5737 +00:37:40 4.6012 +00:37:45 4.5268 +00:37:50 4.5338 +00:37:55 4.5797 +00:38:00 4.6208 +00:38:05 4.5725 +00:38:10 4.4286 +00:38:15 4.5019 +00:38:20 4.4811 +00:38:25 4.4893 +00:38:30 4.5711 +00:38:35 4.5490 +00:38:40 4.5073 +00:38:45 4.4377 +00:38:50 4.5116 +00:38:55 4.6269 +00:39:00 4.6124 +00:39:05 4.6049 +00:39:10 4.5082 +00:39:15 4.4839 +00:39:20 4.5409 +00:39:25 4.5523 +00:39:30 4.4416 +00:39:35 4.5306 +00:39:40 4.5770 +00:39:45 4.6104 +00:39:50 4.6233 +00:39:55 4.5381 +00:40:00 4.5173 +00:40:05 4.5568 +00:40:10 4.5026 +00:40:15 4.5160 +00:40:20 4.4674 +00:40:25 4.4774 +00:40:30 4.4854 +00:40:35 4.4668 +00:40:40 4.4376 +00:40:45 4.4997 +00:40:50 4.5646 +00:40:55 4.5126 +00:41:00 4.4743 +00:41:05 4.5321 +00:41:10 4.5567 +00:41:15 4.5144 +00:41:20 4.5040 +00:41:25 4.5271 +00:41:30 4.3999 +00:41:35 4.4462 +00:41:40 4.4895 +00:41:45 4.5344 +00:41:50 4.5659 +00:41:55 4.5152 +00:42:00 4.5203 +00:42:05 4.4866 +00:42:10 4.4151 +00:42:15 4.4226 +00:42:20 4.5671 +00:42:25 4.4509 +00:42:30 4.4198 +00:42:35 4.5083 +00:42:40 4.5386 +00:42:45 4.5630 +00:42:50 4.4550 +00:42:55 4.4774 +00:43:00 4.4932 +00:43:05 4.5156 +00:43:10 4.5474 +00:43:15 4.5158 +00:43:20 4.5327 +00:43:25 4.5506 +00:43:30 4.4828 +00:43:35 4.3712 +00:43:40 4.4493 +00:43:45 4.4934 +00:43:50 4.5200 +00:43:55 4.4524 +00:44:00 4.4418 +00:44:05 4.5536 +00:44:10 4.5164 +00:44:15 4.3941 +00:44:20 4.4460 +00:44:25 4.4619 +00:44:30 4.4449 +00:44:35 4.4079 +00:44:40 4.4321 +00:44:45 4.4676 +00:44:50 4.4853 +00:44:55 4.5050 +00:45:00 4.4927 +00:45:05 4.5000 +00:45:10 4.4526 +00:45:15 4.5871 +00:45:20 4.4945 +00:45:25 4.4748 +00:45:30 4.4008 +00:45:35 4.4567 +00:45:40 4.5168 +00:45:45 4.4177 +00:45:50 4.4600 +00:45:55 4.4661 +00:46:00 4.4410 +00:46:05 4.4642 +00:46:10 4.4806 +00:46:15 4.4312 +00:46:20 4.4568 +00:46:25 4.5353 +00:46:30 4.5235 +00:46:35 4.4324 +00:46:40 4.4251 +00:46:45 4.4565 +00:46:50 4.4686 +00:46:55 4.3992 +00:47:00 4.4211 +00:47:05 4.4312 +00:47:10 4.4105 +00:47:15 4.4845 +00:47:20 4.4690 +00:47:25 4.5173 +00:47:30 4.4620 +00:47:35 4.4822 +00:47:40 4.4820 +00:47:45 4.4630 +00:47:50 4.4731 +00:47:55 4.3761 +00:48:00 4.4958 +00:48:05 4.4974 +00:48:10 4.4085 +00:48:15 4.4012 +00:48:20 4.3988 +00:48:25 4.4623 +00:48:30 4.4448 +00:48:35 4.4673 +00:48:40 4.5114 +00:48:45 4.4476 +00:48:50 4.3874 +00:48:55 4.4134 +00:49:00 4.4743 +00:49:05 4.3290 +00:49:10 4.4620 +00:49:15 4.4206 +00:49:20 4.4504 +00:49:25 4.4320 +00:49:30 4.5030 +00:49:35 4.4395 +00:49:40 4.4745 +00:49:45 4.4807 +00:49:50 4.4628 +00:49:55 4.4855 +00:50:00 4.4465 +00:50:05 4.4064 +00:50:10 4.3766 +00:50:15 4.4768 +00:50:20 4.4859 +00:50:25 4.4232 +00:50:30 4.4185 +00:50:35 4.3699 +00:50:40 4.3610 +00:50:45 4.4088 +00:50:50 4.4081 +00:50:55 4.3916 +00:51:00 4.4049 +00:51:05 4.4238 +00:51:10 4.4703 +00:51:15 4.4308 +00:51:20 4.3797 +00:51:25 4.3573 +00:51:30 4.4307 +00:51:35 4.4622 +00:51:40 4.4205 +00:51:45 4.4631 +00:51:50 4.4219 +00:51:55 4.3917 +00:52:00 4.4872 +00:52:05 4.4361 +00:52:10 4.4310 +00:52:15 4.4007 +00:52:20 4.3004 +00:52:25 4.3968 +00:52:30 4.4389 +00:52:35 4.3863 +00:52:40 4.3400 +00:52:45 4.3791 +00:52:50 4.4838 +00:52:55 4.4260 +00:53:00 4.3531 +00:53:05 4.3816 +00:53:10 4.3660 +00:53:15 4.3466 +00:53:20 4.3526 +00:53:25 4.3207 +00:53:30 4.3762 +00:53:35 4.4650 +00:53:40 4.4402 +00:53:45 4.3859 +00:53:50 4.4056 +00:53:55 4.3779 +00:54:00 4.3604 +00:54:05 4.2799 +00:54:10 4.4375 +00:54:15 4.4396 +00:54:20 4.4272 +00:54:25 4.3911 +00:54:30 4.2900 +00:54:35 4.3089 +00:54:40 4.3577 +00:54:45 4.5759 +00:54:50 4.5102 +00:54:55 4.4915 +00:55:00 4.4122 +00:55:05 4.4031 +00:55:10 4.4639 +00:55:15 4.5257 +00:55:20 4.5316 +00:55:25 4.4545 +00:55:30 4.3464 +00:55:35 4.3142 +00:55:40 4.3456 +00:55:45 4.3361 +00:55:50 4.3511 +00:55:55 4.3789 +00:56:00 4.4700 +00:56:05 4.3797 +00:56:10 4.3984 +00:56:15 4.3820 +00:56:20 4.3497 +00:56:25 4.4434 +00:56:30 4.4500 +00:56:35 4.3652 +00:56:40 4.4015 +00:56:45 4.4029 +00:56:50 4.4404 +00:56:55 4.4655 +00:57:00 4.3896 +00:57:05 4.4025 +00:57:10 4.4612 +00:57:15 4.4121 +00:57:20 4.2687 +00:57:25 4.3414 +00:57:30 4.3969 +00:57:35 4.4380 +00:57:40 4.4466 +00:57:45 4.4784 +00:57:50 4.3828 +00:57:55 4.4135 +00:58:00 4.3907 +00:58:05 4.2682 +00:58:10 4.3720 +00:58:15 4.4584 +00:58:20 4.4061 +00:58:25 4.4598 +00:58:30 4.4075 +00:58:35 4.3735 +00:58:40 4.4250 +00:58:45 4.4295 +00:58:50 4.3214 +00:58:55 4.3382 +00:59:00 4.3685 +00:59:05 4.4048 +00:59:10 4.4172 +00:59:15 4.3918 +00:59:20 4.4032 +00:59:25 4.4608 +00:59:30 4.5191 +00:59:35 4.3325 +00:59:40 4.2876 +00:59:45 4.3512 +00:59:50 4.4767 +00:59:55 4.4332 +01:00:00 4.4074 +01:00:05 4.3878 +01:00:10 4.4312 +01:00:15 4.4159 +01:00:20 4.4617 +01:00:25 4.3944 +01:00:30 4.3727 +01:00:35 4.3883 +01:00:40 4.3865 +01:00:45 4.4664 +01:00:50 4.4872 +01:00:55 4.3948 +01:01:00 4.3590 +01:01:05 4.3126 +01:01:10 4.3429 +01:01:15 4.4328 +01:01:20 4.3562 +01:01:25 4.2807 +01:01:30 4.3410 +01:01:35 4.4265 +01:01:40 4.4184 +01:01:45 4.4009 +01:01:50 4.3631 +01:01:55 4.4086 +01:02:00 4.3344 +01:02:05 4.4368 +01:02:10 4.4384 +01:02:15 4.4348 +01:02:20 4.4381 +01:02:25 4.3338 +01:02:30 4.4227 +01:02:35 4.3804 +01:02:40 4.3475 +01:02:45 4.2865 +01:02:50 4.3633 +01:02:55 4.4499 +01:03:00 4.3904 +01:03:05 4.4279 +01:03:10 4.3076 +01:03:15 4.3375 +01:03:20 4.3368 +01:03:25 4.3967 +01:03:30 4.2929 +01:03:35 4.4090 +01:03:40 4.2816 +01:03:45 4.3679 +01:03:50 4.2956 +01:03:55 4.1736 +01:04:00 4.3769 +01:04:05 4.3249 +01:04:10 4.3678 +01:04:15 4.3364 +01:04:20 4.4167 +01:04:25 4.3658 +01:04:30 4.3167 +01:04:35 4.4009 +01:04:40 4.4293 +01:04:45 4.3985 +01:04:50 4.3601 +01:04:55 4.3750 +01:05:00 4.4278 +01:05:05 4.3288 +01:05:10 4.2940 +01:05:15 4.3823 +01:05:20 4.3564 +01:05:25 4.2809 +01:05:30 4.3604 +01:05:35 4.3538 +01:05:40 4.2968 +01:05:45 4.4204 +01:05:50 4.4499 +01:05:55 4.3640 +01:06:00 4.3667 +01:06:05 4.3279 +01:06:10 4.3124 +01:06:15 4.3250 +01:06:20 4.3208 +01:06:25 4.3676 +01:06:30 4.3484 +01:06:35 4.3444 +01:06:40 4.3129 +01:06:45 4.4036 +01:06:50 4.3900 +01:06:55 4.2903 +01:07:00 4.3628 +01:07:05 4.3733 +01:07:10 4.3928 +01:07:15 4.3860 +01:07:20 4.3117 +01:07:25 4.3622 +01:07:30 4.3702 +01:07:35 4.4324 +01:07:40 4.4328 +01:07:45 4.2880 +01:07:50 4.3981 +01:07:55 4.4315 +01:08:00 4.3964 +01:08:05 4.4300 +01:08:10 4.3672 +01:08:15 4.4513 +01:08:20 4.4274 +01:08:25 4.4875 +01:08:30 4.3679 +01:08:35 4.2216 +01:08:40 4.3919 +01:08:45 4.3782 +01:08:50 4.4025 +01:08:55 4.3142 +01:09:00 4.3559 +01:09:05 4.4162 +01:09:10 4.2810 +01:09:15 4.3664 +01:09:20 4.3626 +01:09:25 4.3086 +01:09:30 4.2889 +01:09:35 4.3088 +01:09:40 4.3192 +01:09:45 4.3935 +01:09:50 4.3739 +01:09:55 4.4131 +01:10:00 4.4618 +01:10:05 4.3094 +01:10:10 4.3700 +01:10:15 4.4166 +01:10:20 4.3390 +01:10:25 4.3123 +01:10:30 4.3284 +01:10:35 4.2842 +01:10:40 4.2512 +01:10:45 4.3096 +01:10:50 4.2674 +01:10:55 4.2534 +01:11:00 4.3029 +01:11:05 4.3657 +01:11:10 4.3892 +01:11:15 4.3644 +01:11:20 4.3541 +01:11:25 4.3757 +01:11:30 4.2622 +01:11:35 4.3126 +01:11:40 4.2781 +01:11:45 4.3066 +01:11:50 4.3498 +01:11:55 4.3250 +01:12:00 4.2310 +01:12:05 4.3490 +01:12:10 4.3291 +01:12:15 4.3629 +01:12:20 4.4209 +01:12:25 4.3311 +01:12:30 4.3032 +01:12:35 4.2930 +01:12:40 4.2438 +01:12:45 4.3059 +01:12:50 4.3176 +01:12:55 4.3965 +01:13:00 4.3454 +01:13:05 4.3334 +01:13:10 4.3779 +01:13:15 4.3510 +01:13:20 4.3688 +01:13:25 4.4130 +01:13:30 4.3286 +01:13:35 4.2304 +01:13:40 4.2886 +01:13:45 4.3177 +01:13:50 4.2048 +01:13:55 4.2450 +01:14:00 4.2222 +01:14:05 4.2135 +01:14:10 4.3035 +01:14:15 4.3195 +01:14:20 4.3443 +01:14:25 4.3293 +01:14:30 4.4398 +01:14:35 4.4170 +01:14:40 4.4308 +01:14:45 4.4393 +01:14:50 4.3871 +01:14:55 4.3797 +01:15:00 4.3682 +01:15:05 4.3024 +01:15:10 4.2482 +01:15:15 4.2591 +01:15:20 4.2860 +01:15:25 4.2180 +01:15:30 4.2693 +01:15:35 4.3441 +01:15:40 4.4240 +01:15:45 4.4088 +01:15:50 4.3174 +01:15:55 4.1964 +01:16:00 4.1919 +01:16:05 4.2968 +01:16:10 4.2617 +01:16:15 4.3784 +01:16:20 4.4402 +01:16:25 4.3435 +01:16:30 4.2817 +01:16:35 4.2669 +01:16:40 4.3331 +01:16:45 4.3752 +01:16:50 4.3216 +01:16:55 4.3644 +01:17:00 4.4401 +01:17:05 4.4274 +01:17:10 4.4199 +01:17:15 4.4060 +01:17:20 4.4387 +01:17:25 4.4009 +01:17:30 4.3730 +01:17:35 4.3241 +01:17:40 4.3408 +01:17:45 4.3974 +01:17:50 4.3881 +01:17:55 4.3509 +01:18:00 4.3589 +01:18:05 4.3207 +01:18:10 4.1858 +01:18:15 4.1990 +01:18:20 4.2375 +01:18:25 4.3330 +01:18:30 4.2635 +01:18:35 4.2315 +01:18:40 4.2903 +01:18:45 4.3211 +01:18:50 4.2690 +01:18:55 4.2920 +01:19:00 4.2308 +01:19:05 4.3474 +01:19:10 4.2146 +01:19:15 4.1216 +01:19:20 4.2235 +01:19:25 4.3442 +01:19:30 4.3767 +01:19:35 4.2057 +01:19:40 4.2764 +01:19:45 4.3103 +01:19:50 4.3302 +01:19:55 4.2683 +01:20:00 4.2502 +01:20:05 4.3316 +01:20:10 4.3343 +01:20:15 4.2909 +01:20:20 4.3180 +01:20:25 4.3041 +01:20:30 4.3077 +01:20:35 4.4170 +01:20:40 4.3604 +01:20:45 4.3762 +01:20:50 4.3053 +01:20:55 4.2744 +01:21:00 4.2616 +01:21:05 4.3052 +01:21:10 4.3376 +01:21:15 4.3167 +01:21:20 4.2615 +01:21:25 4.3503 +01:21:30 4.2688 +01:21:35 4.2535 +01:21:40 4.3053 +01:21:45 4.2801 +01:21:50 4.2813 +01:21:55 4.1952 +01:22:00 4.2809 +01:22:05 4.2797 +01:22:10 4.1903 +01:22:15 4.2976 +01:22:20 4.3677 +01:22:25 4.3010 +01:22:30 4.3400 +01:22:35 4.2822 +01:22:40 4.2737 +01:22:45 4.3052 +01:22:50 4.3109 +01:22:55 4.2432 +01:23:00 4.2939 +01:23:05 4.3674 +01:23:10 4.2411 +01:23:15 4.3157 +01:23:20 4.2849 +01:23:25 4.2359 +01:23:30 4.2021 +01:23:35 4.2924 +01:23:40 4.3079 +01:23:45 4.2460 +01:23:50 4.1668 +01:23:55 4.2529 +01:24:00 4.4067 +01:24:05 4.3127 +01:24:10 4.2327 +01:24:15 4.1798 +01:24:20 4.2193 +01:24:25 4.2881 +01:24:30 4.3695 +01:24:35 4.3524 +01:24:40 4.3117 +01:24:45 4.2311 +01:24:50 4.2728 +01:24:55 4.3012 +01:25:00 4.1993 +01:25:05 4.2352 +01:25:10 4.2526 +01:25:15 4.3132 +01:25:20 4.3455 +01:25:25 4.3509 +01:25:30 4.2849 +01:25:35 4.2709 +01:25:40 4.2689 +01:25:45 4.3433 +01:25:50 4.3799 +01:25:55 4.2826 +01:26:00 4.2487 +01:26:05 4.2188 +01:26:10 4.3184 +01:26:15 4.2784 +01:26:20 4.2291 +01:26:25 4.1846 +01:26:30 4.2868 +01:26:35 4.3480 +01:26:40 4.2550 +01:26:45 4.1924 +01:26:50 4.2310 +01:26:55 4.2801 +01:27:00 4.1942 +01:27:05 4.2334 +01:27:10 4.2259 +01:27:15 4.0900 +01:27:20 4.0884 +01:27:25 4.1630 +01:27:30 4.3014 +01:27:35 4.2224 +01:27:40 4.2081 +01:27:45 4.2610 +01:27:50 4.3704 +01:27:55 4.4366 +01:28:00 4.4452 +01:28:05 4.3496 +01:28:10 4.2793 +01:28:15 4.2978 +01:28:20 4.3159 +01:28:25 4.3629 +01:28:30 4.3018 +01:28:35 4.3273 +01:28:40 4.4155 +01:28:45 4.2741 +01:28:50 4.2176 +01:28:55 4.2639 +01:29:00 4.1603 +01:29:05 4.1439 +01:29:10 4.2079 +01:29:15 4.2192 +01:29:20 4.2047 +01:29:25 4.2561 +01:29:30 4.3081 +01:29:35 4.2536 +01:29:40 4.2755 +01:29:45 4.3029 +01:29:50 4.2376 +01:29:55 4.3001 +01:30:00 4.3716 +01:30:05 4.2692 +01:30:10 4.2148 +01:30:15 4.2638 +01:30:20 4.2353 +01:30:25 4.2661 +01:30:30 4.2432 +01:30:35 4.2199 +01:30:40 4.2256 +01:30:45 4.1887 +01:30:50 4.2642 +01:30:55 4.2412 +01:31:00 4.2898 +01:31:05 4.3127 +01:31:10 4.3356 +01:31:15 4.2739 +01:31:20 4.2238 +01:31:25 4.3690 +01:31:30 4.3755 +01:31:35 4.3401 +01:31:40 4.3084 +01:31:45 4.2572 +01:31:50 4.3122 +01:31:55 4.2877 +01:32:00 4.2884 +01:32:05 4.2979 +01:32:10 4.3234 +01:32:15 4.3327 +01:32:20 4.2900 +01:32:25 4.2857 +01:32:30 4.1883 +01:32:35 4.3443 +01:32:40 4.3081 +01:32:45 4.2883 +01:32:50 4.2240 +01:32:55 4.2875 +01:33:00 4.1297 +01:33:05 4.3225 +01:33:10 4.3878 +01:33:15 4.3296 +01:33:20 4.2770 +01:33:25 4.2104 +01:33:30 4.2457 +01:33:35 4.1824 +01:33:40 4.2668 +01:33:45 4.2670 +01:33:50 4.2819 +01:33:55 4.3288 +01:34:00 4.2190 +01:34:05 4.2515 +01:34:10 4.2429 +01:34:15 4.1617 +01:34:20 4.2730 +01:34:25 4.3284 +01:34:30 4.3647 +01:34:35 4.2928 +01:34:40 4.2354 +01:34:45 4.2455 +01:34:50 4.1060 +01:34:55 4.1587 +01:35:00 4.2831 +01:35:05 4.2546 +01:35:10 4.1568 +01:35:15 4.2157 +01:35:20 4.3083 +01:35:25 4.2934 +01:35:30 4.2754 +01:35:35 4.2668 +01:35:40 4.2287 +01:35:45 4.1834 +01:35:50 4.2074 +01:35:55 4.2359 +01:36:00 4.2081 +01:36:05 4.1676 +01:36:10 4.1535 +01:36:15 4.1325 +01:36:20 4.1498 +01:36:25 4.2650 +01:36:30 4.3042 +01:36:35 4.2334 +01:36:40 4.1819 +01:36:45 4.2260 +01:36:50 4.2139 +01:36:55 4.1902 +01:37:00 4.2531 +01:37:05 4.2760 +01:37:10 4.2208 +01:37:15 4.2232 +01:37:20 4.3085 +01:37:25 4.2708 +01:37:30 4.1897 +01:37:35 4.2197 +01:37:40 4.1470 +01:37:45 4.2209 +01:37:50 4.2196 +01:37:55 4.1837 +01:38:00 4.2346 +01:38:05 4.2365 +01:38:10 4.2668 +01:38:15 4.2396 +01:38:20 4.3110 +01:38:25 4.2493 +01:38:30 4.2611 +01:38:35 4.2662 +01:38:40 4.2682 +01:38:45 4.3168 +01:38:50 4.2553 +01:38:55 4.2737 +01:39:00 4.1937 +01:39:05 4.1429 +01:39:10 4.1617 +01:39:15 4.2568 +01:39:20 4.2969 +01:39:25 4.2391 +01:39:30 4.2342 +01:39:35 4.1928 +01:39:40 4.3157 +01:39:45 4.2762 +01:39:50 4.2450 +01:39:55 4.1989 +01:40:00 4.2564 +01:40:05 4.2765 +01:40:10 4.2582 +01:40:15 4.1943 +01:40:20 4.1835 +01:40:25 4.0968 +01:40:30 4.0941 +01:40:35 4.1501 +01:40:40 4.2886 +01:40:45 4.3196 +01:40:50 4.2262 +01:40:55 4.2092 +01:41:00 4.1783 +01:41:05 4.1852 +01:41:10 4.2378 +01:41:15 4.2286 +01:41:20 4.2927 +01:41:25 4.2118 +01:41:30 4.2027 +01:41:35 4.3257 +01:41:40 4.1457 +01:41:45 4.2147 +01:41:50 4.2161 +01:41:55 4.2594 +01:42:00 4.2502 +01:42:05 4.2376 +01:42:10 4.2423 +01:42:15 4.2457 +01:42:20 4.1655 +01:42:25 4.1631 +01:42:30 4.2012 +01:42:35 4.1697 +01:42:40 4.1257 +01:42:45 4.1734 +01:42:50 4.2098 +01:42:55 4.2399 +01:43:00 4.2934 +01:43:05 4.2841 +01:43:10 4.2590 +01:43:15 4.1963 +01:43:20 4.2217 +01:43:25 4.2081 +01:43:30 4.2363 +01:43:35 4.2559 +01:43:40 4.2674 +01:43:45 4.2594 +01:43:50 4.2685 +01:43:55 4.2744 +01:44:00 4.2889 +01:44:05 4.2594 +01:44:10 4.2123 +01:44:15 4.3099 +01:44:20 4.1992 +01:44:25 4.1929 +01:44:30 4.1578 +01:44:35 4.2486 +01:44:40 4.2728 +01:44:45 4.2610 +01:44:50 4.2551 +01:44:55 4.2723 +01:45:00 4.2300 +01:45:05 4.2470 +01:45:10 4.2280 +01:45:15 4.2317 +01:45:20 4.2540 +01:45:25 4.2366 +01:45:30 4.2608 +01:45:35 4.3071 +01:45:40 4.2898 +01:45:45 4.2723 +01:45:50 4.2507 +01:45:55 4.2628 +01:46:00 4.2086 +01:46:05 4.1165 +01:46:10 4.1797 +01:46:15 4.1349 +01:46:20 4.1984 +01:46:25 4.1699 +01:46:30 4.2308 +01:46:35 4.1957 +01:46:40 4.1803 +01:46:45 4.1799 +01:46:50 4.2133 +01:46:55 4.2774 +01:47:00 4.3289 +01:47:05 4.2297 +01:47:10 4.2222 +01:47:15 4.2664 +01:47:20 4.2692 +01:47:25 4.1359 +01:47:30 4.1273 +01:47:35 4.1603 +01:47:40 4.2406 +01:47:45 4.3238 +01:47:50 4.3462 +01:47:55 4.1751 +01:48:00 4.2187 +01:48:05 4.1814 +01:48:10 4.1655 +01:48:15 4.2362 +01:48:20 4.2035 +01:48:25 4.3006 +01:48:30 4.2959 +01:48:35 4.1243 +01:48:40 4.1373 +01:48:45 4.1800 +01:48:50 4.1638 +01:48:55 4.1661 +01:49:00 4.1770 +01:49:05 4.1154 +01:49:10 4.1435 +01:49:15 4.2417 +01:49:20 4.1634 +01:49:25 4.1975 +01:49:30 4.2265 +01:49:35 4.2450 +01:49:40 4.2221 +01:49:45 4.2714 +01:49:50 4.2248 +01:49:55 4.2468 +01:50:00 4.2673 +01:50:05 4.1332 +01:50:10 4.0830 +01:50:15 4.1515 +01:50:20 4.1578 +01:50:25 4.1853 +01:50:30 4.2576 +01:50:35 4.2916 +01:50:40 4.2545 +01:50:45 4.1881 +01:50:50 4.2642 +01:50:55 4.1965 +01:51:00 4.1919 +01:51:05 4.2664 +01:51:10 4.2576 +01:51:15 4.1617 +01:51:20 4.0520 +01:51:25 4.1565 +01:51:30 4.1739 +01:51:35 4.1447 +01:51:40 4.1384 +01:51:45 4.0848 +01:51:50 4.1338 +01:51:55 4.1580 +01:52:00 4.1424 +01:52:05 4.1841 +01:52:10 4.3262 +01:52:15 4.3730 +01:52:20 4.2504 +01:52:25 4.1584 +01:52:30 4.1602 +01:52:35 4.2115 +01:52:40 4.1357 +01:52:45 4.1133 +01:52:50 4.2357 +01:52:55 4.3365 +01:53:00 4.3347 +01:53:05 4.1840 +01:53:10 4.1411 +01:53:15 4.1639 +01:53:20 4.2088 +01:53:25 4.1393 +01:53:30 4.1373 +01:53:35 4.2098 +01:53:40 4.1607 +01:53:45 4.2383 +01:53:50 4.3454 +01:53:55 4.2582 +01:54:00 4.2127 +01:54:05 4.2903 +01:54:10 4.1963 +01:54:15 4.2025 +01:54:20 4.1597 +01:54:25 4.1388 +01:54:30 4.1784 +01:54:35 4.1066 +01:54:40 4.1775 +01:54:45 4.0933 +01:54:50 4.1585 +01:54:55 4.2532 +01:55:00 4.1524 +01:55:05 4.1612 +01:55:10 4.2077 +01:55:15 4.1442 +01:55:20 4.0676 +01:55:25 4.0646 +01:55:30 4.1976 +01:55:35 4.2229 +01:55:40 4.1372 +01:55:45 4.2025 +01:55:50 4.1936 +01:55:55 4.1025 +01:56:00 4.1542 +01:56:05 4.2241 +01:56:10 4.2420 +01:56:15 4.2951 +01:56:20 4.2478 +01:56:25 4.2304 +01:56:30 4.1308 +01:56:35 4.1927 +01:56:40 4.2100 +01:56:45 4.1867 +01:56:50 4.1005 +01:56:55 4.1250 +01:57:00 4.2474 +01:57:05 4.0925 +01:57:10 4.0985 +01:57:15 4.1772 +01:57:20 4.2640 +01:57:25 4.3186 +01:57:30 4.3245 +01:57:35 4.1488 +01:57:40 4.1370 +01:57:45 4.1608 +01:57:50 4.1749 +01:57:55 4.2099 +01:58:00 4.1796 +01:58:05 4.2413 +01:58:10 4.1701 +01:58:15 4.1882 +01:58:20 4.2289 +01:58:25 4.1413 +01:58:30 4.1463 +01:58:35 4.2139 +01:58:40 4.2376 +01:58:45 4.2608 +01:58:50 4.1610 +01:58:55 4.1512 +01:59:00 4.1924 +01:59:05 4.1531 +01:59:10 4.2604 +01:59:15 4.2036 +01:59:20 4.1720 +01:59:25 4.2576 +01:59:30 4.2635 +01:59:35 4.2920 +01:59:40 4.2709 +01:59:45 4.1864 +01:59:50 4.1624 +01:59:55 4.2660 +02:00:00 4.2869 +02:00:05 4.2162 +02:00:10 4.2257 +02:00:15 4.2174 +02:00:20 4.2145 +02:00:25 4.1686 +02:00:30 4.1531 +02:00:35 4.2616 +02:00:40 4.1421 +02:00:45 4.1592 +02:00:50 4.1543 +02:00:57 4.2177 +02:01:00 4.1393 +02:01:05 4.0961 +02:01:10 4.2240 +02:01:15 4.2032 +02:01:20 4.2786 +02:01:26 4.1941 +02:01:33 4.2383 +02:01:35 4.1760 +02:01:40 4.1527 +02:01:45 4.2268 +02:01:50 4.1889 +02:01:55 4.1927 +02:02:04 4.1210 +02:02:05 4.0578 +02:02:10 4.2631 +02:02:17 4.1613 +02:02:20 4.2224 +02:02:25 4.2431 +02:02:30 4.2004 +02:02:38 4.2561 +02:02:40 4.1968 +02:02:54 4.2976 +02:02:55 4.2810 +02:03:04 4.2890 +02:03:05 4.2452 +02:03:11 4.1637 +02:03:15 4.1673 +02:03:23 4.1914 +02:03:25 4.1546 +02:03:30 4.1526 +02:03:35 4.2043 +02:03:40 4.1873 +02:03:45 4.1885 +02:03:50 4.1001 +02:03:55 4.2377 +02:04:00 4.1227 +02:04:05 4.1880 +02:04:10 4.2458 +02:04:15 4.2478 +02:04:20 4.2256 +02:04:25 4.1936 +02:04:30 4.1542 +02:04:35 4.2099 +02:04:40 4.1645 +02:04:45 4.2206 +02:04:50 4.1015 +02:04:55 4.2085 +02:05:00 4.1834 +02:05:05 4.1393 +02:05:10 4.1510 +02:05:15 4.2278 +02:05:20 4.2378 +02:05:25 4.2219 +02:05:30 4.1474 +02:05:35 4.0868 +02:05:40 4.1444 +02:05:45 4.2461 +02:05:50 4.1874 +02:05:55 4.1083 +02:06:00 4.1602 +02:06:05 4.2128 +02:06:10 4.2630 +02:06:15 4.3383 +02:06:20 4.2578 +02:06:25 4.2083 +02:06:30 4.2456 +02:06:35 4.2095 +02:06:40 4.1901 +02:06:45 4.1899 +02:06:50 4.2019 +02:06:55 4.2836 +02:07:00 4.1863 +02:07:05 4.2520 +02:07:10 4.1594 +02:07:15 4.1631 +02:07:20 4.2255 +02:07:25 4.2283 +02:07:30 4.2226 +02:07:35 4.1901 +02:07:40 4.1505 +02:07:45 4.1915 +02:07:50 4.1757 +02:07:55 4.1837 +02:08:00 4.2191 +02:08:05 4.1176 +02:08:10 4.3030 +02:08:15 4.2399 +02:08:20 4.1212 +02:08:25 4.0837 +02:08:30 4.2064 +02:08:35 4.2857 +02:08:40 4.1326 +02:08:45 4.1940 +02:08:50 4.1988 +02:08:55 4.1505 +02:09:00 4.0519 +02:09:05 4.1586 +02:09:10 4.1768 +02:09:15 4.1767 +02:09:20 4.2283 +02:09:25 4.2380 +02:09:30 4.1900 +02:09:35 4.1687 +02:09:40 4.2090 +02:09:45 4.1846 +02:09:50 4.2362 +02:09:55 4.1410 +02:10:00 4.0728 +02:10:05 4.1472 +02:10:10 4.1651 +02:10:15 4.2404 +02:10:20 4.2664 +02:10:25 4.2732 +02:10:30 4.1561 +02:10:35 4.1633 +02:10:40 4.1870 +02:10:45 4.2008 +02:10:50 4.1688 +02:10:55 4.2411 +02:11:00 4.2295 +02:11:05 4.1135 +02:11:10 4.1679 +02:11:15 4.1828 +02:11:20 4.3140 +02:11:25 4.2713 +02:11:30 4.2126 +02:11:35 4.1046 +02:11:40 4.1238 +02:11:45 4.1780 +02:11:50 4.1458 +02:11:55 4.1722 +02:12:00 4.1893 +02:12:05 4.1432 +02:12:10 4.1492 +02:12:15 4.2084 +02:12:20 4.2075 +02:12:25 4.1427 +02:12:30 4.1393 +02:12:35 4.1441 +02:12:40 4.2886 +02:12:45 4.2406 +02:12:50 4.1813 +02:12:55 4.2433 +02:13:00 4.2855 +02:13:05 4.1842 +02:13:10 4.1000 +02:13:15 4.1187 +02:13:20 3.9957 +02:13:25 4.0570 +02:13:30 4.1108 +02:13:35 4.0943 +02:13:40 4.1335 +02:13:45 4.1902 +02:13:50 4.1332 +02:13:55 4.1841 +02:14:00 4.2023 +02:14:05 4.0799 +02:14:10 4.1584 +02:14:15 4.2099 +02:14:20 4.1308 +02:14:25 4.0924 +02:14:30 4.1697 +02:14:35 4.2515 +02:14:40 4.1511 +02:14:45 4.1536 +02:14:50 4.1607 +02:14:55 4.1614 +02:15:00 4.1799 +02:15:05 4.1321 +02:15:10 4.1604 +02:15:15 4.1079 +02:15:20 4.1907 +02:15:25 4.2797 +02:15:30 4.1837 +02:15:35 4.1903 +02:15:40 4.2137 +02:15:45 4.1559 +02:15:50 4.1595 +02:15:55 4.0787 +02:16:00 4.1085 +02:16:05 4.1644 +02:16:10 4.1593 +02:16:15 4.1139 +02:16:20 4.1045 +02:16:25 4.1906 +02:16:30 4.1429 +02:16:35 4.1104 +02:16:40 4.1160 +02:16:45 4.1655 +02:16:50 4.2069 +02:16:55 4.1726 +02:17:00 4.1455 +02:17:05 4.1373 +02:17:10 4.1775 +02:17:15 4.1469 +02:17:20 4.1154 +02:17:25 4.1441 +02:17:30 4.1747 +02:17:35 4.1642 +02:17:40 4.1866 +02:17:45 4.1925 +02:17:50 4.1631 +02:17:55 4.1778 +02:18:00 4.1929 +02:18:05 4.1938 +02:18:10 4.1939 +02:18:15 4.1975 +02:18:20 4.1560 +02:18:25 4.0924 +02:18:30 4.0546 +02:18:35 4.0638 +02:18:40 4.1209 +02:18:45 4.1445 +02:18:50 4.2099 +02:18:55 4.1579 +02:19:00 4.1800 +02:19:05 4.1459 +02:19:10 4.2127 +02:19:15 4.1959 +02:19:20 4.1844 +02:19:25 4.1316 +02:19:30 4.2238 +02:19:35 4.1779 +02:19:40 4.1592 +02:19:45 4.1347 +02:19:50 4.1292 +02:19:55 4.2150 +02:20:00 4.1576 +02:20:05 4.1293 +02:20:10 4.2231 +02:20:15 4.2236 +02:20:20 4.1652 +02:20:25 4.1424 +02:20:30 4.1101 +02:20:35 4.1493 +02:20:40 4.2230 +02:20:45 4.1677 +02:20:50 4.1060 +02:20:55 4.0078 +02:21:00 4.0629 +02:21:05 4.1757 +02:21:10 4.1624 +02:21:15 4.1619 +02:21:20 4.1910 +02:21:25 4.1314 +02:21:30 4.1274 +02:21:35 4.0989 +02:21:40 4.0430 +02:21:45 4.1582 +02:21:50 4.1620 +02:21:55 4.1397 +02:22:00 4.1915 +02:22:05 4.1760 +02:22:10 4.1728 +02:22:15 4.1563 +02:22:20 4.0636 +02:22:25 4.1132 +02:22:30 4.0741 +02:22:35 3.9961 +02:22:40 4.2086 +02:22:45 4.1362 +02:22:50 4.1086 +02:22:55 4.2161 +02:23:00 4.2087 +02:23:05 4.1678 +02:23:10 4.1245 +02:23:15 4.1171 +02:23:20 4.1182 +02:23:25 4.1488 +02:23:30 4.1352 +02:23:35 4.1624 +02:23:40 4.1783 +02:23:45 4.1696 +02:23:50 4.1530 +02:23:55 4.1571 +02:24:00 4.1551 +02:24:05 4.1015 +02:24:10 4.1744 +02:24:15 4.1372 +02:24:20 4.1478 +02:24:25 4.1699 +02:24:30 4.1840 +02:24:35 4.2447 +02:24:40 4.2078 +02:24:45 4.1995 +02:24:50 4.2052 +02:24:55 4.2432 +02:25:00 4.1355 +02:25:05 4.0729 +02:25:10 4.1021 +02:25:15 4.1477 +02:25:20 4.2625 +02:25:25 4.2272 +02:25:30 4.0843 +02:25:35 3.9715 +02:25:40 4.1757 +02:25:45 4.0842 +02:25:50 4.0888 +02:25:55 4.0031 +02:26:00 4.1396 +02:26:05 4.1742 +02:26:10 4.1386 +02:26:15 4.2124 +02:26:20 4.2847 +02:26:25 4.2304 +02:26:30 4.1550 +02:26:35 4.1215 +02:26:40 4.0619 +02:26:45 4.1776 +02:26:50 4.1781 +02:26:55 4.0659 +02:27:00 4.0054 +02:27:05 4.1167 +02:27:10 4.2470 +02:27:15 4.2732 +02:27:20 4.2631 +02:27:25 4.2288 +02:27:30 4.1261 +02:27:35 4.0833 +02:27:40 4.1067 +02:27:45 4.1005 +02:27:50 4.0911 +02:27:55 4.1113 +02:28:00 4.1578 +02:28:05 4.2158 +02:28:10 4.2389 +02:28:15 4.1523 +02:28:20 4.0341 +02:28:25 4.0798 +02:28:30 4.1384 +02:28:35 4.1562 +02:28:40 4.1895 +02:28:45 4.2099 +02:28:50 4.0879 +02:28:55 4.0612 +02:29:00 4.2817 +02:29:05 4.3487 +02:29:10 4.2034 +02:29:15 4.1399 +02:29:20 4.1486 +02:29:25 4.1208 +02:29:30 4.1977 +02:29:35 4.1000 +02:29:40 4.0890 +02:29:45 4.1176 +02:29:50 4.1399 +02:29:55 4.1026 +02:30:00 4.1313 +02:30:05 4.2516 +02:30:10 4.1480 +02:30:15 4.0434 +02:30:20 4.1688 +02:30:25 4.1513 +02:30:30 4.1302 +02:30:35 4.2523 +02:30:40 4.1802 +02:30:45 4.0270 +02:30:50 4.1505 +02:30:55 4.2245 +02:31:00 4.2088 +02:31:05 4.2055 +02:31:10 4.0597 +02:31:15 4.0762 +02:31:20 4.1495 +02:31:25 4.1026 +02:31:30 4.1775 +02:31:35 4.1374 +02:31:40 4.1534 +02:31:45 4.1217 +02:31:50 4.1739 +02:31:55 4.1841 +02:32:00 4.1247 +02:32:05 4.1161 +02:32:10 4.1725 +02:32:15 4.1800 +02:32:20 4.1806 +02:32:25 4.0624 +02:32:30 4.0874 +02:32:35 4.0759 +02:32:40 4.0354 +02:32:45 4.0869 +02:32:50 4.1132 +02:32:55 4.0266 +02:33:00 4.1799 +02:33:05 4.2289 +02:33:10 4.0643 +02:33:15 4.1263 +02:33:20 4.1694 +02:33:25 4.0679 +02:33:30 4.0708 +02:33:35 4.0465 +02:33:40 4.1215 +02:33:45 4.1559 +02:33:50 4.1174 +02:33:55 4.0351 +02:34:00 4.1682 +02:34:05 4.1579 +02:34:10 4.0796 +02:34:15 4.0866 +02:34:20 4.0562 +02:34:25 4.0234 +02:34:30 4.0912 +02:34:35 4.1336 +02:34:40 4.1380 +02:34:45 4.2108 +02:34:50 4.1740 +02:34:55 4.2215 +02:35:00 4.2123 +02:35:05 4.1473 +02:35:10 4.2102 +02:35:15 4.1829 +02:35:20 4.1742 +02:35:25 4.1526 +02:35:30 4.1790 +02:35:35 4.1885 +02:35:40 4.0966 +02:35:45 4.1016 +02:35:50 4.0770 +02:35:55 4.1873 +02:36:00 4.1292 +02:36:05 4.0955 +02:36:10 4.0837 +02:36:15 4.1253 +02:36:20 4.2201 +02:36:25 4.1908 +02:36:30 4.1791 +02:36:35 4.1767 +02:36:40 4.0042 +02:36:45 4.0460 +02:36:50 4.2050 +02:36:55 4.2273 +02:37:00 4.2083 +02:37:05 4.1263 +02:37:10 4.1522 +02:37:15 4.1717 +02:37:20 4.2156 +02:37:25 4.1146 +02:37:30 4.1627 +02:37:35 4.2009 +02:37:40 4.1631 +02:37:45 4.1166 +02:37:50 4.1653 +02:37:55 4.2368 +02:38:00 4.1604 +02:38:05 4.1990 +02:38:10 4.2026 +02:38:15 4.1110 +02:38:20 4.0789 +02:38:25 3.9994 +02:38:30 4.0533 +02:38:35 4.1610 +02:38:40 4.1382 +02:38:45 4.1700 +02:38:50 4.1390 +02:38:55 4.1865 +02:39:00 4.1247 +02:39:05 4.0953 +02:39:10 4.1854 +02:39:15 4.1128 +02:39:20 4.1533 +02:39:25 4.1766 +02:39:30 4.1894 +02:39:35 4.0903 +02:39:40 4.1487 +02:39:45 4.1484 +02:39:50 4.1423 +02:39:55 4.1871 +02:40:00 4.1722 +02:40:05 4.1034 +02:40:10 4.1258 +02:40:15 4.1105 +02:40:20 4.1927 +02:40:25 4.1886 +02:40:30 4.1579 +02:40:35 4.1461 +02:40:40 4.1335 +02:40:45 4.1607 +02:40:50 4.1729 +02:40:55 4.1343 +02:41:00 4.1075 +02:41:05 4.0258 +02:41:10 4.1284 +02:41:15 4.1438 +02:41:20 4.1218 +02:41:25 4.1181 +02:41:30 4.0841 +02:41:35 4.1964 +02:41:40 4.1918 +02:41:45 4.1610 +02:41:50 4.1043 +02:41:55 4.0863 +02:42:00 4.1567 +02:42:05 4.0846 +02:42:10 4.1127 +02:42:15 4.1260 +02:42:20 4.1477 +02:42:25 4.2246 +02:42:30 4.2126 +02:42:35 4.1910 +02:42:40 4.0283 +02:42:45 4.1561 +02:42:50 4.1828 +02:42:55 4.0757 +02:43:00 4.0900 +02:43:05 4.1173 +02:43:10 4.1026 +02:43:15 4.0553 +02:43:20 4.1566 +02:43:25 4.2606 +02:43:30 4.2622 +02:43:35 4.2466 +02:43:40 4.1505 +02:43:45 4.1419 +02:43:50 4.0965 +02:43:55 4.1334 +02:44:00 4.1435 +02:44:05 4.1135 +02:44:10 4.1799 +02:44:15 4.1538 +02:44:20 4.1534 +02:44:25 4.0787 +02:44:30 4.0327 +02:44:35 4.0828 +02:44:40 4.2327 +02:44:45 4.2298 +02:44:50 4.1914 +02:44:55 4.1753 +02:45:00 4.2077 +02:45:05 4.1789 +02:45:10 4.1985 +02:45:15 4.2293 +02:45:20 4.1592 +02:45:25 4.1241 +02:45:30 4.1730 +02:45:35 4.1365 +02:45:40 4.0295 +02:45:45 4.1047 +02:45:50 4.1216 +02:45:55 4.1105 +02:46:00 4.0771 +02:46:05 4.0411 +02:46:10 4.0778 +02:46:15 3.9794 +02:46:20 4.0359 +02:46:25 4.0793 +02:46:30 4.0933 +02:46:35 4.1006 +02:46:40 4.1307 +02:46:45 4.1044 +02:46:50 4.1122 +02:46:55 4.0169 +02:47:00 4.1364 +02:47:05 4.1860 +02:47:10 4.1452 +02:47:15 4.1383 +02:47:20 4.1360 +02:47:25 4.1525 +02:47:30 4.1283 +02:47:35 4.1275 +02:47:40 4.0927 +02:47:45 4.1161 +02:47:50 4.0778 +02:47:55 4.0021 +02:48:00 4.0826 +02:48:05 4.1117 +02:48:10 4.0457 +02:48:15 4.0271 +02:48:20 4.0872 +02:48:25 4.0760 +02:48:30 4.0597 +02:48:35 4.0439 +02:48:40 4.1604 +02:48:45 4.1231 +02:48:50 4.1584 +02:48:55 4.0520 +02:49:00 4.0423 +02:49:05 4.0744 +02:49:10 4.0702 +02:49:15 4.1211 +02:49:20 4.0647 +02:49:25 4.0743 +02:49:30 4.1030 +02:49:35 4.0490 +02:49:40 4.0653 +02:49:45 4.1020 +02:49:50 4.1297 +02:49:55 4.2229 +02:50:00 4.2171 +02:50:05 4.0967 +02:50:10 4.1476 +02:50:15 4.1656 +02:50:20 4.1595 +02:50:25 4.1204 +02:50:30 4.1451 +02:50:35 4.2053 +02:50:40 4.2125 +02:50:45 4.0964 +02:50:50 4.1665 +02:50:55 4.1531 +02:51:00 4.0733 +02:51:05 4.1222 +02:51:10 4.1475 +02:51:15 4.1120 +02:51:20 4.1071 +02:51:25 4.0775 +02:51:30 4.1331 +02:51:35 4.2072 +02:51:40 4.1793 +02:51:45 4.1334 +02:51:50 4.0925 +02:51:55 4.1463 +02:52:00 4.1764 +02:52:05 4.0773 +02:52:10 4.1061 +02:52:15 4.0837 +02:52:20 3.9810 +02:52:25 4.0003 +02:52:30 4.1147 +02:52:35 4.1598 +02:52:40 4.1805 +02:52:45 4.1585 +02:52:50 4.0546 +02:52:55 4.0306 +02:53:00 4.0552 +02:53:05 4.1020 +02:53:10 4.2909 +02:53:15 4.2427 +02:53:20 4.1641 +02:53:25 4.1636 +02:53:30 4.1516 +02:53:35 4.1762 +02:53:40 4.2587 +02:53:45 4.2502 +02:53:50 4.2213 +02:53:55 4.2318 +02:54:00 4.1470 +02:54:05 4.1614 +02:54:10 4.1091 +02:54:15 4.0696 +02:54:20 4.0259 +02:54:25 3.9875 +02:54:30 4.0774 +02:54:35 4.0842 +02:54:40 4.0771 +02:54:45 4.1425 +02:54:50 4.1238 +02:54:55 4.0883 +02:55:00 4.0167 +02:55:05 4.0868 +02:55:10 4.1583 +02:55:15 4.2231 +02:55:20 4.1593 +02:55:25 4.1239 +02:55:30 4.0983 +02:55:35 4.1409 +02:55:40 4.1461 +02:55:45 4.0387 +02:55:50 4.1010 +02:55:55 4.2396 +02:56:00 4.1935 +02:56:05 4.0276 +02:56:10 4.0077 +02:56:15 4.0500 +02:56:20 4.2064 +02:56:25 4.0581 +02:56:30 4.1043 +02:56:35 4.2815 +02:56:40 4.2406 +02:56:45 4.1377 +02:56:50 3.9394 +02:56:55 3.9447 +02:57:00 4.0772 +02:57:05 4.1259 +02:57:10 4.2053 +02:57:15 4.1411 +02:57:20 4.0934 +02:57:25 4.2224 +02:57:30 4.2731 +02:57:35 4.1185 +02:57:40 4.1182 +02:57:45 4.0903 +02:57:50 4.0693 +02:57:55 4.0738 +02:58:00 4.0514 +02:58:05 4.1283 +02:58:10 4.1135 +02:58:15 4.0932 +02:58:20 4.1098 +02:58:25 4.1166 +02:58:30 4.1771 +02:58:35 4.1442 +02:58:40 4.1452 +02:58:45 4.1107 +02:58:50 4.0279 +02:58:55 4.0332 +02:59:00 4.0770 +02:59:05 4.1350 +02:59:10 4.2132 +02:59:15 4.1704 +02:59:20 4.1093 +02:59:25 4.1111 +02:59:30 4.0772 +02:59:35 4.0856 +02:59:40 4.1295 +02:59:45 4.1113 +02:59:50 4.0839 +02:59:55 4.1054 +03:00:00 4.0688 +03:00:05 4.1299 +03:00:10 4.0491 +03:00:15 4.0669 +03:00:20 4.1296 +03:00:25 4.0701 +03:00:30 4.1557 +03:00:35 4.0725 +03:00:40 4.1471 +03:00:45 4.1281 +03:00:50 4.1193 +03:00:55 4.0028 +03:01:00 4.1313 +03:01:05 4.0617 +03:01:10 4.0163 +03:01:15 4.0496 +03:01:20 4.1076 +03:01:25 4.0784 +03:01:30 4.0805 +03:01:35 4.1099 +03:01:40 4.0485 +03:01:45 4.1234 +03:01:50 4.1263 +03:01:55 4.1518 +03:02:00 4.1629 +03:02:05 4.1010 +03:02:10 4.0419 +03:02:15 4.0679 +03:02:20 4.0246 +03:02:25 4.0989 +03:02:30 4.0984 +03:02:35 4.1170 +03:02:40 4.1115 +03:02:45 4.1782 +03:02:50 4.1394 +03:02:55 4.0243 +03:03:00 4.1398 +03:03:05 4.1272 +03:03:10 4.1218 +03:03:15 4.1797 +03:03:20 4.0746 +03:03:25 4.0411 +03:03:30 4.0641 +03:03:35 4.0930 +03:03:40 4.1379 +03:03:45 4.0847 +03:03:50 4.0956 +03:03:55 4.1175 +03:04:00 4.1251 +03:04:05 4.1154 +03:04:10 4.1951 +03:04:15 4.1457 +03:04:20 4.0859 +03:04:25 4.1019 +03:04:30 4.2113 +03:04:35 4.1909 +03:04:40 4.0402 +03:04:45 4.0572 +03:04:50 4.0732 +03:04:55 4.0113 +03:05:00 4.0661 +03:05:05 4.2068 +03:05:10 4.1588 +03:05:15 4.1435 +03:05:20 4.1476 +03:05:25 4.0680 +03:05:30 4.0687 +03:05:35 4.1901 +03:05:40 4.2462 +03:05:45 4.1328 +03:05:50 4.1404 +03:05:55 4.1439 +03:06:00 4.1157 +03:06:05 4.1096 +03:06:10 4.1543 +03:06:15 4.1000 +03:06:20 4.1197 +03:06:25 4.1629 +03:06:30 4.1778 +03:06:35 4.1347 +03:06:40 4.1694 +03:06:45 4.0586 +03:06:50 4.1128 +03:06:55 4.1279 +03:07:00 4.1506 +03:07:05 4.1491 +03:07:10 4.1245 +03:07:15 4.1581 +03:07:20 4.1156 +03:07:25 4.0766 +03:07:30 4.1468 +03:07:35 4.1760 +03:07:40 4.1077 +03:07:45 4.1175 +03:07:50 4.1451 +03:07:55 4.0797 +03:08:00 4.1240 +03:08:05 4.1027 +03:08:10 4.1440 +03:08:15 4.1360 +03:08:20 4.0976 +03:08:25 4.0771 +03:08:30 4.0802 +03:08:35 4.1210 +03:08:40 4.1056 +03:08:45 4.1336 +03:08:50 4.1100 +03:08:55 4.0467 +03:09:00 4.0225 +03:09:05 4.0678 +03:09:10 4.0075 +03:09:15 4.0357 +03:09:20 4.0428 +03:09:25 4.0406 +03:09:30 4.0600 +03:09:35 4.0433 +03:09:40 4.1408 +03:09:45 4.1136 +03:09:50 4.1204 +03:09:55 4.0246 +03:10:00 4.0828 +03:10:05 4.1390 +03:10:10 4.0488 +03:10:15 4.0668 +03:10:20 4.0832 +03:10:25 4.1146 +03:10:30 4.0666 +03:10:35 4.0692 +03:10:40 4.1054 +03:10:45 4.0989 +03:10:50 4.0424 +03:10:55 4.0947 +03:11:00 4.0327 +03:11:05 3.9934 +03:11:10 4.0688 +03:11:15 4.0088 +03:11:20 4.1014 +03:11:25 4.0932 +03:11:30 4.0402 +03:11:35 4.1291 +03:11:40 4.1372 +03:11:45 4.0839 +03:11:50 4.0783 +03:11:55 4.1791 +03:12:00 4.1564 +03:12:05 4.0737 +03:12:10 4.1292 +03:12:15 4.1274 +03:12:20 4.1224 +03:12:25 4.0596 +03:12:30 4.0650 +03:12:35 4.0860 +03:12:40 4.0893 +03:12:45 4.1373 +03:12:50 4.1264 +03:12:55 4.1000 +03:13:00 4.1198 +03:13:05 4.0719 +03:13:10 4.0167 +03:13:15 4.1536 +03:13:20 4.1055 +03:13:25 4.0760 +03:13:30 4.0403 +03:13:35 4.0570 +03:13:40 4.0695 +03:13:45 4.0837 +03:13:50 4.1057 +03:13:55 4.1097 +03:14:00 4.1634 +03:14:05 4.0933 +03:14:10 4.0823 +03:14:15 4.0529 +03:14:20 4.1354 +03:14:25 4.1684 +03:14:30 4.2188 +03:14:35 4.1617 +03:14:40 4.0973 +03:14:45 4.0808 +03:14:50 4.0971 +03:14:55 4.1060 +03:15:00 4.1402 +03:15:05 4.0381 +03:15:10 4.0710 +03:15:15 4.1055 +03:15:20 4.1075 +03:15:25 4.1232 +03:15:30 4.0364 +03:15:35 4.0091 +03:15:40 3.9933 +03:15:45 3.8853 +03:15:50 4.0392 +03:15:55 4.0995 +03:16:00 4.1262 +03:16:05 4.0573 +03:16:10 4.0465 +03:16:15 3.9943 +03:16:20 4.0505 +03:16:25 4.1423 +03:16:30 4.2078 +03:16:35 4.1614 +03:16:40 4.1824 +03:16:45 4.1035 +03:16:50 4.0936 +03:16:55 4.0976 +03:17:00 4.0418 +03:17:05 4.1097 +03:17:10 4.1738 +03:17:15 4.1959 +03:17:20 4.1691 +03:17:25 4.1501 +03:17:30 4.0586 +03:17:35 4.0942 +03:17:40 4.1271 +03:17:45 4.0632 +03:17:50 4.0544 +03:17:55 4.1258 +03:18:00 4.1190 +03:18:05 4.0506 +03:18:10 4.0809 +03:18:15 4.1472 +03:18:20 4.1121 +03:18:25 4.1344 +03:18:30 4.1406 +03:18:35 4.1596 +03:18:40 4.1191 +03:18:45 4.1143 +03:18:50 4.1009 +03:18:55 4.1065 +03:19:00 4.0991 +03:19:05 4.0660 +03:19:10 4.1063 +03:19:15 4.1200 +03:19:20 4.0719 +03:19:25 4.1635 +03:19:30 4.1574 +03:19:35 4.1018 +03:19:40 4.1351 +03:19:45 4.1640 +03:19:50 4.2062 +03:19:55 4.0675 +03:20:00 4.0413 +03:20:05 4.1516 +03:20:10 4.1455 +03:20:15 4.0872 +03:20:20 4.0921 +03:20:25 4.1274 +03:20:30 4.1323 +03:20:35 4.0566 +03:20:40 4.0706 +03:20:45 4.0695 +03:20:50 4.0917 +03:20:55 4.1306 +03:21:00 4.0980 +03:21:05 4.0703 +03:21:10 4.0007 +03:21:15 4.0700 +03:21:20 4.1399 +03:21:25 4.1356 +03:21:30 4.1054 +03:21:35 4.1969 +03:21:40 4.1810 +03:21:45 4.1381 +03:21:50 4.0862 +03:21:55 4.0516 +03:22:00 4.0927 +03:22:05 4.1543 +03:22:10 4.1429 +03:22:15 4.0967 +03:22:20 4.1220 +03:22:25 4.1505 +03:22:30 4.0861 +03:22:35 4.0619 +03:22:40 4.1568 +03:22:45 4.0920 +03:22:50 4.0637 +03:22:55 4.0182 +03:23:00 4.0144 +03:23:05 4.0843 +03:23:10 4.0707 +03:23:15 4.1107 +03:23:20 4.0430 +03:23:25 4.0661 +03:23:30 4.0051 +03:23:35 3.9915 +03:23:40 4.0533 +03:23:45 4.0918 +03:23:50 4.1738 +03:23:55 4.1084 +03:24:00 4.0252 +03:24:05 4.1564 +03:24:10 4.1298 +03:24:15 4.1455 +03:24:20 4.1364 +03:24:25 4.0543 +03:24:30 4.0216 +03:24:35 4.1261 +03:24:40 4.1728 +03:24:45 4.0437 +03:24:50 4.0671 +03:24:55 4.1263 +03:25:00 4.0551 +03:25:05 4.0718 +03:25:10 4.1349 +03:25:15 4.0825 +03:25:20 4.0279 +03:25:25 4.0257 +03:25:30 4.1480 +03:25:35 4.1636 +03:25:40 4.1250 +03:25:45 4.1213 +03:25:50 4.0553 +03:25:55 4.1455 +03:26:00 4.2220 +03:26:05 4.1360 +03:26:10 4.0771 +03:26:15 4.0674 +03:26:20 4.1989 +03:26:25 4.1933 +03:26:30 4.2114 +03:26:35 4.0949 +03:26:40 4.0010 +03:26:45 4.0408 +03:26:50 3.9995 +03:26:55 4.0116 +03:27:00 4.0847 +03:27:05 4.0871 +03:27:10 4.0559 +03:27:15 4.0309 +03:27:20 4.0139 +03:27:25 4.0344 +03:27:30 4.0061 +03:27:35 3.9770 +03:27:40 4.0691 +03:27:45 4.0890 +03:27:50 4.1624 +03:27:55 4.1714 +03:28:00 4.1638 +03:28:05 4.0514 +03:28:10 3.9973 +03:28:15 4.0042 +03:28:20 4.0733 +03:28:25 4.1493 +03:28:30 4.2131 +03:28:35 4.1347 +03:28:40 4.0391 +03:28:45 3.9889 +03:28:50 4.0210 +03:28:55 4.0736 +03:29:00 4.1372 +03:29:05 4.1210 +03:29:10 4.1327 +03:29:15 4.1271 +03:29:20 4.1268 +03:29:25 4.0642 +03:29:30 4.0466 +03:29:35 4.1035 +03:29:40 4.1575 +03:29:45 4.1185 +03:29:50 4.1214 +03:29:55 4.1195 +03:30:00 4.1219 +03:30:05 4.1849 +03:30:10 4.2003 +03:30:15 4.1411 +03:30:20 4.1188 +03:30:25 4.1439 +03:30:30 4.1558 +03:30:35 4.1287 +03:30:40 4.0971 +03:30:45 4.1250 +03:30:50 4.0095 +03:30:55 4.0387 +03:31:00 4.0435 +03:31:05 4.0927 +03:31:10 4.0469 +03:31:15 4.1214 +03:31:20 4.1057 +03:31:25 4.0247 +03:31:30 4.0024 +03:31:35 4.0644 +03:31:40 4.1388 +03:31:45 4.0509 +03:31:50 4.0903 +03:31:55 4.0752 +03:32:00 4.1232 +03:32:05 4.2227 +03:32:10 4.0351 +03:32:15 4.0138 +03:32:20 4.0174 +03:32:25 4.0164 +03:32:30 4.0900 +03:32:35 4.0515 +03:32:40 4.0767 +03:32:45 4.1111 +03:32:50 4.0863 +03:32:55 4.1281 +03:33:00 4.1409 +03:33:05 4.1926 +03:33:10 4.1241 +03:33:15 4.0211 +03:33:20 4.1523 +03:33:25 4.0626 +03:33:30 4.0456 +03:33:35 4.1214 +03:33:40 4.0988 +03:33:45 4.1106 +03:33:50 4.0771 +03:33:55 4.1017 +03:34:00 4.0340 +03:34:05 4.1042 +03:34:10 4.1357 +03:34:15 4.1079 +03:34:20 4.0983 +03:34:25 4.1115 +03:34:30 4.0105 +03:34:35 4.0296 +03:34:40 4.0804 +03:34:45 4.1351 +03:34:50 4.1214 +03:34:55 4.0661 +03:35:00 4.0082 +03:35:05 4.0327 +03:35:10 4.0934 +03:35:15 4.0779 +03:35:20 4.0803 +03:35:25 4.1371 +03:35:30 4.1480 +03:35:35 4.1340 +03:35:40 4.0830 +03:35:45 4.1148 +03:35:50 4.1593 +03:35:55 4.0933 +03:36:00 4.0524 +03:36:05 4.0881 +03:36:10 4.1333 +03:36:15 4.1515 +03:36:20 4.0873 +03:36:25 4.1275 +03:36:30 4.1389 +03:36:35 4.0835 +03:36:40 4.0352 +03:36:45 4.0414 +03:36:50 4.0521 +03:36:55 4.0319 +03:37:00 4.1085 +03:37:05 4.1735 +03:37:10 4.1726 +03:37:15 4.0721 +03:37:20 4.0644 +03:37:25 4.0078 +03:37:30 4.0888 +03:37:35 4.0549 +03:37:40 3.9830 +03:37:45 3.9840 +03:37:50 4.1003 +03:37:55 4.1493 +03:38:00 4.1249 +03:38:05 4.1075 +03:38:10 4.1733 +03:38:15 4.1136 +03:38:20 4.0827 +03:38:25 4.1236 +03:38:30 4.1258 +03:38:35 4.0725 +03:38:40 4.0357 +03:38:45 3.9690 +03:38:50 4.1165 +03:38:55 4.1759 +03:39:00 4.1197 +03:39:05 4.1025 +03:39:10 4.0569 +03:39:15 4.0400 +03:39:20 3.9677 +03:39:25 3.9899 +03:39:30 4.0343 +03:39:35 4.0667 +03:39:40 4.1553 +03:39:45 4.1993 +03:39:50 4.0512 +03:39:55 4.0495 +03:40:00 4.2104 +03:40:05 4.1452 +03:40:10 4.0911 +03:40:15 4.1267 +03:40:20 4.0580 +03:40:25 4.0931 +03:40:30 4.2129 +03:40:35 4.1885 +03:40:40 4.1646 +03:40:45 4.1272 +03:40:50 4.0508 +03:40:55 4.0526 +03:41:00 4.0093 +03:41:05 3.9395 +03:41:10 4.0097 +03:41:15 4.1250 +03:41:20 4.0749 +03:41:25 4.0373 +03:41:30 4.0265 +03:41:35 3.9805 +03:41:40 4.0195 +03:41:45 3.9868 +03:41:50 4.0456 +03:41:55 4.1267 +03:42:00 4.1139 +03:42:05 4.1279 +03:42:10 4.1334 +03:42:15 4.0094 +03:42:20 4.0214 +03:42:25 4.0687 +03:42:30 3.9961 +03:42:35 4.0201 +03:42:40 4.0599 +03:42:45 4.0127 +03:42:50 3.9634 +03:42:55 4.0015 +03:43:00 4.0272 +03:43:05 4.1380 +03:43:10 4.2216 +03:43:15 4.1309 +03:43:20 4.0389 +03:43:25 3.9899 +03:43:30 3.9616 +03:43:35 4.0915 +03:43:40 4.0850 +03:43:45 4.0882 +03:43:50 4.0155 +03:43:55 4.0403 +03:44:00 4.0989 +03:44:05 4.0829 +03:44:10 4.0665 +03:44:15 4.0139 +03:44:20 3.9861 +03:44:25 4.0388 +03:44:30 4.0862 +03:44:35 4.0795 +03:44:40 4.1346 +03:44:45 4.1377 +03:44:50 4.0644 +03:44:55 4.1428 +03:45:00 4.1881 +03:45:05 4.1589 +03:45:10 4.0610 +03:45:15 4.0326 +03:45:20 4.1169 +03:45:25 4.1220 +03:45:30 4.1094 +03:45:35 4.0821 +03:45:40 4.1222 +03:45:45 4.1364 +03:45:50 4.1695 +03:45:55 4.0808 +03:46:00 4.0312 +03:46:05 4.0693 +03:46:10 4.0875 +03:46:15 4.1168 +03:46:20 4.1181 +03:46:25 4.0864 +03:46:30 4.0701 +03:46:35 4.1188 +03:46:40 4.0679 +03:46:45 4.0386 +03:46:50 4.0968 +03:46:55 4.0646 +03:47:00 4.0605 +03:47:05 4.1020 +03:47:10 4.0454 +03:47:15 4.0461 +03:47:20 4.0385 +03:47:25 4.1900 +03:47:30 4.1727 +03:47:35 4.0939 +03:47:40 4.0743 +03:47:45 4.0681 +03:47:50 3.9906 +03:47:55 4.0196 +03:48:00 4.0161 +03:48:05 4.0575 +03:48:10 4.1365 +03:48:15 4.1526 +03:48:20 4.1624 +03:48:25 4.2395 +03:48:30 4.1461 +03:48:35 4.0544 +03:48:40 4.1201 +03:48:45 4.1805 +03:48:50 4.0824 +03:48:55 4.0525 +03:49:00 3.9447 +03:49:05 3.9959 +03:49:10 4.0445 +03:49:15 4.0889 +03:49:20 4.0726 +03:49:25 4.1557 +03:49:30 4.1940 +03:49:35 4.1565 +03:49:40 4.0872 +03:49:45 4.0207 +03:49:50 4.0388 +03:49:55 4.0634 +03:50:00 4.1249 +03:50:05 4.0759 +03:50:10 4.0690 +03:50:15 4.0278 +03:50:20 4.0300 +03:50:25 4.0809 +03:50:30 4.0543 +03:50:35 3.9684 +03:50:40 3.9701 +03:50:45 4.0408 +03:50:50 4.0582 +03:50:55 3.9921 +03:51:00 3.9987 +03:51:05 4.0121 +03:51:10 4.0869 +03:51:15 4.0599 +03:51:20 3.9479 +03:51:25 3.9299 +03:51:30 3.9944 +03:51:35 4.0353 +03:51:40 4.1287 +03:51:45 4.2029 +03:51:50 4.1889 +03:51:55 4.0635 +03:52:00 4.0499 +03:52:05 4.0087 +03:52:10 4.0939 +03:52:15 4.0038 +03:52:20 4.1144 +03:52:25 4.1320 +03:52:30 4.0804 +03:52:35 4.0936 +03:52:40 4.1385 +03:52:45 4.1975 +03:52:50 4.1150 +03:52:55 4.0685 +03:53:00 4.0558 +03:53:05 4.0661 +03:53:10 4.1773 +03:53:15 4.1220 +03:53:20 4.0951 +03:53:25 4.1330 +03:53:30 3.9785 +03:53:35 4.0393 +03:53:40 4.0464 +03:53:45 4.0887 +03:53:50 4.0785 +03:53:55 4.0773 +03:54:00 4.0992 +03:54:05 4.0371 +03:54:10 4.0279 +03:54:15 4.0739 +03:54:20 4.0866 +03:54:25 4.1586 +03:54:30 4.1835 +03:54:35 4.0854 +03:54:40 4.0849 +03:54:45 4.1371 +03:54:50 4.1244 +03:54:55 4.0534 +03:55:00 4.0000 +03:55:05 4.1373 +03:55:10 4.1107 +03:55:15 4.1157 +03:55:20 4.2205 +03:55:25 4.0826 +03:55:30 4.0982 +03:55:35 4.0992 +03:55:40 4.0231 +03:55:45 4.1023 +03:55:50 4.0665 +03:55:55 4.1014 +03:56:00 4.1579 +03:56:05 4.0374 +03:56:10 3.9536 +03:56:15 3.9601 +03:56:20 4.0342 +03:56:25 4.0892 +03:56:30 4.1104 +03:56:35 4.0786 +03:56:40 4.0338 +03:56:45 4.0734 +03:56:50 4.1287 +03:56:55 4.1460 +03:57:00 4.1107 +03:57:05 3.9202 +03:57:10 3.9638 +03:57:15 4.0306 +03:57:20 4.0301 +03:57:25 3.9349 +03:57:30 3.8937 +03:57:35 3.9744 +03:57:40 4.0193 +03:57:45 4.0096 +03:57:50 4.1072 +03:57:55 4.1041 +03:58:00 4.0964 +03:58:05 4.0788 +03:58:10 4.1031 +03:58:15 4.1508 +03:58:20 4.1031 +03:58:25 4.0651 +03:58:30 4.0691 +03:58:35 4.0602 +03:58:40 4.0623 +03:58:45 4.0295 +03:58:50 4.0300 +03:58:55 4.1210 +03:59:00 4.1525 +03:59:05 4.1610 +03:59:10 4.0985 +03:59:15 4.1171 +03:59:20 4.1181 +03:59:25 4.0968 +03:59:30 4.0856 +03:59:35 4.0566 +03:59:40 4.0068 +03:59:45 4.0150 +03:59:50 4.0226 +03:59:55 4.0169 +04:00:00 4.0679 +04:00:05 4.1281 +04:00:10 4.0493 +04:00:15 4.0775 +04:00:20 4.0697 +04:00:25 4.0661 +04:00:30 4.0754 +04:00:35 4.0200 +04:00:40 4.0925 +04:00:45 4.0704 +04:00:50 4.1350 +04:00:55 4.1498 +04:01:00 4.0286 +04:01:05 4.0097 +04:01:10 4.0457 +04:01:15 4.0688 +04:01:20 4.0411 +04:01:25 4.0013 +04:01:30 4.0320 +04:01:35 4.0575 +04:01:40 4.0417 +04:01:45 4.0236 +04:01:50 4.0083 +04:01:55 4.0328 +04:02:00 4.0877 +04:02:05 4.0233 +04:02:10 4.0447 +04:02:15 4.0790 +04:02:20 4.0779 +04:02:25 4.1271 +04:02:30 4.0494 +04:02:35 4.0827 +04:02:40 4.0855 +04:02:45 3.9795 +04:02:50 3.9926 +04:02:55 3.9872 +04:03:00 3.9898 +04:03:15 4.1434 +04:03:20 4.0862 +04:03:25 4.0710 +04:03:30 4.1321 +04:03:35 4.0485 +04:03:40 4.0912 +04:03:45 4.1749 +04:03:50 4.1120 +04:03:55 4.0377 +04:04:00 4.0652 +04:04:05 4.1590 +04:04:10 4.1452 +04:04:15 4.0786 +04:04:20 4.0665 +04:04:25 4.0450 +04:04:30 4.0794 +04:04:35 4.1068 +04:04:40 4.0494 +04:04:45 4.1125 +04:04:50 4.1474 +04:04:55 4.0877 +04:05:00 4.0910 +04:05:05 4.1541 +04:05:10 4.0742 +04:05:15 4.0808 +04:05:20 4.1614 +04:05:25 4.0797 +04:05:30 4.0938 +04:05:35 4.0854 +04:05:40 4.0572 +04:05:45 4.1223 +04:05:50 4.0129 +04:05:55 4.0117 +04:06:00 4.0416 +04:06:05 4.0288 +04:06:10 4.0170 +04:06:15 4.0264 +04:06:20 3.9962 +04:06:25 4.0271 +04:06:30 4.0211 +04:06:35 3.9995 +04:06:40 4.0868 +04:06:45 4.0743 +04:06:50 4.1167 +04:06:55 4.0344 +04:07:00 4.0152 +04:07:05 4.0559 +04:07:10 4.0426 +04:07:15 4.0358 +04:07:20 4.0760 +04:07:25 4.0081 +04:07:30 3.9883 +04:07:35 4.0747 +04:07:40 4.1201 +04:07:45 4.1002 +04:07:50 3.9981 +04:07:55 4.0132 +04:08:00 3.9810 +04:08:05 3.9970 +04:08:10 4.0591 +04:08:15 4.0192 +04:08:20 4.0776 +04:08:25 3.9858 +04:08:30 3.9701 +04:08:35 4.0298 +04:08:40 4.0461 +04:08:45 4.1026 +04:08:50 4.0422 +04:08:55 4.0782 +04:09:00 4.1013 +04:09:05 4.0557 +04:09:10 4.0287 +04:09:15 4.0880 +04:09:20 4.0791 +04:09:25 4.0986 +04:09:30 4.1017 +04:09:35 4.0603 +04:09:40 4.0401 +04:09:45 4.0433 +04:09:50 4.0454 +04:09:55 4.0437 +04:10:00 4.0338 +04:10:05 4.1308 +04:10:10 4.0189 +04:10:15 4.0419 +04:10:20 4.0833 +04:10:25 4.0988 +04:10:30 4.1208 +04:10:35 4.0149 +04:10:40 4.0414 +04:10:45 4.0626 +04:10:50 4.0934 +04:10:55 3.9615 +04:11:00 4.0348 +04:11:05 4.0945 +04:11:10 4.0446 +04:11:15 4.0064 +04:11:20 4.0353 +04:11:25 4.0910 +04:11:30 4.0711 +04:11:35 4.0977 +04:11:40 4.0508 +04:11:45 4.0511 +04:11:50 4.0279 +04:11:55 4.0479 +04:12:00 4.0377 +04:12:05 4.0103 +04:12:10 3.9387 +04:12:15 3.9166 +04:12:20 3.9891 +04:12:25 4.0158 +04:12:30 4.0790 +04:12:35 4.1182 +04:12:40 4.0019 +04:12:45 3.8491 +04:12:50 4.0451 +04:12:55 4.1162 +04:13:00 4.0950 +04:13:05 4.1231 +04:13:10 4.0735 +04:13:15 4.0462 +04:13:20 4.0216 +04:13:25 4.0860 +04:13:30 4.0824 +04:13:35 4.0969 +04:13:40 4.0873 +04:13:45 3.9946 +04:13:50 4.0223 +04:13:55 3.9728 +04:14:00 4.0428 +04:14:05 4.0623 +04:14:10 4.0626 +04:14:15 4.1187 +04:14:20 4.0752 +04:14:25 4.0912 +04:14:30 4.0005 +04:14:35 4.0054 +04:14:40 4.0669 +04:14:45 4.1372 +04:14:50 4.0446 +04:14:55 4.0436 +04:15:00 4.0354 +04:15:05 4.0954 +04:15:10 4.0800 +04:15:15 4.0128 +04:15:20 4.0240 +04:15:25 4.0094 +04:15:30 4.1446 +04:15:35 4.1474 +04:15:40 4.0492 +04:15:45 4.0400 +04:15:50 3.9749 +04:15:55 4.0986 +04:16:00 4.0816 +04:16:05 4.0116 +04:16:10 4.1562 +04:16:15 4.0844 +04:16:20 4.0762 +04:16:25 4.0181 +04:16:30 4.0866 +04:16:35 4.0120 +04:16:40 3.9740 +04:16:45 4.0272 +04:16:50 4.0410 +04:16:55 4.0270 +04:17:00 3.9885 +04:17:05 3.8586 +04:17:10 3.8953 +04:17:15 4.0647 +04:17:20 4.0308 +04:17:25 4.1195 +04:17:30 4.1192 +04:17:35 4.0678 +04:17:40 4.0904 +04:17:45 4.0457 +04:17:50 4.0033 +04:17:55 4.0700 +04:18:00 4.0485 +04:18:05 4.0782 +04:18:10 3.9996 +04:18:15 4.0400 +04:18:20 4.0871 +04:18:25 4.1521 +04:18:30 4.1135 +04:18:35 4.0407 +04:18:40 4.0883 +04:18:45 4.1141 +04:18:50 4.0726 +04:18:55 4.1482 +04:19:00 4.0820 +04:19:05 4.0976 +04:19:10 4.0710 +04:19:15 4.0883 +04:19:20 4.0456 +04:19:25 3.9887 +04:19:30 4.0172 +04:19:35 4.1133 +04:19:40 4.1168 +04:19:45 4.0405 +04:19:50 3.9421 +04:19:55 3.9902 +04:20:00 4.0676 +04:20:05 4.0501 +04:20:10 4.0215 +04:20:15 4.0471 +04:20:20 4.1573 +04:20:25 4.1254 +04:20:30 4.1137 +04:20:35 4.0218 +04:20:40 4.0644 +04:20:45 4.1014 +04:20:50 4.0293 +04:20:55 4.0704 +04:21:00 4.0560 +04:21:05 3.9641 +04:21:10 4.1124 +04:21:15 4.1308 +04:21:20 4.0865 +04:21:25 4.1106 +04:21:30 4.0873 +04:21:35 4.0260 +04:21:40 4.1024 +04:21:45 4.1577 +04:21:50 4.1546 +04:21:55 4.0419 +04:22:00 3.9838 +04:22:05 3.9895 +04:22:10 4.0644 +04:22:15 4.0941 +04:22:20 4.0800 +04:22:25 4.1094 +04:22:30 4.0694 +04:22:35 4.0247 +04:22:40 4.0559 +04:22:45 4.0296 +04:22:50 3.9198 +04:22:55 3.9093 +04:23:00 4.0556 +04:23:05 4.0296 +04:23:10 4.0937 +04:23:15 4.0862 +04:23:20 4.1121 +04:23:25 4.0896 +04:23:30 4.1232 +04:23:35 4.0697 +04:23:40 4.0028 +04:23:45 4.0742 +04:23:50 4.1085 +04:23:55 4.1121 +04:24:00 4.0926 +04:24:05 4.0860 +04:24:10 4.1171 +04:24:15 4.0818 +04:24:20 4.0521 +04:24:25 4.1181 +04:24:30 4.1291 +04:24:35 4.1055 +04:24:40 4.0621 +04:24:45 4.0248 +04:24:50 4.0452 +04:24:55 4.0003 +04:25:00 3.9861 +04:25:05 4.0202 +04:25:10 4.0330 +04:25:15 4.1033 +04:25:20 4.0639 +04:25:25 4.0326 +04:25:30 4.0411 +04:25:35 4.0748 +04:25:40 4.0267 +04:25:45 3.8942 +04:25:50 3.9230 +04:25:55 3.9923 +04:26:00 4.0184 +04:26:05 4.1140 +04:26:10 4.1631 +04:26:15 4.1512 +04:26:20 4.1172 +04:26:25 3.9456 +04:26:30 3.9539 +04:26:35 3.9670 +04:26:40 3.9803 +04:26:45 4.0176 +04:26:50 4.0582 +04:26:55 4.0807 +04:27:00 4.0090 +04:27:05 3.9903 +04:27:10 4.0705 +04:27:15 4.1370 +04:27:20 4.1659 +04:27:25 4.1442 +04:27:30 4.0738 +04:27:35 3.9483 +04:27:40 4.0582 +04:27:45 4.0499 +04:27:50 4.0891 +04:27:55 4.1162 +04:28:00 4.0254 +04:28:05 4.0193 +04:28:10 4.0301 +04:28:15 4.0661 +04:28:20 4.0938 +04:28:25 4.1089 +04:28:30 4.1480 +04:28:35 4.1721 +04:28:40 4.1785 +04:28:45 4.2213 +04:28:50 4.0574 +04:28:55 3.9775 +04:29:00 3.9938 +04:29:05 4.0620 +04:29:10 4.0487 +04:29:15 3.9717 +04:29:20 3.9880 +04:29:25 4.0630 +04:29:30 4.0240 +04:29:35 3.9478 +04:29:40 4.0095 +04:29:45 4.0468 +04:29:50 4.0174 +04:29:55 3.9363 +04:30:00 3.9969 +04:30:05 3.9682 +04:30:10 4.0608 +04:30:15 4.0622 +04:30:20 3.9997 +04:30:25 4.1280 +04:30:30 4.1360 +04:30:35 4.0142 +04:30:40 4.0664 +04:30:45 4.1031 +04:30:50 4.0027 +04:30:55 3.9513 +04:31:00 4.1246 +04:31:05 4.0150 +04:31:10 3.9790 +04:31:15 4.1175 +04:31:20 4.1218 +04:31:25 4.1292 +04:31:30 4.0749 +04:31:35 3.9309 +04:31:40 3.9193 +04:31:45 3.9333 +04:31:50 3.9845 +04:31:55 4.0423 +04:32:00 3.9989 +04:32:05 3.9556 +04:32:10 4.0899 +04:32:15 4.1073 +04:32:20 4.0402 +04:32:25 4.0683 +04:32:30 4.1364 +04:32:35 4.1568 +04:32:40 4.0797 +04:32:45 4.0491 +04:32:50 4.0471 +04:32:55 3.9937 +04:33:00 4.0290 +04:33:05 4.0669 +04:33:10 4.0924 +04:33:15 3.9666 +04:33:20 4.0217 +04:33:25 4.1640 +04:33:30 4.1051 +04:33:35 4.0035 +04:33:40 4.0447 +04:33:45 4.0698 +04:33:50 4.0754 +04:33:55 4.0518 +04:34:00 4.0559 +04:34:05 4.0504 +04:34:10 3.9753 +04:34:15 4.0496 +04:34:20 4.0948 +04:34:25 4.0597 +04:34:30 3.9724 +04:34:35 3.9955 +04:34:40 3.9453 +04:34:45 3.9633 +04:34:50 4.0974 +04:34:55 4.0312 +04:35:00 3.9932 +04:35:05 3.9990 +04:35:10 4.0152 +04:35:15 4.0381 +04:35:20 4.0324 +04:35:25 4.0169 +04:35:30 3.9831 +04:35:35 4.0750 +04:35:40 4.1812 +04:35:45 4.0404 +04:35:50 3.9617 +04:35:55 4.1232 +04:36:00 4.1599 +04:36:05 4.0862 +04:36:10 4.0233 +04:36:15 3.9876 +04:36:20 3.9762 +04:36:25 3.9575 +04:36:30 4.0419 +04:36:35 4.0650 +04:36:40 4.0659 +04:36:45 4.0091 +04:36:50 4.0967 +04:36:55 4.1526 +04:37:00 4.1363 +04:37:05 4.1243 +04:37:10 4.0998 +04:37:15 4.0470 +04:37:20 4.0278 +04:37:25 4.0642 +04:37:30 4.0673 +04:37:35 4.0763 +04:37:40 4.0777 +04:37:45 4.0406 +04:37:50 4.0179 +04:37:55 4.0860 +04:38:00 4.0051 +04:38:05 4.0037 +04:38:10 3.9706 +04:38:15 4.0890 +04:38:20 4.1843 +04:38:25 4.0746 +04:38:30 4.0455 +04:38:35 4.1092 +04:38:40 4.1336 +04:38:45 4.1179 +04:38:50 4.0065 +04:38:55 4.1217 +04:39:00 4.1688 +04:39:05 4.0801 +04:39:10 4.1168 +04:39:15 4.1245 +04:39:20 4.0489 +04:39:25 4.0563 +04:39:30 4.0822 +04:39:35 4.0695 +04:39:40 4.0185 +04:39:45 4.0599 +04:39:50 4.0696 +04:39:55 3.9724 +04:40:00 3.9328 +04:40:05 4.0173 +04:40:10 3.9281 +04:40:15 3.9980 +04:40:20 4.0663 +04:40:25 4.0474 +04:40:30 4.0927 +04:40:35 4.1530 +04:40:40 4.0857 +04:40:45 3.9822 +04:40:50 3.9937 +04:40:55 4.0347 +04:41:00 3.9632 +04:41:05 3.9870 +04:41:10 4.0363 +04:41:15 4.0968 +04:41:20 4.0706 +04:41:25 4.0496 +04:41:30 4.0511 +04:41:35 4.0849 +04:41:40 4.0673 +04:41:45 4.0049 +04:41:50 3.9664 +04:41:55 4.0196 +04:42:00 4.1047 +04:42:05 4.1748 +04:42:10 4.0686 +04:42:15 4.0325 +04:42:20 4.1578 +04:42:25 4.0263 +04:42:30 4.0201 +04:42:35 4.0448 +04:42:40 4.1217 +04:42:45 4.1234 +04:42:50 4.0319 +04:42:55 3.9412 +04:43:00 4.0178 +04:43:05 4.0216 +04:43:10 3.9699 +04:43:15 4.0257 +04:43:20 3.9940 +04:43:25 3.9998 +04:43:30 3.9991 +04:43:35 4.0872 +04:43:40 4.0749 +04:43:45 3.9980 +04:43:50 4.0289 +04:43:55 4.1160 +04:44:00 4.0755 +04:44:05 3.9337 +04:44:10 3.9097 +04:44:15 3.9304 +04:44:20 3.9577 +04:44:25 4.0328 +04:44:30 4.0767 +04:44:35 4.0620 +04:44:40 4.0071 +04:44:45 3.9375 +04:44:50 3.9684 +04:44:55 3.9330 +04:45:00 4.0307 +04:45:05 4.0880 +04:45:10 4.1111 +04:45:15 4.0458 +04:45:20 4.1208 +04:45:25 4.0728 +04:45:30 4.0772 +04:45:35 4.0650 +04:45:40 4.0691 +04:45:45 4.0325 +04:45:50 4.0589 +04:45:55 3.9878 +04:46:00 3.9400 +04:46:05 4.0024 +04:46:10 4.0577 +04:46:15 4.0792 +04:46:20 4.0263 +04:46:25 4.0433 +04:46:30 4.0115 +04:46:35 4.0174 +04:46:40 3.9451 +04:46:45 4.0304 +04:46:50 4.1312 +04:46:55 4.0724 +04:47:00 4.0202 +04:47:05 4.0692 +04:47:10 4.0563 +04:47:15 4.0069 +04:47:20 3.9528 +04:47:25 4.0735 +04:47:30 4.1346 +04:47:35 4.0450 +04:47:40 4.0102 +04:47:45 4.0361 +04:47:50 4.0086 +04:47:55 3.9418 +04:48:00 3.9217 +04:48:05 3.9529 +04:48:10 3.9716 +04:48:15 3.9808 +04:48:20 3.9298 +04:48:25 3.9863 +04:48:30 3.9945 +04:48:35 4.0286 +04:48:40 4.0448 +04:48:45 3.9649 +04:48:50 3.9530 +04:48:55 4.0075 +04:49:00 4.0545 +04:49:05 4.0567 +04:49:10 4.0356 +04:49:15 3.9127 +04:49:20 3.9304 +04:49:25 4.0614 +04:49:30 4.1176 +04:49:35 4.0574 +04:49:40 4.1142 +04:49:45 3.9921 +04:49:50 4.0908 +04:49:55 4.0824 +04:50:00 4.0464 +04:50:05 4.0131 +04:50:10 4.0662 +04:50:15 4.0134 +04:50:20 3.9700 +04:50:25 3.9606 +04:50:30 4.0021 +04:50:35 4.0559 +04:50:40 4.0254 +04:50:45 4.0097 +04:50:50 4.0800 +04:50:55 4.0495 +04:51:00 3.9839 +04:51:05 3.9539 +04:51:10 3.9653 +04:51:15 3.9804 +04:51:20 3.9662 +04:51:25 4.0419 +04:51:30 4.0276 +04:51:35 3.9820 +04:51:40 3.9505 +04:51:45 4.0233 +04:51:50 4.0825 +04:51:55 4.0070 +04:52:00 3.9917 +04:52:05 4.0483 +04:52:10 4.0865 +04:52:15 4.1142 +04:52:20 4.0097 +04:52:25 4.0742 +04:52:30 4.0780 +04:52:35 4.0742 +04:52:40 4.0592 +04:52:45 3.9919 +04:52:50 4.0200 +04:52:55 4.0358 +04:53:00 3.9553 +04:53:05 4.1021 +04:53:10 4.1821 +04:53:15 4.0040 +04:53:20 4.0133 +04:53:25 4.0050 +04:53:30 4.0187 +04:53:35 4.0102 +04:53:40 4.0105 +04:53:45 4.1021 +04:53:50 4.2023 +04:53:55 4.1127 +04:54:00 4.0408 +04:54:05 4.0162 +04:54:10 3.9951 +04:54:15 4.0203 +04:54:20 4.0174 +04:54:25 4.0912 +04:54:30 4.0568 +04:54:35 4.1196 +04:54:40 4.0730 +04:54:45 4.0207 +04:54:50 4.0810 +04:54:55 4.0254 +04:55:00 4.0795 +04:55:05 4.0982 +04:55:10 4.0606 +04:55:15 4.0646 +04:55:20 4.0625 +04:55:25 3.9119 +04:55:30 3.9269 +04:55:35 4.0132 +04:55:40 4.0285 +04:55:45 4.0033 +04:55:50 4.0155 +04:55:55 4.1137 +04:56:00 4.0598 +04:56:05 3.9974 +04:56:10 3.9730 +04:56:15 3.9831 +04:56:20 4.0056 +04:56:25 4.0557 +04:56:30 4.1451 +04:56:35 4.0730 +04:56:40 4.1052 +04:56:45 4.0564 +04:56:50 4.0280 +04:56:55 3.9777 +04:57:00 3.9634 +04:57:05 4.0319 +04:57:10 3.9843 +04:57:15 3.9357 +04:57:20 4.1220 +04:57:25 4.1077 +04:57:30 4.1096 +04:57:35 4.0185 +04:57:40 3.9911 +04:57:45 4.0613 +04:57:50 3.9361 +04:57:55 3.9882 +04:58:00 3.9713 +04:58:05 3.9836 +04:58:10 4.0431 +04:58:15 4.0119 +04:58:20 3.9807 +04:58:25 4.0440 +04:58:30 4.0461 +04:58:35 3.9829 +04:58:40 3.9985 +04:58:45 4.0120 +04:58:50 3.9697 +04:58:55 4.0349 +04:59:00 3.9237 +04:59:05 3.9496 +04:59:10 3.9637 +04:59:15 3.9592 +04:59:20 3.9284 +04:59:25 4.0911 +04:59:30 4.1203 +04:59:35 4.0178 +04:59:40 4.0563 +04:59:45 4.0422 +04:59:50 4.1392 +04:59:55 4.0839 +05:00:00 4.1005 +05:00:05 4.0823 +05:00:10 4.0330 +05:00:15 3.9789 +05:00:20 4.1093 +05:00:25 4.1192 +05:00:30 4.0097 +05:00:35 3.9476 +05:00:40 3.9867 +05:00:45 4.0762 +05:00:50 4.1117 +05:00:55 4.1008 +05:01:00 4.1118 +05:01:05 4.0646 +05:01:10 4.0719 +05:01:15 3.9779 +05:01:20 3.9895 +05:01:25 3.9001 +05:01:30 3.9116 +05:01:35 4.1276 +05:01:40 4.0535 +05:01:45 4.0223 +05:01:50 4.0789 +05:01:55 4.0723 +05:02:00 4.0670 +05:02:05 4.0946 +05:02:10 3.9596 +05:02:15 3.9062 +05:02:20 4.0096 +05:02:25 3.9794 +05:02:30 3.9969 +05:02:35 4.0688 +05:02:40 4.1149 +05:02:45 4.0991 +05:02:50 4.0563 +05:02:55 4.0717 +05:03:00 3.9942 +05:03:05 4.0824 +05:03:10 4.1180 +05:03:15 4.1147 +05:03:20 4.0025 +05:03:25 4.0557 +05:03:30 4.0616 +05:03:35 3.9961 +05:03:40 3.9924 +05:03:45 4.0248 +05:03:50 3.9910 +05:03:55 4.0633 +05:04:00 3.9836 +05:04:05 3.9526 +05:04:10 4.0025 +05:04:15 4.0381 +05:04:20 4.0244 +05:04:25 4.0230 +05:04:30 3.9620 +05:04:35 3.9785 +05:04:40 4.0251 +05:04:45 4.0341 +05:04:50 4.0953 +05:04:55 4.0845 +05:05:00 4.0608 +05:05:05 3.9270 +05:05:10 3.9282 +05:05:15 3.9512 +05:05:20 3.9260 +05:05:25 3.9832 +05:05:30 3.9713 +05:05:35 3.9984 +05:05:40 3.9281 +05:05:45 3.9784 +05:05:50 3.9317 +05:05:55 3.9634 +05:06:00 4.0001 +05:06:05 4.0738 +05:06:10 4.1557 +05:06:15 4.1455 +05:06:20 4.1086 +05:06:25 4.1060 +05:06:30 4.2315 +05:06:35 4.1571 +05:06:40 3.9597 +05:06:45 4.0078 +05:06:50 4.0029 +05:06:55 3.9877 +05:07:00 3.9628 +05:07:05 3.9551 +05:07:10 4.0480 +05:07:15 4.1010 +05:07:20 4.0584 +05:07:25 4.0790 +05:07:30 4.0826 +05:07:35 4.0263 +05:07:40 4.0443 +05:07:45 4.0782 +05:07:50 4.0182 +05:07:55 4.0530 +05:08:00 4.0537 +05:08:05 3.9777 +05:08:10 3.9180 +05:08:15 3.9743 +05:08:20 3.9598 +05:08:25 3.9713 +05:08:30 4.0212 +05:08:35 4.0200 +05:08:40 3.9919 +05:08:45 3.9922 +05:08:50 3.9178 +05:08:55 3.9291 +05:09:00 4.0094 +05:09:05 3.9609 +05:09:10 3.9438 +05:09:15 4.0234 +05:09:20 4.1200 +05:09:25 4.1329 +05:09:30 4.1652 +05:09:35 4.1415 +05:09:40 4.0762 +05:09:45 4.1329 +05:09:50 4.0953 +05:09:55 3.8990 +05:10:00 3.8846 +05:10:05 4.0111 +05:10:10 3.9337 +05:10:15 4.0101 +05:10:20 4.0262 +05:10:25 3.9887 +05:10:30 4.0008 +05:10:35 4.0902 +05:10:40 4.1082 +05:10:45 4.0730 +05:10:50 4.0820 +05:10:55 4.0312 +05:11:00 4.1161 +05:11:05 4.1682 +05:11:10 4.0720 +05:11:15 4.0744 +05:11:20 4.1188 +05:11:25 4.1617 +05:11:30 4.1923 +05:11:35 4.0848 +05:11:40 4.0537 +05:11:45 4.0036 +05:11:50 4.0755 +05:11:55 4.1602 +05:12:00 4.1596 +05:12:05 4.0492 +05:12:10 3.9942 +05:12:15 4.0317 +05:12:20 3.9840 +05:12:25 3.9928 +05:12:30 4.0829 +05:12:35 4.2336 +05:12:40 4.1728 +05:12:45 3.9226 +05:12:50 3.9484 +05:12:55 4.1295 +05:13:00 4.0784 +05:13:05 3.9632 +05:13:10 4.0279 +05:13:15 3.9690 +05:13:20 4.0670 +05:13:25 4.0654 +05:13:30 4.1157 +05:13:35 4.0596 +05:13:40 4.0237 +05:13:45 3.9491 +05:13:50 3.9518 +05:13:55 3.8894 +05:14:00 3.8565 +05:14:05 3.9942 +05:14:10 4.1227 +05:14:15 4.1769 +05:14:20 4.1755 +05:14:25 4.1414 +05:14:30 3.9659 +05:14:35 4.0244 +05:14:40 4.0729 +05:14:45 3.9686 +05:14:50 4.0504 +05:14:55 4.0340 +05:15:00 4.0612 +05:15:05 4.0373 +05:15:10 4.1597 +05:15:15 4.1397 +05:15:20 4.2113 +05:15:25 4.0832 +05:15:30 3.9224 +05:15:35 3.9244 +05:15:40 3.9591 +05:15:45 4.0134 +05:15:50 4.1359 +05:15:55 4.1176 +05:16:00 4.0698 +05:16:05 4.0724 +05:16:10 4.0516 +05:16:15 3.9557 +05:16:20 3.9562 +05:16:25 4.0732 +05:16:30 4.1650 +05:16:35 4.1153 +05:16:40 3.9765 +05:16:45 3.9362 +05:16:50 3.9534 +05:16:55 3.9735 +05:17:00 4.0370 +05:17:05 3.9799 +05:17:10 4.0066 +05:17:15 4.0314 +05:17:20 4.0204 +05:17:25 3.9923 +05:17:30 4.0754 +05:17:35 4.1158 +05:17:40 4.0750 +05:17:45 3.9841 +05:17:50 3.9588 +05:17:55 4.0754 +05:18:00 4.0409 +05:18:05 4.0354 +05:18:10 4.0434 +05:18:15 4.0971 +05:18:20 4.0848 +05:18:25 4.0453 +05:18:30 4.0234 +05:18:35 4.0434 +05:18:40 3.9350 +05:18:45 3.9637 +05:18:50 4.0434 +05:18:55 4.0813 +05:19:00 4.0989 +05:19:05 4.0604 +05:19:10 4.0595 +05:19:15 3.9402 +05:19:20 3.9722 +05:19:25 4.0588 +05:19:30 3.8899 +05:19:35 3.9005 +05:19:40 4.0755 +05:19:45 4.0624 +05:19:50 4.0787 +05:19:55 4.0361 +05:20:00 3.9414 +05:20:05 3.8973 +05:20:10 4.0548 +05:20:15 4.1327 +05:20:20 4.0757 +05:20:25 4.0434 +05:20:30 4.0666 +05:20:35 4.1163 +05:20:40 4.0652 +05:20:45 4.0386 +05:20:50 4.1065 +05:20:55 4.0857 +05:21:00 4.0233 +05:21:05 4.0483 +05:21:10 3.9654 +05:21:15 3.9281 +05:21:20 4.0686 +05:21:25 4.1152 +05:21:30 4.0880 +05:21:35 4.0649 +05:21:40 4.0110 +05:21:45 4.0514 +05:21:50 4.1078 +05:21:55 4.0576 +05:22:00 4.0856 +05:22:05 4.0073 +05:22:10 3.8719 +05:22:15 3.9039 +05:22:20 4.0179 +05:22:25 4.0596 +05:22:30 3.9878 +05:22:35 3.9312 +05:22:40 4.0146 +05:22:45 4.1367 +05:22:50 4.1125 +05:22:55 4.0238 +05:23:00 4.0405 +05:23:05 4.0863 +05:23:10 4.0653 +05:23:15 3.9480 +05:23:20 3.9509 +05:23:25 4.0156 +05:23:30 4.1546 +05:23:35 4.0237 +05:23:40 3.9349 +05:23:45 3.9310 +05:23:50 4.0000 +05:23:55 4.1101 +05:24:00 4.0802 +05:24:05 4.0400 +05:24:10 3.9909 +05:24:15 4.0744 +05:24:20 4.1465 +05:24:25 4.0202 +05:24:30 4.0184 +05:24:35 4.1569 +05:24:40 4.1560 +05:24:45 4.0571 +05:24:50 4.0274 +05:24:55 3.9574 +05:25:00 4.0683 +05:25:05 4.0198 +05:25:10 4.0666 +05:25:15 4.0840 +05:25:20 4.0627 +05:25:25 4.0795 +05:25:30 4.0956 +05:25:35 4.0872 +05:25:40 4.0169 +05:25:45 4.0092 +05:25:50 3.9868 +05:25:55 4.1247 +05:26:00 3.9962 +05:26:05 4.0233 +05:26:10 4.0705 +05:26:15 4.0153 +05:26:20 4.0387 +05:26:25 4.0720 +05:26:30 4.0567 +05:26:35 4.0355 +05:26:40 4.0126 +05:26:45 4.0193 +05:26:50 4.0335 +05:26:55 4.0248 +05:27:00 4.0045 +05:27:05 3.9814 +05:27:10 4.0175 +05:27:15 4.0857 +05:27:20 3.9838 +05:27:25 3.9323 +05:27:30 3.9683 +05:27:35 4.0118 +05:27:40 4.0353 +05:27:45 4.0634 +05:27:50 3.9777 +05:27:55 4.0892 +05:28:00 4.0480 +05:28:05 3.9904 +05:28:10 3.9814 +05:28:15 4.0214 +05:28:20 3.9256 +05:28:25 3.9723 +05:28:30 3.9705 +05:28:35 3.9578 +05:28:40 3.9923 +05:28:45 4.0150 +05:28:50 4.0643 +05:28:55 4.0808 +05:29:00 4.0285 +05:29:05 4.1046 +05:29:10 4.1040 +05:29:15 4.0242 +05:29:20 4.0321 +05:29:25 4.0391 +05:29:30 4.0092 +05:29:35 4.0503 +05:29:40 4.1086 +05:29:45 4.1444 +05:29:50 4.0605 +05:29:55 4.0231 +05:30:00 3.9905 +05:30:05 4.0091 +05:30:10 3.9994 +05:30:15 4.0265 +05:30:20 4.0502 +05:30:25 4.0520 +05:30:30 3.9881 +05:30:35 4.0149 +05:30:40 3.9681 +05:30:45 4.0283 +05:30:50 3.9902 +05:30:55 4.1023 +05:31:00 4.1816 +05:31:05 3.9594 +05:31:10 4.0310 +05:31:15 4.0230 +05:31:20 4.0737 +05:31:25 3.9949 +05:31:30 4.0291 +05:31:35 3.9467 +05:31:40 4.0530 +05:31:45 4.0110 +05:31:50 4.0133 +05:31:55 4.0921 +05:32:00 3.9730 +05:32:05 3.9922 +05:32:10 3.9897 +05:32:15 3.9340 +05:32:20 3.9980 +05:32:25 3.9750 +05:32:30 4.0471 +05:32:35 4.0378 +05:32:40 4.0781 +05:32:45 4.0486 +05:32:50 3.9735 +05:32:55 4.0491 +05:33:00 4.0852 +05:33:05 4.0811 +05:33:10 4.0820 +05:33:15 4.0845 +05:33:20 4.0546 +05:33:25 4.1458 +05:33:30 3.9829 +05:33:35 3.9757 +05:33:40 4.0239 +05:33:45 3.9886 +05:33:50 4.0253 +05:33:55 4.0371 +05:34:00 3.9402 +05:34:05 4.0037 +05:34:10 4.0686 +05:34:15 4.0809 +05:34:20 4.0600 +05:34:25 4.0044 +05:34:30 4.0283 +05:34:35 4.0178 +05:34:40 4.0708 +05:34:45 4.1020 +05:34:50 4.0662 +05:34:55 4.0643 +05:35:00 4.0689 +05:35:05 4.0659 +05:35:10 3.9862 +05:35:15 4.0853 +05:35:20 4.0073 +05:35:25 3.9596 +05:35:30 4.0488 +05:35:35 4.0862 +05:35:40 4.0254 +05:35:45 4.0315 +05:35:50 4.0298 +05:35:55 4.0169 +05:36:00 4.0667 +05:36:05 4.1020 +05:36:10 4.1282 +05:36:15 4.1660 +05:36:20 4.1609 +05:36:25 4.0417 +05:36:30 4.0510 +05:36:35 4.0294 +05:36:40 3.9828 +05:36:45 4.0479 +05:36:50 4.0842 +05:36:55 4.0757 +05:37:00 4.0737 +05:37:05 3.9804 +05:37:10 4.0315 +05:37:15 4.0639 +05:37:20 4.0562 +05:37:25 3.9678 +05:37:30 4.0074 +05:37:35 3.9024 +05:37:40 3.9283 +05:37:45 3.9981 +05:37:50 3.9695 +05:37:55 4.0160 +05:38:00 4.0826 +05:38:05 3.9864 +05:38:10 3.8747 +05:38:15 3.9072 +05:38:20 3.9908 +05:38:25 3.9917 +05:38:30 3.9780 +05:38:35 3.9940 +05:38:40 3.9975 +05:38:45 3.9652 +05:38:50 3.9325 +05:38:55 4.0795 +05:39:00 4.0939 +05:39:05 4.0404 +05:39:10 3.9968 +05:39:15 3.9670 +05:39:20 4.0181 +05:39:25 3.9806 +05:39:30 3.9411 +05:39:35 3.9074 +05:39:40 3.9909 +05:39:45 4.0188 +05:39:50 4.0338 +05:39:55 4.1087 +05:40:00 4.1136 +05:40:05 4.0293 +05:40:10 3.9057 +05:40:15 3.8556 +05:40:20 3.9532 +05:40:25 4.0547 +05:40:30 4.0134 +05:40:35 4.0241 +05:40:40 4.0298 +05:40:45 4.0863 +05:40:50 4.0795 +05:40:55 4.0180 +05:41:00 3.9222 +05:41:05 4.0064 +05:41:10 4.0968 +05:41:15 4.0550 +05:41:20 4.0259 +05:41:25 4.0079 +05:41:30 4.0487 +05:41:35 4.0482 +05:41:40 4.0365 +05:41:45 4.0293 +05:41:50 4.0333 +05:41:55 3.9853 +05:42:00 3.9389 +05:42:05 3.8535 +05:42:10 3.8987 +05:42:15 3.9676 +05:42:20 3.9482 +05:42:25 3.9365 +05:42:30 4.0422 +05:42:35 4.1327 +05:42:40 4.0429 +05:42:45 4.0438 +05:42:50 4.0842 +05:42:55 4.0562 +05:43:00 3.9240 +05:43:05 3.9118 +05:43:10 4.1380 +05:43:15 4.0341 +05:43:20 3.9054 +05:43:25 3.9613 +05:43:30 4.1454 +05:43:35 4.0313 +05:43:40 4.0300 +05:43:45 4.0106 +05:43:50 4.0083 +05:43:55 4.0324 +05:44:00 4.0789 +05:44:05 4.1212 +05:44:10 4.0296 +05:44:15 4.0418 +05:44:20 4.0538 +05:44:25 4.0184 +05:44:30 4.0524 +05:44:35 4.0374 +05:44:40 4.0485 +05:44:45 4.0335 +05:44:50 4.0416 +05:44:55 3.9450 +05:45:00 3.9253 +05:45:05 3.9846 +05:45:10 4.0010 +05:45:15 4.0776 +05:45:20 3.9868 +05:45:25 3.9960 +05:45:30 4.0521 +05:45:35 4.0802 +05:45:40 4.0759 +05:45:45 3.9252 +05:45:50 4.0595 +05:45:55 4.1202 +05:46:00 4.0560 +05:46:05 4.0504 +05:46:10 3.9597 +05:46:15 3.9817 +05:46:20 4.0705 +05:46:25 4.1000 +05:46:30 4.0613 +05:46:35 3.9375 +05:46:40 3.9097 +05:46:45 3.9326 +05:46:50 4.0195 +05:46:55 3.9969 +05:47:00 4.0152 +05:47:05 4.0234 +05:47:10 4.0862 +05:47:15 4.1406 +05:47:20 3.9848 +05:47:25 3.9162 +05:47:30 3.9939 +05:47:35 3.9839 +05:47:40 3.9383 +05:47:45 3.9617 +05:47:50 3.9759 +05:47:55 4.0162 +05:48:00 4.1114 +05:48:05 4.1442 +05:48:10 4.0080 +05:48:15 4.0580 +05:48:20 4.0782 +05:48:25 3.9457 +05:48:30 3.8404 +05:48:35 3.9785 +05:48:40 4.0268 +05:48:45 4.0039 +05:48:50 3.9964 +05:48:55 4.0408 +05:49:00 4.0219 +05:49:05 3.9825 +05:49:10 4.0371 +05:49:15 4.0372 +05:49:20 3.9748 +05:49:25 3.9560 +05:49:30 4.1484 +05:49:35 4.0574 +05:49:40 4.0345 +05:49:45 4.1272 +05:49:50 4.0986 +05:49:55 4.0086 +05:50:00 4.0381 +05:50:05 4.0692 +05:50:10 3.9905 +05:50:15 3.9711 +05:50:20 4.0155 +05:50:25 4.1440 +05:50:30 3.9857 +05:50:35 4.0101 +05:50:40 3.8332 +05:50:45 4.0081 +05:50:50 4.0484 +05:50:55 3.9693 +05:51:00 4.0239 +05:51:05 4.0665 +05:51:10 3.9896 +05:51:15 3.9873 +05:51:20 4.0120 +05:51:25 3.9885 +05:51:30 4.0110 +05:51:35 4.0517 +05:51:40 4.0226 +05:51:45 3.9928 +05:51:50 4.0513 +05:51:55 3.9864 +05:52:00 4.0096 +05:52:05 3.9893 +05:52:10 4.0864 +05:52:15 3.9491 +05:52:20 4.0037 +05:52:25 3.9779 +05:52:30 4.0903 +05:52:35 4.0606 +05:52:40 4.0247 +05:52:45 4.0076 +05:52:50 4.1525 +05:52:55 4.0896 +05:53:00 4.0238 +05:53:05 4.0584 +05:53:10 4.0828 +05:53:15 4.0653 +05:53:20 4.0665 +05:53:25 4.0082 +05:53:30 4.0509 +05:53:35 4.1037 +05:53:40 4.1212 +05:53:45 4.1162 +05:53:50 4.0823 +05:53:55 4.0813 +05:54:00 4.1238 +05:54:05 4.1565 +05:54:10 4.1289 +05:54:15 4.0658 +05:54:20 3.9914 +05:54:25 3.9883 +05:54:30 3.9539 +05:54:35 3.9636 +05:54:40 3.9748 +05:54:45 4.0288 +05:54:50 4.0021 +05:54:55 4.0125 +05:55:00 4.0139 +05:55:05 3.9366 +05:55:10 3.9871 +05:55:15 4.0757 +05:55:20 4.1867 +05:55:25 4.0775 +05:55:30 4.0470 +05:55:35 4.0716 +05:55:40 3.9972 +05:55:45 3.9263 +05:55:50 4.0035 +05:55:55 4.0283 +05:56:00 4.0104 +05:56:05 4.0255 +05:56:10 3.9939 +05:56:15 4.0421 +05:56:20 3.9902 +05:56:25 4.1271 +05:56:30 4.0322 +05:56:35 3.9803 +05:56:40 3.9694 +05:56:45 3.9638 +05:56:50 3.9507 +05:56:55 3.9549 +05:57:00 4.0321 +05:57:05 4.0143 +05:57:10 4.0883 +05:57:15 3.9813 +05:57:20 4.0304 +05:57:25 3.8573 +05:57:30 4.0400 +05:57:35 3.9688 +05:57:40 4.1615 +05:57:45 3.9676 +05:57:50 4.0420 +05:57:55 4.0141 +05:58:00 4.0613 +05:58:05 3.9247 +05:58:10 3.9690 +05:58:15 4.0550 +05:58:20 3.9891 +05:58:25 4.1317 +05:58:30 4.0304 +05:58:35 4.2440 +05:58:40 4.1693 +05:58:45 3.8674 +05:58:50 4.1601 +05:58:55 4.3482 +05:59:00 4.3380 +05:59:05 4.2261 +05:59:10 4.0161 +05:59:15 3.7786 +05:59:20 4.0456 +05:59:25 4.1072 +05:59:30 3.8229 +05:59:35 4.1354 +05:59:40 3.9949 +05:59:45 3.7738 +05:59:50 4.0424 +05:59:55 4.1347 +06:00:00 3.8138 +06:00:05 4.0091 +06:00:10 3.8842 +06:00:15 4.0465 +06:00:20 3.8646 +06:00:25 3.9424 +06:00:30 4.0879 +06:00:35 3.7941 +06:00:40 3.9625 +06:00:45 4.1684 +06:00:50 3.8858 +06:00:55 3.8894 +06:01:00 4.1800 +06:01:05 4.1976 +06:01:10 3.9712 +06:01:15 3.7711 +06:01:20 3.9812 +06:01:25 4.2501 +06:01:30 4.0721 +06:01:35 3.7665 +06:01:40 3.9385 +06:01:45 4.2517 +06:01:50 4.3196 +06:01:55 4.1565 +06:02:00 3.8765 +06:02:05 3.7777 +06:02:10 4.0914 +06:02:15 4.0697 +06:02:20 3.8624 +06:02:25 4.1952 +06:02:30 4.0316 +06:02:35 3.9369 +06:02:40 4.2495 +06:02:45 3.9883 +06:02:50 4.1001 +06:02:55 3.9869 +06:03:00 4.1206 +06:03:05 4.0776 +06:03:10 4.0767 +06:03:15 4.0731 +06:03:20 4.0797 +06:03:25 3.9095 +06:03:30 4.1020 +06:03:35 4.0972 +06:03:40 4.0048 +06:03:45 4.0338 +06:03:50 3.9782 +06:03:55 3.9568 +06:04:00 4.0195 +06:04:05 4.0047 +06:04:10 3.9893 +06:04:15 3.9731 +06:04:20 4.0429 +06:04:25 3.9806 +06:04:30 3.9913 +06:04:35 4.0624 +06:04:40 4.1403 +06:04:45 4.0663 +06:04:50 4.1456 +06:04:55 4.0777 +06:05:00 3.9606 +06:05:05 4.0521 +06:05:10 4.0187 +06:05:15 3.8738 +06:05:20 3.9367 +06:05:25 4.0593 +06:05:30 4.0309 +06:05:35 4.0096 +06:05:40 3.9774 +06:05:45 4.0143 +06:05:50 4.0059 +06:05:55 3.9602 +06:06:00 3.9879 +06:06:05 4.0893 +06:06:10 4.1146 +06:06:15 4.0646 +06:06:20 3.9981 +06:06:25 4.0240 +06:06:30 4.0364 +06:06:35 4.0008 +06:06:40 3.9995 +06:06:45 4.1008 +06:06:50 4.1579 +06:06:55 4.0629 +06:07:00 3.9330 +06:07:05 4.1331 +06:07:10 4.0083 +06:07:15 3.8909 +06:07:20 3.9585 +06:07:25 4.0487 +06:07:30 4.0272 +06:07:35 4.1226 +06:07:40 4.0669 +06:07:45 3.9678 +06:07:50 4.0382 +06:07:55 4.0324 +06:08:00 4.0213 +06:08:05 3.9802 +06:08:10 3.9809 +06:08:15 4.0578 +06:08:20 3.9545 +06:08:25 4.0086 +06:08:30 4.0553 +06:08:35 3.9466 +06:08:40 4.0394 +06:08:45 4.1302 +06:08:50 4.1209 +06:08:55 3.9321 +06:09:00 4.0294 +06:09:05 3.9726 +06:09:10 3.9885 +06:09:15 4.0039 +06:09:20 4.0628 +06:09:25 4.0929 +06:09:30 4.1167 +06:09:35 4.0593 +06:09:40 4.0418 +06:09:45 3.9812 +06:09:50 3.9876 +06:09:55 3.9265 +06:10:00 4.0799 +06:10:05 3.9188 +06:10:10 3.9254 +06:10:15 4.1133 +06:10:20 4.1515 +06:10:25 4.1022 +06:10:30 4.0136 +06:10:35 4.0075 +06:10:40 3.9264 +06:10:45 3.9674 +06:10:50 4.0547 +06:10:55 4.1296 +06:11:00 4.0505 +06:11:05 3.8903 +06:11:10 3.9230 +06:11:15 4.0097 +06:11:20 3.9845 +06:11:25 3.9805 +06:11:30 4.0357 +06:11:35 4.0182 +06:11:40 4.0370 +06:11:45 3.9872 +06:11:50 3.9934 +06:11:55 4.0155 +06:12:00 4.0425 +06:12:05 3.9948 +06:12:10 4.0033 +06:12:15 4.0513 +06:12:20 4.0196 +06:12:25 4.0342 +06:12:30 4.0350 +06:12:35 4.0833 +06:12:40 4.0915 +06:12:45 4.0796 +06:12:50 3.9381 +06:12:55 3.9408 +06:13:00 3.9292 +06:13:05 3.9622 +06:13:10 4.0420 +06:13:15 3.9674 +06:13:20 3.9889 +06:13:25 4.0358 +06:13:30 4.0834 +06:13:35 3.9950 +06:13:40 3.9830 +06:13:45 4.0502 +06:13:50 4.0534 +06:13:55 4.0837 +06:14:00 4.0505 +06:14:05 4.0335 +06:14:10 3.9288 +06:14:15 3.9730 +06:14:20 3.9804 +06:14:25 4.0327 +06:14:30 4.0537 +06:14:35 4.0352 +06:14:40 4.0054 +06:14:45 4.0995 +06:14:50 4.0636 +06:14:55 4.1006 +06:15:00 4.0644 +06:15:05 3.9299 +06:15:10 4.0545 +06:15:15 4.0474 +06:15:20 3.9872 +06:15:25 4.0708 +06:15:30 3.9799 +06:15:35 4.0184 +06:15:40 3.9290 +06:15:45 3.8605 +06:15:50 3.9508 +06:15:55 4.0805 +06:16:00 4.0116 +06:16:05 3.8933 +06:16:10 4.0197 +06:16:15 4.0638 +06:16:20 4.0323 +06:16:25 4.0504 +06:16:30 4.0453 +06:16:35 3.9988 +06:16:40 3.9216 +06:16:45 3.9930 +06:16:50 4.0450 +06:16:55 3.9851 +06:17:00 3.9977 +06:17:05 4.0020 +06:17:10 4.0208 +06:17:15 3.9797 +06:17:20 3.9730 +06:17:25 3.9775 +06:17:30 3.9990 +06:17:35 4.0467 +06:17:40 3.9976 +06:17:45 4.0432 +06:17:50 4.1148 +06:17:55 4.1437 +06:18:00 4.0544 +06:18:05 4.0317 +06:18:10 4.0332 +06:18:15 4.0739 +06:18:20 4.0135 +06:18:25 3.9700 +06:18:30 3.9524 +06:18:35 4.0156 +06:18:40 4.0926 +06:18:45 3.9357 +06:18:50 3.9813 +06:18:55 3.9703 +06:19:00 4.1161 +06:19:05 4.0710 +06:19:10 4.0411 +06:19:15 4.1033 +06:19:20 4.1593 +06:19:25 3.9931 +06:19:30 3.9826 +06:19:35 3.9897 +06:19:40 3.9919 +06:19:45 4.0720 +06:19:50 4.1227 +06:19:55 4.0834 +06:20:00 4.0475 +06:20:05 3.9274 +06:20:10 3.9668 +06:20:15 4.0320 +06:20:20 4.0473 +06:20:25 4.0008 +06:20:30 4.0679 +06:20:35 4.1393 +06:20:40 4.0428 +06:20:45 3.9793 +06:20:50 4.0347 +06:20:55 4.0680 +06:21:00 4.0613 +06:21:05 4.0313 +06:21:10 4.0692 +06:21:15 4.0599 +06:21:20 4.0042 +06:21:25 3.8952 +06:21:30 3.9207 +06:21:35 3.9797 +06:21:40 3.9868 +06:21:45 4.0658 +06:21:50 4.1330 +06:21:55 4.0715 +06:22:00 4.0715 +06:22:05 4.0936 +06:22:10 4.0112 +06:22:15 4.1013 +06:22:20 4.1534 +06:22:25 4.1277 +06:22:30 4.0573 +06:22:35 4.0131 +06:22:40 4.1352 +06:22:45 4.0525 +06:22:50 4.0031 +06:22:55 3.9824 +06:23:00 3.9629 +06:23:05 3.9879 +06:23:10 4.0359 +06:23:15 4.0483 +06:23:20 4.0434 +06:23:25 3.9926 +06:23:30 4.0077 +06:23:35 4.0834 +06:23:40 4.0062 +06:23:45 3.9782 +06:23:50 4.0037 +06:23:55 3.9103 +06:24:00 3.8524 +06:24:05 3.9231 +06:24:10 3.9172 +06:24:15 3.8818 +06:24:20 3.8964 +06:24:25 3.9317 +06:24:30 4.0464 +06:24:35 4.1698 +06:24:40 3.9657 +06:24:45 3.8814 +06:24:50 4.0269 +06:24:55 3.9641 +06:25:00 3.9458 +06:25:05 3.9963 +06:25:10 4.1203 +06:25:15 4.0289 +06:25:20 3.9439 +06:25:25 3.9701 +06:25:30 4.0381 +06:25:35 3.9808 +06:25:40 3.9464 +06:25:45 4.0152 +06:25:50 4.0383 +06:25:55 4.0020 +06:26:00 3.9840 +06:26:05 3.9859 +06:26:10 3.9492 +06:26:15 4.0026 +06:26:20 4.0466 +06:26:25 4.0205 +06:26:30 3.9759 +06:26:35 4.0363 +06:26:40 4.0835 +06:26:45 4.0650 +06:26:50 3.9495 +06:26:55 4.0020 +06:27:00 4.0378 +06:27:05 3.9929 +06:27:10 3.9894 +06:27:15 4.0142 +06:27:20 3.9368 +06:27:25 3.9272 +06:27:30 3.9602 +06:27:35 3.9395 +06:27:40 4.0158 +06:27:45 3.9678 +06:27:50 4.0151 +06:27:55 4.0905 +06:28:00 4.0269 +06:28:05 4.0996 +06:28:10 4.1586 +06:28:15 4.1555 +06:28:20 4.0571 +06:28:25 4.0996 +06:28:30 4.0343 +06:28:35 3.9772 +06:28:40 3.9756 +06:28:45 3.9715 +06:28:50 3.9966 +06:28:55 4.1019 +06:29:00 3.9966 +06:29:05 4.0712 +06:29:10 4.0458 +06:29:15 3.9927 +06:29:20 3.9587 +06:29:25 4.0979 +06:29:30 4.0072 +06:29:35 4.0082 +06:29:40 4.0524 +06:29:45 4.0697 +06:29:50 4.0533 +06:29:55 4.0725 +06:30:00 4.1108 +06:30:05 4.0082 +06:30:10 3.9808 +06:30:15 4.0699 +06:30:20 3.9749 +06:30:25 3.9944 +06:30:30 4.0641 +06:30:35 4.1012 +06:30:40 4.0091 +06:30:45 4.0115 +06:30:50 3.9490 +06:30:55 3.9773 +06:31:00 4.0031 +06:31:05 3.9464 +06:31:10 4.0065 +06:31:15 4.0236 +06:31:20 3.9699 +06:31:25 4.0255 +06:31:30 4.0504 +06:31:35 4.0139 +06:31:40 3.9802 +06:31:45 3.9900 +06:31:50 3.9958 +06:31:55 3.9918 +06:32:00 3.9307 +06:32:05 4.0192 +06:32:10 4.0102 +06:32:15 3.9907 +06:32:20 4.0055 +06:32:25 3.9888 +06:32:30 4.0779 +06:32:35 4.1182 +06:32:40 4.0371 +06:32:45 3.9783 +06:32:50 4.0427 +06:32:55 4.0590 +06:33:00 4.0814 +06:33:05 4.1308 +06:33:10 4.0686 +06:33:15 4.0238 +06:33:20 4.0449 +06:33:25 4.0385 +06:33:30 3.9259 +06:33:35 3.8935 +06:33:40 3.9582 +06:33:45 4.0289 +06:33:50 4.0976 +06:33:55 4.0776 +06:34:00 4.0640 +06:34:05 4.0025 +06:34:10 3.9537 +06:34:15 4.0068 +06:34:20 4.0388 +06:34:25 4.1455 +06:34:30 4.0271 +06:34:35 3.9976 +06:34:40 3.9965 +06:34:45 4.0808 +06:34:50 4.1517 +06:34:55 4.0567 +06:35:00 4.0359 +06:35:05 4.0113 +06:35:10 3.9532 +06:35:15 4.0300 +06:35:20 4.0281 +06:35:25 4.0480 +06:35:30 4.0662 +06:35:35 4.0586 +06:35:40 4.0679 +06:35:45 3.9804 +06:35:50 4.0005 +06:35:55 4.0137 +06:36:00 4.1174 +06:36:05 4.0850 +06:36:10 3.9586 +06:36:15 3.9372 +06:36:20 3.9295 +06:36:25 4.0010 +06:36:30 4.0006 +06:36:35 3.9443 +06:36:40 4.0495 +06:36:45 3.9798 +06:36:50 4.0384 +06:36:55 4.0338 +06:37:00 4.0468 +06:37:05 4.0395 +06:37:10 3.9745 +06:37:15 4.1172 +06:37:20 4.0751 +06:37:25 3.9681 +06:37:30 3.9864 +06:37:35 4.0490 +06:37:40 4.0410 +06:37:45 3.9037 +06:37:50 3.9332 +06:37:55 3.9749 +06:38:00 4.0355 +06:38:05 4.0879 +06:38:10 4.0711 +06:38:15 4.0833 +06:38:20 4.0838 +06:38:25 4.1429 +06:38:30 4.1355 +06:38:35 3.9725 +06:38:40 4.0009 +06:38:45 4.0159 +06:38:50 4.0639 +06:38:55 4.0691 +06:39:00 3.9039 +06:39:05 3.9397 +06:39:10 3.9629 +06:39:15 4.0702 +06:39:20 4.0202 +06:39:25 4.0870 +06:39:30 4.0470 +06:39:35 3.9035 +06:39:40 3.9427 +06:39:45 4.0009 +06:39:50 3.9188 +06:39:55 3.9683 +06:40:00 3.9317 +06:40:05 3.8776 +06:40:10 3.9272 +06:40:15 3.9511 +06:40:20 3.9787 +06:40:25 4.0614 +06:40:30 4.0323 +06:40:35 4.0462 +06:40:40 4.0632 +06:40:45 4.0148 +06:40:50 3.9354 +06:40:55 3.8587 +06:41:00 3.9297 +06:41:05 4.0154 +06:41:10 4.0309 +06:41:15 3.9076 +06:41:20 3.8425 +06:41:25 3.9678 +06:41:30 3.9994 +06:41:35 3.9514 +06:41:40 3.8752 +06:41:45 3.9188 +06:41:50 4.0335 +06:41:55 3.9698 +06:42:00 3.8869 +06:42:05 3.9570 +06:42:10 3.9939 +06:42:15 4.0065 +06:42:20 3.9378 +06:42:25 3.9644 +06:42:30 4.1126 +06:42:35 4.1333 +06:42:40 4.1117 +06:42:45 4.0763 +06:42:50 3.9416 +06:42:55 4.1359 +06:43:00 3.9159 +06:43:05 3.9935 +06:43:10 4.0022 +06:43:15 3.9571 +06:43:20 3.9977 +06:43:25 4.1070 +06:43:30 3.9932 +06:43:35 3.9097 +06:43:40 3.9839 +06:43:45 4.0938 +06:43:50 4.0176 +06:43:55 4.0039 +06:44:00 4.0405 +06:44:05 4.0810 +06:44:10 3.9846 +06:44:15 3.9213 +06:44:20 4.0476 +06:44:25 4.0070 +06:44:30 4.0001 +06:44:35 3.9969 +06:44:40 4.0824 +06:44:45 3.9960 +06:44:50 3.9373 +06:44:55 3.9570 +06:45:00 3.9755 +06:45:05 3.9827 +06:45:10 4.0924 +06:45:15 4.0019 +06:45:20 3.9615 +06:45:25 3.8977 +06:45:30 3.9703 +06:45:35 3.9808 +06:45:40 4.0556 +06:45:45 4.0945 +06:45:50 4.0766 +06:45:55 3.9836 +06:46:00 4.0565 +06:46:05 4.0331 +06:46:10 3.9955 +06:46:15 4.0104 +06:46:20 4.0255 +06:46:25 3.9976 +06:46:30 3.9362 +06:46:35 3.9559 +06:46:40 3.9848 +06:46:45 4.0349 +06:46:50 4.1207 +06:46:55 4.0099 +06:47:00 4.0102 +06:47:05 4.1017 +06:47:10 4.0967 +06:47:15 3.9915 +06:47:20 4.0579 +06:47:25 4.0007 +06:47:30 3.9833 +06:47:35 4.0522 +06:47:40 4.0015 +06:47:45 3.9836 +06:47:50 3.9660 +06:47:55 4.0128 +06:48:00 4.0877 +06:48:05 4.0973 +06:48:10 3.9909 +06:48:15 3.9149 +06:48:20 3.8896 +06:48:25 3.9363 +06:48:30 3.9740 +06:48:35 4.0081 +06:48:40 3.9416 +06:48:45 3.9349 +06:48:50 3.9669 +06:48:55 4.0102 +06:49:00 3.9837 +06:49:05 4.0245 +06:49:10 4.0829 +06:49:15 3.9924 +06:49:20 3.9646 +06:49:25 4.0084 +06:49:30 4.0494 +06:49:35 4.1198 +06:49:40 4.1607 +06:49:45 4.1463 +06:49:50 4.0824 +06:49:55 4.0940 +06:50:00 4.0684 +06:50:05 3.9402 +06:50:10 3.9368 +06:50:15 3.9505 +06:50:20 3.9956 +06:50:25 3.9391 +06:50:30 3.9975 +06:50:35 4.0344 +06:50:40 3.9680 +06:50:45 3.9830 +06:50:50 4.0807 +06:50:55 4.0149 +06:51:00 3.9959 +06:51:05 3.9729 +06:51:10 3.9622 +06:51:15 3.9055 +06:51:20 3.9722 +06:51:25 4.0455 +06:51:30 4.0666 +06:51:35 4.0557 +06:51:40 4.1153 +06:51:45 4.1206 +06:51:50 4.0225 +06:51:55 4.1170 +06:52:00 4.0962 +06:52:05 4.0770 +06:52:10 4.0262 +06:52:15 3.9813 +06:52:20 3.9521 +06:52:25 4.0269 +06:52:30 3.9999 +06:52:35 3.9486 +06:52:40 4.0238 +06:52:45 4.0770 +06:52:50 4.1414 +06:52:55 4.0131 +06:53:00 4.0697 +06:53:05 4.1102 +06:53:10 3.9915 +06:53:15 3.9090 +06:53:20 4.0242 +06:53:25 4.0915 +06:53:30 4.0556 +06:53:35 4.0612 +06:53:40 4.0513 +06:53:45 3.9826 +06:53:50 4.0115 +06:53:55 3.9892 +06:54:00 3.9874 +06:54:05 4.0737 +06:54:10 4.0885 +06:54:15 4.0771 +06:54:20 4.0311 +06:54:25 3.9413 +06:54:30 3.9437 +06:54:35 4.0125 +06:54:40 4.0390 +06:54:45 4.0535 +06:54:50 3.9141 +06:54:55 3.9560 +06:55:00 3.9341 +06:55:05 3.8642 +06:55:10 4.0236 +06:55:15 4.1296 +06:55:20 4.0704 +06:55:25 3.9924 +06:55:30 3.9740 +06:55:35 3.9602 +06:55:40 3.9654 +06:55:45 3.9701 +06:55:50 4.0623 +06:55:55 4.0142 +06:56:00 4.0448 +06:56:05 4.0820 +06:56:10 4.0365 +06:56:15 3.9266 +06:56:20 3.9595 +06:56:25 3.9843 +06:56:30 3.9427 +06:56:35 4.0404 +06:56:40 4.0518 +06:56:45 3.9705 +06:56:50 3.9764 +06:56:55 3.9667 +06:57:00 3.9202 +06:57:05 3.9962 +06:57:10 3.9640 +06:57:15 4.0297 +06:57:20 4.0456 +06:57:25 4.0210 +06:57:30 4.0652 +06:57:35 4.0877 +06:57:40 4.0350 +06:57:45 4.0749 +06:57:50 4.0401 +06:57:55 4.0858 +06:58:00 3.8732 +06:58:05 4.1284 +06:58:10 3.9439 +06:58:15 4.1414 +06:58:20 4.1725 +06:58:25 3.8822 +06:58:30 4.1414 +06:58:35 4.0606 +06:58:40 3.8751 +06:58:45 4.1245 +06:58:50 3.9912 +06:58:55 4.0360 +06:59:00 3.8316 +06:59:05 4.0849 +06:59:10 4.0422 +06:59:15 3.9732 +06:59:20 3.9548 +06:59:25 3.9863 +06:59:30 3.9323 +06:59:35 4.1113 +06:59:40 3.9223 +06:59:45 4.0607 +06:59:50 3.9225 +06:59:55 4.0887 +07:00:00 4.0021 +07:00:05 3.8956 +07:00:10 3.8939 +07:00:15 4.0065 +07:00:20 3.9460 +07:00:25 4.0282 +07:00:30 3.9262 +07:00:35 4.0558 +07:00:40 3.8442 +07:00:45 4.1191 +07:00:50 4.0505 +07:00:55 3.8881 +07:01:00 4.2165 +07:01:05 4.4364 +07:01:10 4.2761 +07:01:15 3.9200 +07:01:20 3.7595 +07:01:25 4.0905 +07:01:30 4.2338 +07:01:35 3.8811 +07:01:40 3.7836 +07:01:45 4.1002 +07:01:50 4.2713 +07:01:55 4.3623 +07:02:00 4.1961 +07:02:05 4.0100 +07:02:10 3.9146 +07:02:15 3.9197 +07:02:20 4.1280 +07:02:25 4.2488 +07:02:30 4.2734 +07:02:35 4.1033 +07:02:40 3.8098 +07:02:45 3.8033 +07:02:50 4.0034 +07:02:55 4.1943 +07:03:00 4.2435 +07:03:05 4.0413 +07:03:10 3.7552 +07:03:15 3.6299 +07:03:20 3.8943 +07:03:25 4.1199 +07:03:30 4.2890 +07:03:35 4.2126 +07:03:40 3.9081 +07:03:45 3.7447 +07:03:50 3.9934 +07:03:55 4.2337 +07:04:00 3.9429 +07:04:05 3.9860 +07:04:10 4.2142 +07:04:15 3.9811 +07:04:20 3.9730 +07:04:25 4.0290 +07:04:30 3.8894 +07:04:35 4.1036 +07:04:40 3.8654 +07:04:45 3.9687 +07:04:50 4.0000 +07:04:55 3.9777 +07:05:00 4.1081 +07:05:05 3.8545 +07:05:10 4.0181 +07:05:15 3.9000 +07:05:20 4.0466 +07:05:25 4.1665 +07:05:30 4.0166 +07:05:35 4.0035 +07:05:40 4.0258 +07:05:45 4.0089 +07:05:50 4.0075 +07:05:55 3.9764 +07:06:00 3.9795 +07:06:05 4.0110 +07:06:10 3.9717 +07:06:15 4.0161 +07:06:20 3.9992 +07:06:25 3.9963 +07:06:30 3.8992 +07:06:35 3.9401 +07:06:40 3.8914 +07:06:45 3.8475 +07:06:50 3.9455 +07:06:55 4.0914 +07:07:00 4.0761 +07:07:05 3.9602 +07:07:10 3.9436 +07:07:15 4.0284 +07:07:20 4.0401 +07:07:25 4.0354 +07:07:30 4.0235 +07:07:35 4.0186 +07:07:40 4.1100 +07:07:45 4.0619 +07:07:50 3.9841 +07:07:55 3.9825 +07:08:00 4.0345 +07:08:05 4.0511 +07:08:10 3.9097 +07:08:15 3.9040 +07:08:20 4.0121 +07:08:25 4.0235 +07:08:30 4.1118 +07:08:35 3.9372 +07:08:40 3.9651 +07:08:45 3.9828 +07:08:50 3.9190 +07:08:55 4.0002 +07:09:00 3.9916 +07:09:05 4.0053 +07:09:10 4.0468 +07:09:15 4.0359 +07:09:20 4.0615 +07:09:25 4.1190 +07:09:30 4.0953 +07:09:35 4.0763 +07:09:40 4.0802 +07:09:45 4.0419 +07:09:50 3.9986 +07:09:55 4.0180 +07:10:00 3.9805 +07:10:05 4.0203 +07:10:10 3.9882 +07:10:15 4.0479 +07:10:20 4.0775 +07:10:25 3.9537 +07:10:30 3.9204 +07:10:35 3.9866 +07:10:40 4.0419 +07:10:45 4.0032 +07:10:50 4.0119 +07:10:55 4.0037 +07:11:00 3.9049 +07:11:05 4.0066 +07:11:10 4.0241 +07:11:15 4.0357 +07:11:20 3.9752 +07:11:25 3.9674 +07:11:30 4.0493 +07:11:35 4.0752 +07:11:40 4.0649 +07:11:45 4.1014 +07:11:50 4.0570 +07:11:55 3.9770 +07:12:00 3.8638 +07:12:05 3.9677 +07:12:10 3.9955 +07:12:15 4.0086 +07:12:20 4.0094 +07:12:25 4.0401 +07:12:30 3.9904 +07:12:35 3.9253 +07:12:40 3.9437 +07:12:45 3.9038 +07:12:50 3.9281 +07:12:55 3.9605 +07:13:00 4.0345 +07:13:05 3.9894 +07:13:10 3.9407 +07:13:15 4.0352 +07:13:20 4.0161 +07:13:25 3.9214 +07:13:30 3.9612 +07:13:35 4.0088 +07:13:40 3.9789 +07:13:45 3.8100 +07:13:50 3.9050 +07:13:55 3.9802 +07:14:00 3.9545 +07:14:05 3.9441 +07:14:10 4.0335 +07:14:15 4.0708 +07:14:20 3.9522 +07:14:25 3.9250 +07:14:30 3.9487 +07:14:35 3.9084 +07:14:40 3.9318 +07:14:45 4.0237 +07:14:50 3.9868 +07:14:55 3.9472 +07:15:00 3.9503 +07:15:05 3.9841 +07:15:10 4.0961 +07:15:15 3.9755 +07:15:20 3.9384 +07:15:25 4.0561 +07:15:30 4.0838 +07:15:35 4.0970 +07:15:40 4.0984 +07:15:45 3.9954 +07:15:50 3.9506 +07:15:55 3.9681 +07:16:00 4.0432 +07:16:05 3.9754 +07:16:10 3.8893 +07:16:15 4.0057 +07:16:20 3.9681 +07:16:25 3.9913 +07:16:30 4.0296 +07:16:35 3.9910 +07:16:40 3.9067 +07:16:45 3.9687 +07:16:50 4.0883 +07:16:55 4.0373 +07:17:00 4.0075 +07:17:05 4.0365 +07:17:10 3.9870 +07:17:15 3.9532 +07:17:20 3.9243 +07:17:25 3.9507 +07:17:30 3.9186 +07:17:35 3.9382 +07:17:40 3.9989 +07:17:45 4.0520 +07:17:50 4.0157 +07:17:55 3.9938 +07:18:00 3.9427 +07:18:05 3.9664 +07:18:10 3.9941 +07:18:15 4.0214 +07:18:20 3.9435 +07:18:25 3.9988 +07:18:30 4.0244 +07:18:35 4.0577 +07:18:40 3.9294 +07:18:45 4.0254 +07:18:50 4.0947 +07:18:55 3.9741 +07:19:00 3.9534 +07:19:05 3.9919 +07:19:10 3.9832 +07:19:15 4.0292 +07:19:20 4.1013 +07:19:25 4.1093 +07:19:30 4.1770 +07:19:35 4.1204 +07:19:40 4.1057 +07:19:45 4.0171 +07:19:50 4.0160 +07:19:55 4.0301 +07:20:00 3.9289 +07:20:05 4.0411 +07:20:10 4.0901 +07:20:15 4.0731 +07:20:20 4.0908 +07:20:25 4.0364 +07:20:30 3.9304 +07:20:35 3.9396 +07:20:40 4.0353 +07:20:45 4.0732 +07:20:50 3.9827 +07:20:55 3.9217 +07:21:00 4.0017 +07:21:05 4.0271 +07:21:10 3.9928 +07:21:15 3.9567 +07:21:20 3.9800 +07:21:25 4.0148 +07:21:30 3.8643 +07:21:35 3.8715 +07:21:40 3.9855 +07:21:45 4.0287 +07:21:50 3.9610 +07:21:55 3.9697 +07:22:00 3.9684 +07:22:05 4.0167 +07:22:10 4.0327 +07:22:15 3.9339 +07:22:20 3.9977 +07:22:25 4.0495 +07:22:30 3.9838 +07:22:35 4.0027 +07:22:40 4.0191 +07:22:45 3.9655 +07:22:50 4.0148 +07:22:55 4.0439 +07:23:00 4.0178 +07:23:05 4.0526 +07:23:10 4.1629 +07:23:15 4.0272 +07:23:20 4.0832 +07:23:25 4.0104 +07:23:30 4.0908 +07:23:35 4.0209 +07:23:40 3.9428 +07:23:45 3.9996 +07:23:50 4.0410 +07:23:55 3.9502 +07:24:00 4.0052 +07:24:05 3.9415 +07:24:10 4.0241 +07:24:15 4.0320 +07:24:20 3.9461 +07:24:25 4.0098 +07:24:30 3.9996 +07:24:35 4.0095 +07:24:40 4.0557 +07:24:45 4.0464 +07:24:50 4.1141 +07:24:55 4.0095 +07:25:00 4.0552 +07:25:05 3.9365 +07:25:10 4.0027 +07:25:15 3.9614 +07:25:20 3.8990 +07:25:25 3.9918 +07:25:30 3.9295 +07:25:35 3.9185 +07:25:40 3.8429 +07:25:45 3.9452 +07:25:50 3.9674 +07:25:55 4.0543 +07:26:00 4.0635 +07:26:05 3.9589 +07:26:10 3.9988 +07:26:15 4.0060 +07:26:20 3.9787 +07:26:25 3.9225 +07:26:30 3.9579 +07:26:35 3.9296 +07:26:40 3.9466 +07:26:45 4.0616 +07:26:50 4.0153 +07:26:55 4.0670 +07:27:00 3.9542 +07:27:05 3.9738 +07:27:10 3.9815 +07:27:15 3.9423 +07:27:20 3.9826 +07:27:25 4.0080 +07:27:30 3.9068 +07:27:35 3.9858 +07:27:40 4.0180 +07:27:45 4.0122 +07:27:50 3.9957 +07:27:55 3.9369 +07:28:00 3.9561 +07:28:05 4.0006 +07:28:10 3.9932 +07:28:15 4.0848 +07:28:20 4.0206 +07:28:25 4.1064 +07:28:30 4.0370 +07:28:35 3.9362 +07:28:40 3.9839 +07:28:45 4.1243 +07:28:50 4.0571 +07:28:55 4.0604 +07:29:00 3.9417 +07:29:05 3.9615 +07:29:10 3.9935 +07:29:15 4.1409 +07:29:20 4.0063 +07:29:25 4.0181 +07:29:30 4.0890 +07:29:35 4.0001 +07:29:40 3.8651 +07:29:45 3.9902 +07:29:50 4.0165 +07:29:55 4.0559 +07:30:00 4.0068 +07:30:05 4.0026 +07:30:10 3.9786 +07:30:15 4.0030 +07:30:20 3.9984 +07:30:25 4.0523 +07:30:30 4.0215 +07:30:35 4.0036 +07:30:40 4.0055 +07:30:45 3.9802 +07:30:50 4.0121 +07:30:55 3.9387 +07:31:00 4.0273 +07:31:05 4.0339 +07:31:10 4.1256 +07:31:15 4.0952 +07:31:20 4.0309 +07:31:25 3.9858 +07:31:30 3.9388 +07:31:35 3.9843 +07:31:40 3.9860 +07:31:45 3.9648 +07:31:50 3.9311 +07:31:55 3.9954 +07:32:00 3.9828 +07:32:05 3.9345 +07:32:10 3.9774 +07:32:15 3.9972 +07:32:20 3.9881 +07:32:25 3.9946 +07:32:30 3.9638 +07:32:35 3.9475 +07:32:40 3.9115 +07:32:45 3.9717 +07:32:50 3.9925 +07:32:55 3.9819 +07:33:00 3.9361 +07:33:05 3.9941 +07:33:10 4.1109 +07:33:15 4.0931 +07:33:20 4.0483 +07:33:25 4.0308 +07:33:30 4.0170 +07:33:35 3.9972 +07:33:40 3.9874 +07:33:45 4.0318 +07:33:50 4.0051 +07:33:55 4.0405 +07:34:00 4.0419 +07:34:05 4.0084 +07:34:10 3.9410 +07:34:15 3.9341 +07:34:20 3.9440 +07:34:25 3.9001 +07:34:30 3.9862 +07:34:35 3.9862 +07:34:40 3.9692 +07:34:45 3.9566 +07:34:50 4.0924 +07:34:55 4.0334 +07:35:00 4.0595 +07:35:05 4.0333 +07:35:10 4.0112 +07:35:15 4.0107 +07:35:20 4.0381 +07:35:25 4.0007 +07:35:30 4.0876 +07:35:35 4.1263 +07:35:40 4.0388 +07:35:45 3.9396 +07:35:50 3.9247 +07:35:55 3.9195 +07:36:00 3.9774 +07:36:05 4.0169 +07:36:10 3.9980 +07:36:15 3.9550 +07:36:20 3.9281 +07:36:25 3.9087 +07:36:30 4.0222 +07:36:35 3.9692 +07:36:40 3.9929 +07:36:45 4.0782 +07:36:50 4.0314 +07:36:55 4.0021 +07:37:00 3.9934 +07:37:05 3.9621 +07:37:10 3.9977 +07:37:15 4.0528 +07:37:20 3.9871 +07:37:25 3.9783 +07:37:30 3.9491 +07:37:35 4.0215 +07:37:40 4.0339 +07:37:45 3.9985 +07:37:50 3.9271 +07:37:55 4.0020 +07:38:00 3.9708 +07:38:05 3.9732 +07:38:10 4.0268 +07:38:15 4.0644 +07:38:20 3.9611 +07:38:25 3.9839 +07:38:30 4.0518 +07:38:35 3.9964 +07:38:40 3.9341 +07:38:45 3.9913 +07:38:50 4.0619 +07:38:55 4.0054 +07:39:00 3.9688 +07:39:05 3.9823 +07:39:10 3.9432 +07:39:15 4.0172 +07:39:20 4.0745 +07:39:25 4.0627 +07:39:30 4.0147 +07:39:35 4.0344 +07:39:40 4.1459 +07:39:45 4.0060 +07:39:50 3.9854 +07:39:55 3.9388 +07:40:00 4.0417 +07:40:05 3.9545 +07:40:10 4.0443 +07:40:15 3.9669 +07:40:20 3.9868 +07:40:25 4.0808 +07:40:30 4.0782 +07:40:35 4.0118 +07:40:40 3.8667 +07:40:45 3.8985 +07:40:50 3.9561 +07:40:55 3.9345 +07:41:00 3.9363 +07:41:05 3.9341 +07:41:10 3.9846 +07:41:15 3.9419 +07:41:20 4.0330 +07:41:25 4.0802 +07:41:30 4.0557 +07:41:35 3.9986 +07:41:40 4.0281 +07:41:45 3.9957 +07:41:50 3.9433 +07:41:55 4.0746 +07:42:00 3.9418 +07:42:05 3.9718 +07:42:10 3.9917 +07:42:15 3.9682 +07:42:20 3.9667 +07:42:25 4.0337 +07:42:30 4.0806 +07:42:35 4.0179 +07:42:40 4.0310 +07:42:45 4.0512 +07:42:50 4.0269 +07:42:55 4.0163 +07:43:00 4.0475 +07:43:05 3.9709 +07:43:10 3.9100 +07:43:15 3.9426 +07:43:20 3.9498 +07:43:25 3.9755 +07:43:30 4.0342 +07:43:35 4.0040 +07:43:40 3.9569 +07:43:45 3.9138 +07:43:50 3.9876 +07:43:55 3.8970 +07:44:00 3.9047 +07:44:05 3.9595 +07:44:10 4.1133 +07:44:15 4.1495 +07:44:20 4.0210 +07:44:25 3.9984 +07:44:30 4.0075 +07:44:35 3.9621 +07:44:40 3.9409 +07:44:45 3.9544 +07:44:50 3.9906 +07:44:55 4.0273 +07:45:00 4.0417 +07:45:05 3.9591 +07:45:10 4.0132 +07:45:15 4.0553 +07:45:20 3.9374 +07:45:25 3.8852 +07:45:30 3.9169 +07:45:35 3.9788 +07:45:40 3.9683 +07:45:45 3.9594 +07:45:50 3.9428 +07:45:55 4.0012 +07:46:00 3.9315 +07:46:05 4.0128 +07:46:10 4.0311 +07:46:15 4.0231 +07:46:20 3.9435 +07:46:25 3.9887 +07:46:30 3.9711 +07:46:35 3.9699 +07:46:40 4.0276 +07:46:45 4.0440 +07:46:50 4.0292 +07:46:55 4.0175 +07:47:00 4.0378 +07:47:05 3.9671 +07:47:10 3.9567 +07:47:15 3.9553 +07:47:20 3.9799 +07:47:25 3.9634 +07:47:30 3.9780 +07:47:35 3.9921 +07:47:40 3.9732 +07:47:45 3.9689 +07:47:50 4.0112 +07:47:55 3.9738 +07:48:00 3.9429 +07:48:05 3.9912 +07:48:10 4.0891 +07:48:15 4.1150 +07:48:20 3.9857 +07:48:25 4.0010 +07:48:30 3.9883 +07:48:35 3.9777 +07:48:40 4.0747 +07:48:45 4.0345 +07:48:50 3.9811 +07:48:55 3.9662 +07:49:00 3.9252 +07:49:05 3.8850 +07:49:10 3.9957 +07:49:15 4.0248 +07:49:20 3.9773 +07:49:25 4.1332 +07:49:30 3.9942 +07:49:35 3.9339 +07:49:40 4.0356 +07:49:45 4.0539 +07:49:50 4.0836 +07:49:55 4.0437 +07:50:00 3.9342 +07:50:05 3.9470 +07:50:10 3.9601 +07:50:15 4.0006 +07:50:20 4.0182 +07:50:25 3.9467 +07:50:30 4.0238 +07:50:35 4.0169 +07:50:40 4.0735 +07:50:45 4.0969 +07:50:50 3.9874 +07:50:55 3.9897 +07:51:00 4.0284 +07:51:05 4.0492 +07:51:10 4.0634 +07:51:15 3.9503 +07:51:20 4.0127 +07:51:25 3.9289 +07:51:30 4.0229 +07:51:35 4.0740 +07:51:40 4.0605 +07:51:45 4.0872 +07:51:50 3.9452 +07:51:55 4.0306 +07:52:00 4.0054 +07:52:05 3.9970 +07:52:10 3.9915 +07:52:15 4.0410 +07:52:20 4.0350 +07:52:25 4.0162 +07:52:30 3.9289 +07:52:35 3.8351 +07:52:40 3.9203 +07:52:45 4.0370 +07:52:50 4.0870 +07:52:55 4.0008 +07:53:00 4.0982 +07:53:05 4.0375 +07:53:10 3.9045 +07:53:15 3.9823 +07:53:20 3.9681 +07:53:25 4.0044 +07:53:30 3.9139 +07:53:35 4.0631 +07:53:40 3.9580 +07:53:45 3.9385 +07:53:50 3.9858 +07:53:55 4.0183 +07:54:00 4.0330 +07:54:05 4.0419 +07:54:10 4.0432 +07:54:15 4.0137 +07:54:20 4.0013 +07:54:25 3.9467 +07:54:30 3.9752 +07:54:35 3.8770 +07:54:40 3.9133 +07:54:45 3.9232 +07:54:50 4.0269 +07:54:55 3.9772 +07:55:00 4.0000 +07:55:05 3.9313 +07:55:10 4.0334 +07:55:15 4.0384 +07:55:20 4.0974 +07:55:25 3.8880 +07:55:30 3.8505 +07:55:35 3.9453 +07:55:40 3.9472 +07:55:45 4.0646 +07:55:50 3.9383 +07:55:55 3.9044 +07:56:00 3.8710 +07:56:05 4.0180 +07:56:10 3.9656 +07:56:15 3.9579 +07:56:20 3.8838 +07:56:25 3.9843 +07:56:30 3.9417 +07:56:35 4.0287 +07:56:40 4.1304 +07:56:45 4.1495 +07:56:50 4.0465 +07:56:55 4.0552 +07:57:00 4.0157 +07:57:05 3.9889 +07:57:10 4.0326 +07:57:15 4.0182 +07:57:20 3.9516 +07:57:25 3.9318 +07:57:30 3.9783 +07:57:35 3.9596 +07:57:40 4.0230 +07:57:45 3.9788 +07:57:50 3.9844 +07:57:55 3.9553 +07:58:00 3.9792 +07:58:05 4.0551 +07:58:10 4.0531 +07:58:15 4.0933 +07:58:20 4.0642 +07:58:25 4.1144 +07:58:30 3.9737 +07:58:35 4.0294 +07:58:40 4.1012 +07:58:45 4.0561 +07:58:50 3.9797 +07:58:55 4.0391 +07:59:00 4.0830 +07:59:05 3.9325 +07:59:10 4.0061 +07:59:15 4.0500 +07:59:20 4.0985 +07:59:25 4.0463 +07:59:30 3.9722 +07:59:35 3.9789 +07:59:40 4.0397 +07:59:45 4.0641 +07:59:50 4.0586 +07:59:55 4.0023 +08:00:00 3.8813 +08:00:05 4.0437 +08:00:10 4.0438 +08:00:15 4.0893 +08:00:20 4.1045 +08:00:25 3.9860 +08:00:30 3.9458 +08:00:35 4.0401 +08:00:40 4.0191 +08:00:45 3.9372 +08:00:50 3.9189 +08:00:55 3.8979 +08:01:00 4.0677 +08:01:05 4.0129 +08:01:10 3.9805 +08:01:15 4.0664 +08:01:20 4.0720 +08:01:25 4.0299 +08:01:30 4.0319 +08:01:35 4.0259 +08:01:40 4.0582 +08:01:45 3.9801 +08:01:50 3.9505 +08:01:55 4.0454 +08:02:00 4.0843 +08:02:05 3.9298 +08:02:10 3.8879 +08:02:15 4.0280 +08:02:20 4.0118 +08:02:25 4.0533 +08:02:30 3.9817 +08:02:35 3.9722 +08:02:40 3.9455 +08:02:45 3.9026 +08:02:50 3.8904 +08:02:55 3.9078 +08:03:00 3.9973 +08:03:05 4.0690 +08:03:10 4.0057 +08:03:15 4.0057 +08:03:20 3.9278 +08:03:25 3.9287 +08:03:30 3.9052 +08:03:35 3.9262 +08:03:40 3.9814 +08:03:45 3.9305 +08:03:50 3.9532 +08:03:55 3.9337 +08:04:00 3.8757 +08:04:05 3.9445 +08:04:10 4.0168 +08:04:15 3.9895 +08:04:20 3.9064 +08:04:25 3.8872 +08:04:30 3.9197 +08:04:35 3.9890 +08:04:40 3.9414 +08:04:45 3.9903 +08:04:50 3.9909 +08:04:55 3.9885 +08:05:00 3.9885 +08:05:05 3.9878 +08:05:10 3.9903 +08:05:15 3.9920 +08:05:20 3.9892 +08:05:25 3.9900 +08:05:30 3.9900 +08:05:35 3.9860 +08:05:40 3.9877 +08:05:45 3.9956 +08:05:50 3.9975 +08:05:55 3.9936 +08:06:00 3.9936 +08:06:05 3.9916 +08:06:10 3.9911 +08:06:15 3.9936 +08:06:20 3.9901 +08:06:25 3.9901 +08:06:30 3.9934 +08:06:35 4.0010 +08:06:40 3.9971 +08:06:45 3.9971 +08:06:50 3.9976 +08:06:55 3.9976 +08:07:00 3.9994 +08:07:05 4.0004 +08:07:10 4.0061 +08:07:15 4.0107 +08:07:20 4.0111 +08:07:25 4.0111 +08:07:30 4.0168 +08:07:35 4.0111 +08:07:40 4.0101 +08:07:45 4.0144 +08:07:50 4.0209 +08:07:55 4.0209 +08:08:00 4.0272 +08:08:05 4.0423 +08:08:10 4.0500 +08:08:15 4.0545 +08:08:20 4.0647 +08:08:25 4.0647 +08:08:30 4.0650 +08:08:35 4.0661 +08:08:40 4.0722 +08:08:45 4.0664 +08:08:50 4.0706 +08:08:55 4.0688 +08:09:00 4.0688 +08:09:05 4.0661 +08:09:10 4.0713 +08:09:15 4.0666 +08:09:20 3.9059 +08:09:25 3.9409 +08:09:30 3.9834 +08:09:35 3.9559 +08:09:40 3.8940 +08:09:45 3.8839 +08:09:50 3.8736 +08:09:55 3.9604 +08:10:00 4.0262 +08:10:05 4.0232 +08:10:10 3.9741 +08:10:15 3.9944 +08:10:20 3.9905 +08:10:25 3.8958 +08:10:30 3.8878 +08:10:35 4.0318 +08:10:40 3.9985 +08:10:45 3.9562 +08:10:50 4.0179 +08:10:55 3.9810 +08:11:00 3.9610 +08:11:05 4.0197 +08:11:10 4.0233 +08:11:15 4.0069 +08:11:20 4.0248 +08:11:25 3.9454 +08:11:30 4.0151 +08:11:35 4.0178 +08:11:40 4.0001 +08:11:45 4.0719 +08:11:50 4.0412 +08:11:55 4.0093 +08:12:00 3.9623 +08:12:05 3.9329 +08:12:10 3.9418 +08:12:15 3.9776 +08:12:20 3.9534 +08:12:25 3.9433 +08:12:30 4.0519 +08:12:35 4.0630 +08:12:40 4.0486 +08:12:45 4.0100 +08:12:50 3.9226 +08:12:55 3.9947 +08:13:00 3.9913 +08:13:05 3.9335 +08:13:10 3.9834 +08:13:15 4.0252 +08:13:20 4.0229 +08:13:25 4.0330 +08:13:30 3.9917 +08:13:35 3.9063 +08:13:40 3.9863 +08:13:45 3.9766 +08:13:50 4.0003 +08:13:55 4.0513 +08:14:00 4.0584 +08:14:05 3.9683 +08:14:10 4.0158 +08:14:15 4.0569 +08:14:20 3.8917 +08:14:25 3.9474 +08:14:30 4.0335 +08:14:35 3.9504 +08:14:40 3.9493 +08:14:45 3.9673 +08:14:50 3.9485 +08:14:55 3.9409 +08:15:00 4.0484 +08:15:05 3.9996 +08:15:10 3.9073 +08:15:15 3.9972 +08:15:20 4.0568 +08:15:25 3.9789 +08:15:30 4.0165 +08:15:35 4.0831 +08:15:40 4.0674 +08:15:45 4.0077 +08:15:50 4.0914 +08:15:55 4.0109 +08:16:00 3.9813 +08:16:05 3.9983 +08:16:10 4.0353 +08:16:15 3.9615 +08:16:20 3.9998 +08:16:25 4.0267 +08:16:30 4.0030 +08:16:35 4.0033 +08:16:40 3.9525 +08:16:45 4.0112 +08:16:50 4.0112 +08:16:55 4.0565 +08:17:00 4.0473 +08:17:05 4.0309 +08:17:10 3.9956 +08:17:15 3.9218 +08:17:20 3.9845 +08:17:25 4.0239 +08:17:30 4.0454 +08:17:35 4.0000 +08:17:40 4.0090 +08:17:45 3.9324 +08:17:50 3.8911 +08:17:55 3.9708 +08:18:00 3.9704 +08:18:05 3.9098 +08:18:10 4.0112 +08:18:15 4.0170 +08:18:20 3.9810 +08:18:25 3.9344 +08:18:30 4.0801 +08:18:35 3.9548 +08:18:40 3.9841 +08:18:45 4.0611 +08:18:50 3.9899 +08:18:55 4.0117 +08:19:00 4.1174 +08:19:05 4.0336 +08:19:10 3.9787 +08:19:15 4.0188 +08:19:20 3.9898 +08:19:25 3.8395 +08:19:30 3.9379 +08:19:35 3.9463 +08:19:40 3.9283 +08:19:45 3.9650 +08:19:50 3.9734 +08:19:55 4.0571 +08:20:00 3.9920 +08:20:05 4.0088 +08:20:10 4.0406 +08:20:15 4.0886 +08:20:20 3.9662 +08:20:25 4.0271 +08:20:30 4.0010 +08:20:35 4.0220 +08:20:40 3.9988 +08:20:45 4.0391 +08:20:50 4.0271 +08:20:55 3.9926 +08:21:00 3.9645 +08:21:05 3.9987 +08:21:10 4.0486 +08:21:15 3.9711 +08:21:20 4.0100 +08:21:25 3.9903 +08:21:30 4.0626 +08:21:35 3.9436 +08:21:40 4.0508 +08:21:45 4.0194 +08:21:50 3.9379 +08:21:55 3.9143 +08:22:00 3.9572 +08:22:05 3.8625 +08:22:10 4.0040 +08:22:15 3.9890 +08:22:20 4.0783 +08:22:25 4.0251 +08:22:30 4.1519 +08:22:35 4.0467 +08:22:40 4.0457 +08:22:45 4.0522 +08:22:50 3.9937 +08:22:55 3.9889 +08:23:00 3.9866 +08:23:05 4.1136 +08:23:10 4.0970 +08:23:15 3.9813 +08:23:20 3.9880 +08:23:25 4.0045 +08:23:30 3.8291 +08:23:35 3.9054 +08:23:40 3.9824 +08:23:45 4.0406 +08:23:50 4.0859 +08:23:55 4.1527 +08:24:00 4.0190 +08:24:05 3.9886 +08:24:10 3.9411 +08:24:15 3.9661 +08:24:20 4.0354 +08:24:25 3.9175 +08:24:30 3.9984 +08:24:35 4.0452 +08:24:40 4.0369 +08:24:45 4.0266 +08:24:50 3.9061 +08:24:55 3.9084 +08:25:00 3.9583 +08:25:05 3.9560 +08:25:10 3.9405 +08:25:15 3.9877 +08:25:20 4.0423 +08:25:25 3.9790 +08:25:30 4.0421 +08:25:35 3.9568 +08:25:40 3.9529 +08:25:45 3.9750 +08:25:50 3.9340 +08:25:55 4.0732 +08:26:00 4.0032 +08:26:05 3.9355 +08:26:10 4.0352 +08:26:15 4.0157 +08:26:20 3.9340 +08:26:25 4.0755 +08:26:30 3.9820 +08:26:35 3.9605 +08:26:40 3.9558 +08:26:45 3.9521 +08:26:50 4.0223 +08:26:55 3.9900 +08:27:00 3.9845 +08:27:05 4.0780 +08:27:10 3.9558 +08:27:15 3.9726 +08:27:20 4.0192 +08:27:25 3.9686 +08:27:30 3.9911 +08:27:35 3.9766 +08:27:40 4.0285 +08:27:45 4.0070 +08:27:50 4.0941 +08:27:55 4.1368 +08:28:00 4.0655 +08:28:05 4.0341 +08:28:10 4.0018 +08:28:15 3.9572 +08:28:20 3.9705 +08:28:25 4.0494 +08:28:30 4.1193 +08:28:35 4.0454 +08:28:40 4.0497 +08:28:45 3.9941 +08:28:50 3.9807 +08:28:55 3.9538 +08:29:00 4.0346 +08:29:05 3.9442 +08:29:10 3.8731 +08:29:15 3.9171 +08:29:20 3.9704 +08:29:25 3.9611 +08:29:30 3.9287 +08:29:35 3.9558 +08:29:40 3.9734 +08:29:45 3.9336 +08:29:50 3.9309 +08:29:55 3.9706 +08:30:00 3.9000 +08:30:05 3.9439 +08:30:10 3.9667 +08:30:15 4.0107 +08:30:20 4.0336 +08:30:25 3.9975 +08:30:30 4.0185 +08:30:35 4.0235 +08:30:40 4.0291 +08:30:45 4.0685 +08:30:50 4.0343 +08:30:55 4.0733 +08:31:00 4.0495 +08:31:05 3.9309 +08:31:10 3.8886 +08:31:15 3.8842 +08:31:20 3.8765 +08:31:25 3.9649 +08:31:30 4.0185 +08:31:35 3.9216 +08:31:40 3.9444 +08:31:45 4.0470 +08:31:50 4.0551 +08:31:55 3.9941 +08:32:00 3.9735 +08:32:05 4.0055 +08:32:10 4.0072 +08:32:15 3.9674 +08:32:20 3.9799 +08:32:25 3.9734 +08:32:30 4.0448 +08:32:35 3.9855 +08:32:40 3.9453 +08:32:45 3.9345 +08:32:50 3.9903 +08:32:55 3.9872 +08:33:00 3.8902 +08:33:05 3.9411 +08:33:10 3.9458 +08:33:15 3.9231 +08:33:20 3.9494 +08:33:25 3.9503 +08:33:30 3.8982 +08:33:35 4.0473 +08:33:40 3.9778 +08:33:45 3.9569 +08:33:50 3.9582 +08:33:55 3.9874 +08:34:00 3.9983 +08:34:05 4.0212 +08:34:10 3.9492 +08:34:15 3.9464 +08:34:20 3.9542 +08:34:25 3.9336 +08:34:30 3.9511 +08:34:35 3.8728 +08:34:40 3.8914 +08:34:45 4.0097 +08:34:50 4.0167 +08:34:55 3.9419 +08:35:00 3.9504 +08:35:05 3.9485 +08:35:10 4.0029 +08:35:15 4.0663 +08:35:20 3.9734 +08:35:25 3.9258 +08:35:30 3.9680 +08:35:35 3.9818 +08:35:40 3.9747 +08:35:45 3.9243 +08:35:50 3.9350 +08:35:55 4.0503 +08:36:00 4.0678 +08:36:05 4.0310 +08:36:10 3.9243 +08:36:15 3.9879 +08:36:20 4.0485 +08:36:25 4.0174 +08:36:30 3.8832 +08:36:35 3.8986 +08:36:40 3.9783 +08:36:45 3.8902 +08:36:50 3.8330 +08:36:55 3.9425 +08:37:00 4.0228 +08:37:05 3.9824 +08:37:10 4.0141 +08:37:15 4.0773 +08:37:20 4.0423 +08:37:25 3.9658 +08:37:30 3.9688 +08:37:35 4.0131 +08:37:40 3.9095 +08:37:45 3.9185 +08:37:50 3.9448 +08:37:55 3.9790 +08:38:00 3.9711 +08:38:05 4.0244 +08:38:10 3.9948 +08:38:15 3.9369 +08:38:20 3.9243 +08:38:25 3.9489 +08:38:30 4.0292 +08:38:35 3.9508 +08:38:40 3.9296 +08:38:45 3.9449 +08:38:50 4.0867 +08:38:55 4.0995 +08:39:00 4.0276 +08:39:05 3.9588 +08:39:10 3.9257 +08:39:15 3.8554 +08:39:20 3.9168 +08:39:25 3.9684 +08:39:30 4.1025 +08:39:35 4.0942 +08:39:40 4.1029 +08:39:45 4.0091 +08:39:50 3.9430 +08:39:55 3.9655 +08:40:00 3.9637 +08:40:05 3.9163 +08:40:10 3.8848 +08:40:15 3.9872 +08:40:20 3.9584 +08:40:25 3.8781 +08:40:30 3.9980 +08:40:35 3.9627 +08:40:40 3.9602 +08:40:45 3.9543 +08:40:50 3.9331 +08:40:55 3.9159 +08:41:00 3.9642 +08:41:05 3.9644 +08:41:10 3.9690 +08:41:15 3.9787 +08:41:20 4.0381 +08:41:25 4.0643 +08:41:30 3.9557 +08:41:35 3.9533 +08:41:40 3.9828 +08:41:45 3.9858 +08:41:50 4.0183 +08:41:55 3.9128 +08:42:00 3.8540 +08:42:05 3.9747 +08:42:10 4.0202 +08:42:15 4.0068 +08:42:20 4.0302 +08:42:25 3.9536 +08:42:30 3.9500 +08:42:35 3.9892 +08:42:40 3.8927 +08:42:45 3.9421 +08:42:50 4.0618 +08:42:55 4.1163 +08:43:00 4.0682 +08:43:05 4.1158 +08:43:10 4.0106 +08:43:15 3.9641 +08:43:20 4.0354 +08:43:25 3.9817 +08:43:30 3.9486 +08:43:35 4.0596 +08:43:40 3.9953 +08:43:45 3.9774 +08:43:50 4.0091 +08:43:55 4.0125 +08:44:00 4.0138 +08:44:05 3.9728 +08:44:10 3.9039 +08:44:15 3.9659 +08:44:20 4.0629 +08:44:25 3.9732 +08:44:30 3.9012 +08:44:35 3.9800 +08:44:40 4.0467 +08:44:45 3.9895 +08:44:50 3.9373 +08:44:55 3.9511 +08:45:00 4.0204 +08:45:05 3.9427 +08:45:10 4.0281 +08:45:15 4.0489 +08:45:20 3.9987 +08:45:25 3.9167 +08:45:30 3.9390 +08:45:35 3.9641 +08:45:40 3.8772 +08:45:45 3.9964 +08:45:50 4.0169 +08:45:55 3.9931 +08:46:00 4.0114 +08:46:05 4.0286 +08:46:10 4.0444 +08:46:15 3.9846 +08:46:20 3.9911 +08:46:25 4.0030 +08:46:30 4.0082 +08:46:35 4.0295 +08:46:40 3.9617 +08:46:45 3.8579 +08:46:50 4.0388 +08:46:55 4.0432 +08:47:00 4.0729 +08:47:05 3.9685 +08:47:10 3.9426 +08:47:15 3.9606 +08:47:20 4.0833 +08:47:25 4.1376 +08:47:30 4.0061 +08:47:35 4.0050 +08:47:40 3.9474 +08:47:45 3.9360 +08:47:50 4.0148 +08:47:55 3.9876 +08:48:00 3.9914 +08:48:05 3.9491 +08:48:10 4.0126 +08:48:15 4.0167 +08:48:20 3.9897 +08:48:25 3.9792 +08:48:30 3.9671 +08:48:35 3.8923 +08:48:40 3.8938 +08:48:45 3.9834 +08:48:50 3.9586 +08:48:55 3.9602 +08:49:00 4.0370 +08:49:05 4.0033 +08:49:10 4.0371 +08:49:15 4.0473 +08:49:20 3.9490 +08:49:25 4.0169 +08:49:30 4.0128 +08:49:35 4.0164 +08:49:40 3.9989 +08:49:45 4.0173 +08:49:50 4.0526 +08:49:55 4.0508 +08:50:00 4.0035 +08:50:05 4.0408 +08:50:10 4.0266 +08:50:15 3.9400 +08:50:20 3.9809 +08:50:25 3.9025 +08:50:31 3.9583 +08:50:35 3.9959 +08:50:40 3.9316 +08:50:45 4.0148 +08:50:50 4.1073 +08:50:55 4.1205 +08:51:00 4.0011 +08:51:05 3.9443 +08:51:10 3.9353 +08:51:15 3.9095 +08:51:20 3.9325 +08:51:25 3.9605 +08:51:30 3.9631 +08:51:35 4.0037 +08:51:40 3.9625 +08:51:45 4.0819 +08:51:50 3.9921 +08:51:55 3.9810 +08:52:00 3.9810 +08:52:05 3.9726 +08:52:10 3.9964 +08:52:15 3.9987 +08:52:20 3.9812 +08:52:25 3.9676 +08:52:30 3.9660 +08:52:35 3.9372 +08:52:40 4.0171 +08:52:45 3.9645 +08:52:50 3.9657 +08:52:55 3.9790 +08:53:00 3.9521 +08:53:05 3.9928 +08:53:10 4.0833 +08:53:15 4.0450 +08:53:20 3.9958 +08:53:25 3.9552 +08:53:30 3.8727 +08:53:35 3.9622 +08:53:40 3.8636 +08:53:45 3.9463 +08:53:50 3.9404 +08:53:55 3.9863 +08:54:00 3.9678 +08:54:05 4.0179 +08:54:10 4.0234 +08:54:15 3.9915 +08:54:20 3.9294 +08:54:25 3.9806 +08:54:30 4.0041 +08:54:35 4.0001 +08:54:40 3.9512 +08:54:45 3.9294 +08:54:50 3.9819 +08:54:55 4.0536 +08:55:00 4.0273 +08:55:05 4.0399 +08:55:10 4.0048 +08:55:15 4.0371 +08:55:20 4.0576 +08:55:25 4.0198 +08:55:30 3.8868 +08:55:35 3.8492 +08:55:40 3.9570 +08:55:45 4.0255 +08:55:50 3.9984 +08:55:55 3.9594 +08:56:00 3.9647 +08:56:05 4.0360 +08:56:10 3.9813 +08:56:15 3.9297 +08:56:20 3.9753 +08:56:25 4.0072 +08:56:30 4.0432 +08:56:35 4.0500 +08:56:40 3.9434 +08:56:45 3.9787 +08:56:50 3.9634 +08:56:55 3.9082 +08:57:00 3.7568 +08:57:05 3.7184 +08:57:10 3.8546 +08:57:15 3.9252 +08:57:20 3.9070 +08:57:25 3.9095 +08:57:30 3.9184 +08:57:35 3.9696 +08:57:40 4.0113 +08:57:45 3.9432 +08:57:50 3.9121 +08:57:55 4.0103 +08:58:00 3.9635 +08:58:05 3.9885 +08:58:10 3.9599 +08:58:15 3.9407 +08:58:20 3.9283 +08:58:25 3.9582 +08:58:30 4.0212 +08:58:35 4.0127 +08:58:40 4.0150 +08:58:45 4.0532 +08:58:50 4.0701 +08:58:55 3.9462 +08:59:00 3.9007 +08:59:05 3.9557 +08:59:10 3.9085 +08:59:15 3.9706 +08:59:20 4.0174 +08:59:25 4.0459 +08:59:30 3.9561 +08:59:35 4.0658 +08:59:40 4.1289 +08:59:45 3.9320 +08:59:50 3.8703 +08:59:55 3.9320 +09:00:00 3.9026 +09:00:05 3.9094 +09:00:10 3.9181 +09:00:15 3.9281 +09:00:20 4.0082 +09:00:25 3.9618 +09:00:30 4.1944 +09:00:35 3.8815 +09:00:40 4.0046 +09:00:45 3.9718 +09:00:50 3.8848 +09:00:55 4.0679 +09:01:00 3.8829 +09:01:05 4.0181 +09:01:10 3.8955 +09:01:15 4.1476 +09:01:20 4.0425 +09:01:25 3.8633 +09:01:30 4.2034 +09:01:35 3.9111 +09:01:40 3.9196 +09:01:45 4.1620 +09:01:50 3.9057 +09:01:55 4.0862 +09:02:00 3.8982 +09:02:05 3.9585 +09:02:10 4.0054 +09:02:15 4.0036 +09:02:20 3.9482 +09:02:25 3.9609 +09:02:30 4.0482 +09:02:35 3.9767 +09:02:40 4.0038 +09:02:45 3.9352 +09:02:50 3.9016 +09:02:55 3.9504 +09:03:00 3.9335 +09:03:05 3.9099 +09:03:10 3.9586 +09:03:15 3.9906 +09:03:20 3.9705 +09:03:25 3.9033 +09:03:30 3.9194 +09:03:35 3.9398 +09:03:40 4.0247 +09:03:45 3.9545 +09:03:50 3.9992 +09:03:55 3.9596 +09:04:00 3.9864 +09:04:05 3.9992 +09:04:10 4.0276 +09:04:15 4.0089 +09:04:20 3.9199 +09:04:25 3.9587 +09:04:30 4.0258 +09:04:35 3.9671 +09:04:40 3.9195 +09:04:45 3.9699 +09:04:50 4.0437 +09:04:55 4.1013 +09:05:00 4.0913 +09:05:05 3.9621 +09:05:10 3.9603 +09:05:15 4.0663 +09:05:20 4.1009 +09:05:25 4.0497 +09:05:30 4.0423 +09:05:35 4.0485 +09:05:40 4.0168 +09:05:45 3.9509 +09:05:50 3.9718 +09:05:55 3.9458 +09:06:00 3.9538 +09:06:05 3.9652 +09:06:10 4.0019 +09:06:15 3.9861 +09:06:20 4.0160 +09:06:25 4.0185 +09:06:30 3.9952 +09:06:35 4.0694 +09:06:40 3.9237 +09:06:45 3.9054 +09:06:50 3.9866 +09:06:55 3.9762 +09:07:00 3.8969 +09:07:05 3.9303 +09:07:10 3.9698 +09:07:15 3.9757 +09:07:20 3.9898 +09:07:25 3.9540 +09:07:30 3.9883 +09:07:35 4.0885 +09:07:40 4.0357 +09:07:45 4.0111 +09:07:50 3.9162 +09:07:55 3.9756 +09:08:00 4.0568 +09:08:05 4.0227 +09:08:10 4.0309 +09:08:15 3.9628 +09:08:20 3.9529 +09:08:25 3.9398 +09:08:30 3.8903 +09:08:35 3.8768 +09:08:40 3.9322 +09:08:45 3.9810 +09:08:50 3.9501 +09:08:55 3.9341 +09:09:00 4.0024 +09:09:05 4.0412 +09:09:10 4.0311 +09:09:15 3.9860 +09:09:20 3.9736 +09:09:25 3.9748 +09:09:30 4.0204 +09:09:35 3.9503 +09:09:40 3.9509 +09:09:45 3.9139 +09:09:50 3.9201 +09:09:55 3.9490 +09:10:00 4.0020 +09:10:05 3.9734 +09:10:10 3.9946 +09:10:15 4.0287 +09:10:20 4.0056 +09:10:25 3.9963 +09:10:30 3.9700 +09:10:35 3.9943 +09:10:40 3.8822 +09:10:45 3.9416 +09:10:50 4.0093 +09:10:55 4.0461 +09:11:00 4.0392 +09:11:05 3.9744 +09:11:10 3.9849 +09:11:15 3.9157 +09:11:20 4.0314 +09:11:25 4.0579 +09:11:30 4.0791 +09:11:35 4.0032 +09:11:40 3.9909 +09:11:45 4.0130 +09:11:50 3.9939 +09:11:55 3.9481 +09:12:00 3.9951 +09:12:05 4.0153 +09:12:10 3.9742 +09:12:15 3.9734 +09:12:20 3.8981 +09:12:25 3.8917 +09:12:30 4.0098 +09:12:35 3.9335 +09:12:40 3.9522 +09:12:45 3.9576 +09:12:50 3.9824 +09:12:55 3.8814 +09:13:00 3.8504 +09:13:05 3.9867 +09:13:10 3.9064 +09:13:15 3.8306 +09:13:20 3.8611 +09:13:25 3.9154 +09:13:30 3.8721 +09:13:35 3.8510 +09:13:40 3.9872 +09:13:45 4.0319 +09:13:50 3.8819 +09:13:55 4.0158 +09:14:00 3.9158 +09:14:05 3.9536 +09:14:10 4.0790 +09:14:15 4.0152 +09:14:20 4.0560 +09:14:25 3.9705 +09:14:30 4.0517 +09:14:35 4.0736 +09:14:40 4.0872 +09:14:45 4.1996 +09:14:50 4.0228 +09:14:55 4.0313 +09:15:00 4.0599 +09:15:05 4.0157 +09:15:10 3.9526 +09:15:15 3.9166 +09:15:20 3.8356 +09:15:25 3.8660 +09:15:30 3.8097 +09:15:35 3.9104 +09:15:40 3.9859 +09:15:45 3.9674 +09:15:50 3.9716 +09:15:55 4.1186 +09:16:00 4.0244 +09:16:05 3.9607 +09:16:10 3.8917 +09:16:15 3.9409 +09:16:20 3.9663 +09:16:25 3.9814 +09:16:30 3.9684 +09:16:35 3.9023 +09:16:40 4.0013 +09:16:45 3.9684 +09:16:50 3.9354 +09:16:55 3.9427 +09:17:00 3.9185 +09:17:05 3.9001 +09:17:10 3.8790 +09:17:15 3.8939 +09:17:20 3.9965 +09:17:25 3.9104 +09:17:30 3.9415 +09:17:35 3.9409 +09:17:40 3.9442 +09:17:45 3.9813 +09:17:50 4.0043 +09:17:55 4.0353 +09:18:00 3.9322 +09:18:05 3.9964 +09:18:10 3.9802 +09:18:15 3.8984 +09:18:20 3.9210 +09:18:25 3.9290 +09:18:30 4.0317 +09:18:35 4.0445 +09:18:40 4.0734 +09:18:45 3.9932 +09:18:50 3.8709 +09:18:55 3.9434 +09:19:00 3.8759 +09:19:05 3.9505 +09:19:10 3.9768 +09:19:15 3.9329 +09:19:20 3.9821 +09:19:25 3.9729 +09:19:30 4.0061 +09:19:35 4.0010 +09:19:40 3.9859 +09:19:45 3.9958 +09:19:50 3.9214 +09:19:55 3.9344 +09:20:00 4.0097 +09:20:05 3.9930 +09:20:10 3.9946 +09:20:15 3.9889 +09:20:20 3.9376 +09:20:25 3.9850 +09:20:30 4.0629 +09:20:35 4.0633 +09:20:40 3.9687 +09:20:45 3.9667 +09:20:50 3.9618 +09:20:55 3.9653 +09:21:00 3.9441 +09:21:05 3.8934 +09:21:10 3.8937 +09:21:15 3.9045 +09:21:20 3.9774 +09:21:25 4.0146 +09:21:30 3.9514 +09:21:35 3.9383 +09:21:40 3.8049 +09:21:45 3.8884 +09:21:50 3.9176 +09:21:55 3.9486 +09:22:00 3.9925 +09:22:05 3.8731 +09:22:10 3.8810 +09:22:15 3.9566 +09:22:20 3.9881 +09:22:25 3.9633 +09:22:30 4.0458 +09:22:35 3.9979 +09:22:40 4.0002 +09:22:45 3.9824 +09:22:50 4.0000 +09:22:55 3.9607 +09:23:00 3.9936 +09:23:05 4.0417 +09:23:10 4.0602 +09:23:15 4.0866 +09:23:20 4.0276 +09:23:25 4.0074 +09:23:30 3.9939 +09:23:35 3.8641 +09:23:40 3.8143 +09:23:45 3.8374 +09:23:50 3.9005 +09:23:55 3.9436 +09:24:00 4.0564 +09:24:05 3.9793 +09:24:10 3.9287 +09:24:15 3.9742 +09:24:20 4.0483 +09:24:25 3.9959 +09:24:30 3.8512 +09:24:35 3.9290 +09:24:40 3.9476 +09:24:45 3.9360 +09:24:50 4.0257 +09:24:55 3.9716 +09:25:00 3.9111 +09:25:05 3.8669 +09:25:10 3.9086 +09:25:15 4.0175 +09:25:20 4.0335 +09:25:25 3.9244 +09:25:30 3.9637 +09:25:35 3.9755 +09:25:40 3.8314 +09:25:45 3.9610 +09:25:50 3.9638 +09:25:55 3.9125 +09:26:00 4.0177 +09:26:05 4.0074 +09:26:10 4.0639 +09:26:15 3.9969 +09:26:20 3.9355 +09:26:25 3.9460 +09:26:30 4.0225 +09:26:35 3.9444 +09:26:40 3.9885 +09:26:45 3.9520 +09:26:50 3.9252 +09:26:55 3.8318 +09:27:00 3.9500 +09:27:05 3.9884 +09:27:10 3.9043 +09:27:15 3.9582 +09:27:20 3.9076 +09:27:25 3.9684 +09:27:30 4.0209 +09:27:35 4.0364 +09:27:40 3.9894 +09:27:45 3.9853 +09:27:50 4.0116 +09:27:55 4.0085 +09:28:00 4.0179 +09:28:05 3.9244 +09:28:10 3.9808 +09:28:15 3.8864 +09:28:20 3.9076 +09:28:25 4.0409 +09:28:30 3.9916 +09:28:35 4.0585 +09:28:40 4.0840 +09:28:45 4.0490 +09:28:50 3.9851 +09:28:55 3.9885 +09:29:00 4.1232 +09:29:05 4.0850 +09:29:10 4.0292 +09:29:15 3.9309 +09:29:20 3.9597 +09:29:25 3.9522 +09:29:30 3.9379 +09:29:35 4.0095 +09:29:40 4.0190 +09:29:45 4.0249 +09:29:50 4.0412 +09:29:55 3.9565 +09:30:00 4.0236 +09:30:05 4.0018 +09:30:10 3.9787 +09:30:15 3.9928 +09:30:20 3.9974 +09:30:25 3.9451 +09:30:30 4.0004 +09:30:35 3.9485 +09:30:40 3.9685 +09:30:45 4.0494 +09:30:50 3.8650 +09:30:55 3.9053 +09:31:00 4.0077 +09:31:05 3.9653 +09:31:10 3.9742 +09:31:15 4.0010 +09:31:20 3.8874 +09:31:25 3.8892 +09:31:30 3.9428 +09:31:35 3.9144 +09:31:40 3.9430 +09:31:45 3.8940 +09:31:50 3.8977 +09:31:55 3.9750 +09:32:00 4.0103 +09:32:05 4.0475 +09:32:10 4.0435 +09:32:15 4.0587 +09:32:20 3.9976 +09:32:25 4.0013 +09:32:30 4.0503 +09:32:35 4.0356 +09:32:40 3.9835 +09:32:45 3.9023 +09:32:50 3.9678 +09:32:55 3.9503 +09:33:02 3.9728 +09:33:05 3.9769 +09:33:10 3.9422 +09:33:15 3.9545 +09:33:21 3.9696 +09:33:25 3.8915 +09:33:31 3.9039 +09:33:35 3.9445 +09:33:40 4.0206 +09:33:45 3.9472 +09:33:52 3.9385 +09:33:55 3.8471 +09:34:00 3.9455 +09:34:05 4.0128 +09:34:10 3.9719 +09:34:15 3.9362 +09:34:20 3.8932 +09:34:25 4.0424 +09:34:30 4.0974 +09:34:35 3.9899 +09:34:40 4.0433 +09:34:45 4.0237 +09:34:50 3.9966 +09:34:55 3.8746 +09:35:00 3.8128 +09:35:05 3.9183 +09:35:10 3.9684 +09:35:15 4.0538 +09:35:20 4.1515 +09:35:25 4.1264 +09:35:30 4.0369 +09:35:35 4.0213 +09:35:40 4.0043 +09:35:45 4.0158 +09:35:50 3.8874 +09:35:55 3.8374 +09:36:00 3.8926 +09:36:07 3.9555 +09:36:10 3.9158 +09:36:15 3.8723 +09:36:20 3.8382 +09:36:25 3.8439 +09:36:30 3.9041 +09:36:35 3.9704 +09:36:40 3.9511 +09:36:45 3.9337 +09:36:50 4.0467 +09:36:55 4.0334 +09:37:00 3.9430 +09:37:05 3.8771 +09:37:10 3.9500 +09:37:15 3.9846 +09:37:20 3.9649 +09:37:25 3.9022 +09:37:30 3.8949 +09:37:35 3.9527 +09:37:40 3.9218 +09:37:45 3.9184 +09:37:50 3.9804 +09:37:55 3.9053 +09:38:00 3.9329 +09:38:05 3.9465 +09:38:10 3.9204 +09:38:15 3.8679 +09:38:20 3.9099 +09:38:25 3.9964 +09:38:30 3.9820 +09:38:35 4.0495 +09:38:40 4.0729 +09:38:45 4.0411 +09:38:50 4.0335 +09:38:55 4.0293 +09:39:00 4.0594 +09:39:05 3.9820 +09:39:10 3.9536 +09:39:15 3.8824 +09:39:20 3.8979 +09:39:25 3.9119 +09:39:30 3.9845 +09:39:35 4.0669 +09:39:40 4.0154 +09:39:45 3.8817 +09:39:50 3.9392 +09:39:55 3.9675 +09:40:00 3.9735 +09:40:05 3.9735 +09:40:10 3.9781 +09:40:15 3.9865 +09:40:20 3.9901 +09:40:25 3.9914 +09:40:30 3.9495 +09:40:35 3.9514 +09:40:40 3.9518 +09:40:45 3.9480 +09:40:50 3.9451 +09:40:55 3.9441 +09:41:00 3.9600 +09:41:05 4.0559 +09:41:10 4.0028 +09:41:15 4.0028 +09:41:20 3.9576 +09:41:25 3.8866 +09:41:30 3.9163 +09:41:35 3.9252 +09:41:40 3.9763 +09:41:45 4.0747 +09:41:50 4.0355 +09:41:55 4.0340 +09:42:00 4.0756 +09:42:05 4.0985 +09:42:10 4.0372 +09:42:15 3.9845 +09:42:20 4.0437 +09:42:25 3.9746 +09:42:30 4.0273 +09:42:35 3.8792 +09:42:40 3.9676 +09:42:45 4.0374 +09:42:50 4.1033 +09:42:55 4.1044 +09:43:00 4.1182 +09:43:05 4.0746 +09:43:10 4.1441 +09:43:15 4.0915 +09:43:20 4.0743 +09:43:25 4.1226 +09:43:30 4.0927 +09:43:35 4.0978 +09:43:40 4.0538 +09:43:45 4.0307 +09:43:50 3.9976 +09:43:55 3.9155 +09:44:00 4.0192 +09:44:05 4.0911 +09:44:10 4.1070 +09:44:15 4.0718 +09:44:20 4.0149 +09:44:25 4.0042 +09:44:30 3.9882 +09:44:35 4.0548 +09:44:40 4.0148 +09:44:45 3.9106 +09:44:50 4.0067 +09:44:55 4.0710 +09:45:00 3.9924 +09:45:05 4.0026 +09:45:10 3.9525 +09:45:15 4.0169 +09:45:20 3.9477 +09:45:25 3.9071 +09:45:30 3.9583 +09:45:35 3.9589 +09:45:40 3.9991 +09:45:45 4.0727 +09:45:50 4.0091 +09:45:55 3.9534 +09:46:00 4.0820 +09:46:05 4.1160 +09:46:10 4.0894 +09:46:15 4.0011 +09:46:20 3.9954 +09:46:25 3.9608 +09:46:30 3.9897 +09:46:35 3.9456 +09:46:40 3.9599 +09:46:45 3.9983 +09:46:50 4.0550 +09:46:55 4.0984 +09:47:00 4.0649 +09:47:05 4.0484 +09:47:10 3.9757 +09:47:15 3.9836 +09:47:20 4.0030 +09:47:25 4.0606 +09:47:30 4.0414 +09:47:35 4.0162 +09:47:40 4.0602 +09:47:45 4.0070 +09:47:50 4.1211 +09:47:55 4.0743 +09:48:00 4.0283 +09:48:05 4.1394 +09:48:10 4.2489 +09:48:15 4.1891 +09:48:20 4.1098 +09:48:25 4.0643 +09:48:30 4.0177 +09:48:35 3.9889 +09:48:40 4.0019 +09:48:45 4.1154 +09:48:50 4.1039 +09:48:55 4.0413 +09:49:00 4.0292 +09:49:05 4.0173 +09:49:10 4.0202 +09:49:15 4.0435 +09:49:20 4.0260 +09:49:25 4.0894 +09:49:30 4.0815 +09:49:35 4.1953 +09:49:40 4.1304 +09:49:45 4.1109 +09:49:50 4.0761 +09:49:55 4.0359 +09:50:00 3.9914 +09:50:05 4.0975 +09:50:10 4.1445 +09:50:15 4.1314 +09:50:20 4.0451 +09:50:25 4.0479 +09:50:30 4.0062 +09:50:35 4.0001 +09:50:40 4.0693 +09:50:45 4.1258 +09:50:50 4.0258 +09:50:55 4.0563 +09:51:00 4.1786 +09:51:05 4.0785 +09:51:10 4.0746 +09:51:15 4.0489 +09:51:20 3.9864 +09:51:25 4.0283 +09:51:30 4.0087 +09:51:35 4.0923 +09:51:40 4.1493 +09:51:45 4.1672 +09:51:50 4.0838 +09:51:55 4.0516 +09:52:00 4.0783 +09:52:05 4.1618 +09:52:10 4.1663 +09:52:15 4.0433 +09:52:20 4.0241 +09:52:25 3.9010 +09:52:30 3.9354 +09:52:35 4.0255 +09:52:40 4.0281 +09:52:45 4.0441 +09:52:50 4.0796 +09:52:55 4.1222 +09:53:00 4.0795 +09:53:05 4.0863 +09:53:10 4.1284 +09:53:15 4.1350 +09:53:20 4.1341 +09:53:25 4.1147 +09:53:30 4.1407 +09:53:35 4.1428 +09:53:40 4.1368 +09:53:45 4.1213 +09:53:50 4.0971 +09:53:55 3.9504 +09:54:00 3.9375 +09:54:05 4.0359 +09:54:10 4.0653 +09:54:15 4.0977 +09:54:20 4.0772 +09:54:25 4.1851 +09:54:30 4.2068 +09:54:35 4.1559 +09:54:40 4.1528 +09:54:45 4.1780 +09:54:50 4.1068 +09:54:55 4.0843 +09:55:00 4.0484 +09:55:05 4.0639 +09:55:10 4.1047 +09:55:15 4.0662 +09:55:20 3.9734 +09:55:25 3.9199 +09:55:30 4.0582 +09:55:35 4.1753 +09:55:40 4.2284 +09:55:45 4.1133 +09:55:50 4.0931 +09:55:55 4.0467 +09:56:00 4.0667 +09:56:05 4.1194 +09:56:10 4.0805 +09:56:15 4.0952 +09:56:20 4.1551 +09:56:25 4.2370 +09:56:30 4.1593 +09:56:35 4.0834 +09:56:40 4.1003 +09:56:45 4.1730 +09:56:50 4.1709 +09:56:55 4.1149 +09:57:00 4.1200 +09:57:05 4.1790 +09:57:10 4.1433 +09:57:15 4.1328 +09:57:20 4.0720 +09:57:25 4.1192 +09:57:30 4.1593 +09:57:35 4.1201 +09:57:40 4.0631 +09:57:46 4.0085 +09:57:50 4.0861 +09:57:55 4.0710 +09:58:00 4.1447 +09:58:05 4.1334 +09:58:10 4.1315 +09:58:15 4.1230 +09:58:20 4.2004 +09:58:25 4.2006 +09:58:30 4.0918 +09:58:35 4.0489 +09:58:40 4.1218 +09:58:46 4.1397 +09:58:50 4.1492 +09:58:55 4.2171 +09:59:00 4.1661 +09:59:05 4.1092 +09:59:10 4.0616 +09:59:15 4.0564 +09:59:20 4.0529 +09:59:25 4.1183 +09:59:30 4.1689 +09:59:35 4.1584 +09:59:40 4.1458 +09:59:45 4.0754 +09:59:50 4.0178 +09:59:55 4.0501 +10:00:00 4.1977 +10:00:05 4.2674 +10:00:10 4.1983 +10:00:15 4.0753 +10:00:20 3.9931 +10:00:25 4.0636 +10:00:30 4.0834 +10:00:45 4.0694 +10:00:50 4.1598 +10:00:55 4.1347 +10:01:00 4.1412 +10:01:05 4.1510 +10:01:10 4.1470 +10:01:15 4.0717 +10:01:20 4.0523 +10:01:25 4.2238 +10:01:30 4.1766 +10:01:35 4.1164 +10:01:40 4.1662 +10:01:45 4.1937 +10:01:50 4.1156 +10:01:55 4.0887 +10:02:00 4.2136 +10:02:05 4.1548 +10:02:12 4.1868 +10:02:15 4.1844 +10:02:20 4.1122 +10:02:25 4.0962 +10:02:30 4.0991 +10:02:35 4.0933 +10:02:42 4.2038 +10:02:45 4.1918 +10:02:50 4.1831 +10:02:55 4.0717 +10:03:00 4.0739 +10:03:05 4.0588 +10:03:10 4.1502 +10:03:15 4.1033 +10:03:21 4.1834 +10:03:25 4.1737 +10:03:30 4.2225 +10:03:35 4.0744 +10:03:40 4.0806 +10:03:45 4.1095 +10:03:50 4.1095 +10:03:55 4.1157 +10:04:00 4.0868 +10:04:05 4.1876 +10:04:10 4.2363 +10:04:15 4.2441 +10:04:20 4.2084 +10:04:25 4.0711 +10:04:30 4.0777 +10:04:35 4.0843 +10:04:40 4.0911 +10:04:45 4.0911 +10:04:50 4.0977 +10:04:55 4.1013 +10:05:00 4.1850 +10:05:05 4.2107 +10:05:10 4.1775 +10:05:15 4.2481 +10:05:22 4.1634 +10:05:25 4.2640 +10:05:30 4.2360 +10:05:35 4.2693 +10:05:40 4.3123 +10:05:45 4.2252 +10:05:50 4.2214 +10:05:55 4.2603 +10:06:00 4.2239 +10:06:05 4.1652 +10:06:10 4.1733 +10:06:18 4.3517 +10:06:21 4.3203 +10:06:25 4.3227 +10:06:30 4.3146 +10:06:35 4.3042 +10:06:40 4.2688 +10:06:46 4.3110 +10:06:50 4.3023 +10:06:55 4.3432 +10:07:00 4.3735 +10:07:05 4.3672 +10:07:10 4.3883 +10:07:15 4.2332 +10:07:20 4.2698 +10:07:25 4.2874 +10:07:30 4.3263 +10:07:35 4.3695 +10:07:40 4.3052 +10:07:45 4.2942 +10:07:51 4.3971 +10:07:55 4.4498 +10:08:00 4.4626 +10:08:05 4.4267 +10:08:10 4.4793 +#period 5 exact 1 isdst 1 +10:08:16 +10:08:20 undefined +10:08:25 4.5309 +10:08:30 4.4898 +10:08:35 4.4469 +10:08:40 4.4667 +10:08:45 4.4009 +10:08:50 4.4302 +10:08:55 4.4369 +10:09:00 4.4604 +10:09:05 4.4402 +10:09:10 4.4093 +10:09:15 4.3947 +10:09:20 4.4626 +10:09:25 4.4533 +10:09:30 4.5054 +10:09:35 4.6057 +10:09:40 4.5314 +10:09:45 4.5361 +10:09:50 4.5028 +10:09:55 4.5615 +10:10:00 4.6017 +10:10:05 4.5683 +10:10:10 4.5588 +10:10:15 4.5805 +10:10:20 4.5144 +10:10:25 4.4799 +10:10:30 4.5251 +10:10:35 4.5545 +10:10:40 4.5417 +10:10:45 4.5881 +10:10:50 4.6495 +10:10:55 4.6175 +10:11:00 4.5833 +10:11:05 4.5402 +10:11:10 4.6276 +10:11:15 4.6846 +10:11:20 4.6756 +10:11:25 4.6362 +10:11:31 4.7040 +10:11:35 4.7006 +10:11:40 4.7173 +10:11:45 4.6859 +10:11:50 4.7699 +10:11:55 4.8866 +10:12:00 4.8699 +10:12:05 4.7715 +10:12:11 4.9611 +10:12:15 4.9410 +10:12:20 4.9797 +10:12:25 4.9349 +10:12:30 5.0345 +10:12:35 5.1417 +10:12:40 5.0372 +10:12:45 5.0190 +10:12:50 5.1549 +10:12:55 4.9726 +10:13:00 4.8602 +10:13:05 4.9784 +10:13:10 4.8996 +10:13:15 4.8955 +10:13:20 4.7904 +10:13:25 4.6539 +10:13:30 4.7712 +10:13:35 4.6408 +10:13:40 4.0118 +10:13:45 4.2130 +10:13:50 3.9624 +10:13:55 3.8323 +10:14:00 3.8840 +10:14:05 3.7873 +10:14:12 3.7908 +10:14:15 3.7038 +10:14:20 3.8138 +10:14:25 3.6026 +10:14:30 3.4014 +10:14:37 3.0824 +10:14:40 3.1093 +10:14:45 3.0469 +10:14:50 3.0370 +10:14:55 2.9698 +10:15:02 2.9821 +10:15:05 2.9281 +10:15:10 2.9533 +10:15:16 2.7299 +10:15:20 2.8013 +10:15:25 2.7915 +10:15:30 2.7123 +10:15:37 2.7727 +10:15:40 2.6613 +10:15:45 2.6136 +10:15:50 2.5886 +10:15:55 2.5668 +10:16:01 2.5513 +10:16:06 2.5195 +10:16:10 2.5175 +10:16:16 2.4045 +10:16:21 2.3603 +10:16:25 2.3563 +10:16:30 2.3686 +10:16:35 2.2853 +10:16:40 2.2018 +10:16:45 2.1908 +10:16:51 2.1988 +10:16:56 2.1741 +10:17:00 2.1728 +10:17:05 2.1435 +10:17:10 2.0850 +10:17:15 2.0945 +10:17:20 2.0995 +10:17:25 2.1094 +10:17:30 2.0759 +10:17:35 2.0773 +10:17:40 2.0447 +10:17:45 1.9825 +10:17:50 2.0116 +10:17:55 2.0028 +10:18:00 1.9688 +10:18:05 2.0344 +10:18:10 1.9971 +10:18:15 1.8735 +10:18:20 1.8866 +10:18:25 1.9595 +10:18:30 1.9283 +10:18:36 1.8870 +10:18:40 1.8669 +10:18:45 1.8315 +10:18:50 1.8762 +10:18:55 1.8520 +10:19:00 1.7964 +10:19:05 1.7248 +10:19:10 1.7084 +10:19:15 1.7557 +10:19:20 1.7257 +10:19:25 1.7357 +10:19:30 1.6880 +10:19:35 1.7390 +10:19:40 1.7337 +10:19:45 1.6693 +10:19:50 1.6945 +10:19:55 1.6755 +10:20:00 1.6237 +10:20:05 1.6217 +10:20:10 1.6092 +10:20:15 1.6295 +10:20:20 1.6135 +10:20:25 1.6078 +10:20:30 1.6020 +10:20:35 1.6016 +10:20:40 1.5988 +10:20:45 1.5802 +10:20:50 1.6069 +10:20:55 1.6013 +10:21:00 1.6061 +10:21:05 1.5960 +10:21:11 1.5893 +10:21:15 1.5743 +10:21:20 1.5583 +10:21:25 1.5448 +10:21:30 1.5502 +10:21:35 1.5512 +10:21:40 1.5029 +10:21:45 1.5095 +10:21:50 1.4845 +10:21:55 1.4593 +10:22:00 1.4726 +10:22:05 1.4739 +10:22:10 1.4852 +10:22:15 1.4988 +10:22:20 1.4806 +10:22:25 1.4789 +10:22:30 1.4713 +10:22:35 1.4371 +10:22:40 1.4391 +10:22:45 1.4764 +10:22:50 1.5071 +10:22:55 1.4604 +10:23:00 1.4464 +10:23:05 1.4523 +10:23:10 1.4435 +10:23:15 1.4598 +10:23:20 1.4583 +10:23:25 1.4309 +10:23:30 1.4178 +10:23:35 1.4097 +10:23:40 1.4047 +10:23:45 1.4366 +10:23:50 1.4170 +10:23:55 1.4189 +10:24:00 1.3959 +10:24:05 1.3850 +10:24:10 1.3815 +10:24:15 1.3833 +10:24:20 1.3898 +10:24:28 1.4062 +10:24:30 1.4138 +10:24:35 1.4155 +10:24:40 1.4018 +10:24:46 1.3788 +10:24:50 1.3887 +10:24:55 1.3709 +10:25:07 1.3212 +10:25:10 1.3345 +10:25:15 1.3373 +10:25:20 1.3470 +10:25:25 1.3533 +10:25:30 1.3266 +10:25:35 1.3014 +10:25:40 1.3064 +10:25:45 1.3088 +10:25:50 1.3298 +10:25:55 1.3265 +10:26:00 1.3176 +10:26:05 1.3095 +10:26:10 1.3285 +10:26:15 1.3067 +10:26:20 1.3128 +10:26:25 1.3157 +10:26:30 1.3198 +10:26:35 1.3351 +10:26:40 1.3204 +10:26:45 1.3256 +10:26:50 1.3135 +10:26:55 1.2743 +10:27:00 1.2764 +10:27:05 1.3021 +10:27:10 1.2929 +10:27:15 1.2802 +10:27:20 1.2837 +10:27:25 1.2751 +10:27:30 1.2797 +10:27:35 1.2815 +10:27:40 1.2969 +10:27:45 1.2695 +10:27:50 1.2570 +10:27:55 1.2657 +10:28:00 1.2556 +10:28:05 1.2593 +10:28:10 1.2378 +10:28:15 1.2661 +10:28:20 1.2492 +10:28:25 1.2548 +10:28:30 1.2944 +10:28:35 1.2595 +10:28:40 1.2985 +10:28:45 1.3029 +10:28:50 1.3073 +10:28:55 1.2707 +10:29:00 1.2547 +10:29:05 1.2262 +10:29:10 1.2370 +10:29:15 1.2449 +10:29:20 1.2542 +10:29:25 1.2477 +10:29:30 1.2694 +10:29:35 1.2559 +10:29:40 1.2441 +10:29:45 1.2658 +10:29:50 1.2425 +10:29:55 1.2307 +10:30:00 1.2271 +10:30:05 1.2296 +10:30:10 1.2629 +10:30:15 1.2348 +10:30:20 1.2277 +10:30:25 1.2394 +10:30:30 1.2062 +10:30:35 1.1937 +10:30:40 1.2118 +10:30:45 1.2176 +10:30:50 1.2219 +10:30:55 1.2156 +10:31:00 1.2225 +10:31:05 1.2177 +10:31:10 1.2405 +10:31:15 1.2575 +10:31:20 1.2432 +10:31:25 1.2235 +10:31:30 1.2277 +10:31:35 1.2281 +10:31:40 1.2086 +10:31:45 1.2086 +10:31:50 1.2286 +10:32:05 1.2398 +10:32:10 1.2044 +10:32:15 1.2039 +10:32:20 1.1998 +10:32:25 1.2254 +10:32:30 1.2332 +10:32:35 1.2403 +10:32:40 1.2338 +10:32:45 1.2160 +10:32:50 1.2091 +10:32:55 1.2151 +10:33:00 1.2040 +10:33:05 1.2147 +10:33:10 1.2183 +10:33:15 1.2197 +10:33:20 1.2240 +10:33:25 1.2205 +10:33:30 1.1993 +10:33:35 1.2179 +10:33:40 1.2217 +10:33:45 1.2175 +10:33:50 1.2162 +10:33:55 1.2168 +10:34:00 1.2218 +10:34:05 1.2217 +10:34:10 1.2016 +10:34:15 1.2193 +10:34:20 1.2085 +10:34:25 1.2214 +10:34:30 1.1953 +10:34:35 1.1889 +10:34:40 1.2015 +10:34:45 1.1777 +10:34:50 1.1770 +10:34:55 1.1864 +10:35:00 1.1965 +10:35:05 1.2061 +10:35:10 1.1853 +10:35:15 1.1827 +10:35:20 1.1663 +10:35:25 1.1647 +10:35:30 1.1472 +10:35:35 1.1622 +10:35:40 1.1622 +10:35:45 1.1618 +10:35:50 1.1602 +10:35:55 1.1596 +10:36:00 1.1582 +10:36:05 1.1554 +10:36:10 1.1554 +10:36:15 1.1543 +10:36:20 1.1524 +10:36:25 1.1500 +10:36:30 1.1475 +10:36:35 1.1467 +10:36:40 1.1467 +10:36:45 1.1441 +10:36:50 1.1424 +10:36:55 1.1390 +10:37:00 1.1365 +10:37:05 1.1365 +10:37:10 1.1349 +10:37:15 1.1324 +10:37:20 1.1300 +10:37:25 1.1276 +10:37:30 1.1245 +10:37:35 1.1233 +10:37:40 1.1233 +10:37:45 1.1225 +10:37:50 1.1191 +10:37:55 1.1180 +10:38:00 1.1145 +10:38:05 1.1145 +10:38:10 1.1113 +10:38:15 1.1082 +10:38:20 1.1069 +10:38:25 1.1015 +10:38:30 1.0979 +10:38:35 1.0979 +10:38:40 1.0936 +10:38:45 1.0879 +10:38:50 1.0828 +10:38:55 1.0792 +10:39:00 1.0729 +10:39:05 1.0729 +10:39:10 1.0676 +10:39:15 1.0605 +10:39:22 1.0539 +10:39:26 1.0467 +10:39:30 0.84536 +10:39:35 0.74483 +10:39:40 0.75113 +10:39:45 0.74009 +10:39:50 0.73113 +10:39:55 0.72446 +10:40:00 0.72089 +10:40:05 0.71807 +10:40:10 0.70345 +10:40:15 0.70250 +10:40:20 0.69386 +10:40:25 0.68588 +10:40:30 0.66583 +10:40:35 0.65567 +10:40:40 0.65210 +10:40:45 0.64048 +10:40:50 0.63952 +10:40:55 0.62747 +10:41:00 0.62174 +10:41:05 0.61403 +10:41:10 0.60431 +10:41:15 0.60070 +10:41:20 0.59183 +10:41:25 0.58700 +10:41:30 0.57518 +10:41:35 0.56262 +10:41:40 0.55496 +10:41:45 0.55109 +10:41:50 0.53962 +10:41:55 0.53210 +10:42:00 0.52577 +10:42:05 0.52365 +10:42:10 0.51646 +10:42:15 0.50681 +10:42:20 0.49762 +10:42:25 0.49408 +10:42:30 0.48980 +10:42:35 0.48224 +10:42:40 0.47788 +10:42:45 0.47288 +10:42:50 0.46190 +10:42:55 0.45356 +10:43:00 0.44897 +10:43:05 0.44388 +10:43:10 0.43695 +10:43:15 0.43316 +10:43:20 0.42751 +10:43:25 0.42078 +10:43:30 0.41658 +10:43:35 0.41287 +10:43:40 0.40774 +10:43:45 0.40262 +10:43:50 0.39624 +10:43:55 0.38923 +10:44:00 0.38594 +10:44:05 0.38164 +10:44:10 0.37612 +10:44:15 0.37139 +10:44:20 0.36717 +10:44:25 0.36472 +10:44:30 0.36209 +10:44:35 0.35429 +10:44:41 0.35104 +10:44:45 0.35039 +10:44:51 0.34263 +10:44:55 0.34034 +10:45:00 0.33901 +10:45:05 0.33084 +10:45:10 0.32455 +10:45:15 0.32082 +10:45:20 0.31893 +10:45:25 0.31708 +10:45:30 0.31320 +10:45:36 0.30916 +10:45:40 0.30400 +10:45:45 0.30150 +10:45:50 0.29944 +10:45:55 0.29693 +10:46:00 0.29333 +10:46:05 0.28846 +10:46:10 0.28612 +10:46:15 0.28194 +10:46:20 0.27922 +10:46:25 0.27704 +10:46:30 0.27601 +10:46:35 0.27250 +10:46:40 0.27030 +10:46:45 0.26873 +10:46:50 0.26542 +10:46:55 0.26364 +10:47:13 0.26133 +10:47:15 0.25953 +10:47:20 0.25731 +10:47:25 0.25488 +10:47:30 0.25295 +10:47:35 0.25086 +10:47:40 0.24804 +10:47:45 0.24557 +10:47:50 0.24362 +10:47:55 0.24290 +10:48:00 0.23928 +10:48:05 0.23789 +10:48:10 0.23654 +10:48:15 0.23578 +10:48:20 0.23481 +10:48:25 0.23269 +10:48:30 0.23017 +10:48:36 0.22944 +10:48:40 0.22824 +10:48:45 0.22601 +10:48:50 0.22445 +10:48:55 0.22392 +10:49:00 0.22162 +10:49:05 0.22056 +10:49:10 0.21970 +10:49:15 0.21829 +10:49:20 0.21726 +10:49:25 0.21563 +10:49:30 0.21467 +10:49:35 0.21332 +10:49:40 0.21325 +10:49:45 0.21151 +10:49:50 0.20937 +10:49:55 0.20929 +10:50:00 0.20912 +10:50:05 0.20758 +10:50:10 0.20683 +10:50:45 0.20683 +10:50:50 0.20361 +10:50:55 0.19867 +10:51:00 0.20091 +10:51:05 0.19896 +10:51:10 0.19481 +10:51:15 0.19445 +10:51:20 0.19477 +10:51:25 0.19518 +10:51:30 0.19576 +10:51:35 0.19480 +10:51:40 0.19300 +10:51:45 0.19219 +10:51:50 0.19360 +10:51:55 0.19238 +10:52:00 0.19138 +10:52:05 0.19190 +10:52:10 0.19302 +10:52:15 0.18943 +10:52:20 0.18850 +10:52:25 0.19098 +10:52:30 0.18732 +10:52:35 0.18793 +10:52:40 0.18731 +10:52:45 0.18768 +10:52:50 0.18947 +10:52:55 0.18657 +10:53:00 0.18429 +10:53:05 0.18504 +10:53:10 0.18570 +10:53:15 0.18377 +10:53:20 0.18366 +10:53:26 0.18473 +10:53:30 0.18327 +10:53:35 0.18286 +10:53:40 0.18259 +10:53:45 0.18108 +10:53:50 0.18386 +10:53:55 0.18327 +10:54:00 0.18113 +10:54:05 0.18104 +10:54:10 0.17978 +10:54:15 0.18180 +10:54:20 0.18140 +10:54:25 0.17852 +10:54:30 0.17879 +10:54:35 0.17776 +10:54:40 0.17910 +10:54:45 0.17814 +10:54:50 0.17834 +10:54:55 0.17832 +10:55:00 0.17793 +10:55:05 0.17900 +10:55:10 0.17671 +10:55:15 0.17583 +10:55:20 0.17775 +10:55:25 0.17560 +10:55:30 0.17490 +10:55:35 0.17670 +10:55:40 0.17595 +10:55:45 0.17613 +10:55:50 0.17471 +10:55:55 0.17515 +10:56:00 0.17577 +10:56:05 0.17558 +10:56:10 0.17623 +10:56:15 0.17700 +10:56:20 0.17579 +10:56:25 0.17303 +10:56:30 0.17407 +10:56:35 0.17452 +10:56:40 0.17587 +10:56:45 0.17579 +10:56:50 0.17391 +10:56:55 0.17416 +10:57:00 0.17470 +10:57:05 0.17509 +10:57:10 0.17758 +10:57:15 0.17691 +10:57:20 0.17655 +10:57:25 0.17521 +10:57:30 0.17390 +10:57:35 0.17355 +10:57:40 0.17325 +10:57:45 0.17285 +10:57:50 0.17206 +10:57:55 0.17371 +10:58:00 0.17464 +10:58:05 0.17539 +10:58:10 0.17357 +10:58:15 0.17354 +10:58:20 0.17328 +10:58:25 0.17219 +10:58:30 0.17345 +10:58:35 0.17295 +10:58:40 0.17402 +10:58:45 0.17367 +10:58:50 0.17251 +10:58:55 0.17370 +10:59:00 0.17298 +10:59:05 0.17233 +10:59:10 0.17306 +10:59:15 0.17183 +10:59:20 0.17074 +10:59:25 0.17206 +10:59:30 0.17406 +10:59:35 0.17503 +10:59:42 0.17345 +10:59:45 0.17100 +10:59:50 0.17206 +10:59:55 0.17148 +11:00:00 0.17226 +11:00:05 0.17189 +11:00:10 0.17252 +11:00:15 0.17095 +11:00:20 0.17170 +11:00:25 0.17195 +11:00:30 0.17073 +11:00:35 0.17342 +11:00:40 0.17349 +11:00:45 0.17298 +11:00:50 0.17270 +11:00:55 0.17201 +11:01:00 0.17278 +11:01:05 0.17146 +11:01:10 0.17165 +11:01:15 0.17264 +11:01:20 0.17293 +11:01:25 0.17341 +11:01:30 0.17291 +11:01:35 0.17303 +11:01:40 0.17342 +11:01:45 0.17244 +11:01:50 0.17070 +11:01:55 0.16949 +11:02:00 0.17083 +11:02:05 0.17189 +11:02:10 0.17100 +11:02:15 0.17224 +11:02:20 0.17130 +11:02:25 0.17118 +11:02:30 0.17205 +11:02:35 0.17104 +11:02:40 0.17005 +11:02:45 0.17039 +11:02:50 0.17138 +11:02:55 0.17199 +11:03:00 0.17222 +11:03:05 0.17008 +11:03:10 0.17144 +11:03:15 0.17236 +11:03:20 0.17117 +11:03:25 0.17320 +11:03:30 0.17169 +11:03:35 0.17078 +11:03:40 0.16918 +11:03:45 0.16948 +11:03:50 0.16729 +11:03:55 0.17117 +11:04:00 0.17135 +11:04:05 0.17234 +11:04:10 0.17061 +11:04:15 0.17112 +11:04:20 0.17200 +11:04:25 0.17329 +11:04:30 0.17292 +11:04:35 0.17379 +11:04:40 0.17288 +11:04:45 0.17322 +11:04:50 0.17342 +11:04:55 0.17063 +11:05:00 0.17190 +11:05:05 0.17150 +11:05:10 0.17237 +11:05:15 0.17141 +11:05:20 0.17062 +11:05:25 0.16872 +11:05:30 0.17156 +11:05:35 0.17223 +11:05:40 0.17161 +11:05:45 0.16884 +11:05:50 0.17009 +11:05:55 0.17003 +11:06:00 0.16997 +11:06:05 0.16861 +11:06:10 0.16865 +11:06:15 0.16881 +11:06:20 0.16837 +11:06:25 0.16955 +11:06:30 0.16943 +11:06:35 0.16899 +11:06:40 0.17035 +11:06:45 0.16953 +11:06:50 0.16769 +11:06:55 0.16894 +11:07:00 0.17079 +11:07:05 0.17013 +11:07:10 0.16827 +11:07:15 0.16696 +11:07:20 0.16713 +11:07:25 0.17030 +11:07:30 0.16981 +11:07:35 0.17028 +11:07:40 0.17114 +11:07:45 0.17002 +11:07:50 0.16801 +11:07:55 0.16763 +11:08:00 0.16885 +11:08:05 0.16950 +11:08:10 0.16966 +11:08:15 0.16711 +11:08:20 0.16819 +11:08:25 0.16835 +11:08:30 0.16825 +11:08:35 0.16766 +11:08:40 0.16834 +11:08:45 0.16834 +11:08:50 0.16887 +11:08:55 0.16744 +11:09:00 0.16829 +11:09:05 0.16791 +11:09:10 0.16852 +11:09:15 0.16674 +11:09:20 0.16763 +11:09:25 0.16774 +11:09:30 0.16982 +11:09:35 0.16970 +11:09:40 0.16953 +11:09:45 0.16923 +11:09:50 0.16882 +11:09:55 0.16741 +11:10:00 0.16742 +11:10:05 0.16757 +11:10:10 0.16716 +11:10:15 0.16858 +11:10:20 0.16842 +11:10:25 0.16707 +11:10:30 0.16772 +11:10:35 0.16719 +11:10:40 0.16849 +11:10:45 0.17013 +11:10:50 0.16863 +11:10:55 0.16834 +11:11:00 0.16861 +11:11:05 0.16860 +11:11:10 0.17049 +11:11:15 0.16984 +11:11:20 0.16889 +11:11:25 0.16696 +11:11:30 0.16720 +11:11:35 0.16795 +11:11:40 0.16761 +11:11:45 0.16731 +11:11:50 0.16815 +11:11:55 0.16858 +11:12:00 0.16598 +11:12:05 0.16389 +11:12:10 0.16437 +11:12:15 0.16605 +11:12:20 0.16766 +11:12:25 0.16852 +11:12:30 0.16975 +11:12:35 0.16718 +11:12:40 0.16852 +11:12:45 0.16623 +11:12:50 0.16528 +11:12:55 0.16771 +11:13:00 0.16789 +11:13:05 0.16746 +11:13:10 0.16804 +11:13:15 0.16724 +11:13:20 0.16721 +11:13:25 0.16864 +11:13:30 0.16929 +11:13:35 0.16842 +11:13:40 0.16849 +11:13:45 0.16800 +11:13:50 0.16834 +11:13:55 0.16788 +11:14:00 0.16716 +11:14:05 0.16872 +11:14:10 0.16797 +11:14:15 0.16766 +11:14:20 0.16801 +11:14:25 0.16852 +11:14:30 0.16771 +11:14:35 0.16969 +11:14:40 0.17053 +11:14:45 0.16788 +11:14:50 0.16806 +11:14:55 0.17059 +11:15:00 0.16848 +11:15:05 0.16675 +11:15:10 0.16590 +11:15:15 0.16748 +11:15:20 0.16795 +11:15:25 0.16861 +11:15:30 0.16923 +11:15:35 0.16723 +11:15:40 0.16869 +11:15:45 0.16887 +11:15:50 0.16936 +11:15:55 0.16794 +11:16:00 0.16773 +11:16:05 0.16881 +11:16:10 0.16798 +11:16:15 0.16671 +11:16:20 0.16740 +11:16:26 0.16839 +11:16:30 0.16834 +11:16:35 0.16775 +11:16:40 0.16933 +11:16:46 0.17123 +11:16:50 0.16948 +11:16:55 0.16880 +11:17:00 0.17043 +11:17:05 0.16880 +11:17:10 0.16783 +11:17:15 0.16921 +11:17:20 0.16759 +11:17:25 0.16682 +11:17:30 0.16761 +11:17:36 0.16722 +11:17:40 0.16778 +11:17:45 0.16816 +11:17:50 0.16604 +11:17:55 0.16583 +11:18:02 0.16627 +11:18:07 0.16714 +11:18:10 0.16747 +11:18:15 0.16686 +11:18:20 0.16604 +11:18:25 0.16638 +11:18:30 0.16838 +11:18:35 0.16923 +11:18:40 0.16864 +11:18:45 0.16720 +11:18:50 0.16739 +11:18:55 0.16785 +11:19:00 0.16762 +11:19:05 0.16838 +11:19:10 0.16712 +11:19:15 0.16734 +11:19:20 0.16841 +11:19:25 0.16940 +11:19:30 0.16815 +11:19:35 0.16607 +11:19:40 0.16655 +11:19:45 0.16817 +11:19:50 0.16744 +11:19:55 0.16822 +11:20:00 0.16871 +11:20:06 0.16801 +11:20:11 0.16741 +11:20:15 0.16816 +11:20:20 0.16876 +11:20:25 0.16859 +11:20:30 0.16689 +11:20:35 0.16718 +11:20:40 0.16904 +11:20:45 0.16991 +11:20:50 0.16842 +11:20:55 0.16692 +11:21:01 0.17043 +11:21:05 0.16805 +11:21:10 0.16636 +11:21:15 0.16793 +11:21:20 0.16950 +11:21:26 0.16994 +11:21:30 0.16887 +11:21:35 0.16761 +11:21:41 0.16704 +11:21:45 0.16595 +11:21:50 0.16655 +11:22:06 0.16854 +11:22:10 0.16860 +11:22:15 0.16760 +11:22:20 0.16762 +11:22:25 0.16694 +11:22:30 0.16717 +11:22:35 0.16594 +11:22:40 0.16646 +11:22:45 0.16853 +11:22:50 0.16712 +11:22:55 0.16666 +11:23:00 0.16712 +11:23:05 0.16726 +11:23:10 0.16805 +11:23:15 0.16821 +11:23:20 0.16831 +11:23:25 0.16886 +11:23:30 0.16968 +11:23:35 0.16924 +11:23:40 0.16925 +11:23:45 0.16800 +11:23:50 0.16708 +11:23:56 0.16636 +11:24:00 0.16582 +11:24:05 0.16608 +11:24:10 0.16755 +11:24:15 0.16837 +11:24:24 0.16679 +11:24:25 0.16745 +11:24:30 0.16763 +11:24:35 0.16793 +11:24:40 0.16724 +11:24:46 0.16732 +11:24:50 0.16937 +11:24:56 0.16865 +#period 5 exact 1 isdst 1 +11:25:02 +11:25:08 undefined +11:25:10 0.16569 +11:25:15 0.16780 +11:25:20 0.16914 +11:25:25 0.16709 +11:25:30 0.16637 +11:25:42 0.16662 +11:25:45 0.16746 +11:25:50 0.16715 +11:25:55 0.16675 +11:26:00 0.16642 +11:26:05 0.16650 +11:26:10 0.16836 +11:26:15 0.16760 +11:26:20 0.16687 +11:26:25 0.16660 +11:26:30 0.16597 +11:26:35 0.16758 +11:26:40 0.16734 +11:26:45 0.16683 +11:26:50 0.16935 +11:26:55 0.16817 +11:27:00 0.16830 +11:27:05 0.17000 +11:27:10 0.16855 +11:27:15 0.16712 +11:27:20 0.16844 +11:27:25 0.16978 +11:27:30 0.16931 +11:27:35 0.17017 +11:27:40 0.16953 +11:27:45 0.16890 +11:27:50 0.16699 +11:27:55 0.16745 +11:28:00 0.16577 +11:28:05 0.16523 +11:28:10 0.16571 +11:28:15 0.16856 +11:28:20 0.16771 +11:28:25 0.16680 +11:28:30 0.16751 +11:28:35 0.16886 +11:28:40 0.16900 +11:28:45 0.16960 +11:28:50 0.16849 +11:28:55 0.16824 +11:29:00 0.16911 +11:29:05 0.16797 +11:29:10 0.16759 +11:29:15 0.16819 +11:29:20 0.16609 +11:29:25 0.16441 +11:29:30 0.16637 +11:29:35 0.16731 +11:29:40 0.16724 +11:29:45 0.16788 +11:29:50 0.16833 +11:29:55 0.16854 +11:30:00 0.16597 +11:30:05 0.16670 +11:30:10 0.16639 +11:30:15 0.16540 +11:30:20 0.16672 +11:30:25 0.16862 +11:30:30 0.16860 +11:30:35 0.16610 +11:30:40 0.16525 +11:30:45 0.16755 +11:30:50 0.16710 +11:30:55 0.16703 +11:31:00 0.16640 +11:31:05 0.16715 +11:31:10 0.16835 +11:31:15 0.16808 +11:31:20 0.16869 +11:31:25 0.16671 +11:31:30 0.16719 +11:31:35 0.16659 +11:31:40 0.16743 +11:31:45 0.16758 +11:31:50 0.16752 +11:31:55 0.16582 +11:32:00 0.16755 +11:32:05 0.16897 +11:32:10 0.16824 +11:32:15 0.16738 +11:32:20 0.16826 +11:32:25 0.16943 +11:32:30 0.16754 +11:32:35 0.16890 +11:32:40 0.16896 +11:32:45 0.16641 +#period 5 exact 1 isdst 1 +11:32:51 +11:32:54 undefined +11:32:55 0.16691 +11:33:00 0.16803 +11:33:05 0.16942 +11:33:10 0.16927 +11:33:15 0.16927 +11:33:20 0.16815 +11:33:25 0.16657 +11:33:30 0.16763 +#period 5 exact 1 isdst 1 +11:33:34 +11:33:36 undefined +11:33:40 0.16720 +11:33:45 0.16802 +11:33:50 0.16828 +11:33:55 0.16962 +11:34:00 0.16724 +11:34:05 0.18807 +11:34:10 0.26405 +11:34:15 0.29695 +11:34:20 0.28557 +11:34:25 0.27158 +11:34:30 0.26607 +11:34:35 0.25766 +11:34:40 0.24693 +11:34:45 0.24104 +11:34:50 0.23841 +11:34:55 0.23652 +11:35:00 0.22990 +11:35:05 0.22422 +11:35:10 0.22408 +11:35:15 0.22204 +11:35:20 0.21966 +11:35:25 0.21860 +11:35:30 0.21610 +11:35:35 0.21556 +11:35:40 0.21210 +11:35:45 0.21183 +11:35:50 0.20973 +11:35:55 0.20951 +11:36:00 0.20950 +11:36:05 0.20584 +11:36:10 0.20517 +11:36:15 0.20570 +11:36:20 0.20696 +11:36:25 0.20412 +11:36:30 0.20317 +11:36:35 0.20353 +11:36:40 0.20343 +11:36:45 0.20220 +11:36:50 0.20114 +11:36:55 0.19993 +11:37:00 0.19829 +11:37:05 0.21647 +11:37:19 0.24839 +11:37:20 0.25409 +11:37:25 0.30658 +11:37:30 0.31093 +11:37:35 0.30337 +11:37:40 0.28532 +11:37:45 0.27527 +11:37:50 0.26959 +11:37:55 0.26272 +11:38:00 0.29671 +11:38:05 0.37862 +11:38:10 0.40128 +11:38:15 0.38633 +11:38:20 0.37319 +11:38:25 0.36633 +11:38:30 0.36209 +11:38:35 0.34749 +11:38:40 0.33123 +11:38:45 0.32494 +11:38:50 0.31280 +11:38:55 0.30351 +11:39:00 0.30360 +11:39:05 0.29811 +11:39:10 0.28625 +11:39:15 0.28150 +11:39:20 0.27588 +11:39:25 0.27431 +11:39:30 0.27511 +11:39:35 0.26988 +11:39:40 0.26626 +11:39:45 0.26515 +11:39:50 0.26306 +11:39:55 0.25825 +11:40:00 0.25979 +11:40:05 0.25523 +11:40:10 0.25450 +11:40:15 0.24938 +11:40:20 0.24825 +11:40:25 0.24672 +11:40:30 0.24364 +11:40:35 0.24264 +11:40:40 0.24064 +11:40:45 0.24055 +11:40:50 0.24332 +11:40:55 0.23543 +11:41:00 0.23481 +11:41:05 0.23377 +11:41:10 0.23128 +11:41:15 0.23124 +11:41:20 0.23077 +11:41:25 0.23547 +11:41:30 0.24277 +11:41:35 0.23868 +11:41:40 0.24692 +11:41:45 0.24863 +11:41:50 0.24454 +11:41:55 0.24667 +11:42:00 0.24791 +11:42:05 0.24928 +11:42:10 0.25067 +11:42:15 0.25331 +11:42:20 0.25700 +11:42:25 0.25861 +11:42:30 0.25518 +11:42:35 0.25326 +11:42:40 0.26100 +11:42:45 0.26359 +11:42:50 0.26235 +11:42:55 0.26845 +11:43:00 0.26646 +11:43:05 0.26620 +11:43:10 0.26791 +11:43:15 0.26933 +11:43:20 0.27137 +11:43:25 0.27263 +11:43:30 0.27153 +11:43:35 0.27250 +11:43:40 0.27287 +11:43:45 0.27401 +11:43:50 0.27699 +11:43:55 0.27201 +11:44:00 0.27471 +11:44:05 0.28284 +11:44:10 0.28228 +11:44:15 0.27845 +11:44:20 0.27478 +11:44:25 0.27466 +11:44:30 0.27295 +11:44:35 0.27613 +11:44:40 0.28173 +11:44:45 0.28299 +11:44:50 0.28044 +11:44:55 0.28030 +11:45:00 0.28614 +11:45:05 0.27933 +11:45:10 0.28259 +11:45:15 0.28707 +11:45:20 0.28120 +11:45:25 0.28212 +11:45:30 0.29001 +11:45:35 0.29033 +11:45:40 0.29131 +11:45:45 0.28370 +11:45:50 0.28132 +11:45:55 0.28151 +11:46:00 0.28219 +11:46:05 0.28960 +11:46:10 0.29348 +11:46:15 0.29167 +11:46:20 0.29311 +11:46:25 0.28740 +11:46:30 0.28994 +11:46:35 0.28390 +11:46:40 0.28080 +11:46:45 0.28895 +11:46:50 0.28762 +11:46:55 0.28376 +11:47:00 0.28751 +11:47:05 0.28868 +11:47:10 0.29128 +11:47:15 0.28934 +11:47:20 0.29290 +11:47:25 0.29253 +11:47:30 0.28533 +11:47:35 0.28683 +11:47:40 0.28639 +11:47:45 0.28520 +11:47:50 0.29097 +11:47:55 0.29217 +11:48:00 0.29287 +11:48:05 0.29543 +11:48:10 0.29524 +11:48:15 0.29272 +11:48:20 0.29203 +11:48:25 0.29265 +11:48:30 0.28751 +11:48:35 0.29346 +11:48:40 0.29456 +11:48:45 0.28842 +11:48:50 0.29005 +11:48:55 0.29033 +11:49:00 0.29074 +11:49:05 0.28890 +11:49:10 0.28963 +11:49:15 0.29586 +11:49:20 0.29522 +11:49:25 0.28917 +11:49:30 0.29223 +11:49:35 0.29215 +11:49:40 0.29093 +11:49:45 0.29264 +11:49:50 0.28628 +11:49:55 0.28850 +11:50:00 0.29223 +11:50:05 0.29216 +11:50:10 0.28504 +11:50:15 0.28805 +11:50:20 0.28356 +11:50:25 0.28175 +11:50:30 0.28778 +11:50:35 0.28934 +11:50:40 0.28585 +11:50:45 0.28721 +11:50:50 0.28924 +11:50:55 0.28060 +11:51:00 0.28262 +11:51:05 0.28506 +11:51:10 0.28300 +11:51:15 0.28656 +11:51:20 0.28978 +11:51:25 0.28865 +11:51:30 0.28767 +11:51:35 0.28674 +11:51:40 0.28746 +11:51:45 0.29161 +11:51:50 0.28296 +11:51:55 0.28497 +11:52:00 0.28275 +11:52:05 0.28303 +11:52:10 0.28743 +11:52:15 0.28640 +11:52:20 0.28970 +11:52:25 0.28897 +11:52:30 0.29344 +11:52:35 0.29036 +11:52:40 0.28510 +11:52:45 0.28446 +11:52:50 0.28213 +11:52:55 0.28207 +11:53:00 0.28403 +11:53:05 0.28457 +11:53:10 0.28352 +11:53:15 0.28732 +11:53:20 0.29326 +11:53:25 0.29274 +11:53:30 0.28827 +11:53:35 0.28761 +11:53:40 0.28629 +11:53:45 0.29315 +11:53:50 0.28785 +11:53:55 0.28157 +11:54:00 0.28102 +11:54:05 0.28919 +11:54:10 0.28777 +11:54:15 0.28712 +11:54:20 0.28504 +11:54:25 0.29126 +11:54:30 0.29298 +11:54:35 0.28833 +11:54:40 0.28915 +11:54:45 0.28398 +11:54:50 0.28303 +11:54:55 0.29030 +11:55:00 0.28888 +11:55:05 0.29384 +11:55:10 0.29249 +11:55:15 0.28721 +11:55:20 0.28445 +11:55:25 0.28846 +11:55:30 0.28781 +11:55:35 0.28483 +11:55:40 0.28906 +11:55:45 0.28108 +11:55:50 0.27826 +11:55:55 0.27961 +11:56:00 0.28645 +11:56:05 0.28628 +11:56:10 0.27372 +11:56:15 0.27578 +11:56:20 0.28568 +11:56:25 0.29089 +11:56:30 0.28513 +11:56:35 0.28347 +11:56:40 0.28412 +11:56:45 0.28837 +11:56:50 0.29010 +11:56:55 0.28629 +11:57:00 0.28043 +11:57:05 0.27714 +11:57:10 0.28387 +11:57:15 0.28829 +11:57:20 0.28218 +11:57:25 0.28140 +11:57:30 0.28849 +11:57:35 0.28841 +11:57:40 0.28098 +11:57:45 0.28179 +11:57:50 0.28267 +11:57:55 0.28353 +11:58:00 0.28730 +11:58:05 0.28866 +11:58:10 0.28537 +11:58:15 0.28595 +11:58:20 0.28376 +11:58:25 0.28350 +11:58:30 0.28550 +11:58:35 0.28326 +11:58:40 0.27693 +11:58:45 0.28583 +11:58:50 0.28777 +11:58:55 0.28133 +11:59:00 0.28455 +11:59:05 0.27978 +11:59:10 0.28112 +11:59:15 0.28937 +11:59:20 0.29163 +11:59:25 0.28607 +11:59:30 0.27981 +11:59:35 0.28470 +11:59:40 0.28645 +11:59:45 0.28762 +11:59:50 0.28596 +11:59:55 0.28529 +12:00:00 0.28652 +12:00:05 0.28992 +12:00:10 0.28573 +12:00:15 0.28059 +12:00:20 0.27977 +12:00:25 0.28098 +12:00:30 0.28549 +12:00:35 0.28617 +12:00:40 0.28493 +12:00:45 0.28359 +12:00:58 0.27947 +12:01:00 0.28060 +12:01:05 0.27632 +12:01:10 0.28396 +12:01:15 0.28060 +12:01:20 0.28801 +12:01:25 0.28313 +12:01:30 0.28327 +12:01:35 0.27912 +12:01:40 0.28490 +12:01:45 0.28252 +12:01:50 0.27599 +12:01:55 0.27515 +12:02:00 0.27723 +12:02:05 0.28290 +12:02:10 0.28261 +12:02:15 0.28090 +12:02:20 0.28051 +12:02:25 0.28137 +12:02:30 0.28021 +12:02:35 0.28208 +12:02:40 0.28686 +12:02:45 0.28068 +12:02:50 0.28100 +12:02:55 0.27616 +12:03:00 0.28653 +12:03:05 0.28356 +12:03:10 0.28128 +12:03:15 0.27708 +12:03:20 0.28264 +12:03:25 0.28207 +12:03:30 0.28218 +12:03:35 0.28667 +12:03:40 0.28311 +12:03:45 0.27664 +12:03:50 0.28180 +12:03:55 0.28178 +12:04:00 0.27786 +12:04:05 0.27898 +12:04:10 0.27972 +12:04:15 0.28501 +12:04:20 0.28061 +12:04:25 0.28874 +12:04:30 0.28868 +12:04:35 0.28539 +12:04:40 0.28550 +12:04:45 0.28114 +12:04:50 0.29205 +12:04:55 0.28986 +12:05:00 0.28379 +12:05:05 0.28717 +12:05:10 0.28431 +12:05:15 0.28524 +12:05:20 0.28247 +12:05:25 0.28585 +12:05:30 0.28957 +12:05:35 0.28666 +12:05:40 0.28035 +12:05:45 0.28286 +12:05:50 0.28679 +12:05:55 0.28496 +12:06:00 0.28120 +12:06:05 0.27804 +12:06:10 0.27675 +12:06:15 0.28127 +12:06:20 0.28136 +12:06:25 0.27526 +12:06:30 0.27554 +12:06:35 0.27410 +12:06:40 0.27554 +12:06:45 0.28015 +12:06:50 0.28421 +12:06:55 0.28968 +12:07:00 0.28335 +12:07:05 0.27568 +12:07:10 0.27486 +12:07:15 0.27840 +12:07:20 0.28633 +12:07:25 0.29157 +12:07:30 0.28866 +12:07:35 0.28296 +12:07:40 0.27713 +12:07:45 0.27529 +12:07:50 0.27422 +12:07:55 0.27648 +12:08:00 0.27666 +12:08:05 0.28298 +12:08:10 0.28214 +12:08:15 0.28234 +12:08:20 0.27996 +12:08:25 0.28431 +12:08:30 0.28672 +12:08:35 0.28481 +12:08:40 0.28366 +12:08:45 0.29053 +12:08:50 0.28212 +12:08:55 0.27817 +12:09:00 0.28424 +12:09:05 0.28097 +12:09:10 0.28493 +12:09:15 0.28187 +12:09:20 0.28381 +12:09:25 0.27760 +12:09:30 0.28174 +12:09:35 0.28708 +12:09:40 0.28282 +12:09:45 0.28350 +12:09:50 0.27818 +12:09:55 0.27843 +12:10:00 0.28212 +12:10:05 0.27964 +12:10:10 0.27637 +12:10:15 0.27943 +12:10:20 0.28054 +12:10:25 0.28487 +12:10:30 0.28663 +12:10:35 0.28540 +12:10:40 0.28336 +12:10:45 0.28469 +12:10:50 0.28395 +12:10:55 0.28488 +12:11:00 0.28385 +12:11:05 0.27723 +12:11:10 0.27843 +12:11:15 0.27950 +12:11:20 0.27552 +12:11:25 0.28300 +12:11:30 0.28948 +12:11:35 0.28157 +12:11:40 0.27650 +12:11:45 0.27835 +12:11:50 0.27656 +12:11:56 0.28258 +12:12:00 0.28731 +12:12:05 0.28385 +12:12:10 0.27960 +12:12:15 0.27315 +12:12:20 0.27115 +12:12:25 0.26546 +12:12:30 0.25897 +12:12:35 0.25771 +12:12:40 0.25365 +12:12:45 0.25193 +12:12:50 0.24619 +12:12:55 0.24197 +12:13:00 0.23827 +12:13:05 0.23745 +12:13:10 0.23425 +12:13:15 0.23232 +12:13:20 0.23308 +12:13:25 0.22913 +12:13:30 0.22556 +12:13:35 0.22570 +12:13:40 0.22582 +12:13:45 0.22558 +12:13:50 0.22294 +12:13:55 0.22043 +12:14:00 0.21928 +12:14:05 0.21625 +12:14:10 0.21417 +12:14:15 0.21048 +12:14:20 0.20958 +12:14:25 0.21040 +12:14:30 0.21001 +12:14:35 0.21015 +12:14:40 0.20922 +12:14:45 0.20292 +12:14:50 0.20317 +12:14:55 0.20195 +12:15:00 0.20223 +12:15:05 0.20020 +12:15:10 0.20124 +12:15:15 0.20379 +12:15:20 0.20381 +12:15:25 0.20113 +12:15:30 0.19836 +12:15:35 0.19736 +12:15:40 0.19562 +12:15:45 0.19593 +12:15:50 0.19735 +12:15:55 0.19302 +12:16:00 0.19330 +12:16:12 0.19388 +12:16:15 0.19313 +12:16:20 0.19340 +12:16:25 0.19243 +12:16:30 0.19154 +12:16:35 0.19109 +12:16:40 0.19096 +12:16:45 0.19029 +12:16:50 0.18966 +12:16:55 0.18957 +12:17:00 0.18759 +12:17:05 0.18749 +12:17:10 0.18655 +12:17:15 0.18451 +12:17:20 0.18272 +12:17:25 0.18386 +12:17:30 0.18335 +12:17:35 0.18347 +12:17:40 0.18327 +12:17:45 0.18279 +12:17:50 0.18208 +12:17:55 0.18080 +12:18:00 0.17834 +12:18:05 0.17804 +12:18:10 0.18084 +12:18:15 0.18084 +12:18:20 0.17781 +12:18:25 0.17810 +12:18:30 0.18083 +12:18:35 0.17748 +12:18:40 0.17834 +12:18:45 0.17727 +12:18:50 0.17616 +12:18:55 0.17637 +12:19:00 0.17572 +12:19:05 0.17637 +12:19:10 0.17446 +12:19:15 0.17425 +12:19:20 0.17554 +12:19:25 0.17587 +12:19:30 0.17406 +12:19:35 0.17334 +12:19:40 0.17426 +12:19:45 0.17520 +12:19:50 0.17546 +12:19:55 0.17407 +12:20:00 0.17176 +12:20:05 0.17265 +12:20:10 0.17367 +12:20:15 0.17416 +12:20:20 0.17396 +12:20:25 0.17122 +12:20:30 0.17141 +12:20:35 0.17216 +12:20:40 0.17265 +12:20:45 0.17193 +12:20:50 0.17296 +12:20:55 0.17496 +12:21:00 0.17498 +12:21:05 0.17169 +12:21:10 0.17248 +12:21:15 0.17191 +12:21:20 0.17071 +12:21:25 0.17148 +12:21:30 0.17218 +12:21:35 0.17191 +12:21:40 0.17350 +12:21:45 0.17271 +12:21:50 0.17143 +12:21:55 0.16946 +12:22:00 0.16722 +12:22:05 0.17004 +12:22:10 0.16908 +12:22:15 0.17020 +12:22:20 0.17186 +12:22:25 0.16888 +12:22:30 0.16917 +12:22:35 0.16968 +12:22:40 0.17129 +12:22:45 0.17212 +12:22:50 0.17214 +12:22:55 0.17007 +12:23:00 0.16836 +12:23:05 0.16840 +12:23:10 0.16907 +12:23:15 0.16930 +12:23:20 0.17108 +12:23:25 0.17082 +12:23:30 0.17012 +12:23:35 0.16980 +12:23:40 0.16841 +12:23:45 0.16726 +12:23:50 0.16810 +12:23:55 0.16807 +12:24:00 0.16786 +12:24:05 0.16824 +12:24:10 0.17097 +12:24:15 0.16806 +12:24:20 0.16672 +12:24:25 0.16929 +12:24:30 0.17059 +12:24:35 0.16944 +12:24:40 0.16668 +12:24:45 0.16582 +12:24:50 0.16586 +12:24:55 0.16804 +12:25:00 0.16883 +12:25:05 0.16870 +12:25:10 0.16860 +12:25:15 0.16684 +12:25:20 0.16697 +12:25:25 0.16794 +12:25:30 0.16783 +12:25:35 0.16733 +12:25:40 0.16689 +12:25:45 0.16924 +12:25:50 0.16883 +12:25:55 0.16911 +12:26:00 0.17011 +12:26:05 0.16709 +12:26:10 0.16440 +12:26:15 0.16596 +12:26:20 0.16702 +12:26:25 0.16762 +12:26:30 0.16814 +12:26:35 0.16771 +12:26:40 0.16758 +12:26:45 0.16637 +12:26:50 0.16649 +12:26:55 0.16576 +12:27:00 0.16567 +12:27:05 0.16692 +12:27:10 0.16817 +12:27:15 0.16816 +12:27:20 0.16906 +12:27:25 0.16941 +12:27:30 0.16469 +12:27:35 0.16572 +12:27:40 0.16886 +12:27:45 0.16713 +12:27:50 0.16799 +12:27:55 0.16760 +12:28:00 0.16586 +12:28:05 0.16565 +12:28:10 0.16531 +12:28:15 0.16712 +12:28:20 0.16831 +12:28:25 0.16740 +12:28:30 0.16653 +12:28:35 0.16407 +12:28:40 0.16696 +12:28:45 0.16742 +12:28:50 0.16743 +12:28:55 0.16777 +12:29:00 0.16637 +12:29:05 0.16657 +12:29:10 0.16613 +12:29:15 0.16702 +12:29:20 0.16690 +12:29:25 0.16756 +12:29:30 0.16612 +12:29:35 0.16630 +12:29:40 0.16498 +12:29:45 0.16655 +12:29:50 0.16509 +12:29:55 0.16424 +12:30:00 0.16584 +12:30:05 0.16422 +12:30:10 0.16488 +12:30:15 0.16468 +12:30:20 0.16543 +12:30:25 0.16447 +12:30:30 0.16706 +12:30:35 0.16532 +12:30:40 0.16521 +12:30:45 0.16788 +12:30:50 0.16791 +12:30:55 0.16719 +12:31:00 0.16615 +12:31:05 0.16737 +12:31:10 0.16957 +12:31:15 0.16640 +12:31:20 0.16549 +12:31:25 0.16514 +12:31:30 0.16700 +12:31:35 0.16567 +12:31:40 0.16594 +12:31:45 0.16675 +12:31:50 0.16676 +12:31:55 0.16810 +12:32:00 0.16789 +12:32:05 0.16683 +12:32:10 0.16825 +12:32:15 0.16701 +12:32:20 0.16531 +12:32:25 0.16763 +12:32:30 0.16915 +12:32:35 0.16811 +12:32:40 0.16758 +12:32:45 0.16837 +12:32:50 0.16728 +12:32:55 0.16736 +12:33:00 0.16781 +12:33:05 0.16719 +12:33:10 0.16745 +12:33:15 0.16911 +12:33:20 0.16840 +12:33:25 0.16591 +12:33:30 0.16562 +12:33:35 0.16626 +12:33:40 0.16697 +12:33:45 0.16656 +12:33:50 0.16501 +12:33:55 0.16548 +12:34:00 0.16733 +12:34:05 0.16640 +12:34:10 0.16576 +12:34:15 0.16563 +12:34:20 0.16349 +12:34:25 0.16511 +12:34:30 0.16449 +12:34:35 0.16445 +12:34:40 0.16785 +12:34:45 0.16735 +12:34:50 0.16633 +12:34:55 0.16691 +12:35:00 0.16678 +12:35:05 0.16664 +12:35:10 0.16561 +12:35:15 0.16550 +12:35:20 0.16545 +12:35:25 0.16554 +12:35:30 0.16576 +12:35:35 0.16480 +12:35:40 0.16581 +12:35:45 0.16489 +12:35:50 0.16631 +12:35:55 0.16682 +12:36:00 0.16606 +12:36:05 0.16608 +12:36:10 0.16748 +12:36:15 0.16726 +12:36:20 0.16726 +12:36:25 0.16763 +12:36:30 0.16650 +12:36:35 0.16437 +12:36:40 0.16410 +12:36:45 0.16233 +12:36:50 0.16389 +12:36:55 0.16657 +12:37:00 0.16791 +12:37:05 0.16757 +12:37:10 0.16549 +12:37:15 0.16536 +12:37:20 0.16706 +12:37:25 0.16711 +12:37:30 0.16784 +12:37:35 0.16858 +12:37:40 0.16604 +12:37:45 0.16487 +12:37:50 0.16393 +12:37:55 0.16650 +12:38:00 0.16613 +12:38:05 0.16659 +12:38:10 0.16630 +12:38:15 0.16691 +12:38:20 0.16714 +12:38:25 0.16875 +12:38:30 0.16663 +12:38:35 0.16463 +12:38:40 0.16635 +12:38:45 0.16470 +12:38:50 0.16550 +12:38:55 0.16756 +12:39:00 0.16735 +12:39:05 0.16743 +12:39:10 0.16630 +12:39:15 0.16601 +12:39:20 0.16742 +12:39:25 0.16488 +12:39:30 0.16529 +12:39:35 0.16502 +12:39:40 0.16419 +12:39:45 0.16576 +12:39:50 0.16612 +12:39:55 0.16614 +12:40:00 0.16651 +12:40:05 0.16622 +12:40:10 0.16518 +12:40:15 0.16642 +12:40:20 0.16724 +12:40:25 0.16888 +12:40:30 0.17002 +12:40:35 0.16705 +12:40:40 0.16443 +12:40:45 0.16496 +12:40:50 0.16588 +12:41:03 0.16597 +12:41:05 0.16633 +12:41:10 0.16829 +12:41:15 0.16658 +12:41:20 0.16543 +12:41:25 0.16479 +12:41:30 0.16722 +12:41:35 0.16915 +12:41:40 0.17190 +12:41:45 0.17187 +12:41:50 0.17233 +12:41:55 0.17193 +12:42:00 0.17260 +12:42:05 0.17296 +12:42:10 0.17336 +12:42:15 0.17228 +12:42:20 0.17204 +12:42:25 0.17205 +12:42:30 0.17356 +12:42:35 0.17191 +12:42:40 0.17303 +12:42:45 0.17523 +12:42:50 0.17202 +12:42:55 0.17201 +12:43:00 0.17191 +12:43:05 0.17225 +12:43:10 0.17215 +12:43:15 0.17165 +12:43:20 0.17106 +12:43:25 0.17173 +12:43:30 0.17116 +12:43:35 0.16903 +12:43:40 0.16805 +12:43:45 0.17000 +12:43:50 0.17148 +12:43:55 0.17189 +12:44:00 0.17325 +12:44:05 0.17133 +12:44:10 0.17066 +12:44:15 0.17095 +12:44:20 0.17147 +12:44:25 0.17083 +12:44:30 0.17106 +12:44:35 0.17198 +12:44:40 0.17020 +12:44:45 0.16957 +12:44:50 0.16958 +12:44:55 0.17149 +12:45:00 0.17087 +12:45:05 0.16999 +12:45:10 0.17000 +12:45:15 0.16946 +12:45:20 0.16974 +12:45:25 0.16970 +12:45:30 0.17029 +12:45:35 0.17129 +12:45:40 0.17081 +12:45:45 0.16911 +12:45:50 0.17047 +12:45:55 0.16942 +12:46:00 0.17009 +12:46:05 0.17074 +12:46:10 0.16971 +12:46:15 0.16926 +12:46:20 0.16956 +12:46:25 0.16780 +12:46:30 0.16769 +12:46:35 0.16937 +12:46:40 0.17070 +12:46:45 0.17150 +12:46:50 0.17022 +12:46:55 0.17115 +12:47:00 0.17010 +12:47:05 0.16870 +12:47:10 0.16951 +12:47:15 0.17081 +12:47:20 0.17127 +12:47:25 0.17136 +12:47:30 0.17005 +12:47:35 0.17012 +12:47:40 0.16997 +12:47:45 0.17256 +12:47:50 0.17229 +12:47:55 0.17022 +12:48:00 0.16860 +12:48:05 0.16884 +12:48:10 0.16972 +12:48:15 0.17053 +12:48:20 0.17089 +12:48:25 0.16936 +12:48:30 0.17126 +12:48:35 0.17293 +12:48:40 0.17029 +12:48:45 0.16701 +12:48:50 0.16833 +12:48:55 0.17218 +12:49:00 0.17212 +12:49:05 0.17145 +12:49:10 0.17046 +12:49:15 0.16905 +12:49:20 0.16949 +12:49:25 0.17103 +12:49:30 0.17171 +12:49:35 0.17154 +12:49:40 0.17064 +12:49:45 0.16880 +12:49:50 0.16894 +12:49:55 0.17009 +12:50:00 0.16962 +12:50:05 0.17074 +12:50:10 0.16984 +12:50:15 0.16755 +12:50:20 0.16833 +12:50:25 0.16859 +12:50:30 0.16935 +12:50:35 0.16855 +12:50:40 0.17144 +12:50:45 0.17259 +12:50:50 0.17259 +12:50:55 0.16946 +12:51:00 0.16941 +12:51:05 0.17033 +12:51:10 0.16934 +12:51:15 0.16906 +12:51:20 0.17040 +12:51:25 0.17123 +12:51:30 0.16983 +12:51:35 0.16774 +12:51:40 0.16944 +12:51:45 0.16716 +12:51:50 0.16651 +12:51:55 0.16765 +12:52:00 0.16863 +12:52:05 0.17000 +12:52:10 0.16979 +12:52:15 0.17139 +12:52:20 0.17045 +12:52:25 0.16960 +12:52:30 0.17219 +12:52:35 0.17328 +12:52:40 0.17109 +12:52:45 0.17001 +12:52:50 0.16912 +12:52:55 0.16970 +12:53:00 0.17020 +12:53:05 0.17018 +12:53:10 0.17023 +12:53:15 0.16906 +12:53:20 0.16994 +12:53:25 0.16909 +12:53:30 0.16992 +12:53:35 0.16858 +12:53:40 0.16923 +12:53:45 0.17082 +12:53:50 0.17090 +12:53:55 0.17100 +12:54:00 0.17180 +12:54:05 0.17271 +12:54:10 0.17214 +12:54:15 0.17190 +12:54:20 0.17035 +12:54:25 0.16961 +12:54:30 0.17157 +12:54:35 0.17314 +12:54:40 0.17135 +12:54:45 0.17098 +12:54:50 0.17007 +12:54:55 0.17098 +12:55:00 0.16912 +12:55:05 0.16869 +12:55:10 0.16809 +12:55:15 0.16840 +12:55:20 0.17040 +12:55:25 0.17081 +12:55:30 0.17120 +12:55:35 0.16993 +12:55:40 0.17137 +12:55:45 0.17048 +12:55:50 0.17036 +12:55:55 0.17057 +12:56:00 0.17067 +12:56:05 0.17005 +12:56:10 0.17242 +12:56:15 0.16972 +12:56:20 0.17101 +12:56:25 0.17157 +12:56:30 0.17031 +12:56:35 0.16906 +12:56:40 0.16921 +12:56:45 0.16922 +12:56:50 0.17215 +12:56:55 0.17062 +12:57:00 0.17167 +12:57:06 0.17293 +12:57:10 0.17011 +12:57:15 0.16947 +12:57:20 0.16934 +12:57:25 0.17120 +12:57:30 0.17013 +12:57:35 0.16917 +12:57:40 0.17000 +12:57:45 0.17029 +12:57:50 0.16919 +12:57:55 0.16805 +12:58:00 0.16869 +12:58:05 0.17253 +12:58:10 0.17194 +12:58:15 0.17042 +12:58:20 0.16863 +12:58:25 0.17030 +12:58:30 0.17248 +12:58:35 0.17002 +12:58:40 0.16747 +12:58:45 0.17191 +12:58:50 0.17105 +12:58:55 0.17030 +12:59:00 0.17243 +12:59:05 0.16989 +12:59:10 0.17047 +12:59:15 0.17127 +12:59:20 0.17053 +12:59:25 0.17100 +12:59:30 0.17137 +12:59:35 0.17005 +12:59:40 0.17153 +12:59:45 0.17100 +12:59:50 0.16898 +12:59:55 0.16877 +13:00:00 0.16969 +13:00:05 0.17042 +13:00:10 0.17211 +13:00:15 0.17025 +13:00:20 0.16993 +13:00:25 0.16917 +13:00:30 0.16963 +13:00:35 0.17077 +13:00:40 0.17096 +13:00:45 0.16990 +13:00:50 0.16958 +13:00:55 0.17004 +13:01:00 0.17113 +13:01:05 0.17006 +13:01:10 0.16838 +13:01:15 0.16798 +13:01:20 0.17018 +13:01:25 0.17075 +13:01:36 0.17041 +13:01:40 0.16961 +13:01:45 0.17040 +13:01:50 0.17035 +13:01:55 0.17111 +13:02:00 0.16994 +13:02:05 0.16971 +13:02:10 0.16919 +13:02:15 0.16985 +13:02:20 0.17191 +13:02:25 0.17140 +#period 5 exact 1 isdst 1 +13:02:30 +13:02:32 undefined +13:02:35 0.16961 +13:02:40 0.16945 +13:02:45 0.16898 +13:02:50 0.17194 +13:02:55 0.17203 +13:03:00 0.17090 +13:03:05 0.16941 +13:03:10 0.16938 +13:03:15 0.17127 +13:03:20 0.16868 +13:03:25 0.16685 +13:03:30 0.17044 +13:03:35 0.17033 +13:03:40 0.16883 +13:03:45 0.16870 +13:03:50 0.16834 +13:03:55 0.16866 +13:04:00 0.16796 +13:04:05 0.16947 +13:04:10 0.16968 +13:04:15 0.16833 +13:04:20 0.16826 +13:04:25 0.16863 +13:04:30 0.16905 +13:04:35 0.16720 +13:04:40 0.16625 +13:04:45 0.16721 +13:04:50 0.16612 +13:04:55 0.16629 +13:05:00 0.16907 +13:05:05 0.16946 +13:05:10 0.16713 +13:05:15 0.16851 +13:05:20 0.16901 +13:05:25 0.16770 +13:05:30 0.16922 +13:05:35 0.16773 +13:05:40 0.16787 +13:06:01 0.16824 +13:06:05 0.16749 +13:06:33 0.16764 +13:06:35 0.16850 +13:06:40 0.16905 +13:06:45 0.16828 +13:06:50 0.16694 +13:06:55 0.16857 +13:07:00 0.16601 +#period 5 exact 1 isdst 1 +13:07:06 +13:07:08 undefined +13:07:10 0.17018 +13:07:15 0.16628 +13:07:20 0.16709 +13:07:25 0.16646 +13:07:30 0.16505 +13:07:35 0.16710 +13:07:40 0.16544 +13:07:45 0.16825 +13:07:50 0.17227 +13:07:55 0.17411 +13:08:00 0.17251 +13:08:05 0.17249 +13:08:10 0.17160 +13:08:15 0.17400 +13:08:20 0.17340 +13:08:25 0.17109 +13:08:30 0.17206 +13:08:35 0.17242 +13:08:40 0.16953 +13:08:45 0.17057 +13:08:50 0.17080 +13:08:55 0.16985 +13:09:00 0.17148 +13:09:05 0.17258 +13:09:10 0.17202 +13:09:15 0.17125 +13:09:20 0.17098 +13:09:25 0.17167 +13:09:30 0.17156 +13:09:35 0.16973 +13:09:40 0.17168 +13:09:45 0.17064 +13:09:50 0.16770 +13:09:55 0.16862 +13:10:00 0.16948 +13:10:05 0.16830 +13:10:10 0.17019 +13:10:15 0.17189 +13:10:20 0.17232 +13:10:25 0.17118 +13:10:30 0.17022 +13:10:35 0.16962 +13:10:40 0.16996 +13:10:45 0.17309 +13:10:50 0.17238 +13:10:55 0.17085 +13:11:00 0.17038 +13:11:05 0.17081 +13:11:10 0.17179 +13:11:15 0.17083 +13:11:20 0.17061 +13:11:25 0.16986 +13:11:30 0.17154 +13:11:36 0.17122 +13:11:40 0.17242 +13:11:45 0.17146 +13:11:52 0.17084 +13:11:55 0.16807 +13:12:00 0.16878 +13:12:05 0.16965 +13:12:10 0.17142 +13:12:15 0.17043 +13:12:20 0.17007 +13:12:25 0.17030 +13:12:30 0.16939 +13:12:35 0.17003 +13:12:40 0.17069 +13:12:45 0.16971 +13:12:50 0.17087 +13:12:55 0.16932 +13:13:00 0.16974 +13:13:05 0.17009 +13:13:10 0.17117 +13:13:15 0.17025 +13:13:20 0.17112 +13:13:25 0.16892 +13:13:30 0.17046 +13:13:35 0.16943 +13:13:40 0.16908 +13:13:45 0.16970 +13:13:50 0.16991 +13:13:55 0.17048 +13:14:00 0.16939 +13:14:05 0.16937 +13:14:10 0.16822 +13:14:15 0.16776 +13:14:20 0.16925 +13:14:25 0.16878 +13:14:30 0.16868 +13:14:35 0.16683 +13:14:40 0.16860 +13:14:45 0.16993 +13:14:50 0.16916 +13:14:55 0.16858 +13:15:00 0.17018 +13:15:05 0.17160 +13:15:10 0.17176 +13:15:15 0.16945 +13:15:20 0.17059 +13:15:25 0.17194 +13:15:30 0.17228 +13:15:35 0.17107 +13:15:40 0.16990 +13:15:45 0.16804 +13:15:50 0.16878 +13:15:55 0.16936 +13:16:00 0.16923 +13:16:05 0.17072 +13:16:10 0.17079 +13:16:15 0.16991 +13:16:20 0.17098 +13:16:25 0.17077 +13:16:30 0.16931 +13:16:35 0.17011 +13:16:40 0.17093 +13:16:45 0.16852 +13:16:50 0.16685 +13:16:55 0.17080 +13:17:00 0.17003 +13:17:05 0.16824 +13:17:10 0.17036 +13:17:15 0.17121 +13:17:20 0.16901 +13:17:25 0.16920 +13:17:30 0.17034 +13:17:35 0.16925 +13:17:40 0.16954 +13:17:45 0.16979 +13:17:50 0.16842 +13:17:55 0.16913 +13:18:00 0.17033 +13:18:05 0.16942 +13:18:10 0.16927 +13:18:15 0.16965 +13:18:20 0.17072 +13:18:25 0.17081 +13:18:30 0.16878 +13:18:35 0.16849 +13:18:40 0.16906 +13:18:45 0.16978 +13:18:50 0.17065 +13:18:55 0.16952 +13:19:00 0.17285 +13:19:05 0.17239 +13:19:10 0.16909 +13:19:15 0.16886 +13:19:20 0.16987 +13:19:25 0.17015 +13:19:30 0.16913 +13:19:35 0.16951 +13:19:40 0.16887 +13:19:45 0.16814 +13:19:50 0.16991 +13:19:55 0.16936 +13:20:00 0.17138 +13:20:05 0.16963 +13:20:10 0.16979 +13:20:15 0.16874 +13:20:20 0.17020 +13:20:25 0.16983 +13:20:30 0.17088 +13:20:35 0.17070 +13:20:40 0.17009 +13:20:45 0.16879 +13:20:50 0.16755 +13:20:55 0.16779 +13:21:07 0.16919 +13:21:10 0.17003 +13:21:15 0.16891 +13:21:25 0.17083 +13:21:30 0.17019 +13:21:39 0.16888 +13:21:40 0.16948 +13:21:46 0.17054 +13:21:50 0.16989 +13:21:55 0.16745 +13:22:03 0.16879 +13:22:05 0.16966 +13:22:10 0.16923 +13:22:17 0.17088 +13:22:20 0.16836 +13:22:25 0.16805 +13:22:30 0.16837 +13:22:35 0.16677 +13:22:40 0.16803 +13:22:45 0.17088 +13:22:50 0.17014 +13:22:55 0.16876 +13:23:01 0.16877 +13:23:05 0.16957 +13:23:10 0.17060 +13:23:15 0.16844 +13:23:20 0.16930 +13:23:25 0.16815 +13:23:30 0.16645 +13:23:35 0.16850 +13:23:40 0.16830 +13:23:45 0.16912 +13:23:50 0.16890 +13:23:55 0.17178 +13:24:00 0.17248 +13:24:05 0.17216 +13:24:10 0.17213 +13:24:15 0.17670 +13:26:55 0.17670 +13:27:00 0.17698 +13:27:05 0.17711 +13:27:10 0.17738 +13:27:15 0.17884 +13:27:23 0.18748 +13:27:25 0.18717 +13:27:30 0.18209 +13:27:35 0.17551 +13:27:40 0.17145 +13:27:45 0.16991 +13:27:52 0.16461 +13:27:55 0.16565 +13:28:00 0.16950 +13:28:05 0.16527 +13:28:10 0.16973 +13:28:15 0.16447 +13:28:20 0.16096 +13:28:25 0.16224 +13:28:30 0.16901 +13:28:35 0.16590 +13:28:40 0.15760 +13:28:45 0.15738 +13:28:50 0.15536 +13:29:00 0.15971 +13:29:05 0.15667 +13:29:10 0.15590 +13:29:15 0.16156 +13:29:20 0.16147 +13:29:25 0.15904 +13:29:30 0.16192 +13:29:35 0.16236 +13:29:40 0.15791 +13:29:45 0.16440 +13:29:50 0.16307 +13:29:55 0.16639 +13:30:00 0.15786 +13:30:05 0.15923 +13:30:10 0.15471 +13:30:15 0.15761 +13:30:20 0.15708 +13:30:25 0.15905 +13:30:30 0.16344 +13:30:36 0.15675 +13:30:40 0.15264 +13:30:47 0.15270 +13:30:50 0.15478 +13:30:55 0.16107 +13:31:00 0.16781 +13:31:05 0.16402 +13:31:10 0.15810 +13:31:15 0.15550 +13:31:20 0.15648 +13:31:25 0.16440 +13:31:30 0.15813 +13:31:35 0.16189 +13:31:40 0.15355 +13:31:45 0.15782 +13:31:50 0.15822 +13:31:55 0.15695 +13:32:00 0.15562 +13:32:05 0.15600 +13:32:10 0.15832 +13:32:15 0.16088 +13:32:20 0.15847 +13:32:25 0.15991 +13:32:30 0.15635 +13:32:35 0.16079 +13:32:40 0.16014 +13:32:45 0.15929 +13:32:50 0.15751 +13:32:55 0.15782 +13:33:00 0.15591 +13:33:05 0.15729 +13:33:10 0.15574 +13:33:15 0.16319 +13:33:20 0.15527 +13:33:25 0.16070 +13:33:30 0.16396 +13:33:35 0.15524 +13:33:40 0.15581 +13:33:45 0.15331 +13:33:50 0.15960 +13:33:55 0.15923 +13:34:00 0.15694 +13:34:05 0.15627 +13:34:10 0.16303 +13:34:15 0.16244 +13:34:20 0.16105 +13:34:25 0.16186 +13:34:30 0.15468 +13:34:35 0.16119 +13:34:40 0.15480 +13:34:45 0.16179 +13:34:50 0.16174 +13:34:55 0.16252 +13:35:00 0.15568 +13:35:05 0.15771 +13:35:10 0.15818 +13:35:15 0.15813 +13:35:20 0.15601 +13:35:25 0.15565 +13:35:30 0.15791 +13:35:35 0.15855 +13:35:40 0.16231 +13:35:45 0.15308 +13:35:50 0.16210 +13:35:55 0.15676 +13:36:00 0.15505 +13:36:05 0.15574 +13:36:10 0.15444 +13:36:15 0.15714 +13:36:20 0.15427 +13:36:29 0.15533 +13:36:30 0.15823 +13:36:35 0.15654 +13:36:40 0.15967 +13:36:45 0.16103 +13:36:50 0.16069 +13:36:55 0.16245 +13:37:00 0.15846 +13:37:05 0.15410 +13:37:10 0.15790 +13:37:15 0.16438 +13:37:20 0.15626 +13:37:25 0.16028 +13:37:30 0.15657 +13:37:35 0.15854 +13:37:40 0.15441 +13:37:45 0.16417 +13:37:50 0.16192 +13:37:55 0.16755 +13:38:00 0.15580 +13:38:05 0.15580 +13:38:10 0.15563 +13:38:15 0.15520 +13:38:20 0.15540 +13:38:25 0.15348 +13:38:30 0.15579 +13:38:35 0.15645 +13:38:40 0.15767 +13:38:45 0.15707 +13:38:50 0.15301 +13:38:55 0.15804 +13:39:00 0.16147 +13:39:05 0.15843 +13:39:10 0.15897 +13:39:15 0.15840 +13:39:20 0.15366 +13:39:25 0.15438 +13:39:30 0.15983 +13:39:35 0.15944 +13:39:40 0.15479 +13:39:45 0.16169 +13:39:50 0.15395 +13:39:55 0.15564 +13:40:00 0.15225 +13:40:05 0.15655 +13:40:10 0.15721 +13:40:15 0.15065 +13:40:20 0.15673 +13:40:25 0.14899 +13:40:30 0.15467 +13:40:35 0.15818 +13:40:40 0.16559 +13:40:45 0.15694 +13:40:50 0.15839 +13:40:55 0.16370 +13:41:00 0.16477 +13:41:05 0.15744 +13:41:10 0.15403 +13:41:15 0.15584 +13:41:20 0.16130 +13:41:25 0.15488 +13:41:30 0.15879 +13:41:35 0.16157 +13:41:40 0.15426 +13:41:45 0.15830 +13:41:50 0.16092 +13:41:55 0.16017 +13:42:00 0.15878 +13:42:05 0.15673 +13:42:10 0.15612 +13:42:15 0.16204 +13:42:20 0.15767 +13:42:25 0.15518 +13:42:30 0.15441 +13:42:35 0.15466 +13:42:40 0.15947 +13:42:45 0.15578 +13:42:50 0.15308 +13:42:55 0.15618 +13:43:00 0.15858 +13:43:05 0.15642 +13:43:10 0.15540 +13:43:15 0.15818 +13:43:20 0.16102 +13:43:25 0.16497 +13:43:30 0.15631 +13:43:35 0.15772 +13:43:40 0.16198 +13:43:45 0.16265 +13:43:50 0.15636 +13:43:55 0.15847 +13:44:00 0.15487 +13:44:05 0.15723 +13:44:10 0.15401 +13:44:15 0.15416 +13:44:20 0.15882 +13:44:25 0.15994 +13:44:30 0.16299 +13:44:35 0.15974 +13:44:40 0.15967 +13:44:45 0.16412 +13:44:50 0.15464 +13:44:55 0.15609 +13:45:00 0.15822 +13:45:05 0.15684 +13:45:10 0.15404 +13:45:15 0.15192 +13:45:20 0.15077 +13:45:25 0.16113 +13:45:30 0.15858 +13:45:35 0.15885 +13:45:40 0.15769 +13:45:45 0.15259 +13:45:50 0.15496 +13:45:55 0.15775 +13:46:00 0.15885 +13:46:05 0.15881 +13:46:10 0.15537 +13:46:15 0.15495 +13:46:20 0.15336 +13:46:25 0.15300 +13:46:30 0.16676 +13:46:35 0.15952 +13:46:40 0.15519 +13:46:45 0.15425 +13:46:50 0.15140 +13:46:55 0.15244 +13:47:00 0.15164 +13:47:05 0.15577 +13:47:10 0.16006 +13:47:15 0.15516 +13:47:20 0.15368 +13:47:25 0.15887 +13:47:30 0.15966 +13:47:35 0.15314 +13:47:40 0.15636 +13:47:45 0.15515 +13:47:50 0.15745 +13:47:55 0.15327 +13:48:00 0.15312 +13:48:05 0.15372 +13:48:10 0.15587 +13:48:15 0.16069 +13:48:20 0.15856 +13:48:25 0.16313 +13:48:30 0.16347 +13:48:35 0.15901 +13:48:40 0.15241 +13:48:45 0.15674 +13:48:50 0.16314 +13:48:55 0.16475 +13:49:00 0.15921 +13:49:05 0.15758 +13:49:10 0.15477 +13:49:15 0.15122 +13:49:20 0.15348 +13:49:25 0.15055 +13:49:30 0.15150 +13:49:35 0.14807 +13:49:40 0.15193 +13:49:45 0.15561 +13:49:50 0.15405 +13:49:55 0.15491 +13:50:00 0.15479 +13:50:05 0.15308 +13:50:10 0.15616 +13:50:15 0.15880 +13:50:20 0.15403 +13:50:25 0.15545 +13:50:30 0.16036 +13:50:35 0.15506 +13:50:40 0.15406 +13:50:45 0.15230 +13:50:50 0.15301 +13:50:55 0.15608 +13:51:00 0.16314 +13:51:05 0.16482 +13:51:10 0.15504 +13:51:15 0.14897 +13:51:20 0.15338 +13:51:25 0.16191 +13:51:30 0.15958 +13:51:35 0.15498 +13:51:40 0.15679 +13:51:45 0.16010 +13:51:50 0.16052 +13:51:55 0.16214 +13:52:00 0.15889 +13:52:05 0.15303 +13:52:10 0.15368 +13:52:15 0.15814 +13:52:20 0.15845 +13:52:25 0.15826 +13:52:30 0.15815 +13:52:35 0.15857 +13:52:40 0.15942 +13:52:45 0.16220 +13:52:50 0.16362 +13:52:55 0.15838 +13:53:00 0.15771 +13:53:05 0.15590 +13:53:10 0.15878 +13:53:15 0.16084 +13:53:20 0.15630 +13:53:25 0.15379 +13:53:30 0.15305 +13:53:35 0.14820 +13:53:40 0.15387 +13:53:45 0.16189 +13:53:50 0.16235 +13:53:55 0.16847 +13:54:00 0.15823 +13:54:05 0.15132 +13:54:10 0.15320 +13:54:15 0.15679 +13:54:20 0.16128 +13:54:25 0.15859 +13:54:30 0.15606 +13:54:35 0.15344 +13:54:40 0.15424 +13:54:45 0.15545 +13:54:50 0.15846 +13:54:55 0.15692 +13:55:00 0.16054 +13:55:05 0.15718 +13:55:10 0.16181 +13:55:15 0.15596 +13:55:20 0.15808 +13:55:25 0.15706 +13:55:30 0.15933 +13:55:35 0.16558 +13:55:40 0.15604 +13:55:45 0.14879 +13:55:50 0.15633 +13:55:55 0.16189 +13:56:00 0.15535 +13:56:05 0.15347 +13:56:10 0.14894 +13:56:15 0.15314 +13:56:20 0.15700 +13:56:25 0.15889 +13:56:30 0.15127 +13:56:35 0.15765 +13:56:40 0.15548 +13:56:45 0.15216 +13:56:50 0.15362 +13:56:55 0.15360 +13:57:00 0.14620 +13:57:05 0.14955 +13:57:10 0.15740 +13:57:15 0.15442 +13:57:20 0.15938 +13:57:25 0.15866 +13:57:30 0.15868 +13:57:35 0.15542 +13:57:40 0.15381 +13:57:45 0.15708 +13:57:50 0.16142 +13:57:55 0.15780 +13:58:00 0.15464 +13:58:05 0.15476 +13:58:10 0.15718 +13:58:15 0.15782 +13:58:20 0.15996 +13:58:25 0.16345 +13:58:30 0.15711 +13:58:35 0.15284 +13:58:40 0.15065 +13:58:45 0.15378 +13:58:50 0.15303 +13:58:55 0.15797 +13:59:00 0.16215 +13:59:05 0.16014 +13:59:10 0.16201 +13:59:15 0.15971 +13:59:20 0.16175 +13:59:25 0.16074 +13:59:30 0.16122 +13:59:35 0.15715 +13:59:40 0.15513 +13:59:45 0.15546 +13:59:50 0.16014 +13:59:55 0.15992 +14:00:00 0.16061 +14:00:05 0.15941 +14:00:10 0.15571 +14:00:15 0.15057 +14:00:20 0.15410 +14:00:25 0.15692 +14:00:30 0.16004 +14:00:35 0.16792 +14:00:40 0.16303 +14:00:45 0.15769 +14:00:50 0.15909 +14:00:55 0.15617 +14:01:00 0.15802 +14:01:05 0.15589 +14:01:14 0.15559 +14:01:15 0.15559 +14:01:20 0.15652 +14:01:25 0.15729 +14:01:30 0.16341 +14:01:35 0.15561 +14:01:40 0.14942 +14:01:45 0.16009 +14:01:50 0.16436 +14:01:55 0.15884 +14:02:00 0.15882 +14:02:05 0.15491 +14:02:10 0.15566 +14:02:15 0.15410 +14:02:20 0.15053 +14:02:25 0.15540 +14:02:30 0.15887 +14:02:35 0.15906 +14:02:40 0.16310 +14:02:45 0.15313 +14:02:50 0.15593 +14:02:55 0.15595 +14:03:00 0.16020 +14:03:05 0.15867 +14:03:10 0.15602 +14:03:15 0.15852 +14:03:20 0.15876 +14:03:25 0.15372 +14:03:30 0.15532 +14:03:35 0.14972 +14:03:40 0.15123 +14:03:45 0.15268 +14:03:50 0.15505 +14:03:55 0.15555 +14:04:00 0.15793 +14:04:05 0.15638 +14:04:10 0.15151 +14:04:15 0.15293 +14:04:20 0.15168 +14:04:25 0.15615 +14:04:30 0.15618 +14:04:35 0.15629 +14:04:40 0.15565 +14:04:45 0.15305 +14:04:50 0.15867 +14:04:55 0.15600 +14:05:00 0.15395 +14:05:05 0.15512 +14:05:10 0.15928 +14:05:15 0.16120 +14:05:20 0.15480 +14:05:25 0.15436 +14:05:30 0.15851 +14:05:35 0.15500 +14:05:40 0.15609 +14:05:45 0.15579 +14:05:50 0.15773 +14:05:55 0.15955 +14:06:00 0.15358 +14:06:05 0.15607 +14:06:10 0.15945 +14:06:15 0.15886 +14:06:20 0.16407 +14:06:25 0.15947 +14:06:30 0.15587 +14:06:35 0.15901 +14:06:40 0.15552 +14:06:45 0.15570 +14:06:50 0.16119 +14:06:55 0.15811 +14:07:00 0.15512 +14:07:05 0.15735 +14:07:10 0.15098 +14:07:15 0.15158 +14:07:20 0.15634 +14:07:25 0.15568 +14:07:30 0.15239 +14:07:35 0.16040 +14:07:40 0.15708 +14:07:45 0.16067 +14:07:50 0.16128 +14:07:55 0.15798 +14:08:00 0.15416 +14:08:05 0.15632 +14:08:10 0.16083 +14:08:15 0.16430 +14:08:20 0.15546 +14:08:25 0.15473 +14:08:30 0.15280 +14:08:35 0.15266 +14:08:40 0.15706 +14:08:45 0.15607 +14:08:50 0.15674 +14:08:55 0.15789 +14:09:00 0.15476 +14:09:05 0.15638 +14:09:10 0.16471 +14:09:15 0.15893 +14:09:20 0.15499 +14:09:25 0.16237 +14:09:30 0.16163 +14:09:35 0.16158 +14:09:40 0.15589 +14:09:45 0.15782 +14:09:50 0.16190 +14:09:55 0.15579 +14:10:00 0.15959 +14:10:05 0.16088 +14:10:10 0.15538 +14:10:15 0.16015 +14:10:20 0.15317 +14:10:25 0.15347 +14:10:30 0.15172 +14:10:35 0.15541 +14:10:40 0.15531 +14:10:45 0.16080 +14:10:50 0.15850 +14:10:55 0.15483 +14:11:00 0.15525 +14:11:05 0.15587 +14:11:10 0.16014 +14:11:15 0.16037 +14:11:20 0.15471 +14:11:25 0.15468 +14:11:30 0.15693 +14:11:35 0.15578 +14:11:40 0.15762 +14:11:45 0.16030 +14:11:50 0.15710 +14:11:55 0.15185 +14:12:00 0.15749 +14:12:05 0.15434 +14:12:10 0.16149 +14:12:15 0.15955 +14:12:20 0.15518 +14:12:25 0.15625 +14:12:30 0.15635 +14:12:35 0.16165 +14:12:40 0.16037 +14:12:45 0.16260 +14:12:50 0.16008 +14:12:55 0.15674 +14:13:00 0.15469 +14:13:05 0.15361 +14:13:10 0.16202 +14:13:15 0.15663 +14:13:20 0.16224 +14:13:25 0.16374 +14:13:30 0.15420 +14:13:35 0.15573 +14:13:40 0.15660 +14:13:45 0.15721 +14:13:50 0.15214 +14:13:55 0.15493 +14:14:00 0.15992 +14:14:05 0.15460 +14:14:10 0.15397 +14:14:15 0.15975 +14:14:20 0.15309 +14:14:25 0.16019 +14:14:30 0.15858 +14:14:35 0.15617 +14:14:40 0.15724 +14:14:45 0.15765 +14:14:50 0.15196 +14:14:55 0.15928 +14:15:00 0.15934 +14:15:05 0.15683 +14:15:10 0.16168 +14:15:15 0.16156 +14:15:20 0.15372 +14:15:25 0.15673 +14:15:30 0.15563 +14:15:35 0.15123 +14:15:40 0.15079 +14:15:45 0.15237 +14:15:50 0.15699 +14:15:55 0.15886 +14:16:00 0.15827 +14:16:05 0.15838 +14:16:10 0.15600 +14:16:15 0.15679 +14:16:25 0.16225 +14:16:30 0.15933 +14:16:35 0.15388 +14:16:40 0.15906 +14:16:45 0.15541 +14:16:50 0.15509 +14:16:55 0.15687 +14:17:00 0.15256 +14:17:05 0.15621 +14:17:10 0.15507 +14:17:15 0.15627 +14:17:20 0.15783 +14:17:25 0.15454 +14:17:30 0.15960 +14:17:35 0.16179 +14:17:40 0.16288 +14:17:45 0.16232 +14:17:50 0.16373 +14:17:55 0.16898 +14:18:00 0.16840 +14:18:05 0.16562 +14:18:10 0.17473 +14:18:15 0.17406 +14:18:20 0.17487 +14:18:25 0.17801 +14:18:30 0.18845 +14:18:35 0.18892 +14:18:40 0.21422 +14:18:45 0.41001 +14:18:50 0.78100 +14:18:55 0.87237 +14:19:00 1.2188 +14:19:05 1.4900 +14:19:10 1.5785 +14:19:15 1.2923 +14:19:20 1.0776 +14:19:25 1.2900 +14:19:30 1.4591 +14:19:35 1.4109 +14:19:40 1.3475 +14:19:45 1.2398 +14:19:50 1.3375 +14:19:55 1.5821 +14:20:00 1.5364 +14:20:05 4.8250 +14:20:10 3.1921 +14:20:15 1.4507 +14:20:20 1.3861 +14:20:25 1.3782 +14:20:30 1.4600 +14:20:35 2.1113 +14:20:40 2.0152 +14:20:45 2.1944 +14:20:50 1.9211 +14:20:55 1.9631 +14:21:00 2.9701 +14:21:05 1.9396 +14:21:10 1.8230 +14:21:15 2.9968 +14:21:20 2.9712 +14:21:25 2.0347 +14:21:30 1.6284 +14:21:35 2.1419 +14:21:40 3.0369 +14:21:45 2.1591 +14:21:50 2.0545 +14:21:55 2.7250 +14:22:00 1.9995 +14:22:05 1.6586 +14:22:13 2.1303 +14:22:15 2.1813 +14:22:20 2.5220 +14:22:25 2.6809 +14:22:30 1.5945 +14:22:35 1.4464 +14:22:40 1.4437 +14:22:45 1.3317 +14:22:50 1.6946 +14:22:55 1.6581 +14:23:00 1.7462 +14:23:05 3.0054 +14:23:10 2.0527 +14:23:15 2.2458 +14:23:20 1.8125 +14:23:25 1.2014 +14:23:30 1.3047 +14:23:35 1.2093 +14:23:40 1.2969 +14:23:45 1.6198 +14:23:50 2.2268 +14:23:55 2.3651 +14:24:00 2.1144 +14:24:05 1.4402 +14:24:10 2.1089 +14:24:15 2.0186 +14:24:20 2.1608 +14:24:25 2.1114 +14:24:30 2.7092 +14:24:35 2.6155 +14:24:40 3.4728 +14:24:45 2.1291 +14:24:50 1.8464 +14:24:55 2.0649 +14:25:00 2.0490 +14:25:05 1.5565 +14:25:10 2.1299 +14:25:15 4.1631 +14:25:20 2.8430 +14:25:25 2.7431 +14:25:30 3.4791 +14:25:35 2.5467 +14:25:40 2.0791 +14:25:45 3.8225 +14:25:50 3.8369 +14:25:55 2.6653 +14:26:00 2.4913 +14:26:05 3.0326 +14:26:10 2.2092 +14:26:15 1.8703 +14:26:20 2.1218 +14:26:25 1.9838 +14:26:30 1.9627 +14:26:35 1.8702 +14:26:40 2.3995 +14:26:45 2.0044 +14:26:50 1.9100 +14:26:55 1.9704 +14:27:00 2.2946 +14:27:05 2.2029 +14:27:10 2.3654 +14:27:15 2.1168 +14:27:20 1.6774 +14:27:25 1.8196 +14:27:30 1.7340 +14:27:35 2.2993 +14:27:40 2.5057 +14:27:45 2.4950 +14:27:50 3.1228 +14:27:55 3.1616 +14:28:00 2.9337 +14:28:05 2.9027 +14:28:10 2.6826 +14:28:15 1.9078 +14:28:20 1.5077 +14:28:25 1.6715 +14:28:30 2.0773 +14:28:35 1.9607 +14:28:40 2.8687 +14:28:45 2.2899 +14:28:50 2.6356 +14:28:55 3.1693 +14:29:00 2.6068 +14:29:05 1.8361 +14:29:10 2.1318 +14:29:15 2.1678 +14:29:20 1.7904 +14:29:25 1.8703 +14:29:30 3.1321 +14:29:35 3.3451 +14:29:40 2.5354 +14:29:45 1.9244 +14:29:50 2.0543 +14:29:55 1.8395 +14:30:00 1.5418 +14:30:05 2.1691 +14:30:10 2.3013 +14:30:15 1.8439 +14:30:20 1.8641 +14:30:25 2.7176 +14:30:30 2.5047 +14:30:35 2.1262 +14:30:40 1.4688 +14:30:45 1.6228 +14:30:50 1.7463 +14:30:55 1.7207 +14:31:00 2.0140 +14:31:05 1.5982 +14:31:10 1.8905 +14:31:15 2.1515 +14:31:20 2.6844 +14:31:25 3.1188 +14:31:30 2.1709 +14:31:35 2.5886 +14:31:40 3.1698 +14:31:45 2.5839 +14:31:50 2.7280 +14:31:55 4.0561 +14:32:00 1.6991 +14:32:05 1.5750 +14:32:10 1.3896 +14:32:15 1.7427 +14:32:20 1.4348 +14:32:25 1.4334 +14:32:30 1.5415 +14:32:35 2.4559 +14:32:40 2.5026 +14:32:45 2.2687 +14:32:50 3.3489 +14:32:55 3.8634 +14:33:00 2.7512 +14:33:05 1.8408 +14:33:10 2.3280 +14:33:15 2.3215 +14:33:20 2.7826 +14:33:25 2.6021 +14:33:30 3.6104 +14:33:35 2.0327 +14:33:40 2.1239 +14:33:45 2.1737 +14:33:50 2.0805 +14:33:55 2.5848 +14:34:00 3.0732 +14:34:05 2.5781 +14:34:10 2.1309 +14:34:15 2.1244 +14:34:20 2.3401 +14:34:25 2.1999 +14:34:30 2.9446 +14:34:35 3.4992 +14:34:40 3.9875 +14:34:45 3.0706 +14:34:50 4.7272 +14:34:58 5.1302 +14:35:05 4.0056 +14:35:10 4.4945 +14:35:17 5.0313 +14:35:20 5.0499 +14:35:25 5.1350 +14:35:30 5.0106 +14:35:35 3.9304 +14:35:40 4.1074 +14:35:46 4.4212 +14:35:54 3.6196 +14:35:55 4.5012 +14:36:00 4.7160 +14:36:05 4.8141 +14:36:10 4.1347 +14:36:15 4.7422 +14:36:20 4.2952 +14:36:25 4.7712 +14:36:31 4.6552 +14:36:35 4.2307 +14:36:40 4.0650 +14:36:45 4.0060 +14:36:52 4.7759 +14:36:59 5.0065 +14:37:01 4.8188 +14:37:07 4.2559 +14:37:10 5.0478 +14:37:15 4.9210 +14:37:20 3.4581 +14:37:25 3.8950 +14:37:30 4.8515 +14:37:35 4.3551 +14:37:40 3.9469 +14:37:45 4.8318 +14:37:50 4.1543 +14:37:55 4.5691 +14:38:00 3.8149 +14:38:05 4.9151 +14:38:10 3.9805 +14:38:15 4.4270 +14:38:20 3.5962 +14:38:25 3.6687 +14:38:30 4.4751 +14:38:35 3.0519 +14:38:40 3.4429 +14:38:45 3.2280 +14:38:50 3.1266 +14:38:55 3.4860 +14:39:03 4.3663 +14:39:05 3.7392 +14:39:10 2.6529 +14:39:15 3.0949 +14:39:20 3.7387 +14:39:25 3.5572 +14:39:30 4.2081 +14:39:35 4.1362 +14:39:40 4.5150 +14:39:45 4.9422 +14:39:50 5.1242 +14:39:55 5.1242 +14:40:00 5.0244 +14:40:05 4.9493 +14:40:10 3.7043 +14:40:15 3.8544 +14:40:20 4.4121 +14:40:25 5.0255 +14:40:30 4.8742 +14:40:35 4.6467 +14:40:40 4.6296 +14:40:45 3.7527 +14:40:50 3.7917 +14:40:55 3.4857 +14:41:00 4.0162 +14:41:05 4.1214 +14:41:10 3.8011 +14:41:15 4.1370 +14:41:20 4.1956 +14:41:25 3.5047 +14:41:30 4.0278 +14:41:35 5.0463 +14:41:40 5.0872 +14:41:45 4.9564 +14:41:50 4.3404 +14:41:55 3.1634 +14:42:00 4.5703 +14:42:05 4.0812 +14:42:10 4.2885 +14:42:15 3.9365 +14:42:20 5.0816 +14:42:25 4.6555 +14:42:30 3.6089 +14:42:35 3.4086 +14:42:40 4.2345 +14:42:45 4.5008 +14:42:50 4.7698 +14:42:55 4.6087 +14:43:00 5.0890 +14:43:05 3.9844 +14:43:10 3.3929 +14:43:15 3.5147 +14:43:20 4.4961 +14:43:25 4.7387 +14:43:30 4.7217 +14:43:35 5.0412 +14:43:40 5.0206 +14:43:45 4.9618 +14:43:50 4.5130 +14:43:55 4.0343 +14:44:00 3.1452 +14:44:05 3.2401 +14:44:10 3.0429 +14:44:15 3.8125 +14:44:20 3.9854 +14:44:25 4.0588 +14:44:30 4.2503 +14:44:35 4.1770 +14:44:40 4.2310 +14:44:45 4.3937 +14:44:50 2.9416 +14:44:55 3.2820 +14:45:00 2.9899 +14:45:05 3.0242 +14:45:10 2.9708 +14:45:15 2.7438 +14:45:20 3.0548 +14:45:25 2.7919 +14:45:30 3.6389 +14:45:35 3.2412 +14:45:40 3.3260 +14:45:45 4.0548 +14:45:50 3.4130 +14:45:55 3.5946 +14:46:00 2.8852 +14:46:05 3.7608 +14:46:10 4.7485 +14:46:15 4.9187 +14:46:20 4.4179 +14:46:25 4.2325 +14:46:30 4.8619 +14:46:35 4.4754 +14:46:40 3.5703 +14:46:45 4.5403 +14:46:50 3.4993 +14:46:55 3.0152 +14:47:00 3.1246 +14:47:05 3.1586 +14:47:10 4.0283 +14:47:15 3.6102 +14:47:20 4.5847 +14:47:25 4.2917 +14:47:30 3.5848 +14:47:35 3.8719 +14:47:40 4.6561 +14:47:45 4.2296 +14:47:50 3.5808 +14:47:55 4.2895 +14:48:00 4.0953 +14:48:05 3.1817 +14:48:10 4.4750 +14:48:15 4.3748 +14:48:20 3.0079 +14:48:25 3.8458 +14:48:30 3.4098 +14:48:35 4.1065 +14:48:40 4.9178 +14:48:45 4.4329 +14:48:50 3.1905 +14:48:55 3.3332 +14:49:00 3.5097 +14:49:05 4.5185 +14:49:10 4.2362 +14:49:15 3.9386 +14:49:20 2.0419 +14:49:25 3.1712 +14:49:30 4.4247 +14:49:35 4.9970 +14:49:40 4.8842 +14:49:45 5.1506 +14:49:50 4.3711 +14:49:55 3.5476 +14:50:00 3.9071 +14:50:05 3.8639 +14:50:10 3.5371 +14:50:15 4.4881 +14:50:20 4.4470 +14:50:25 4.3819 +14:50:30 4.4402 +14:50:35 4.6129 +14:50:40 3.4963 +14:50:45 3.7861 +14:50:50 4.5448 +14:50:55 4.2310 +14:51:00 3.8084 +14:51:05 3.9762 +14:51:10 3.9739 +14:51:15 3.5739 +14:51:20 3.9396 +14:51:25 4.2651 +14:51:30 4.4844 +14:51:35 3.9608 +14:51:40 3.6818 +14:51:45 3.4129 +14:51:50 3.7100 +14:51:55 3.5340 +14:52:00 3.8764 +14:52:05 4.6628 +14:52:10 4.8502 +14:52:15 4.9944 +14:52:20 4.2582 +14:52:25 4.5458 +14:52:30 5.0109 +14:52:35 4.8235 +14:52:40 4.8607 +14:52:45 4.8896 +14:52:50 4.6132 +14:52:55 3.6442 +14:53:00 4.4602 +14:53:05 4.9746 +14:53:10 3.1687 +14:53:15 4.3439 +14:53:20 4.1353 +14:53:25 4.0062 +14:53:30 4.0938 +14:53:35 4.2403 +14:53:40 3.5565 +14:53:45 3.6352 +14:53:50 5.0975 +14:53:55 4.7209 +14:54:00 4.6470 +14:54:05 5.1167 +14:54:10 4.2715 +14:54:15 4.9665 +14:54:20 4.0763 +14:54:25 4.2809 +14:54:30 4.4555 +14:54:35 4.6470 +14:54:40 5.0003 +14:54:45 4.7497 +14:54:50 4.5890 +14:54:55 4.8740 +14:55:00 4.0362 +14:55:05 4.9024 +14:55:10 3.7485 +14:55:15 3.1337 +14:55:20 3.9894 +14:55:25 4.7961 +14:55:30 4.5765 +14:55:35 4.7683 +14:55:40 3.7457 +14:55:45 3.2225 +14:55:50 2.4384 +14:55:55 2.8683 +14:56:00 2.7061 +14:56:05 4.0842 +14:56:10 2.5299 +14:56:15 4.4479 +14:56:20 2.8100 +14:56:25 4.7457 +14:56:30 3.2385 +14:56:35 3.7688 +14:56:40 4.5341 +14:56:45 4.6938 +14:56:50 5.0368 +14:56:55 5.0211 +14:57:00 3.7509 +14:57:05 3.8207 +14:57:10 3.7379 +14:57:15 3.2405 +14:57:20 2.5792 +14:57:25 3.2422 +14:57:30 3.6622 +14:57:35 3.2560 +14:57:40 4.6923 +14:57:45 3.6954 +14:57:50 3.5134 +14:57:56 4.3686 +14:58:00 3.9063 +14:58:05 4.6352 +14:58:10 4.9259 +14:58:15 4.6910 +14:58:20 4.4678 +14:58:25 4.5679 +14:58:30 3.3506 +14:58:35 4.0658 +14:58:40 3.6075 +14:58:45 2.3810 +14:58:50 3.2624 +14:58:55 4.6035 +14:59:00 4.4081 +14:59:13 4.9171 +14:59:17 4.0662 +14:59:20 4.1487 +14:59:25 4.7783 +14:59:30 4.6604 +14:59:36 4.9341 +14:59:40 4.6574 +14:59:45 4.9124 +14:59:50 4.4971 +14:59:55 4.3894 +15:00:00 5.1211 +15:00:05 3.9982 +15:00:10 4.8046 +15:00:15 4.7012 +15:00:20 3.8995 +15:00:26 3.0856 +15:00:30 3.3430 +15:00:35 4.5266 +15:00:40 4.3647 +15:00:45 4.6591 +15:00:50 4.7625 +15:00:55 4.6689 +15:01:00 4.7110 +15:01:05 3.8538 +15:01:10 3.5960 +15:01:16 3.5279 +15:01:20 2.6005 +15:01:25 4.5662 +15:01:30 3.8245 +15:01:38 4.2261 +15:01:40 3.8425 +15:01:45 4.7769 +15:01:50 4.5973 +15:01:56 4.4149 +15:02:00 3.8324 +15:02:07 3.4295 +15:02:10 4.6343 +15:02:15 4.0480 +15:02:20 5.0389 +15:02:25 3.0484 +15:02:30 4.0833 +15:02:35 5.1093 +15:02:40 3.9803 +15:02:45 4.9780 +15:02:50 3.2970 +15:02:55 4.4228 +15:03:00 2.8577 +15:03:05 3.5472 +15:03:10 3.6960 +15:03:15 4.1321 +15:03:20 3.5264 +15:03:25 4.5213 +15:03:30 4.6481 +15:03:35 4.2143 +15:03:40 4.1998 +15:03:45 3.4891 +15:03:51 4.5291 +15:03:58 4.0335 +15:04:00 3.4658 +15:04:05 3.6556 +15:04:11 2.9325 +15:04:15 3.1396 +15:04:20 4.3290 +15:04:26 3.6793 +15:04:30 3.9021 +15:04:35 3.7590 +15:04:40 4.5041 +15:04:47 4.1426 +15:04:51 3.3112 +15:04:57 3.7590 +15:05:02 4.3033 +15:05:05 4.4554 +15:05:12 4.0625 +15:05:15 4.0331 +15:05:22 4.6265 +15:05:28 4.3487 +15:05:30 3.1857 +15:05:36 2.9882 +15:05:42 3.5770 +15:05:45 4.0475 +15:05:51 4.4456 +15:06:00 4.0065 +15:06:05 2.7791 +15:06:10 4.2369 +15:06:15 3.0891 +15:06:20 3.8759 +15:06:25 3.9173 +15:06:31 4.2046 +15:06:35 3.4916 +15:06:40 3.3164 +15:06:45 3.6887 +15:06:50 3.2659 +15:06:55 3.9265 +15:07:00 3.1595 +15:07:05 3.9887 +15:07:10 3.9594 +15:07:15 3.1072 +15:07:20 4.7449 +15:07:25 3.8658 +15:07:30 4.2975 +15:07:35 4.5659 +15:07:40 4.2452 +15:07:45 4.2052 +15:07:50 3.2710 +15:07:55 2.8941 +15:08:00 3.9788 +15:08:05 4.7096 +15:08:10 3.3579 +15:08:15 4.6452 +15:08:20 3.4665 +15:08:25 4.3437 +15:08:30 4.4395 +15:08:35 5.0097 +15:08:40 4.9457 +15:08:45 3.9214 +15:08:50 4.7544 +15:08:55 3.4557 +15:09:00 3.6499 +15:09:05 3.7397 +15:09:10 3.0223 +15:09:15 3.5375 +15:09:20 4.4060 +15:09:25 4.9537 +15:09:30 4.1028 +15:09:36 4.7996 +15:09:40 4.5860 +15:09:45 4.3259 +15:09:50 4.3007 +15:09:55 4.2802 +15:10:00 3.2956 +15:10:05 3.1497 +15:10:10 3.6630 +15:10:16 4.2005 +15:10:20 3.7970 +15:10:26 3.6850 +15:10:32 4.0624 +15:10:35 3.3703 +15:10:40 3.5958 +15:10:45 4.1215 +15:10:50 4.3751 +15:10:56 3.7933 +15:11:00 3.6074 +15:11:05 3.5466 +15:11:10 4.2689 +15:11:16 4.1222 +15:11:21 4.2462 +15:11:26 4.1700 +15:11:40 3.4369 +15:11:45 3.6291 +15:11:51 4.8817 +15:11:57 4.7252 +15:12:00 4.6008 +15:12:05 3.3738 +15:12:10 3.7236 +15:12:15 3.9230 +15:12:20 3.7132 +15:12:25 4.4135 +15:12:30 4.7577 +15:12:35 3.9632 +15:12:40 4.7232 +15:12:45 3.9490 +15:12:50 3.9311 +15:12:55 3.8749 +15:13:00 4.8197 +15:13:05 4.8255 +15:13:10 4.1803 +15:13:15 3.5291 +15:13:21 3.3685 +15:13:25 4.1323 +15:13:30 4.2274 +15:13:35 4.0041 +15:13:41 3.8375 +15:13:46 4.2266 +15:13:54 4.3074 +15:13:55 3.5857 +15:14:00 3.4089 +15:14:05 3.5144 +15:14:11 4.0357 +15:14:17 4.3330 +15:14:20 3.9776 +15:14:27 4.6330 +15:14:30 4.5952 +15:14:35 3.9972 +15:14:42 3.1962 +15:14:45 3.7487 +15:14:55 4.2996 +15:15:06 4.2906 +15:15:13 5.0396 +15:15:18 4.3532 +15:15:20 3.1873 +15:15:25 1.8356 +15:15:34 4.6100 +15:15:35 2.7322 +15:15:40 3.6042 +15:15:45 4.2982 +15:15:50 3.6596 +15:15:55 3.7637 +15:16:00 3.8533 +15:16:48 3.8691 +15:16:54 4.0854 +15:16:55 3.9145 +15:17:00 3.8565 +15:17:05 4.0900 +15:17:10 4.2668 +15:17:15 4.5612 +15:17:20 4.6264 +15:17:25 4.7419 +15:17:30 3.3621 +15:17:35 2.8598 +15:17:41 4.5943 +15:17:45 4.6145 +15:17:50 3.0591 +15:17:55 3.5438 +15:18:00 3.7712 +15:18:05 3.1788 +15:18:10 3.4818 +15:18:15 3.8744 +15:18:20 3.7498 +15:18:25 4.3014 +15:18:30 3.9566 +15:18:35 2.6596 +15:18:40 3.6802 +15:18:45 3.7579 +15:18:50 3.9190 +15:18:57 3.8695 +15:19:00 2.6564 +15:19:06 4.6534 +15:19:10 4.4296 +15:19:15 4.0382 +15:19:20 4.9317 +15:19:25 4.5007 +15:19:32 3.6640 +15:19:35 4.8829 +15:19:42 4.4323 +15:19:45 4.2974 +15:19:50 4.7321 +15:19:55 4.1828 +15:20:00 4.0782 +15:20:05 4.2462 +15:20:10 4.2712 +15:20:15 3.9919 +15:20:20 3.6666 +15:20:25 2.9239 +15:20:30 3.7230 +15:20:35 5.0828 +15:20:40 4.5134 +15:20:45 4.4724 +15:20:50 4.7821 +15:20:55 3.4196 +15:21:00 2.7891 +15:21:10 2.7570 +15:21:15 3.9705 +15:21:20 3.9389 +15:21:25 4.6344 +15:21:30 4.8470 +15:21:35 4.9319 +15:21:40 4.9101 +15:21:45 4.2418 +15:21:50 3.7708 +15:21:55 3.6534 +15:22:00 3.0165 +15:22:05 3.1831 +15:22:10 4.1335 +15:22:15 4.6802 +15:22:20 4.6883 +15:22:25 4.7305 +15:22:30 3.5468 +15:22:35 4.4628 +15:22:40 4.9027 +15:22:45 4.1616 +15:22:50 3.7034 +15:22:55 3.6235 +15:23:00 3.6344 +15:23:05 4.1065 +15:23:10 3.6308 +15:23:15 4.4060 +15:23:20 4.9768 +15:23:25 4.7487 +15:23:30 4.5619 +15:23:35 4.1228 +15:23:40 4.0845 +15:23:45 4.4343 +15:23:50 4.7816 +15:23:55 4.6888 +15:24:00 4.1218 +15:24:05 4.2811 +15:24:10 4.9119 +15:24:15 4.7081 +15:24:20 3.8448 +15:24:25 4.2118 +15:24:30 4.3141 +15:24:35 2.8787 +15:24:40 2.3096 +15:24:45 3.0453 +15:24:50 3.1223 +15:24:55 3.4361 +15:25:00 4.6786 +15:25:05 4.8238 +15:25:10 3.9141 +15:25:15 3.0532 +15:25:20 3.5844 +15:25:25 4.1636 +15:25:30 4.6639 +15:25:41 4.2526 +15:25:45 3.5818 +15:25:50 4.3284 +15:25:55 3.0972 +15:26:00 3.3592 +15:26:05 2.6707 +15:26:10 2.5910 +15:26:15 3.0275 +15:26:20 3.3105 +15:26:25 4.1370 +15:26:30 3.3704 +15:26:35 2.3095 +15:26:40 3.1479 +15:26:45 3.4726 +15:26:50 4.0446 +15:26:55 4.5630 +15:27:00 3.5423 +15:27:05 3.9095 +15:27:10 4.5574 +15:27:16 3.7128 +15:27:20 3.6147 +15:27:25 2.3083 +15:27:30 3.8030 +15:27:35 3.9167 +15:27:40 3.6425 +15:27:45 3.5450 +15:27:50 3.5685 +15:27:55 3.5555 +15:28:00 3.4802 +15:28:05 3.4802 +15:28:10 3.7658 +15:28:15 3.4044 +15:28:20 3.4830 +15:28:25 3.8128 +15:28:30 4.8181 +15:28:35 4.7007 +15:28:40 4.6712 +15:28:45 4.4058 +15:28:50 5.0051 +15:28:55 5.0291 +15:29:00 3.9822 +15:29:05 3.4761 +15:29:10 4.2317 +15:29:15 5.1026 +15:29:20 4.3960 +15:29:25 4.2040 +15:29:30 3.9823 +15:29:35 4.3102 +15:29:40 4.2233 +15:29:45 4.0966 +15:29:50 4.3017 +15:29:55 4.2482 +15:30:00 3.7821 +15:30:05 3.7102 +15:30:10 3.8120 +15:30:15 3.7733 +15:30:20 3.7787 +15:30:25 3.7787 +15:30:30 3.7234 +15:30:35 3.3555 +15:30:40 3.4839 +15:30:45 3.4334 +15:30:50 3.5458 +15:30:55 3.5458 +15:31:00 3.5737 +15:31:05 3.8093 +15:31:10 3.8687 +15:31:15 3.6158 +15:31:20 3.6400 +15:31:25 3.8343 +15:31:30 4.3289 +15:31:35 4.6827 +15:31:40 4.0072 +15:31:45 3.2425 +15:31:50 5.0425 +15:31:55 5.0143 +15:32:00 4.0130 +15:32:05 3.9664 +15:32:10 3.4517 +15:32:15 2.9267 +15:32:20 3.2338 +15:32:25 3.5358 +15:32:30 3.8163 +15:32:35 2.9669 +15:32:40 3.4165 +15:32:45 4.0559 +15:32:50 3.7171 +15:32:55 3.8179 +15:33:00 3.4580 +15:33:05 3.4154 +15:33:10 3.5092 +15:33:15 3.5714 +15:33:20 3.7812 +15:33:25 3.5706 +15:33:30 3.4405 +15:33:35 3.8478 +15:33:40 3.6984 +15:33:45 3.8862 +15:33:50 4.0245 +15:33:55 5.1584 +15:34:00 4.2329 +15:34:05 4.4908 +15:34:10 4.6532 +15:34:15 3.9406 +15:34:20 3.7473 +15:34:25 3.6472 +15:34:30 3.4764 +15:34:35 4.1516 +15:34:40 4.1582 +15:34:45 3.4295 +15:34:50 3.9380 +15:34:55 3.7949 +15:35:00 3.8207 +15:35:05 3.8994 +15:35:10 4.7165 +15:35:15 4.3260 +15:35:20 2.8046 +15:35:25 4.3127 +15:35:30 4.6219 +15:35:35 3.7009 +15:35:40 3.2196 +15:35:45 4.1235 +15:35:50 3.3892 +15:35:55 4.1848 +15:36:00 4.2728 +15:36:05 3.0149 +15:36:15 3.5741 +15:36:20 3.3450 +15:36:25 3.5353 +15:36:30 3.7689 +15:36:35 3.1939 +15:36:40 3.3990 +15:36:45 3.7898 +15:36:50 4.0800 +15:36:55 4.1625 +15:37:00 4.0324 +15:37:05 2.6636 +15:37:10 2.9293 +15:37:15 3.4335 +15:37:20 3.0982 +15:37:25 2.9650 +15:37:30 3.0823 +15:37:35 3.9720 +15:37:40 4.6494 +15:37:45 4.0524 +15:37:50 3.3487 +15:37:55 3.0645 +15:38:00 3.5640 +15:38:05 3.1275 +15:38:10 3.8128 +15:38:15 4.5543 +15:38:20 4.9980 +15:38:25 5.0811 +15:38:30 4.4440 +15:38:35 4.6937 +15:38:40 4.5591 +15:38:45 3.6078 +15:38:50 3.5456 +15:38:55 3.7120 +15:39:00 3.2494 +15:39:05 3.7511 +15:39:10 3.3647 +15:39:15 4.6861 +15:39:20 4.7032 +15:39:25 4.2812 +15:39:30 3.5334 +15:39:35 2.9161 +15:39:40 3.7053 +15:39:45 2.9780 +15:39:50 4.4497 +15:39:55 4.5490 +15:40:00 4.8275 +15:40:05 4.9899 +15:40:10 4.6672 +15:40:15 3.9396 +15:40:20 4.7298 +15:40:25 3.8586 +15:40:30 3.6741 +15:40:35 3.9354 +15:40:40 3.5975 +15:40:45 2.8065 +15:40:50 3.5648 +15:40:55 4.0775 +15:41:00 4.9281 +15:41:05 4.7539 +15:41:10 4.9543 +15:41:15 4.2202 +15:41:20 5.0146 +15:41:25 4.0771 +15:41:30 4.5286 +15:41:35 5.0618 +15:41:40 5.1537 +15:41:45 4.8183 +15:41:50 4.9481 +15:41:55 4.3225 +15:42:00 3.4334 +15:42:05 4.0070 +15:42:10 3.1660 +15:42:15 2.7699 +15:42:20 3.7629 +15:42:25 3.9472 +15:42:30 5.0832 +15:42:35 4.8400 +15:42:40 4.7717 +15:42:45 4.0138 +15:42:50 3.5939 +15:42:55 3.7825 +15:43:00 5.0680 +15:43:05 3.8511 +15:43:10 5.1326 +15:43:15 4.0633 +15:43:20 3.2859 +15:43:25 2.0645 +15:43:30 2.0550 +15:43:35 3.5359 +15:43:40 3.5696 +15:43:45 3.2064 +15:43:50 4.5037 +15:43:55 4.4547 +15:44:00 4.2186 +15:44:05 3.2178 +15:44:10 2.2721 +15:44:15 4.1242 +15:44:20 4.7840 +15:44:25 3.0753 +15:44:30 5.1292 +15:44:35 4.0880 +15:44:40 4.3629 +15:44:45 4.6045 +15:44:50 4.0396 +15:44:55 3.6352 +15:45:00 3.4947 +15:45:05 4.2058 +15:45:10 3.6470 +15:45:15 3.2292 +15:45:20 3.3054 +15:45:25 4.3254 +15:45:30 3.3571 +15:45:35 3.4613 +15:45:40 3.6562 +15:45:45 3.9765 +15:45:50 3.8140 +15:45:55 3.2001 +15:46:00 4.2890 +15:46:05 4.2849 +15:46:10 2.8204 +15:46:15 3.1173 +15:46:20 3.3885 +15:46:25 3.7724 +15:46:30 3.2397 +15:46:35 3.3354 +15:46:40 3.9091 +15:46:45 4.1466 +15:46:50 4.3368 +15:46:55 4.6446 +15:47:00 4.5703 +15:47:05 4.5498 +15:47:10 4.6055 +15:47:15 4.2674 +15:47:20 2.9780 +15:47:25 2.9015 +15:47:30 2.9928 +15:47:35 3.1222 +15:47:40 3.6976 +15:47:45 4.0542 +15:47:50 4.9046 +15:47:55 3.9439 +15:48:00 4.4248 +15:48:05 4.6497 +15:48:10 3.4013 +15:48:15 3.9242 +15:48:20 2.8499 +15:48:25 3.5752 +15:48:30 4.1481 +15:48:35 3.6090 +15:48:40 3.4556 +15:48:45 4.0051 +15:48:50 4.5730 +15:48:55 5.0374 +15:49:00 3.7008 +15:49:05 4.3418 +15:49:10 4.5581 +15:49:15 4.4103 +15:49:20 4.3618 +15:49:25 4.8249 +15:49:30 4.5168 +15:49:35 4.3327 +15:49:40 2.8764 +15:49:45 4.5569 +15:49:50 4.4800 +15:49:55 4.5583 +15:50:00 3.6093 +15:50:05 4.0981 +15:50:10 2.7855 +15:50:15 2.4716 +15:50:20 2.5959 +15:50:25 2.6254 +15:50:30 4.3024 +15:50:35 4.2036 +15:50:40 4.3863 +15:50:45 4.2410 +15:50:50 2.7534 +15:50:55 4.0177 +15:51:00 4.0177 +15:51:05 3.9786 +15:51:10 3.9597 +15:51:15 3.9455 +15:51:20 3.9528 +15:51:25 3.9113 +15:51:30 3.9113 +15:51:35 3.8331 +15:51:40 3.8125 +15:51:45 3.8326 +15:51:50 3.8736 +15:51:57 3.9346 +15:52:00 3.9346 +15:52:05 3.9783 +15:52:10 3.9860 +15:52:15 3.9491 +15:52:20 3.9283 +15:52:25 3.8969 +15:52:30 3.8969 +15:52:35 3.7973 +15:52:40 3.7131 +15:52:45 3.6774 +15:52:50 3.5981 +15:52:55 3.5934 +15:53:00 3.5934 +15:53:05 3.5908 +15:53:10 3.6047 +15:53:15 3.6349 +15:53:20 3.7138 +15:53:25 3.7360 +15:53:30 3.7360 +15:53:35 3.6574 +15:53:40 3.5424 +15:53:45 3.5037 +15:53:50 3.5389 +15:53:55 3.5389 +15:54:00 3.6133 +15:54:05 3.5394 +15:54:10 3.5531 +15:54:15 3.6394 +15:54:20 3.7266 +15:54:25 3.7266 +15:54:30 3.5878 +15:54:35 3.6012 +15:54:40 3.7164 +15:54:45 3.9094 +15:54:50 4.0513 +15:54:55 4.0513 +15:55:00 4.1209 +15:55:05 4.1304 +15:55:10 4.0536 diff --git a/mcstas/dmc/vdmcstatus.tcl b/mcstas/dmc/vdmcstatus.tcl index 1b9a1bb9..50cc4e40 100644 --- a/mcstas/dmc/vdmcstatus.tcl +++ b/mcstas/dmc/vdmcstatus.tcl @@ -122,10 +122,10 @@ twothetad failafter 3.000000 twothetad maxretry 3.000000 twothetad movecount 10.000000 # Counter counter -counter SetPreset 60000.000000 +counter SetPreset 6000.000000 counter SetMode Monitor banana CountMode monitor -banana preset 60000.000000 +banana preset 6000.000000 # Motor a1 a1 sign 1.000000 a1 SoftZero 0.000000 @@ -257,7 +257,7 @@ comment2 UNKNOWN comment2 setAccess 2 comment3 UNKNOWN comment3 setAccess 2 -starttime 2008-03-18 13:09:23 +starttime 2008-11-17 13:02:54 starttime setAccess 2 adress 2223 Luketown, 33 Luke Drive adress setAccess 2 @@ -269,7 +269,7 @@ email Luke@luke.ch email setAccess 2 sample_mur 0.000000 sample_mur setAccess 2 -lastdatafile /afs/psi.ch/user/k/koennecke/src/workspace/sics/mcstas/dmc/000/vdmc2008n000230.xml +lastdatafile /afs/psi.ch/user/k/koennecke/src/workspace/sics/mcstas/dmc/000/vdmc2008n000232.xml lastdatafile setAccess 2 lastscancommand unknown scan lastscancommand setAccess 2 diff --git a/mcstascounter.c b/mcstascounter.c index adbf2c02..50d4b8b4 100644 --- a/mcstascounter.c +++ b/mcstascounter.c @@ -16,147 +16,171 @@ #define SCRIPTERROR -110 #define NOTIMPLEMENTED -111 /*====================== interface functions ==============================*/ -static int McStatus(struct __COUNTER *self, float *fControl){ - int status; - pMcStasController pMcStas = NULL; - - pMcStas = (pMcStasController)self->pData; - - status = McStasStatus(pMcStas,fControl); - if(status == HWFault){ - self->iErrorCode = SCRIPTERROR; - return status; - } - return status; +static int McStatus(struct __COUNTER *self, float *fControl) +{ + int status; + pMcStasController pMcStas = NULL; + + pMcStas = (pMcStasController) self->pData; + + status = McStasStatus(pMcStas, fControl); + if (status == HWFault) { + self->iErrorCode = SCRIPTERROR; + return status; + } + return status; } + /*--------------------------------------------------------------------------*/ -static int McStart(struct __COUNTER *self){ - int status; - pMcStasController pMcStas = NULL; - - pMcStas = (pMcStasController)self->pData; - - memset(self->lCounts,0,MAXCOUNT*sizeof(long)); - status = McStasStart(pMcStas,self->eMode,self->fPreset); - if(status == HWFault){ - self->iErrorCode = SCRIPTERROR; - } - return status; +static int McStart(struct __COUNTER *self) +{ + int status; + pMcStasController pMcStas = NULL; + + pMcStas = (pMcStasController) self->pData; + + memset(self->lCounts, 0, MAXCOUNT * sizeof(long)); + status = McStasStart(pMcStas, self->eMode, self->fPreset); + if (status == HWFault) { + self->iErrorCode = SCRIPTERROR; + } + return status; } + /*--------------------------------------------------------------------------*/ -static int McPause(struct __COUNTER *self){ - self->iErrorCode = NOTIMPLEMENTED; - return HWFault; +static int McPause(struct __COUNTER *self) +{ + self->iErrorCode = NOTIMPLEMENTED; + return HWFault; } + /*--------------------------------------------------------------------------*/ -static int McContinue(struct __COUNTER *self){ - self->iErrorCode = NOTIMPLEMENTED; - return HWFault; +static int McContinue(struct __COUNTER *self) +{ + self->iErrorCode = NOTIMPLEMENTED; + return HWFault; } + /*--------------------------------------------------------------------------*/ -static int McHalt(struct __COUNTER *self){ - int status; - pMcStasController pMcStas = NULL; - - pMcStas = (pMcStasController)self->pData; - - status = McStasStop(pMcStas); - if(status == HWFault){ - self->iErrorCode = SCRIPTERROR; - } - return status; +static int McHalt(struct __COUNTER *self) +{ + int status; + pMcStasController pMcStas = NULL; + + pMcStas = (pMcStasController) self->pData; + + status = McStasStop(pMcStas); + if (status == HWFault) { + self->iErrorCode = SCRIPTERROR; + } + return status; } + /*--------------------------------------------------------------------------*/ -static int McReadValues(struct __COUNTER *self){ - int status; - pMcStasController pMcStas = NULL; - - pMcStas = (pMcStasController)self->pData; - - status = McStasTransferData(pMcStas); - if(status == HWFault){ - self->iErrorCode = SCRIPTERROR; - } - self->fTime = time(NULL) - pMcStas->startTime; - return status; +static int McReadValues(struct __COUNTER *self) +{ + int status; + pMcStasController pMcStas = NULL; + + pMcStas = (pMcStasController) self->pData; + + status = McStasTransferData(pMcStas); + if (status == HWFault) { + self->iErrorCode = SCRIPTERROR; + } + self->fTime = time(NULL) - pMcStas->startTime; + return status; } + /*--------------------------------------------------------------------------*/ static int McGetError(struct __COUNTER *self, int *iCode, char *error, - int iErrLen){ - pMcStasController pMcStas = NULL; - pMcStas = (pMcStasController)self->pData; + int iErrLen) +{ + pMcStasController pMcStas = NULL; + pMcStas = (pMcStasController) self->pData; - switch(self->iErrorCode){ - case SCRIPTERROR: - McStasGetError(pMcStas,error,iErrLen); - break; - case NOTIMPLEMENTED: - strncpy(error,"Feauture not implemented",iErrLen); - break; - default: - strncpy(error,"Unknown error code in McStas Driver",iErrLen); - break; - } - return 1; + switch (self->iErrorCode) { + case SCRIPTERROR: + McStasGetError(pMcStas, error, iErrLen); + break; + case NOTIMPLEMENTED: + strlcpy(error, "Feauture not implemented", iErrLen); + break; + default: + strlcpy(error, "Unknown error code in McStas Driver", iErrLen); + break; + } + return 1; } + /*------------------------------------------------------------------------*/ -static int McTryAndFixIt(struct __COUNTER *self, int iCode){ - int status; - pMcStasController pMcStas = NULL; - - pMcStas = (pMcStasController)self->pData; - - status = McStasFix(pMcStas); - return status; +static int McTryAndFixIt(struct __COUNTER *self, int iCode) +{ + int status; + pMcStasController pMcStas = NULL; + + pMcStas = (pMcStasController) self->pData; + + status = McStasFix(pMcStas); + return status; } + /*------------------------------------------------------------------------*/ -static int McSet(struct __COUNTER *self, char *name, int iCter, float FVal){ - return 1; +static int McSet(struct __COUNTER *self, char *name, int iCter, float FVal) +{ + return 1; } + /*------------------------------------------------------------------------*/ -static int McGet(struct __COUNTER *self, char *name, int iCter, float *fVal){ - *fVal = 25.99; - return 1; +static int McGet(struct __COUNTER *self, char *name, int iCter, + float *fVal) +{ + *fVal = 25.99; + return 1; } + /*-------------------------------------------------------------------------*/ -static int McSend(struct __COUNTER *self, char *pText, - char *pReply, int iReplyLen){ - strncpy(pReply,"WARNING: McStas simulation cannot be sent anything", - iReplyLen); - return 1; +static int McSend(struct __COUNTER *self, char *pText, + char *pReply, int iReplyLen) +{ + strlcpy(pReply, "WARNING: McStas simulation cannot be sent anything", + iReplyLen); + return 1; } + /*-------------------------------------------------------------------------*/ -pCounterDriver NewMcStasCounter(char *name){ - pMcStasController pMcStas = NULL; - pCounterDriver pNew = NULL; +pCounterDriver NewMcStasCounter(char *name) +{ + pMcStasController pMcStas = NULL; + pCounterDriver pNew = NULL; - /* - * cannot do it without a McStas Controller - */ - pMcStas = FindCommandData(pServ->pSics,"mccontrol","McStasController"); - if(pMcStas == NULL){ - return NULL; - } - - pNew = CreateCounterDriver(name,"McStas"); - if(pNew == NULL){ - return NULL; - } - pNew->iNoOfMonitors = 10; - pNew->pData = pMcStas; - - pNew->GetStatus = McStatus; - pNew->Start = McStart; - pNew->Halt = McHalt; - pNew->ReadValues = McReadValues; - pNew->GetError = McGetError; - pNew->TryAndFixIt = McTryAndFixIt; - pNew->Pause = McPause; - pNew->Continue = McContinue; - pNew->Set = McSet; - pNew->Get = McGet; - pNew->Send = McSend; - pNew->KillPrivate = NULL; + /* + * cannot do it without a McStas Controller + */ + pMcStas = FindCommandData(pServ->pSics, "mccontrol", "McStasController"); + if (pMcStas == NULL) { + return NULL; + } - return pNew; -} + pNew = CreateCounterDriver(name, "McStas"); + if (pNew == NULL) { + return NULL; + } + pNew->iNoOfMonitors = 10; + pNew->pData = pMcStas; + + pNew->GetStatus = McStatus; + pNew->Start = McStart; + pNew->Halt = McHalt; + pNew->ReadValues = McReadValues; + pNew->GetError = McGetError; + pNew->TryAndFixIt = McTryAndFixIt; + pNew->Pause = McPause; + pNew->Continue = McContinue; + pNew->Set = McSet; + pNew->Get = McGet; + pNew->Send = McSend; + pNew->KillPrivate = NULL; + + return pNew; +} diff --git a/mcstashm.c b/mcstashm.c index 9e2b10e3..16d43e68 100644 --- a/mcstashm.c +++ b/mcstashm.c @@ -17,193 +17,221 @@ #include "stringdict.h" #include "HistDriv.i" /*================= operator functions ====================================*/ -static int McHMConfigure(pHistDriver self, SConnection *pCon, - pStringDict pOpt, SicsInterp *pSics){ - char counterName[80]; - char pError[256]; - - if(StringDictGet(pOpt,"counter",counterName,79) == 1){ - self->pPriv = FindCommandData(pSics,counterName,"SingleCounter"); - if(self->pPriv == NULL){ - snprintf(pError,255, - "ERROR: tried to configure counter but %s not found", - counterName); - SCWrite(pCon,pError,eError); - return 0; - } - } - self->iReconfig = 0; - return configureHMdata(self->data,pOpt,pCon); +static int McHMConfigure(pHistDriver self, SConnection * pCon, + pStringDict pOpt, SicsInterp * pSics) +{ + char counterName[80]; + char pError[256]; + + if (StringDictGet(pOpt, "counter", counterName, 79) == 1) { + self->pPriv = FindCommandData(pSics, counterName, "SingleCounter"); + if (self->pPriv == NULL) { + snprintf(pError, 255, + "ERROR: tried to configure counter but %s not found", + counterName); + SCWrite(pCon, pError, eError); + return 0; + } + } + self->iReconfig = 0; + return configureHMdata(self->data, pOpt, pCon); } + /*-------------------------------------------------------------------------*/ -static int McHMStart(pHistDriver self, SConnection *pCon){ - pCounter pCount = NULL; - - /* - * clear data - */ - clearHMData(self->data); - /* - * if there is a counter, make him start - */ - pCount = (pCounter)self->pPriv; - if(pCount != NULL){ - pCount->pDriv->eMode = self->eCount; - pCount->pDriv->fPreset = self->fCountPreset; - return pCount->pCountInt->StartCount(pCount,pCon); - } else { - return 1; - } +static int McHMStart(pHistDriver self, SConnection * pCon) +{ + pCounter pCount = NULL; + + /* + * clear data + */ + clearHMData(self->data); + /* + * if there is a counter, make him start + */ + pCount = (pCounter) self->pPriv; + if (pCount != NULL) { + pCount->pDriv->eMode = self->eCount; + pCount->pDriv->fPreset = self->fCountPreset; + return pCount->pCountInt->StartCount(pCount, pCon); + } else { + return 1; + } } + /*------------------------------------------------------------------------*/ -static int McHMHalt(pHistDriver self){ - pCounter pCount = NULL; +static int McHMHalt(pHistDriver self) +{ + pCounter pCount = NULL; - pCount = (pCounter)self->pPriv; - if(pCount != NULL){ - return pCount->pCountInt->Halt(pCount); - } else { - return 1; - } + pCount = (pCounter) self->pPriv; + if (pCount != NULL) { + return pCount->pCountInt->Halt(pCount); + } else { + return 1; + } } + /*-------------------------------------------------------------------------*/ -static int McHMCountStatus(pHistDriver self, SConnection *pCon){ - pCounter pCount = NULL; +static int McHMCountStatus(pHistDriver self, SConnection * pCon) +{ + pCounter pCount = NULL; - pCount = (pCounter)self->pPriv; - if(pCount != NULL){ - return pCount->pCountInt->CheckCountStatus(pCount,pCon); - } else { - return HWIdle; - } + pCount = (pCounter) self->pPriv; + if (pCount != NULL) { + return pCount->pCountInt->CheckCountStatus(pCount, pCon); + } else { + return HWIdle; + } } + /*------------------------------------------------------------------------*/ -static int McHMGetError(pHistDriver self, int *iCode, char *error, int errLen){ - pCounter pCount = NULL; +static int McHMGetError(pHistDriver self, int *iCode, char *error, + int errLen) +{ + pCounter pCount = NULL; - pCount = (pCounter)self->pPriv; - if(pCount != NULL){ - return pCount->pDriv->GetError(pCount->pDriv,iCode, error, errLen); - } else { - *iCode = -1000; - strncpy(error,"Feature not implemented in McStasHM",errLen); - return 1; - } + pCount = (pCounter) self->pPriv; + if (pCount != NULL) { + return pCount->pDriv->GetError(pCount->pDriv, iCode, error, errLen); + } else { + *iCode = -1000; + strlcpy(error, "Feature not implemented in McStasHM", errLen); + return 1; + } } + /*-------------------------------------------------------------------------*/ -static int McHMFixIt(pHistDriver self, int iCode){ - pCounter pCount = NULL; +static int McHMFixIt(pHistDriver self, int iCode) +{ + pCounter pCount = NULL; - pCount = (pCounter)self->pPriv; - if(pCount != NULL){ - return pCount->pDriv->TryAndFixIt(pCount->pDriv,iCode); - } else { - return COTERM; - } + pCount = (pCounter) self->pPriv; + if (pCount != NULL) { + return pCount->pDriv->TryAndFixIt(pCount->pDriv, iCode); + } else { + return COTERM; + } } -/*-----------------------------------------------------------------------*/ -static int McHMGetData(pHistDriver self, SConnection *pCon){ - pCounter pCount = NULL; - pCount = (pCounter)self->pPriv; - if(pCount != NULL){ - return pCount->pCountInt->TransferData(pCount,pCon); - } else { - return 1; - } -} /*-----------------------------------------------------------------------*/ -static int McHMGetHistogram(pHistDriver self, SConnection *pCon, - int bank, int start, int end, HistInt *pData){ +static int McHMGetData(pHistDriver self, SConnection * pCon) +{ + pCounter pCount = NULL; + + pCount = (pCounter) self->pPriv; + if (pCount != NULL) { + return pCount->pCountInt->TransferData(pCount, pCon); + } else { + return 1; + } +} + +/*-----------------------------------------------------------------------*/ +static int McHMGetHistogram(pHistDriver self, SConnection * pCon, + int bank, int start, int end, HistInt * pData) +{ /* * make sure data gets transferred */ - return McHMGetData(self,pCon); + return McHMGetData(self, pCon); } -/*-------------------------------------------------------------------------*/ -static int McHMSetHistogram(pHistDriver self, SConnection *pCon, - int bank, int start, int end, - HistInt *pData){ - int i, count = 0; - HistInt *hmData; - - assert(bank == 0); - hmData = self->data->localBuffer; - for(i = start; i < end; i++, count++){ - hmData[i] = pData[count]; - } - return 1; -} /*-------------------------------------------------------------------------*/ -static long McHMMonitor(pHistDriver self, int i, SConnection *pCon){ - pCounter pCount = NULL; +static int McHMSetHistogram(pHistDriver self, SConnection * pCon, + int bank, int start, int end, HistInt * pData) +{ + int i, count = 0; + HistInt *hmData; - pCount = (pCounter)self->pPriv; - if(pCount != NULL){ - return GetMonitor(pCount,i,pCon); - } else { - return 0L; - } + assert(bank == 0); + + hmData = self->data->localBuffer; + for (i = start; i < end; i++, count++) { + hmData[i] = pData[count]; + } + return 1; } -/*-------------------------------------------------------------------------*/ -static float McHMGetTime(pHistDriver self, SConnection *pCon){ - pCounter pCount = NULL; - pCount = (pCounter)self->pPriv; - if(pCount != NULL){ - return GetCountTime(pCount,pCon);; - } else { - return -999.99; - } +/*-------------------------------------------------------------------------*/ +static long McHMMonitor(pHistDriver self, int i, SConnection * pCon) +{ + pCounter pCount = NULL; + + pCount = (pCounter) self->pPriv; + if (pCount != NULL) { + return GetMonitor(pCount, i, pCon); + } else { + return 0L; + } } + +/*-------------------------------------------------------------------------*/ +static float McHMGetTime(pHistDriver self, SConnection * pCon) +{ + pCounter pCount = NULL; + + pCount = (pCounter) self->pPriv; + if (pCount != NULL) { + return GetCountTime(pCount, pCon);; + } else { + return -999.99; + } +} + /*--------------------------------------------------------------------------*/ -static int McHMPreset(pHistDriver self, SConnection *pCon, HistInt val){ - int i; - long length; - HistInt *data; - - length = getHMDataLength(self->data); - data = self->data->localBuffer; - for(i = 0; i < length; i++){ - data[i] = val; - } - return 1; -} -/*------------------------------------------------------------------------*/ -static int McHMPause(pHistDriver self, SConnection *pCon){ - return HWFault; -} -/*-----------------------------------------------------------------------*/ -static int McHMContinue(pHistDriver self, SConnection *pCon){ - return HWFault; -} -/*========================== the actual creation function ================*/ -pHistDriver NewMcStasHM(pStringDict pOpt){ - pHistDriver pNew = NULL; - - pNew = CreateHistDriver(pOpt); - if(pNew == NULL){ - return NULL; - } - pNew->Configure = McHMConfigure; - pNew->Start = McHMStart; - pNew->Halt = McHMHalt; - pNew->GetCountStatus = McHMCountStatus; - pNew->GetError = McHMGetError; - pNew->TryAndFixIt = McHMFixIt; - pNew->GetData = McHMGetData; - pNew->GetHistogram = McHMGetHistogram; - pNew->SetHistogram = McHMSetHistogram; - pNew->GetMonitor = McHMMonitor; - pNew->GetTime = McHMGetTime; - pNew->Preset = McHMPreset; - pNew->FreePrivate = NULL; - pNew->Pause = McHMPause; - pNew->Continue = McHMContinue; - StringDictAddPair(pOpt,"counter","UNKNOWN"); - StringDictUpdate(pOpt,"update","10"); - - return pNew; +static int McHMPreset(pHistDriver self, SConnection * pCon, HistInt val) +{ + int i; + long length; + HistInt *data; + + length = getHMDataLength(self->data); + data = self->data->localBuffer; + for (i = 0; i < length; i++) { + data[i] = val; + } + return 1; } +/*------------------------------------------------------------------------*/ +static int McHMPause(pHistDriver self, SConnection * pCon) +{ + return HWFault; +} + +/*-----------------------------------------------------------------------*/ +static int McHMContinue(pHistDriver self, SConnection * pCon) +{ + return HWFault; +} + +/*========================== the actual creation function ================*/ +pHistDriver NewMcStasHM(pStringDict pOpt) +{ + pHistDriver pNew = NULL; + + pNew = CreateHistDriver(pOpt); + if (pNew == NULL) { + return NULL; + } + pNew->Configure = McHMConfigure; + pNew->Start = McHMStart; + pNew->Halt = McHMHalt; + pNew->GetCountStatus = McHMCountStatus; + pNew->GetError = McHMGetError; + pNew->TryAndFixIt = McHMFixIt; + pNew->GetData = McHMGetData; + pNew->GetHistogram = McHMGetHistogram; + pNew->SetHistogram = McHMSetHistogram; + pNew->GetMonitor = McHMMonitor; + pNew->GetTime = McHMGetTime; + pNew->Preset = McHMPreset; + pNew->FreePrivate = NULL; + pNew->Pause = McHMPause; + pNew->Continue = McHMContinue; + StringDictAddPair(pOpt, "counter", "UNKNOWN"); + StringDictUpdate(pOpt, "update", "10"); + + return pNew; +} diff --git a/mcstashm.h b/mcstashm.h index 4596448e..e17b5944 100644 --- a/mcstashm.h +++ b/mcstashm.h @@ -12,5 +12,5 @@ -------------------------------------------------------------------------*/ #ifndef _MCSTASHM_H_ #define _MCSTASHM_H_ - pHistDriver NewMcStasHM(pStringDict pOpt); -#endif //_MCSTASHM_H_ +pHistDriver NewMcStasHM(pStringDict pOpt); +#endif //_MCSTASHM_H_ diff --git a/mesure.c b/mesure.c deleted file mode 100644 index cb69ba3b..00000000 --- a/mesure.c +++ /dev/null @@ -1,1879 +0,0 @@ -/*------------------------------------------------------------------------- - M E S U R E - - An object for doing four circle diffractometer measurements with - a single counter. - - copyright: see copyright.h - - Mark Koennecke, April 1998 - heavily reworked: Mark Koennecke, February-March 2005 ----------------------------------------------------------------------------*/ -#include -#include -#include -#include -#include -#include "fortify.h" -#include "sics.h" -#include "motor.h" -#include "o2t.h" -#include "scan.h" -#include "scan.i" -#include "stdscan.h" -#include "danu.h" -#include "integrate.h" -#include "hkl.h" -#include "matrix/matrix.h" -#include "hkl.i" -#include "sicsvar.h" -#include "evcontroller.h" -#include "mesure.h" -#include "nxscript.h" -#include "fourtable.h" -#include "lld.h" -#include "stdscan.h" -#include "exeman.h" - - extern void SNXFormatTime(char *pBueffel, int iLen); - extern float nintf(float f); -#define ANGERR 0.2 - -/* -#define MESSDEBUG 1 - - define MESSDEBUG for simulated peaks. This helps in debugging - this code and the initial data correction code -*/ - - extern void SNXFormatTime(char *pBueffel, int iLen); /* nxutil.c */ - -/*------------------- the data structure -----------------------------------*/ - typedef struct __Mesure - { - pObjectDescriptor pDes; /* standard object descriptor */ - pICallBack pCall; /* callback interface for automatic notification */ - pScanData pScanner; /* scan object to use for scans */ - pHKL pCryst; /* hkl object for crystallographic calc - and reflection driving */ - pMotor pOmega; /* motor for omega scans */ - pMotor p2Theta; /* motor for 2 theta scans*/ - char *pCOmega; /* name of omega motor */ - char *pC2Theta; /* name of 2 theta motor */ - char *pFileRoot; /* where to write files */ - pDataNumber pDanu; /* where to get data file number */ - FILE *fRefl; /* reflection profile file */ - FILE *fHKL; /* integrated intensity file */ - int iLogFile; /* log file num at connection */ - SConnection *pCon; /* log file owning connection */ - char *pCurrentFile; /* current file root */ - char headerTemplate[512]; - int iCount; /* count of reflection */ - int CountMode; /* timer or preset */ - int np; /* number of scan points */ - float fPreset; /* counting preset */ - float fStep; /* omega step widths */ - long *lCounts; /* array to store counting values */ - float fPosition[4]; /* the real positions after driving */ - int iCompact; /* true if compact scan ouput. */ - int weak; /* weak flag: remeasure weak reflections */ - long weakThreshold; /* threshold when a peak is so weak that is has to - remeasured */ - int fastScan; /* flag for using fastscans for scanning reflections */ - int psiMode; /* 1 for psi scan mode, 0 else */ - int psd; /* a flag for making 2D detector scans */ - int stepTable; /* mapping of two theta ranges to step width and - variable to scan */ - } Mesure; -/*-------------------------------------------------------------------------*/ -static int SaveMesure(void *pData, char *name, FILE *fd) -{ - pMesure self = (pMesure)pData; - - fprintf(fd,"#Four Circle Dataset Module %s\n",name); - if(self->CountMode == eTimer) - { - fprintf(fd,"%s countmode timer\n",name); - } - else - { - fprintf(fd,"%s countmode monitor\n",name); - } - fprintf(fd,"%s np %d\n", name, self->np); - fprintf(fd,"%s preset %f\n", name, self->fPreset); - fprintf(fd,"%s step %f\n", name, self->fStep); - fprintf(fd,"%s weakthreshold %ld\n", name, self->weakThreshold); - fprintf(fd,"%s compact %d\n", name, self->iCompact); - fprintf(fd,"%s psd %d\n", name, self->psd); - fprintf(fd,"%s weak %d\n", name, self->weak); - fprintf(fd,"%s fastscan %d\n", name, self->fastScan); - SaveFourCircleTable(self->stepTable,name,fd); - return 1; -} -/*-------------------------------------------------------------------------*/ -static void ListMesure(pMesure self, char *name, SConnection *pCon) -{ - Tcl_DString list; - char pBuffer[132]; - - Tcl_DStringInit(&list); - if(self->CountMode == eTimer) - { - snprintf(pBuffer,131,"%s.countmode timer\n",name); - } - else - { - snprintf(pBuffer,131,"%s.countmode monitor\n",name); - } - Tcl_DStringAppend(&list,pBuffer,-1); - snprintf(pBuffer,131,"%s.np %d\n", name, self->np); - Tcl_DStringAppend(&list,pBuffer,-1); - snprintf(pBuffer,131,"%s.preset %f\n", name, self->fPreset); - Tcl_DStringAppend(&list,pBuffer,-1); - snprintf(pBuffer,131,"%s.step %f\n", name, self->fStep); - Tcl_DStringAppend(&list,pBuffer,-1); - snprintf(pBuffer,131,"%s.weakthreshold %ld\n", name, self->weakThreshold); - Tcl_DStringAppend(&list,pBuffer,-1); - snprintf(pBuffer,131,"%s.compact %d\n", name, self->iCompact); - Tcl_DStringAppend(&list,pBuffer,-1); - snprintf(pBuffer,131,"%s.psd %d\n", name, self->psd); - Tcl_DStringAppend(&list,pBuffer,-1); - snprintf(pBuffer,131,"%s.weak %d\n", name, self->weak); - Tcl_DStringAppend(&list,pBuffer,-1); - snprintf(pBuffer,131,"%s.fastscan %d\n", name, self->fastScan); - Tcl_DStringAppend(&list,pBuffer,-1); - SCWrite(pCon,Tcl_DStringValue(&list),eValue); - Tcl_DStringFree(&list); -} -/*--------------------------------------------------------------------------*/ - pMesure CreateMesure(pHKL pCryst, pScanData pScanner, pMotor pOmega, - char *pOm, pMotor p2Theta, char *p2t, - char *pFileRoot, - pDataNumber pDanu, char *hdTemplate) - { - pMesure pNew = NULL; - - assert(pCryst); - assert(pScanner); - assert(pOmega); - assert(pFileRoot); - assert(pDanu); - - /* allocate space............. */ - pNew = (pMesure)malloc(sizeof(Mesure)); - if(!pNew) - { - return NULL; - } - memset(pNew,0,sizeof(Mesure)); - - pNew->pDes = CreateDescriptor("Mesure"); - pNew->pDes->SaveStatus = SaveMesure; - pNew->pCall = CreateCallBackInterface(); - if( !pNew->pDes || !pNew->pCall) - { - free(pNew); - return NULL; - } - - /* asssign defaults */ - pNew->pScanner = pScanner; - pNew->pCryst = pCryst; - pNew->pOmega = pOmega; - pNew->p2Theta = p2Theta; - pNew->pCOmega = strdup(pOm); - pNew->pC2Theta = strdup(p2t); - pNew->pFileRoot = strdup(pFileRoot); - pNew->pDanu = pDanu; - pNew->iCount = 0; - pNew->CountMode = 0; - pNew->np = 50; - pNew->fStep = 0.05; - pNew->fPreset = 2; - pNew->iCompact = 1; - pNew->psd = 0; - pNew->weak = 0; - pNew->weakThreshold = 99999; - pNew->fastScan = 0; - pNew->psiMode = 0; -#ifdef MESSDEBUG - pNew->lCounts = (long *)malloc(90*sizeof(long)); -#endif - pNew->lCounts = (long *)malloc(50*sizeof(long)); - pNew->stepTable = MakeFourCircleTable(); - strncpy(pNew->headerTemplate,hdTemplate,511); - return pNew; - } -/*------------------------------------------------------------------------*/ - void DeleteMesure(void *pData) - { - pMesure self = NULL; - - self = (pMesure)pData; - - if(!pData) - { - return; - } - - if(self->pDes) - DeleteDescriptor(self->pDes); - - if(self->pCall) - DeleteCallBackInterface(self->pCall); - if(self->pFileRoot) - free(self->pFileRoot); - if(self->pCOmega) - free(self->pCOmega); - if(self->fRefl) - MesureClose(self); - if(self->lCounts) - free(self->lCounts); - DeleteFourCircleTable(self->stepTable); - free(self); - } -/*------------------------------------------------------------------------*/ - int MesureFactory(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - pMesure pNew = NULL; - pHKL pCryst = NULL; - pScanData pScan = NULL; - CommandList *pCom = NULL; - pMotor pMot = NULL, pMot2 = NULL; - pDataNumber pDanu = NULL; - pSicsO2T pO2T = NULL; - char pBueffel[512]; - pDummy pDum = NULL; - int iRet; - - assert(pCon); - assert(pSics); - - /* check no of parameters - inicom name hkl scan omega root danu - */ - if(argc < 9) - { - SCWrite(pCon, - "ERROR: Insufficient number of parameters to MesureFactory",eError); - return 0; - } - - /* work parameters one by one, first hkl */ - pCom = FindCommand(pSics,argv[2]); - if(pCom) - { - pDum = (pDummy)pCom->pData; - if(pDum) - { - if(strcmp(pDum->pDescriptor->name,"4-Circle-Calculus") == 0) - { - pCryst = (pHKL)pCom->pData; - } - } - } - if(!pCryst) - { - sprintf(pBueffel,"ERROR: %s is no four circle calculus object",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* scanner */ - pCom = FindCommand(pSics,argv[3]); - if(pCom) - { - pDum = (pDummy)pCom->pData; - if(pDum) - { - if(strcmp(pDum->pDescriptor->name,"ScanObject") == 0) - { - pScan = (pScanData)pCom->pData; - } - } - } - if(!pScan) - { - sprintf(pBueffel,"ERROR: %s is no scan object",argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* omega */ - pMot = FindMotor(pSics,argv[4]); - if(!pMot) - { - sprintf(pBueffel,"ERROR: %s is no motor object ",argv[4]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* 2 theta */ - pMot2 = FindMotor(pSics,argv[5]); - if(!pMot2) - { - sprintf(pBueffel,"ERROR: %s is no motor object ",argv[5]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* Data Number */ - pCom = FindCommand(pSics,argv[7]); - if(pCom) - { - pDum = (pDummy)pCom->pData; - if(pDum) - { - if(strcmp(pDum->pDescriptor->name,"DataNumber") == 0) - { - pDanu = (pDataNumber)pCom->pData; - } - } - } - if(!pDanu) - { - sprintf(pBueffel,"ERROR: %s is no DataNumber object",argv[7]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* finally create the thing */ - pNew = CreateMesure(pCryst,pScan,pMot,argv[4], pMot2, argv[5], - argv[6],pDanu,argv[8]); - if(!pNew) - { - SCWrite(pCon,"ERROR: no memory in MesureFactory",eError); - return 0; - } - - /* add the new command */ - iRet = AddCommand(pSics,argv[1],MesureAction,DeleteMesure,pNew); - if(!iRet) - { - sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - return 1; - } -/*------------------------------------------------------------------------ - This implements the compact scan output for TRICS scans -*/ - static int CompactScanData(pScanData self, int iPoint) - { - pVarEntry pVar = NULL; - void *pDings; - int i, iRet, status; - float fVal; - char pStatus[512], pItem[20]; - char pHead[512]; - CountEntry sCount; - char *pAns = NULL, *pPtr = NULL ; - Tcl_Interp *pTcl; - - assert(self); - assert(self->pCon); - - /* loop over all scan variables */ - status = 1; - memset(pHead,0,512*sizeof(char)); - memset(pStatus,0,512*sizeof(char)); - memset(pItem,0,20*sizeof(char)); - for(i = 0; i < self->iScanVar; i++) - { - DynarGet(self->pScanVar,i,&pDings); - pVar = (pVarEntry)pDings; - if(pVar) - { - fVal = pVar->pInter->GetValue(pVar->pObject,self->pCon); - AppendScanVar(pVar,fVal); - sprintf(pItem,"%-10.10s",pVar->Name); - strcat(pHead,pItem); - sprintf(pItem,"%-10.3f",fVal); - strcat(pStatus,pItem); - } - } - - /* store counter data */ - /* monitors */ - for(i = 1; i < 10; i++) - { - sCount.Monitors[i-1] = GetMonitor((pCounter)self->pCounterData,i, - self->pCon); - } - if( self->iChannel != 0 && self->iChannel != -10 ) - { - sCount.Monitors[self->iChannel - 1] = - GetCounts((pCounter)self->pCounterData, - self->pCon); - } - if(self->iChannel == 0) - { - sCount.lCount = GetCounts((pCounter)self->pCounterData,self->pCon); - } - else - { - sCount.lCount = GetMonitor((pCounter)self->pCounterData, - self->iChannel, self->pCon); - } - - /* stow away */ - DynarReplace(self->pCounts,self->iCounts,&sCount,sizeof(CountEntry)); - self->iCounts++; - - return 1; - } -/*------------------------------------------------------------------------*/ -static int getMesureNP(pMesure self, double twoTheta) -{ - int np; - np = GetFourCircleScanNP(self->stepTable,twoTheta); - if(np < -800){ - np = self->np; - } - return np; -} -/*------------------------------------------------------------------------- - This is slightly tricky: the crystallography module has a scan tolerance. - This is supposed to be automatically set. In order to do so, I need - the step width which in turn is dependent on two theta. Therefore I calculate - two times: the first time with a scan tolerance of 0 to get two theta, the - second time with the scan tolerance ste to a decent value to get the - real thing. - ---------------------------------------------------------------------------*/ -static int MesureCalculateSettings(pMesure self, float fHKL[3], float fSet[4], - float fPsi, SConnection *pCon) -{ - int status, np; - float step, tolerance, fHard; - char *scanvar = NULL; - char buffer[256]; - - SetHKLScanTolerance(self->pCryst,.0); - status = CalculateSettings(self->pCryst,fHKL,fPsi,0,fSet,pCon); - if(!status) - { - return status; - } - step = GetFourCircleStep(self->stepTable, fSet[0]); - if(step < -900.){ - step = self->fStep; - } - np = getMesureNP(self,(double)fSet[0]); - tolerance = (step * (float)np)/2. + .2; - SetHKLScanTolerance(self->pCryst,tolerance); - status = CalculateSettings(self->pCryst,fHKL,fPsi,0,fSet,pCon); - if(status != 1){ - return status; - } - scanvar = GetFourCircleScanVar(self->stepTable,fSet[0]); - if(scanvar != NULL && strcmp(scanvar,"om") != 0){ - tolerance *= 2.; - strcpy(buffer,"ERROR: 2theta limit problem:"); - if(!MotorCheckBoundary(self->p2Theta,fSet[0]-tolerance,&fHard, - buffer,256-strlen(buffer))){ - SCWrite(pCon,buffer,eWarning); - return 0; - } - if(!MotorCheckBoundary(self->p2Theta,fSet[0]+tolerance,&fHard, - buffer,256-strlen(buffer))){ - SCWrite(pCon,buffer,eWarning); - return 0; - } - } - return status; -} -/*--------------------------------------------------------------------------*/ - int MesureReflection(pMesure self, float fHKL[3], float fPsi, - SConnection *pCon) - { - int iRet; - float fSet[4]; - - assert(self); - - iRet = MesureCalculateSettings(self,fHKL,fSet,fPsi,pCon); - if(!iRet) - { - return iRet; - } - return MesureGenReflection(self,fHKL,fSet,pCon); - } -/*-----------------------------------------------------------------------*/ -static int DriveToReflection(pMesure self, float fSet[4], SConnection *pCon) -{ - int iRet, i; - float fDelta; - char pBueffel[132]; - - iRet = DriveSettings(self->pCryst,fSet,pCon); - if(!iRet) - { - return iRet; - } - - /* store achieved position for reporting */ - iRet = GetCurrentPosition(self->pCryst,pCon,self->fPosition); - if(iRet != 1) - { - return iRet; - } - - /* - check if we are really there. - */ - for(i = 0; i < 4; i++) - { - fDelta = fSet[i] - self->fPosition[i]; - if(fDelta < 0.) - fDelta = -fDelta; - if(fDelta > ANGERR) - { - snprintf(pBueffel,131, - "ERROR: angle %d positioned badly, aborting Reflection", - i); - SCWrite(pCon,pBueffel,eError); - return 0; - } - } - return 1; -} -/*----------------------------------------------------------------------- - test if this scan has to be remeasured because it is weak - ------------------------------------------------------------------------*/ -int weakScan(pMesure self, double twoTheta) -{ - int i, np; - long low = 99999, high = -99999; - - /* - the scan is always OK if we do not test for weak conditions or we are in psd mode - */ - if(self->weak == 0 || self->psd == 1){ - return 0; - } - - np = getMesureNP(self,twoTheta); - GetScanCounts(self->pScanner,self->lCounts,np); - for(i = 0; i < np; i++) - { - if(self->lCounts[i] < low) - { - low = self->lCounts[i]; - } - if(self->lCounts[i] > high) - { - high = self->lCounts[i]; - } - } - /* - I am using the weakest point here as a rough estimate of - the background - */ - if(high - 2 * low > self->weakThreshold) - { - return 0; - } - else - { - return 1; - } -} -/*-----------------------------------------------------------------------*/ -static int PerformPSDScan(pMesure self, char *scanVar, float fStart, - float step, int np, float two_theta) -{ - int status; - char pCommand[1024]; - char countMode[20]; - Tcl_Interp *pTcl; - float fPreset; - - /* - PSD scans are done by calling the routine Tcl procedure tricsscan with the - appropriate parameters. tricsscan does only omega scans! - */ - if(self->CountMode == eTimer) - { - strcpy(countMode,"timer"); - } - else - { - strcpy(countMode,"monitor"); - } - fPreset = GetFourCirclePreset(self->stepTable,(double)two_theta); - if(fPreset < .0){ - fPreset = self->fPreset; - } - snprintf(pCommand,1023,"tricsscan %f %f %d %s %f", fStart, step, np, - countMode,fPreset); - pTcl = InterpGetTcl(pServ->pSics); - status = Tcl_Eval(pTcl,pCommand); - if(status != TCL_OK) - { - return 0; - } - else - { - return 1; - } -} -/*------------------------------------------------------------------------*/ -static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon) -{ - float fStart, stepWidth, fPreset; - int iRet, np; - char pBueffel[132]; - char *scanVar = NULL; - - /* calculate scan start */ - iRet = MotorGetSoftPosition(self->pOmega,pCon,&fStart); - if(!iRet) - { - return iRet; - } - scanVar = GetFourCircleScanVar(self->stepTable,(double)twoTheta); - if(strcmp(scanVar,"NOT FOUND") == 0) - { - free(scanVar); - scanVar = strdup(self->pCOmega); - stepWidth = self->fStep; - } else { - stepWidth = GetFourCircleStep(self->stepTable,(double)twoTheta); - } - np = getMesureNP(self,(double)twoTheta); - - if(stepWidth != self->fStep) - { - snprintf(pBueffel,130,"Using stepwidth %f, %d points",stepWidth,np); - SCWrite(pCon,pBueffel,eWarning); - } - fStart -= (np/2)*stepWidth; - - /* - special case: psd mode - */ - if(self->psd == 1) - { - iRet = PerformPSDScan(self,scanVar,fStart, stepWidth, np,twoTheta); - free(scanVar); - return iRet; - } - - /* - below is the code for a single counter scan. - TODO: (maybe) make this clearer and separate this into another subroutine - - Set the scan up - */ - ClearScanVar(self->pScanner); - AddScanVar(self->pScanner, pServ->pSics,pCon,self->pCOmega, - fStart, stepWidth); - snprintf(pBueffel,131,"Scanning om from %f with step %f", fStart, stepWidth); - SCWrite(pCon,pBueffel,eValue); - /* - Oksana does not want o2t scans to be tightly coupled, this is why we - cannot use the normal o2t scan variable. Instead we calculate new limits and - steps for 2 theta and use it as a second scan variable - */ - if(strstr(scanVar,"o2t") != NULL){ - iRet = MotorGetSoftPosition(self->p2Theta,pCon,&fStart); - if(!iRet) - { - return iRet; - } - stepWidth *= 2.; - fStart -= (np/2.)*stepWidth; - AddScanVar(self->pScanner, pServ->pSics,pCon,self->pC2Theta, - fStart, stepWidth); - snprintf(pBueffel,131,"Scanning 2theta from %f with step %f", fStart, stepWidth); - SCWrite(pCon,pBueffel,eValue); - } - - /* - as np can change, we have to reallocate enough space - */ - if(self->lCounts != NULL){ - free(self->lCounts); - self->lCounts = (long *)malloc(np*sizeof(long)); - if(self->lCounts == NULL){ - SCWrite(pCon,"ERROR: out of memory for scan scan data",eError); - SCSetInterrupt(pCon,eAbortScan); - return 0; - } - memset(self->lCounts,0,np*sizeof(long)); - } - - /* - * determine preset - */ - fPreset = GetFourCirclePreset(self->stepTable,(double)twoTheta); - if(fPreset < .0){ - fPreset = self->fPreset; - } - - /* do the scan */ - free(scanVar); - if(self->iCompact) - { - self->pScanner->CollectScanData = CompactScanData; - } - if(self->fastScan >= 1) - { - self->pScanner->ScanDrive = ScanFastDrive; - } - iRet = SilentScan(self->pScanner,np,self->CountMode, - fPreset,pServ->pSics,pCon); - if(weakScan(self,twoTheta)) - { - /* - look for interrupts before restarting scan - */ - if(iRet == 0) - { - if(SCGetInterrupt(pCon) >= eAbortBatch) - { - return 0; - } - else - { - SCSetInterrupt(pCon,eContinue); - } - } - /* - redo scan with preset * 5 - */ - SCWrite(pCon,"Remeasuring weak reflection",eWarning); - iRet = SilentScan(self->pScanner,np,self->CountMode, - fPreset*5.,pServ->pSics,pCon); - - } - ResetScanFunctions(self->pScanner); - return iRet; -} -/*------------------------------------------------------------------------*/ - int MesureGenReflection(pMesure self, float fHKL[3], float fSet[4], - SConnection *pCon) - { - - int iRet, i; - char pBueffel[132]; - - assert(self); - - iRet = DriveToReflection(self,fSet,pCon); - if(!iRet) - { - return iRet; - } - - iRet = ScanReflection(self,fSet[0],pCon); - - return iRet; - } -/*--------------------------------------------------------------------------*/ - int MesureStart(pMesure self, SConnection *pCon) - { - char pFilename[512], pRoot[512]; - char pBueffel[1024]; - char pBuff[132]; - int iYear, iNum, iTaus; - float fVal, fUB[9]; - pSicsVariable pVar = NULL; - char *pFile = NULL, *pPtr; - float zero, pos; - pMotor pMot = NULL; - FILE *temp = NULL; - - assert(self); - assert(pCon); - - /* close open files if so */ - if(self->fRefl != NULL) - { - MesureClose(self); - } - - /* create filename root */ - pFile = makeFilename(pServ->pSics,pCon); - if(!pFile) - { - return 0; - } - pPtr = strrchr(pFile,(int)'.'); - pPtr++; - *pPtr = '\0'; - self->pCurrentFile = strdup(pFile); - free(pFile); - strncpy(pRoot,self->pCurrentFile,511); - - /* do the logfile */ - strcpy(pFilename,pRoot); - strcat(pFilename,"log"); - self->iLogFile = SCAddLogFile(pCon,pFilename); - self->pCon = pCon; - - /* - we do not need reflection files when doing a PSD scan - */ - if(self->psd == 1) - { - sprintf(pBueffel,"Logging to %s.log", pRoot); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - - /* open the reflection file */ - sprintf(pBueffel,"Writing to %s.log, .ccl, .rfl",pRoot); - SCWrite(pCon,pBueffel,eValue); - strcpy(pFilename,pRoot); - strcat(pFilename,"ccl"); - self->fRefl = fopen(pFilename,"w"); - if(!self->fRefl) - { - sprintf(pBueffel,"ERROR: SERIOUS TROUBLE: cannot open %s!", - pFilename); - SCWrite(pCon,pBueffel,eError); - SCSetInterrupt(pCon,eAbortBatch); - return 0; - } - temp = fopen(self->headerTemplate,"r"); - if(temp == NULL) - { - SCWrite(pCon,"ERROR: failed to open header template",eError); - } - if(temp != NULL && self->fRefl != NULL) - { - WriteTemplate(self->fRefl, temp, pFilename, NULL, - pCon, pServ->pSics); - fclose(temp); - } - - - - /* open hkl-data file */ - strcpy(pFilename,pRoot); - strcat(pFilename,"rfl"); - self->fHKL = fopen(pFilename,"w"); - if(!self->fHKL) - { - sprintf(pBueffel,"ERROR: SERIOUS TROUBLE: cannot open %s!", - pFilename); - SCWrite(pCon,pBueffel,eError); - SCSetInterrupt(pCon,eAbortBatch); - return 0; - } - fputs(pFilename,self->fHKL); - fputs("\n",self->fHKL); - - /* write some header data */ - SNXFormatTime(pBueffel,1024); - fprintf(self->fHKL,"filetime = %s\n",pBueffel); - GetLambda(self->pCryst,&fVal); - fprintf(self->fHKL,"lambda = %f Angstroem\n",fVal); - GetUB(self->pCryst,fUB); - fprintf(self->fHKL, - "UB = %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f\n", - fUB[0], fUB[1],fUB[2],fUB[3],fUB[4],fUB[5],fUB[6],fUB[7],fUB[8]); - - /* write sample & user info */ - strcpy(pBueffel,"CCL, Instr=TRICS, "); - pVar = FindVariable(pServ->pSics,"sample"); - if(pVar) - { - fprintf(self->fHKL,"sample = %s\n",pVar->text); - sprintf(pBuff,"sample = %s, ",pVar->text); - strcat(pBueffel,pBuff); - } - pVar = FindVariable(pServ->pSics,"user"); - if(pVar) - { - fprintf(self->fHKL,"user = %s \n",pVar->text); - sprintf(pBuff,"user = %s",pVar->text); - strcat(pBueffel,pBuff); - } - return 1; - } -/*---------------------------------------------------------------------------*/ - int MesureReopen(pMesure self, char *fileroot, SConnection *pCon) - { - char pBueffel[1024]; - char pFile[512]; - - assert(self); - assert(fileroot); - assert(pCon); - - /* close pending files */ - if(self->fRefl != NULL) - { - MesureClose(self); - } - - /* log file */ - strcpy(pFile,self->pFileRoot); - strcat(pFile,"/"); - strcat(pFile,fileroot); - strcat(pFile,".log"); - self->iLogFile = SCAddLogFile(pCon,pFile); - self->pCon = pCon; - - /* - No reopening of reflection files in psd mode - */ - if(self->psd == 1) - { - return 1; - } - - /* check if this is possible */ - strcpy(pFile,self->pFileRoot); - strcat(pFile,"/"); - strcat(pFile,fileroot); - strcat(pFile,".col"); - self->fRefl = fopen(pFile,"r"); - if(!self->fRefl) - { - sprintf(pBueffel,"ERROR: there is no such measurement at %s",fileroot); - SCWrite(pCon,pBueffel,eError); - return 0; - } - fclose(self->fRefl); - - /* well seems to exist, open for append */ - self->fRefl = fopen(pFile,"a"); - - /* rfl file */ - strcpy(pFile,self->pFileRoot); - strcat(pFile,"/"); - strcat(pFile,fileroot); - self->pCurrentFile = strdup(pFile); - strcat(pFile,".rfl"); - self->fHKL = fopen(pFile,"a"); - - - return 1; - } -/*------------------------------------------------------------------------*/ - int MesureClose(pMesure self) - { - assert(self); - - SCDelLogFile(self->pCon,self->iLogFile); - if(self->psd == 1) - { - self->pCon = NULL; - self->iLogFile = -1; - if(self->pCurrentFile) - free(self->pCurrentFile); - return 1; - } - - if(self->fRefl) - { - fclose(self->fRefl); - self->fRefl = NULL; - } - if(self->fHKL) - { - fclose(self->fHKL); - self->fHKL = NULL; - } - self->pCon = NULL; - self->iLogFile = -1; - if(self->pCurrentFile) - free(self->pCurrentFile); - - return 1; - } -/*---------------------------------------------------------------------------*/ -static double getProtonAverage(pMesure self){ - int np, i; - long *lData = NULL, lSum = 0; - - np = GetScanNP(self->pScanner); - lData = (long *)malloc((np+1)*sizeof(long)); - if(lData == NULL || np == 0){ - return 0.; - } - memset(lData,0,(np+1)*sizeof(long)); - GetScanMonitor(self->pScanner,2,lData, np); - for(i = 0; i < np; i++){ - lSum += lData[i]; - } - return (double)lSum/(double)np; -} -/*---------------------------------------------------------------------------*/ - static int WriteReflection(pMesure self, float fHKL[3],SConnection *pCon) - { - float fSum, fSigma, fSet[4], fTemp, fPreset, fStep; - double prot; - static float fMax = 10.; - int iRet, i,ii, iLF, iNP; - char pBueffel[512], pNum[10], pTime[132]; - pEVControl pEva = NULL; - pDummy pPtr = NULL; - pIDrivable pDriv = NULL; - - assert(self); - assert(pCon); - memset(pTime,0,132*sizeof(char)); - -#ifdef MESSDEBUG - self->np = 90; - fMax += 10; - SimScan(self->pScanner,14.,0.5,fMax); - if(fMax > 1000) - { - fMax = 10.; - } -#endif - - /* - no writing in PSD mode - */ - if(self->psd == 1) - { - return 1; - } - - /* get necessary data */ - fSum = 0.; - fSigma = 0.; - iRet = ScanIntegrate(self->pScanner,&fSum, &fSigma); - if(iRet != 1) - { - switch(iRet) - { - case INTEGLEFT: - sprintf(pBueffel, - "WARNING: integration failed --> no left side to: %f %f %f", - fHKL[0], fHKL[1],fHKL[2]); - break; - case INTEGRIGHT: - sprintf(pBueffel, - "WARNING: integration failed -->no right side to: %f %f %f", - fHKL[0], fHKL[1],fHKL[2]); - break; - case INTEGNOPEAK: - sprintf(pBueffel, - "WARNING: integration failed -->no peak found: %f %f %f", - fHKL[0], fHKL[1],fHKL[2]); - break; - case INTEGFUNNYBACK: - sprintf(pBueffel, - "WARNING: integration problem, asymmetric background: %f %f %f", - fHKL[0], fHKL[1],fHKL[2]); - break; - } - SCWrite(pCon,pBueffel,eWarning); - } - iNP = GetScanNP(self->pScanner); - GetScanCounts(self->pScanner,self->lCounts,iNP); - - /* write it */ - if(self->fRefl) - { - fprintf(self->fRefl,"%4d %7.3f %7.3f %7.3f %7.2f %7.2f %7.2f %7.2f %7.0f %7.2f\n", - self->iCount, fHKL[0],fHKL[1],fHKL[2], - self->fPosition[0], self->fPosition[1], - self->fPosition[2],self->fPosition[3], - fSum,fSigma); - } - if(self->fHKL) - { - fprintf(self->fHKL,"%5d %6.2f %6.2f %6.2f %7.2f %7.2f %7.2f %7.2f %7.0f %7.2f\n", - self->iCount, fHKL[0],fHKL[1],fHKL[2], - self->fPosition[0], self->fPosition[1], - self->fPosition[2],self->fPosition[3], - fSum,fSigma); - } - sprintf(pBueffel,"%5d %6.2f %6.2f %6.2f %7.2f %7.2f %7.2f %7.2f %7.0f %7.2f\n", - self->iCount, fHKL[0],fHKL[1],fHKL[2], - self->fPosition[0], self->fPosition[1], - self->fPosition[2],self->fPosition[3], - fSum,fSigma); - SCWrite(pCon,pBueffel,eStatus); - - /* get temperature */ - fTemp = -777.77; - pEva = (pEVControl)FindCommandData(pServ->pSics,"temperature", - "Environment_Controller"); - if(pEva == NULL) - { - pPtr = (pDummy)FindCommandData(pServ->pSics,"temperature", - "RemObject"); - if(pPtr != NULL) - { - pDriv = pPtr->pDescriptor->GetInterface(pPtr,DRIVEID); - if(pDriv != NULL) - { - fTemp = pDriv->GetValue(pPtr,pCon); - } - } - } - else - { - iRet = EVCGetPos(pEva, pCon,&fTemp); - } - - /* write profile */ - if(self->fRefl) - { - /* collect data */ - SNXFormatTime(pBueffel,512); - GetScanVarStep(self->pScanner,0,&fStep); - fPreset = GetScanPreset(self->pScanner); - prot = getProtonAverage(self); - fprintf(self->fRefl,"%3d %7.4f %9.0f %7.3f %12f %s\n",iNP,fStep, - fPreset,fTemp,prot, pBueffel); - for(i = 0; i < iNP; i++) - { - for(ii = 0; ii < 10 && i < iNP; ii++) - { - fprintf(self->fRefl," %7ld",self->lCounts[i]); - iLF = 1; - i++; - } - fprintf(self->fRefl,"\n"); - i--; - iLF = 0; - } - if(iLF) - { - fprintf(self->fRefl,"\n"); - } - fflush(self->fRefl); - } - - /* write data if compact output */ - if(self->iCompact == 1) - { - strcpy(pTime,pBueffel); - sprintf(pBueffel,"%3d%8.4f%10.0f%8.3f %s\n",iNP,fStep, - fPreset,fTemp,pTime); - SCWrite(pCon,pBueffel,eValue); - pBueffel[0] = '\0'; - for(i = 0; i < iNP; i++) - { - for(ii = 0; ii < 10 && i < iNP; ii++) - { - sprintf(pNum," %6ld",self->lCounts[i]); - strcat(pBueffel,pNum); - iLF = 1; - i++; - } - SCWrite(pCon,pBueffel,eValue); - pBueffel[0] = '\0'; - i--; - iLF = 0; - } - if(iLF) - { - SCWrite(pCon,pBueffel,eValue); - } - } - return 1; - } - /*---------------------------------------------------------------------*/ - static FILE *openListFile(char *pName){ - FILE *fd = NULL; - pDynString filename = NULL; - filename = findBatchFile(pServ->pSics,pName); - if(filename != NULL){ - fd = fopen(GetCharArray(filename),"r"); - DeleteDynString(filename); - } else { - fd = fopen(pName,"r"); - } - return fd; - } -/*------------------------------------------------------------------------*/ - int MesureFile(pMesure self, char *pFile, int iSkip, SConnection *pCon) - { - FILE *fd = NULL; - char pBueffel[512], pTime[132], pError[256]; - int i, iRet; - float fHKL[3], fPsi = .0; - - assert(self); - assert(pCon); - - /* well before doing a thing, open the list file */ - fd = openListFile(pFile); - if(!fd) - { - sprintf(pBueffel,"ERROR: reflection file %s NOT found!",pFile); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* check that files are open, if not open */ - if(self->fRefl == NULL) - { - MesureStart(self,pCon); - } - - /* make a mark */ - SNXFormatTime(pTime,131); - sprintf(pBueffel,"Starting at list %s at %s",pFile,pTime); - SCWrite(pCon,pBueffel,eStatus); - - /* skippy! */ - for(i = 0; i < iSkip; i++) - { - fgets(pBueffel,510,fd); - } - self->iCount = iSkip; - - if(self->psiMode > 0){ - SCWrite(pCon,"WARNING: measuring in psi mode",eWarning); - } - - /* loop through space and measure! */ - while(fgets(pBueffel,510,fd) != NULL) - { - for(i = 0; i < 3;i++) - fHKL[i] = 0.; - if(self->psiMode > 0){ - iRet = sscanf(pBueffel,"%f%f%f%f", - &fHKL[0],&fHKL[1],&fHKL[2],&fPsi); - if(iRet != 4){ - snprintf(pError,255,"WARNING: skipping bad line %s",pBueffel); - SCWrite(pCon,pError,eWarning); - continue; - } - } else { - iRet = sscanf(pBueffel,"%f%f%f",&fHKL[0],&fHKL[1],&fHKL[2]); - if(iRet != 3){ - snprintf(pError,255,"WARNING: skipping bad line %s",pBueffel); - SCWrite(pCon,pError,eWarning); - continue; - } - } - self->iCount++; - iRet = MesureReflection(self,fHKL,fPsi,pCon); - if(iRet == 0) - { - if(SCGetInterrupt(pCon) >= eAbortBatch) - { - return 0; - } - else - { - SCSetInterrupt(pCon,eContinue); - continue; - } - } - WriteReflection(self,fHKL,pCon); - } - - /* we are done */ - SNXFormatTime(pTime,131); - sprintf(pBueffel,"Finishing list %s at %s",pFile,pTime); - SCWrite(pCon,pBueffel,eStatus); - - fclose(fd); - return 1; - } -/*------------------------------------------------------------------------*/ - int TestFile(pMesure self, char *pFile, SConnection *pCon) - { - FILE *fd = NULL; - char pBueffel[512], pError[256]; - int i, iRet; - float fHKL[3], fSet[4], fPsi = .0; - int count = 0, good = 0; - - assert(self); - assert(pCon); - - /* well before doing a thing, open the list file */ - fd = openListFile(pFile); - if(!fd) - { - sprintf(pBueffel,"ERROR: reflection file %s NOT found!",pFile); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - if(self->psiMode > 0){ - SCWrite(pCon,"WARNING: measuring in psi mode",eWarning); - } - - /* loop through space and test! */ - while(fgets(pBueffel,510,fd) != NULL) - { - for(i = 0; i < 3;i++) - fHKL[i] = 0.; - if(self->psiMode > 0){ - iRet = sscanf(pBueffel,"%f%f%f%f", - &fHKL[0],&fHKL[1],&fHKL[2],&fPsi); - if(iRet != 4){ - snprintf(pError,255,"WARNING: skipping bad line %s",pBueffel); - SCWrite(pCon,pError,eWarning); - continue; - } - } else { - iRet = sscanf(pBueffel,"%f%f%f",&fHKL[0],&fHKL[1],&fHKL[2]); - if(iRet != 3){ - snprintf(pError,255,"WARNING: skipping bad line %s",pBueffel); - SCWrite(pCon,pError,eWarning); - continue; - } - } - count++; - iRet = MesureCalculateSettings(self,fHKL,fSet,fPsi,pCon); - if(iRet == 1) - { - good++; - } - } - fclose(fd); - snprintf(pBueffel,511,"Of %d reflections on file, %d are good and %d are rotten", - count,good,count-good); - SCWrite(pCon,pBueffel,eValue); - return 1; - } -/*------------------------------------------------------------------------*/ - int MesureGenFile(pMesure self, char *pFile, int iSkip, SConnection *pCon) - { - FILE *fd = NULL; - char pBueffel[512], pTime[132]; - int i, iRet, iH, iK, iL; - float fHKL[3], fSet[4]; - char pDum[4]; - - assert(self); - assert(pCon); - - /* well before doing a thing, open the list file */ - fd = openListFile(pFile); - if(!fd) - { - sprintf(pBueffel,"ERROR: reflection file %s NOT found!",pFile); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* check that files are open, if not open */ - if(self->fRefl == NULL) - { - MesureStart(self,pCon); - } - - /* make a mark */ - SNXFormatTime(pTime,131); - sprintf(pBueffel,"Starting at list %s at %s",pFile,pTime); - SCWrite(pCon,pBueffel,eStatus); - - /* skippy! */ - for(i = 0; i < iSkip; i++) - { - fgets(pBueffel,510,fd); - } - self->iCount = iSkip; - - - /* loop through space and measure! */ - while(fgets(pBueffel,510,fd) != NULL) - { - for(i = 0; i < 3;i++) - fHKL[i] = 0.; - for(i = 0; i < 4;i++) - fSet[i] = 0.; - iRet = sscanf(pBueffel,"%4d%4d%4d%s%f%f%f%f", - &iH,&iK,&iL,pDum, - &fSet[0], &fSet[1],&fSet[2],&fSet[3]); - fHKL[0] = (float)iH; - fHKL[1] = (float)iK; - fHKL[2] = (float)iL; - self->iCount++; - iRet = MesureGenReflection(self,fHKL,fSet,pCon); - if(iRet == 0) - { - if(SCGetInterrupt(pCon) >= eAbortBatch) - { - return 0; - } - else - { - SCSetInterrupt(pCon,eContinue); - continue; - } - } - WriteReflection(self,fHKL,pCon); - } - - /* we are done */ - SNXFormatTime(pTime,131); - sprintf(pBueffel,"Finishing list %s at %s",pFile,pTime); - SCWrite(pCon,pBueffel,eStatus); - - fclose(fd); - return 1; - } -/*--------------------------------------------------------------------------*/ - int MesureSetPar(pMesure self, char *name, float fVal) - { - if(strcmp(name,"np") == 0) - { -#ifndef MESSDEBUG - self->np = (int)fVal; - if(self->lCounts) - free(self->lCounts); - self->lCounts = (long *)malloc(self->np*sizeof(long)); - if(!self->lCounts) - { - return 0; - } -#else - -#endif - return 1; - } - else if(strcmp(name,"step") == 0) - { - self->fStep = fVal; - return 1; - } - else if(strcmp(name,"weakthreshold") == 0) - { - self->weakThreshold = (long)nintf(fVal); - return 1; - } - else if(strcmp(name,"preset") == 0) - { - self->fPreset = fVal; - return 1; - } - else if(strcmp(name,"countmode") == 0) - { - if(fVal < 0.05) - { - self->CountMode = eTimer; - } - else - { - self->CountMode = ePreset; - } - return 1; - } - else if(strcmp(name,"compact") == 0) - { - if(fVal >= 1.) - { - self->iCompact = 1; - } - else - { - self->iCompact = 0; - } - return 1; - } - else if(strcmp(name,"psd") == 0) - { - if(fVal >= 1.) - { - self->psd = 1; - } - else - { - self->psd = 0; - } - return 1; - } - else if(strcmp(name,"weak") == 0) - { - if(fVal >= 1.) - { - self->weak = 1; - } - else - { - self->weak = 0; - } - return 1; - } - else if(strcmp(name,"fastscan") == 0) - { - if(fVal >= 1.) - { - self->fastScan = 1; - } - else - { - self->fastScan = 0; - } - return 1; - } - else if(strcmp(name,"psimode") == 0) - { - if(fVal >= 1.) - { - self->psiMode = 1; - } - else - { - self->psiMode = 0; - } - return 1; - } - else - { - return 0; - } - } -/*-------------------------------------------------------------------------*/ - int MesureGetPar(pMesure self, char *name, float *fVal) - { - if(strcmp(name,"np") == 0) - { - *fVal = self->np; - return 1; - } - else if(strcmp(name,"step") == 0) - { - *fVal = self->fStep; - return 1; - } - else if(strcmp(name,"weakthreshold") == 0) - { - *fVal = (float)self->weakThreshold; - return 1; - } - else if(strcmp(name,"preset") == 0) - { - *fVal = self->fPreset; - return 1; - } - else if(strcmp(name,"countmode") == 0) - { - if(self->CountMode == eTimer) - { - *fVal = 0.; - } - else - { - *fVal = 1.0; - } - return 1; - } - else if(strcmp(name,"compact") == 0) - { - *fVal = self->iCompact; - return 1; - } - else if(strcmp(name,"psd") == 0) - { - *fVal = self->psd; - return 1; - } - else if(strcmp(name,"fastscan") == 0) - { - *fVal = (float)self->fastScan; - return 1; - } - else if(strcmp(name,"weak") == 0) - { - *fVal = (float)self->weak; - return 1; - } - else if(strcmp(name,"psimode") == 0) - { - *fVal = self->psiMode; - return 1; - } - else - { - return 0; - } - } -/*---------------------------------------------------------------------------*/ - int MesureAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - int iRet, iSkip, err; - char pBueffel[1024]; - pMesure self = NULL; - double d; - float fVal, fHKL[3], start, end, step; - - self = (pMesure)pData; - assert(self); - assert(pCon); - - if(argc < 2) - { - sprintf(pBueffel,"ERROR: Insufficient arguments to %s",argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* - catch table processing commands - */ - iRet = HandleFourCircleCommands(&self->stepTable,pCon,argc,argv,&err); - if(iRet == 1) - { - return err; - } - - strtolower(argv[1]); -/*------ start */ - if(strcmp(argv[1],"open") == 0) - { - if(!SCMatchRights(pCon,usUser)) - { - return 0; - } - iRet = MesureStart(self,pCon); - if(iRet) - { - SCSendOK(pCon); - } - return iRet; - } -/*----------- list*/ - else if(strcmp(argv[1],"list") == 0) - { - ListMesure(self,argv[0],pCon); - return 1; - } -/*------ file */ - else if(strcmp(argv[1],"file") == 0) - { - sprintf(pBueffel,"Currently writing to: %s",self->pCurrentFile); - SCWrite(pCon,pBueffel,eValue); - return 1; - } -/*------ nb */ - else if(strcmp(argv[1],"nb") == 0) - { - if(!SCMatchRights(pCon,usUser)) - { - return 0; - } - iRet = SetNOR(self->pCryst,1); - if(!iRet) - { - SCWrite(pCon, - "ERROR: nu motor not configured at hkl, cannot do normal beam", - eError); - return 0; - } - SCSendOK(pCon); - return 1; - } -/*------ bi */ - else if(strcmp(argv[1],"bi") == 0) - { - if(!SCMatchRights(pCon,usUser)) - { - return 0; - } - iRet = SetNOR(self->pCryst,0); - SCSendOK(pCon); - return 1; - } -/*--------- close */ - else if(strcmp(argv[1],"close") == 0) - { - if(!SCMatchRights(pCon,usUser)) - { - return 0; - } - MesureClose(self); - return 1; - } -/*-------- reopen */ - else if(strcmp(argv[1],"reopen") == 0) - { - if(!SCMatchRights(pCon,usUser)) - { - return 0; - } - if(argc < 3) - { - SCWrite(pCon,"ERROR: expected filename as parameter for reopen",eError); - return 0; - } - iRet = MesureReopen(self,argv[2],pCon); - if(iRet) - { - SCSendOK(pCon); - } - return iRet; - } -/*------- measure */ - else if(strcmp(argv[1],"measure") == 0) - { - iSkip = 0; - if(!SCMatchRights(pCon,usUser)) - { - return 0; - } - if(argc < 3) - { - SCWrite(pCon,"ERROR: expected list file name as parameter for measure ",eError); - return 0; - } - if(argc >= 4) - { - iRet = Tcl_GetInt(pSics->pTcl,argv[3],&iSkip); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: expected integer, got %s",argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - } - iRet = MesureFile(self,argv[2],iSkip,pCon); - if(iRet) - { - SCSendOK(pCon); - } - return iRet; - } -/*------- calc */ - else if(strcmp(argv[1],"calc") == 0) - { - if(argc < 3) - { - SCWrite(pCon,"ERROR: expected list file name as parameter for measure ",eError); - return 0; - } - iRet = TestFile(self,argv[2],pCon); - return iRet; - } -/*------- genlist */ - else if(strcmp(argv[1],"genlist") == 0) - { - iSkip = 0; - if(!SCMatchRights(pCon,usUser)) - { - return 0; - } - if(argc < 3) - { - SCWrite(pCon,"ERROR: expected list file name as parameter for measure ",eError); - return 0; - } - if(argc >= 4) - { - iRet = Tcl_GetInt(pSics->pTcl,argv[3],&iSkip); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: expected integer, got %s",argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - } - iRet = MesureGenFile(self,argv[2],iSkip,pCon); - if(iRet) - { - SCSendOK(pCon); - } - return iRet; - } -/* ------ writereflection*/ - else if(strcmp(argv[1],"writereflection") == 0) - { - GetCurrentHKL(self->pCryst,fHKL); - WriteReflection(self,fHKL,pCon); - SCSendOK(pCon); - return 1; - } -/* ------ count mode */ - else if(strcmp(argv[1],"countmode") == 0) - { - if(argc > 2) /* set case */ - { - /* check rights */ - if(!SCMatchRights(pCon,usUser)) - { - SCWrite(pCon,"ERROR: You are not aurhorised to do this!",eError); - return 0; - } - if(strcmp(argv[2],"timer") == 0) - { - fVal = 0.; - } - else if(strcmp(argv[2],"monitor") == 0) - { - fVal = 1.; - } - else - { - SCWrite(pCon,"ERROR: Invalid parameter for countmode",eError); - return 0; - } - MesureSetPar(self,"countmode",fVal); - SCSendOK(pCon); - return 1; - } - else /* get case */ - { - MesureGetPar(self,"countmode",&fVal); - if(fVal < 0.05) - { - sprintf(pBueffel,"%s.countmode = timer",argv[0]); - } - else - { - sprintf(pBueffel,"%s.countmode = monitor", argv[0]); - } - SCWrite(pCon,pBueffel,eValue); - return 1; - } - } -/*------ can be other pars */ - else - { - if(argc > 2) /* set case */ - { - /* check rights */ - if(!SCMatchRights(pCon,usUser)) - { - SCWrite(pCon,"ERROR: You are not aurhorised to do this!",eError); - return 0; - } - iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&d); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: expected numeric value for %s but got %s", - argv[1],argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - fVal = (float)d; - - iRet = MesureSetPar(self,argv[1],fVal); - if(iRet) - { - SCSendOK(pCon); - return 1; - } - else - { - sprintf(pBueffel,"ERROR: parameter %s not known",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - } - else /* get case */ - { - iRet = MesureGetPar(self,argv[1],&fVal); - if(!iRet) - { - sprintf(pBueffel,"ERROR: parameter %s not known",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - sprintf(pBueffel,"%s.%s = %f",argv[0],argv[1],fVal); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - } - } diff --git a/mesure.h b/mesure.h deleted file mode 100644 index 295e3dca..00000000 --- a/mesure.h +++ /dev/null @@ -1,42 +0,0 @@ - -/*---------------------------------------------------------------------------- - M E S U R E - - A SICS object for doing four circle measurements with a single - counter. - - copyright: see copyright.h - - Mark Koennecke, April 1998 - Heavily reworked: Mark Koennecke, February-March 2005 ----------------------------------------------------------------------------*/ -#ifndef SICSMESURE -#define SICSMESURE - - typedef struct __Mesure *pMesure; -/*--------------------- live & death --------------------------------------*/ - pMesure CreateMesure(pHKL pCryst, pScanData pScanner, - pMotor pOmega, char *pom, - pMotor p2Theta, char *p2t, - char *pFileRoot,pDataNumber pDanu, char *headerTemplate); - void DeleteMesure(void *pData); - - int MesureFactory(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); -/*------------------- object functions -----------------------------------*/ - int MesureReflection(pMesure self, float fHKL[3], float fPsi, - SConnection *pCon); - int MesureGenReflection(pMesure self, float fHKL[3],float fSet[4], SConnection *pCon); - int MesureStart(pMesure self, SConnection *pCon); - int MesureReopen(pMesure self, char *filename, SConnection *pCon); - int MesureClose(pMesure self); - int MesureFile(pMesure self, char *pFile, int iSkip, SConnection *pCon); - int MesureGenFile(pMesure self, char *pFile, int iSkip, SConnection *pCon); - int MesureSetPar(pMesure self, char *name, float fVal); - int MesureGetPar(pMesure self, char *name, float *fVal); - - int MesureAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - - -#endif diff --git a/modriv.h b/modriv.h index 8a394dda..f84d0df8 100644 --- a/modriv.h +++ b/modriv.h @@ -14,70 +14,60 @@ #define MOTREDO -1 #define MOTFAIL 0 #define MOTOK 1 -#define TEXTPARLEN 1024 - typedef struct __AbstractMoDriv { - /* general motor driver interface - fields. REQUIRED! - */ - float fUpper; /* upper limit */ - float fLower; /* lower limit */ - char *name; - int (*GetPosition)(void *self, float *fPos); - int (*RunTo)(void *self,float fNewVal); - int (*GetStatus)(void *self); - void (*GetError)(void *self, int *iCode, char *buffer, int iBufLen); - int (*TryAndFixIt)(void *self, int iError,float fNew); - int (*Halt)(void *self); - int (*GetDriverPar)(void *self, char *name, - float *value); - int (*SetDriverPar)(void *self,SConnection *pCon, - char *name, float newValue); - void (*ListDriverPar)(void *self, char *motorName, - SConnection *pCon); - void (*KillPrivate)(void *self); - int (*GetDriverTextPar)(void *self, char *name, - char *textPar); - } MotorDriver; - - /* the first fields above HAVE to be IDENTICAL to those below */ +typedef struct __AbstractMoDriv { + /* general motor driver interface + fields. REQUIRED! + */ + float fUpper; /* upper limit */ + float fLower; /* lower limit */ + char *name; + int (*GetPosition) (void *self, float *fPos); + int (*RunTo) (void *self, float fNewVal); + int (*GetStatus) (void *self); + void (*GetError) (void *self, int *iCode, char *buffer, int iBufLen); + int (*TryAndFixIt) (void *self, int iError, float fNew); + int (*Halt) (void *self); + int (*GetDriverPar) (void *self, char *name, float *value); + int (*SetDriverPar) (void *self, SConnection * pCon, + char *name, float newValue); + void (*ListDriverPar) (void *self, char *motorName, SConnection * pCon); + void (*KillPrivate) (void *self); +} MotorDriver; + + /* the first fields above HAVE to be IDENTICAL to those below */ - typedef struct ___MoSDriv { - /* general motor driver interface - fields. REQUIRED! - */ - float fUpper; /* upper limit */ - float fLower; /* lower limit */ - char *name; - int (*GetPosition)(void *self,float *fPos); - int (*RunTo)(void *self, float fNewVal); - int (*GetStatus)(void *self); - void (*GetError)(void *self, int *iCode, char *buffer, int iBufLen); - int (*TryAndFixIt)(void *self,int iError, float fNew); - int (*Halt)(void *self); - int (*GetDriverPar)(void *self, char *name, - float *value); - int (*SetDriverPar)(void *self,SConnection *pCon, - char *name, float newValue); - void (*ListDriverPar)(void *self, char *motorName, - SConnection *pCon); - void (*KillPrivate)(void *self); - int (*GetDriverTextPar)(void *self, char *name, - char *textPar); - - /* Simulation specific fields */ - float fFailure; /* percent random failures*/ - float fSpeed; - time_t iTime; - float fPos; /* position */ - float fTarget; /* target position */ - } SIMDriv; +typedef struct ___MoSDriv { + /* general motor driver interface + fields. REQUIRED! + */ + float fUpper; /* upper limit */ + float fLower; /* lower limit */ + char *name; + int (*GetPosition) (void *self, float *fPos); + int (*RunTo) (void *self, float fNewVal); + int (*GetStatus) (void *self); + void (*GetError) (void *self, int *iCode, char *buffer, int iBufLen); + int (*TryAndFixIt) (void *self, int iError, float fNew); + int (*Halt) (void *self); + int (*GetDriverPar) (void *self, char *name, float *value); + int (*SetDriverPar) (void *self, SConnection * pCon, + char *name, float newValue); + void (*ListDriverPar) (void *self, char *motorName, SConnection * pCon); + void (*KillPrivate) (void *self); + + /* Simulation specific fields */ + float fFailure; /* percent random failures */ + float fSpeed; + time_t iTime; + float fPos; /* position */ + float fTarget; /* target position */ +} SIMDriv; + - /* ----------------------- Simulation -----------------------------------*/ - MotorDriver *CreateSIM(SConnection *pCon, int argc, char *argv[]); - void KillSIM(void *pData); - MotorDriver *RGMakeMotorDriver(void); +MotorDriver *CreateSIM(SConnection * pCon, int argc, char *argv[]); +void KillSIM(void *pData); +MotorDriver *RGMakeMotorDriver(void); #endif - diff --git a/moregress.c b/moregress.c index de86e59b..e1e4650d 100644 --- a/moregress.c +++ b/moregress.c @@ -7,7 +7,7 @@ * copyright: see file COPYRIGHT * * Mark Koennecke, July 2007 - */ + */ #include #include #include @@ -15,70 +15,72 @@ /*===================== supported errors ======================*/ #define NONE 0 #define STARTFAIL 1 -#define BADPOS 2 /* positioning problem */ -#define FAIL 3 /* failure */ -#define OFFPOS 4 /* off pos by .2 */ -#define READFAIL 5 -#define RUN 6 /* keep running; for interrupt testing */ +#define BADPOS 2 /* positioning problem */ +#define FAIL 3 /* failure */ +#define OFFPOS 4 /* off pos by .2 */ +#define READFAIL 5 +#define RUN 6 /* keep running; for interrupt testing */ /*=============================================================*/ -typedef struct __RGMoDriv{ - /* general motor driver interface - fields. REQUIRED! - */ - float fUpper; /* upper limit */ - float fLower; /* lower limit */ - char *name; - int (*GetPosition)(void *self, float *fPos); - int (*RunTo)(void *self,float fNewVal); - int (*GetStatus)(void *self); - void (*GetError)(void *self, int *iCode, char *buffer, int iBufLen); - int (*TryAndFixIt)(void *self, int iError,float fNew); - int (*Halt)(void *self); - int (*GetDriverPar)(void *self, char *name, - float *value); - int (*SetDriverPar)(void *self,SConnection *pCon, - char *name, float newValue); - void (*ListDriverPar)(void *self, char *motorName, - SConnection *pCon); - void (*KillPrivate)(void *self); - /* your drivers private fields follow below */ - float target; - int errorType; - int recover; - int counter; - } RGMotorDriver; - +typedef struct __RGMoDriv { + /* general motor driver interface + fields. REQUIRED! + */ + float fUpper; /* upper limit */ + float fLower; /* lower limit */ + char *name; + int (*GetPosition) (void *self, float *fPos); + int (*RunTo) (void *self, float fNewVal); + int (*GetStatus) (void *self); + void (*GetError) (void *self, int *iCode, char *buffer, int iBufLen); + int (*TryAndFixIt) (void *self, int iError, float fNew); + int (*Halt) (void *self); + int (*GetDriverPar) (void *self, char *name, float *value); + int (*SetDriverPar) (void *self, SConnection * pCon, + char *name, float newValue); + void (*ListDriverPar) (void *self, char *motorName, SConnection * pCon); + void (*KillPrivate) (void *self); + /* your drivers private fields follow below */ + float target; + int errorType; + int recover; + int counter; +} RGMotorDriver; + /*================================================================ GetPos returns OKOK on success, HWFault on failure ------------------------------------------------------------------*/ -static int RGGetPos(void *data, float *fPos){ +static int RGGetPos(void *data, float *fPos) +{ RGMotorDriver *self = NULL; - - self = (RGMotorDriver *)data; - if(self->errorType == READFAIL){ + + self = (RGMotorDriver *) data; + if (self->errorType == READFAIL) { return HWFault; } - if(self->errorType > 1 && self->errorType < 6){ + if (self->errorType > 1 && self->errorType < 6) { *fPos = self->target - .2; } else { - *fPos = self->target; + *fPos = self->target; } return OKOK; } + /*---------------------------------------------------------------- RunTo starts the motor running. Returns OKOK on success, HWfault on Errors ------------------------------------------------------------------*/ -static int RGRunTo(void *data, float newValue){ +static int RGRunTo(void *data, float newValue) +{ RGMotorDriver *self = NULL; - - self = (RGMotorDriver *)data; + + self = (RGMotorDriver *) data; self->target = newValue; - if(self->errorType == STARTFAIL){ + if (self->errorType == STARTFAIL) { return HWFault; } return OKOK; } + /*----------------------------------------------------------------- CheckStatus queries the sattus of a running motor. Possible return values can be: @@ -88,54 +90,57 @@ static int RGRunTo(void *data, float newValue){ HWIdle : motor finished OK HWWarn : motor issued warning --------------------------------------------------------------------*/ -static int RGCheckStatus(void *data){ +static int RGCheckStatus(void *data) +{ RGMotorDriver *self = NULL; - - self = (RGMotorDriver *)data; - switch(self->errorType){ - case BADPOS: - return HWPosFault; - break; - case FAIL: - return HWFault; - break; - case RUN: - return HWBusy; - break; + + self = (RGMotorDriver *) data; + switch (self->errorType) { + case BADPOS: + return HWPosFault; + break; + case FAIL: + return HWFault; + break; + case RUN: + return HWBusy; + break; } return HWIdle; } + /*------------------------------------------------------------------ GetError gets more information about error which occurred *iCode is an integer error code to be used in TryFixIt as indicator buffer is a buffer for a text description of the problem iBufLen is the length of buffer --------------------------------------------------------------------*/ -static void RGGetError(void *data, int *iCode, char *buffer, - int iBufLen){ +static void RGGetError(void *data, int *iCode, char *buffer, int iBufLen) +{ RGMotorDriver *self = NULL; - - self = (RGMotorDriver *)data; - *iCode = self->errorType; - switch(self->errorType){ - case NONE: - strncpy(buffer,"No error found",iBufLen); - break; - case BADPOS: - strncpy(buffer,"Position not reached",iBufLen); - break; - case FAIL: - strncpy(buffer,"Hardware is mad",iBufLen); - break; - case STARTFAIL: - strncpy(buffer,"Failed to start motor",iBufLen); - break; - case READFAIL: - strncpy(buffer,"Failed to read motor",iBufLen); - break; - + + self = (RGMotorDriver *) data; + *iCode = self->errorType; + switch (self->errorType) { + case NONE: + strlcpy(buffer, "No error found", iBufLen); + break; + case BADPOS: + strlcpy(buffer, "Position not reached", iBufLen); + break; + case FAIL: + strlcpy(buffer, "Hardware is mad", iBufLen); + break; + case STARTFAIL: + strlcpy(buffer, "Failed to start motor", iBufLen); + break; + case READFAIL: + strlcpy(buffer, "Failed to read motor", iBufLen); + break; + } } + /*------------------------------------------------------------------ TryAndFixIt tries everything which is possible in software to fix a problem. iError is the error code from GetError, newValue is @@ -145,114 +150,130 @@ static void RGGetError(void *data, int *iCode, char *buffer, MOTREDO : try again MOTFAIL : cannot fix this --------------------------------------------------------------------*/ -static int RGFixIt(void *data, int iError, float newValue){ +static int RGFixIt(void *data, int iError, float newValue) +{ RGMotorDriver *self = NULL; - - self = (RGMotorDriver *)data; - if(self->recover == 1){ + + self = (RGMotorDriver *) data; + if (self->recover == 1) { self->errorType = NONE; return MOTREDO; } return MOTFAIL; } + /*------------------------------------------------------------------- Halt tries to stop the motor. Halt errors are ignored ---------------------------------------------------------------------*/ -static int RGHalt(void *data){ +static int RGHalt(void *data) +{ RGMotorDriver *self = NULL; - - self = (RGMotorDriver *)data; + + self = (RGMotorDriver *) data; self->errorType = NONE; return 1; } + /*-------------------------------------------------------------------- GetDriverPar retrieves the value of a driver parameter. Name is the name of the parameter, fValue the value when found. Returns 0 on success, 0 else -----------------------------------------------------------------------*/ -static int RGGetDriverPar(void *data, char *name, float *value){ +static int RGGetDriverPar(void *data, char *name, float *value) +{ RGMotorDriver *self = NULL; - - self = (RGMotorDriver *)data; - if(strcmp(name,"errortype") == 0){ - *value = (float)self->errorType; + + self = (RGMotorDriver *) data; + if (strcmp(name, "errortype") == 0) { + *value = (float) self->errorType; return 1; - } else if (strcmp(name,"recover") == 0){ + } else if (strcmp(name, "recover") == 0) { *value = self->recover; return 1; } - + return 0; } + /*---------------------------------------------------------------------- SetDriverPar sets a driver parameter. Returns 0 on failure, 1 on success. Name is the parameter name, pCon the connection to report errors too, value the new value ------------------------------------------------------------------------*/ -static int RGSetDriverPar(void *data, SConnection *pCon, - char *name, float value){ +static int RGSetDriverPar(void *data, SConnection * pCon, + char *name, float value) +{ RGMotorDriver *self = NULL; - - self = (RGMotorDriver *)data; - if(strcmp(name,"errortype") == 0){ - self->errorType = (int)value; + + self = (RGMotorDriver *) data; + if (strcmp(name, "errortype") == 0) { + self->errorType = (int) value; return 1; - } else if (strcmp(name,"recover") == 0){ - self->recover = (int)value; + } else if (strcmp(name, "recover") == 0) { + self->recover = (int) value; + return 1; + } else if (strcmp(name, "hardupperlim") == 0) { + self->fUpper = value; + return 1; + } else if (strcmp(name, "hardlowerlim") == 0) { + self->fLower = value; return 1; } - return 0; + return 0; } + /*----------------------------------------------------------------------- ListDriverPar lists the names and values of driver parameters to pCon. Motorname is the name of the motor ro prefix to the listing. -------------------------------------------------------------------------*/ -static void RGListDriverPar(void *data, char *motorname, - SConnection *pCon){ +static void RGListDriverPar(void *data, char *motorname, + SConnection * pCon) +{ RGMotorDriver *self = NULL; char buffer[256]; - self = (RGMotorDriver *)data; - snprintf(buffer,255,"%s errortype = %d", motorname, - self->errorType); - SCWrite(pCon,buffer,eValue); + self = (RGMotorDriver *) data; + snprintf(buffer, 255, "%s errortype = %d", motorname, self->errorType); + SCWrite(pCon, buffer, eValue); - snprintf(buffer,255,"%s recover = %d", motorname, - self->recover); - SCWrite(pCon,buffer,eValue); + snprintf(buffer, 255, "%s recover = %d", motorname, self->recover); + SCWrite(pCon, buffer, eValue); } + /*----------------------------------------------------------------------- KillPrivate has the task to delete possibly dynamically allocated memory in the private part of the driver structure ------------------------------------------------------------------------*/ -static void RGKillPrivate(void *data){ +static void RGKillPrivate(void *data) +{ RGMotorDriver *self = NULL; - - self = (RGMotorDriver *)data; + + self = (RGMotorDriver *) data; } + /*=======================================================================*/ -MotorDriver *RGMakeMotorDriver(void) { - RGMotorDriver *pNew = NULL; +MotorDriver *RGMakeMotorDriver(void) +{ + RGMotorDriver *pNew = NULL; - pNew = malloc(sizeof(RGMotorDriver)); - if(pNew == NULL){ - return NULL; - } - memset(pNew,0,sizeof(RGMotorDriver)); - - pNew->GetPosition = RGGetPos; - pNew->RunTo = RGRunTo; - pNew->GetStatus = RGCheckStatus; - pNew->GetError = RGGetError; - pNew->TryAndFixIt = RGFixIt; - pNew->Halt = RGHalt; - pNew->GetDriverPar = RGGetDriverPar; - pNew->SetDriverPar = RGSetDriverPar; - pNew->ListDriverPar = RGListDriverPar; - pNew->KillPrivate = RGKillPrivate; - pNew->fLower = -180.; - pNew->fUpper = 180.; - - return (MotorDriver *)pNew; + pNew = malloc(sizeof(RGMotorDriver)); + if (pNew == NULL) { + return NULL; + } + memset(pNew, 0, sizeof(RGMotorDriver)); + + pNew->GetPosition = RGGetPos; + pNew->RunTo = RGRunTo; + pNew->GetStatus = RGCheckStatus; + pNew->GetError = RGGetError; + pNew->TryAndFixIt = RGFixIt; + pNew->Halt = RGHalt; + pNew->GetDriverPar = RGGetDriverPar; + pNew->SetDriverPar = RGSetDriverPar; + pNew->ListDriverPar = RGListDriverPar; + pNew->KillPrivate = RGKillPrivate; + pNew->fLower = -180.; + pNew->fUpper = 180.; + + return (MotorDriver *) pNew; } - diff --git a/motor.c b/motor.c index 8f9c58c1..67ddd2af 100644 --- a/motor.c +++ b/motor.c @@ -1,3 +1,4 @@ + /*------------------------------------------------------------------------ M O T O R S @@ -9,6 +10,10 @@ callback added: Mark Koennecke, August 1997 endscript facility added: Mark Koennecke, August 2002 Modified to support driver parameters, Mark Koennecke, January 2003 + + Reworked to allow for multiple implementations of motors on the same + interface in preparation for second generation motors. + Mark Koennecke, December 2008 Copyright: @@ -76,237 +81,331 @@ #define IGNOREFAULT 10 #define MOVECOUNT 11 -extern double DoubleTime(void); /*-------------------------------------------------------------------------*/ - static void *MotorGetInterface(void *pData, int iID) - { - pMotor self = NULL; - - self = (pMotor)pData; - assert(self); - if(iID == DRIVEID) - { - return self->pDrivInt; - } - else if(iID == CALLBACKINTERFACE) - { - return self->pCall; - } - return NULL; - } -/*------------------------------------------------------------------------*/ - static int MotorHalt(void *sulf) - { - pMotor self; - - assert(sulf); - self = (pMotor)sulf; - - /* reduce the error count by 1. This is because the driver is - expected to return an error when the motor had been stopped. - However, a stop is usually a consequence of a user intervention - or program logic. This prevents to a false motor alarm when the - motor was repeatedly stopped for other reasons. - */ - self->pDrivInt->iErrorCount--; - if(self->pDrivInt->iErrorCount < 0) - self->pDrivInt->iErrorCount = 0; +static void *MotorGetInterface(void *pData, int iID) +{ + pMotor self = NULL; - self->stopped = 1; - return self->pDriver->Halt((void *)self->pDriver); + self = (pMotor) pData; + assert(self); + if (iID == DRIVEID) { + return self->pDrivInt; + } else if (iID == CALLBACKINTERFACE) { + return self->pCall; } + return NULL; +} + +/*------------------------------------------------------------------------*/ +static int MotorHalt(void *sulf) +{ + pMotor self; + + assert(sulf); + self = (pMotor) sulf; + + /* reduce the error count by 1. This is because the driver is + expected to return an error when the motor had been stopped. + However, a stop is usually a consequence of a user intervention + or program logic. This prevents to a false motor alarm when the + motor was repeatedly stopped for other reasons. + */ + self->pDrivInt->iErrorCount--; + if (self->pDrivInt->iErrorCount < 0) + self->pDrivInt->iErrorCount = 0; + + self->stopped = 1; + return self->pDriver->Halt((void *) self->pDriver); +} + + /*--------------------------------------------------------------------------- + MotorCheckBoundary checks for violation of boundary conditions and + transforms from SoftCoordinates to hard coordinates. + */ + +static int MotorCheckBoundaryImpl(pMotor self, float fVal, float *fNew, + char *pError, int iErrLen) +{ + float fHard; + float fZero; + float fLim; + assert(self); + + /* check for fixed */ + if (ObVal(self->ParArray, FIX) >= 0) { + snprintf(pError, iErrLen, "Motor %s is Fixed", self->name); + return 0; /* is this an error? */ + } + + /* check against software boundaries */ + if (fVal > ObVal(self->ParArray, SUPP)) { + snprintf(pError, iErrLen, "%g violates upper software limit %g on %s", + fVal, ObVal(self->ParArray, SUPP), self->name); + return 0; + } + if (fVal < ObVal(self->ParArray, SLOW)) { + snprintf(pError, iErrLen, "%g violates lower software limit %g on %s", + fVal, ObVal(self->ParArray, SLOW), self->name); + return 0; + } + + /* correct for zero point */ + fZero = ObVal(self->ParArray, SZERO); + fZero = -fZero; + fHard = fVal - fZero; + + /* apply sign */ + fHard = fHard * ObVal(self->ParArray, SIGN); + + /* check for hardware limits */ + if (fHard > self->pDriver->fUpper) { + fLim = self->pDriver->fUpper * ObVal(self->ParArray,SIGN) + fZero; + snprintf(pError, iErrLen, + "%g violates upper hardware limit %g (%g) on %s", + fVal, fLim, self->pDriver->fUpper, self->name); + return 0; + } + if (fHard < self->pDriver->fLower) { + fLim = self->pDriver->fLower * ObVal(self->ParArray,SIGN) + fZero; + snprintf(pError, iErrLen, + "%g violates lower hardware limit %g (%g) on %s", + fVal, fLim, self->pDriver->fLower, self->name); + return 0; + } + + *fNew = fHard; + return 1; +} + /*--------------------------------------------------------------------------*/ - static int MotorLimits(void *sulf, float fVal, char *error, int iErrLen) - { - float fHard; - pMotor self; - - assert(sulf); - - self = (pMotor)sulf; - - return MotorCheckBoundary(self,fVal,&fHard,error,iErrLen); +static int MotorLimits(void *sulf, float fVal, char *error, int iErrLen) +{ + float fHard; + pMotor self; + + assert(sulf); + + self = (pMotor) sulf; + + return MotorCheckBoundaryImpl(self, fVal, &fHard, error, iErrLen); +} + + /* ------------------------------------------------------------------------ */ +static int MotorGetSoftPositionImpl(pMotor self, SConnection * pCon, + float *fVal) +{ + int iRet; + float fValue; + + assert(self); + assert(pCon); + + /* get the hard position */ + iRet = MotorGetHardPosition(self, pCon, &fValue); + if (!iRet) { + *fVal = fValue; + return 0; } + /* apply zeropoint */ + if (ObVal(self->ParArray, SIGN) < 0.) { + fValue += ObVal(self->ParArray, SZERO); + } else { + fValue -= ObVal(self->ParArray, SZERO); + } + *fVal = fValue; + + /* apply sign */ + /* *fVal = MotorHardToSoftPosition(self,fValue); */ + + *fVal = fValue * ObVal(self->ParArray, SIGN); + + return 1; +} + /*---------------------------------------------------------------------------*/ - static float MotorGetValue(void *pData, SConnection *pCon) - { - int iRet; - float fVal = 0.; - - assert(pData); - iRet = MotorGetSoftPosition((pMotor)pData,pCon,&fVal); - if(iRet != OKOK) - { - fVal = -9999999.99; - } - return fVal; - } +static float MotorGetValue(void *pData, SConnection * pCon) +{ + int iRet; + float fVal = 0.; + + assert(pData); + iRet = MotorGetSoftPositionImpl((pMotor) pData, pCon, &fVal); + if (iRet != OKOK) { + fVal = -9999999.99; + } + return fVal; +} + /*------------------------------------------------------------------------*/ - static int MotorSaveStatus(void *pData, char *name, FILE *fd) - { - pMotor self = NULL; - char pBueffel[512]; - - assert(pData); - assert(fd); - - self= (pMotor)pData; - fprintf(fd,"# Motor %s\n",name); - sprintf(pBueffel,"%s sign %f\n",name,ObVal(self->ParArray,SIGN)); - fputs(pBueffel,fd); - sprintf(pBueffel,"%s SoftZero %f\n",name,ObVal(self->ParArray,SZERO)); - fputs(pBueffel,fd); - sprintf(pBueffel,"%s SoftLowerLim %f\n",name,ObVal(self->ParArray,SLOW)); - fputs(pBueffel,fd); - sprintf(pBueffel,"%s SoftUpperLim %f\n",name,ObVal(self->ParArray,SUPP)); - fputs(pBueffel,fd); - sprintf(pBueffel,"%s Fixed %f\n",name,ObVal(self->ParArray,FIX)); - fputs(pBueffel,fd); - sprintf(pBueffel,"%s InterruptMode %f\n",name,ObVal(self->ParArray,INT)); - fputs(pBueffel,fd); - sprintf(pBueffel,"%s precision %f\n",name,ObVal(self->ParArray,PREC)); - fputs(pBueffel,fd); - sprintf(pBueffel,"%s ignorefault %f\n",name,ObVal(self->ParArray,IGNOREFAULT)); - fputs(pBueffel,fd); - sprintf(pBueffel,"%s AccessCode %f\n",name,ObVal(self->ParArray,USRIGHTS)); - fputs(pBueffel,fd); - sprintf(pBueffel,"%s failafter %f\n",name,ObVal(self->ParArray,ECOUNT)); - fputs(pBueffel,fd); - sprintf(pBueffel,"%s maxretry %f\n",name,ObVal(self->ParArray,POSCOUNT)); - fputs(pBueffel,fd); - sprintf(pBueffel,"%s movecount %f\n",name, - ObVal(self->ParArray,MOVECOUNT)); - fputs(pBueffel,fd); - return 1; - } +static int MotorSaveStatus(void *pData, char *name, FILE * fd) +{ + pMotor self = NULL; + char pBueffel[512]; + + assert(pData); + assert(fd); + + self = (pMotor) pData; + fprintf(fd, "# Motor %s\n", name); + snprintf(pBueffel,sizeof(pBueffel)-1, "%s sign %f\n", name, ObVal(self->ParArray, SIGN)); + fputs(pBueffel, fd); + snprintf(pBueffel,sizeof(pBueffel)-1, "%s SoftZero %f\n", name, + ObVal(self->ParArray, SZERO)); + fputs(pBueffel, fd); + snprintf(pBueffel,sizeof(pBueffel)-1, "%s SoftLowerLim %f\n", name, + ObVal(self->ParArray, SLOW)); + fputs(pBueffel, fd); + snprintf(pBueffel,sizeof(pBueffel)-1, "%s SoftUpperLim %f\n", name, + ObVal(self->ParArray, SUPP)); + fputs(pBueffel, fd); + snprintf(pBueffel,sizeof(pBueffel)-1, "%s Fixed %f\n", name, ObVal(self->ParArray, FIX)); + fputs(pBueffel, fd); + snprintf(pBueffel,sizeof(pBueffel)-1, "%s InterruptMode %f\n", name, + ObVal(self->ParArray, INT)); + fputs(pBueffel, fd); + snprintf(pBueffel,sizeof(pBueffel)-1, "%s precision %f\n", name, + ObVal(self->ParArray, PREC)); + fputs(pBueffel, fd); + snprintf(pBueffel,sizeof(pBueffel)-1, "%s ignorefault %f\n", name, + ObVal(self->ParArray, IGNOREFAULT)); + fputs(pBueffel, fd); + snprintf(pBueffel,sizeof(pBueffel)-1, "%s AccessCode %f\n", name, + ObVal(self->ParArray, USRIGHTS)); + fputs(pBueffel, fd); + snprintf(pBueffel,sizeof(pBueffel)-1, "%s failafter %f\n", name, + ObVal(self->ParArray, ECOUNT)); + fputs(pBueffel, fd); + snprintf(pBueffel,sizeof(pBueffel)-1, "%s maxretry %f\n", name, + ObVal(self->ParArray, POSCOUNT)); + fputs(pBueffel, fd); + snprintf(pBueffel,sizeof(pBueffel)-1, "%s movecount %f\n", name, + ObVal(self->ParArray, MOVECOUNT)); + fputs(pBueffel, fd); + return 1; +} + /*-------------------------------------------------------------------------*/ - static float absf(float f) - { - if(f < 0.) - { - return -f; - } - else - { - return f; - } - } -/*-------------------------------------------------------------------------*/ - static void MotorInterrupt(SConnection *pCon, int iVal) - { - if(SCGetInterrupt(pCon) < iVal) - { - SCSetInterrupt(pCon,iVal); - } +static float absf(float f) +{ + if (f < 0.) { + return -f; + } else { + return f; } +} + +/*-------------------------------------------------------------------------*/ +static void MotorInterrupt(SConnection * pCon, int iVal) +{ + if (SCGetInterrupt(pCon) < iVal) { + SCSetInterrupt(pCon, iVal); + } +} + /*---------------------------------------------------------------------*/ -static int statusRunTo(pMotor self, SConnection *pCon) +static int statusRunTo(pMotor self, SConnection * pCon) { char pBueffel[256]; - if(self->retryCount >= ObVal(self->ParArray,POSCOUNT)) - { - snprintf(pBueffel,255,"ERROR: aborting motor %s after %d retries", - self->name, self->retryCount); - SCWrite(pCon,pBueffel,eError); + if (self->retryCount >= ObVal(self->ParArray, POSCOUNT)) { + snprintf(pBueffel, 255, "ERROR: aborting motor %s after %d retries", + self->name, self->retryCount); + SCWrite(pCon, pBueffel, eLogError); return HWFault; } - if(SCGetInterrupt(pCon) != eContinue){ - return HWFault; + if (SCGetInterrupt(pCon) != eContinue) { + return HWFault; } self->retryCount++; - snprintf(pBueffel,255,"WARNING: restarting %s, %d time", - self->name,self->retryCount); - SCWrite(pCon,pBueffel,eWarning); - self->pDriver->RunTo(self->pDriver,self->fTarget); + snprintf(pBueffel, 255, "WARNING: restarting %s, %d time", + self->name, self->retryCount); + SCWrite(pCon, pBueffel, eLog); + self->pDriver->RunTo(self->pDriver, self->fTarget); return HWBusy; } + /*--------------------------------------------------------------------*/ -static int checkPosition(pMotor self, SConnection *pCon) +static int checkPosition(pMotor self, SConnection * pCon) { float fHard; char pBueffel[132]; int status; - MotorGetHardPosition(self,pCon,&fHard); + MotorGetHardPosition(self, pCon, &fHard); self->fPosition = fHard; - if(absf(fHard - self->fTarget) > ObVal(self->ParArray,PREC)) - { - if (SCGetInterrupt(pCon) != eContinue) - { - return HWFault; - } - if(self->stopped) - { - snprintf(pBueffel,131,"WARNING: %s stopped", self->name); - SCWrite(pCon,pBueffel, eWarning); - return HWFault; - } - snprintf(pBueffel,131,"WARNING: %s off position by %f%s", - self->name, absf(fHard - self->fTarget), - self->fTarget > fHard ? "-" : ""); - SCWrite(pCon,pBueffel, eWarning); - status = statusRunTo(self,pCon); - return status; + if (absf(fHard - self->fTarget) > ObVal(self->ParArray, PREC)) { + if (SCGetInterrupt(pCon) != eContinue) { + return HWFault; + } + if (self->stopped) { + snprintf(pBueffel, 131, "WARNING: %s stopped", self->name); + SCWrite(pCon, pBueffel, eWarning); + return HWFault; + } + snprintf(pBueffel, 131, "WARNING: %s off position by %f", + self->name, absf(fHard - self->fTarget)); + SCWrite(pCon, pBueffel, eLog); + status = statusRunTo(self, pCon); + return status; } - return HWIdle; + return HWIdle; } + /*--------------------------------------------------------------------*/ -void finishDriving(pMotor self, SConnection *pCon) +static void finishDriving(pMotor self, SConnection * pCon) { MotCallback sCall; - MotorGetSoftPosition(self,pCon,&sCall.fVal); + MotorGetSoftPosition(self, pCon, &sCall.fVal); sCall.pName = self->name; self->fPosition = sCall.fVal; self->fPosition = sCall.fVal; - /* If the moving flag has been reset then skip the invokes */ - if (self->moving == 0) - return; - self->moving = 0; - InvokeCallBack(self->pCall, MOTDRIVE, &sCall); /* send also very last position */ + InvokeCallBack(self->pCall, MOTDRIVE, &sCall); /* send also very last position */ InvokeCallBack(self->pCall, MOTEND, &sCall); + tracePar(self->name,"%f",sCall.fVal); + self->running = 0; } + /*--------------------------------------------------------------------*/ -static int reportAndFixError(pMotor self, SConnection *pCon) +static int reportAndFixError(pMotor self, SConnection * pCon) { char pBueffel[256], pError[131]; int iCode, iRet, newStatus; - self->pDriver->GetError(self->pDriver,&iCode, pError,131); - iRet = self->pDriver->TryAndFixIt(self->pDriver,iCode, self->fTarget); - switch(iRet) - { + self->pDriver->GetError(self->pDriver, &iCode, pError, 131); + iRet = self->pDriver->TryAndFixIt(self->pDriver, iCode, self->fTarget); + switch (iRet) { case MOTFAIL: - snprintf(pBueffel,255,"ERROR: %s on %s",pError,self->name); - SCWrite(pCon,pBueffel,eError); + snprintf(pBueffel, 255, "ERROR: %s on %s", pError, self->name); + SCWrite(pCon, pBueffel, eError); newStatus = HWFault; break; case MOTREDO: - snprintf(pBueffel,255,"WARNING: %s on %s",pError,self->name); - SCWrite(pCon,pBueffel,eWarning); - newStatus = statusRunTo(self,pCon); + snprintf(pBueffel, 255, "WARNING: %s on %s", pError, self->name); + SCWrite(pCon, pBueffel, eWarning); + newStatus = statusRunTo(self, pCon); break; case MOTOK: - snprintf(pBueffel,255,"WARNING: %s on %s",pError,self->name); - SCWrite(pCon,pBueffel,eWarning); + snprintf(pBueffel, 255, "WARNING: %s on %s", pError, self->name); + SCWrite(pCon, pBueffel, eWarning); newStatus = HWIdle; break; default: - SCWrite(pCon,"WARNING: bad status code in motor.c:reportAndFixError", - eWarning); - SCWrite(pCon,"You may continue, but show this to a SICS programmer", - eWarning); + SCWrite(pCon, "WARNING: bad status code in motor.c:reportAndFixError", + eWarning); + SCWrite(pCon, "You may continue, but show this to a SICS programmer", + eWarning); newStatus = HWIdle; break; } return newStatus; } + /*--------------------------------------------------------------------- New version, refactored October 2003 -----------------------------------------------------------------------*/ -static int evaluateStatus(pMotor self, SConnection *pCon) +static int evaluateStatus(pMotor self, SConnection * pCon) { int iRet, iCode, newStatus; MotCallback sCall; @@ -315,31 +414,26 @@ static int evaluateStatus(pMotor self, SConnection *pCon) iRet = self->pDriver->GetStatus(self->pDriver); newStatus = iRet; - switch(iRet) - { + switch (iRet) { case OKOK: case HWIdle: - newStatus = checkPosition(self,pCon); - if(newStatus != HWBusy) - { - finishDriving(self,pCon); + newStatus = checkPosition(self, pCon); + if (newStatus != HWBusy) { + finishDriving(self, pCon); } break; case HWFault: - newStatus = reportAndFixError(self,pCon); + newStatus = reportAndFixError(self, pCon); break; case HWPosFault: - newStatus = reportAndFixError(self,pCon); - if(newStatus == HWFault && ObVal(self->ParArray,IGNOREFAULT) < 1) - { + newStatus = reportAndFixError(self, pCon); + if (newStatus == HWFault && ObVal(self->ParArray, IGNOREFAULT) < 1) { newStatus = HWPosFault; - } - if(newStatus == HWIdle || newStatus == OKOK) - { - newStatus = checkPosition(self,pCon); - if(newStatus != HWBusy) - { - finishDriving(self,pCon); + } + if (newStatus == HWIdle || newStatus == OKOK) { + newStatus = checkPosition(self, pCon); + if (newStatus != HWBusy) { + finishDriving(self, pCon); } } break; @@ -347,629 +441,545 @@ static int evaluateStatus(pMotor self, SConnection *pCon) newStatus = HWBusy; break; case HWWarn: - self->pDriver->GetError(self->pDriver,&iCode, pError,131); - snprintf(pBueffel,255,"WARNING: motor reported: %s", pError); - SCWrite(pCon,pBueffel,eWarning); + self->pDriver->GetError(self->pDriver, &iCode, pError, 131); + snprintf(pBueffel, 255, "WARNING: motor reported: %s", pError); + SCWrite(pCon, pBueffel, eWarning); newStatus = HWIdle; break; default: - SCWrite(pCon,"WARNING: Bad status in motor.c:evaluatStatus",eWarning); - SCWrite(pCon,"You may continue, but show this to a SICS programmer", - eWarning); + SCWrite(pCon, "WARNING: Bad status in motor.c:evaluatStatus", + eWarning); + SCWrite(pCon, "You may continue, but show this to a SICS programmer", + eWarning); break; } - if(newStatus == HWFault) - { - finishDriving(self,pCon); - MotorInterrupt(pCon,ObVal(self->ParArray,INT)); + if (newStatus == HWFault) { + finishDriving(self, pCon); + MotorInterrupt(pCon, ObVal(self->ParArray, INT)); self->retryCount = 0; } return newStatus; } + /*---------------------------------------------------------------------*/ -static void handleMoveCallback(pMotor self, SConnection *pCon) +static void handleMoveCallback(pMotor self, SConnection * pCon) { -#if 1 - double current_time, skip_time; - current_time = DoubleTime(); - skip_time = 0.001 * ObVal(self->ParArray,MOVECOUNT); - if(self->last_report_time + skip_time <= current_time) -#else - self->posCount++; - if(self->posCount >= ObVal(self->ParArray,MOVECOUNT)) -#endif - { - MotCallback sCall; - MotorGetSoftPosition(self,pCon,&sCall.fVal); - sCall.pName = self->name; - InvokeCallBack(self->pCall, MOTDRIVE, &sCall); -#if 1 - self->last_report_time = current_time; -#else - self->posCount = 0; -#endif - } + MotCallback sCall; + + self->posCount++; + if (self->posCount >= ObVal(self->ParArray, MOVECOUNT)) { + MotorGetSoftPosition(self, pCon, &sCall.fVal); + sCall.pName = self->name; + InvokeCallBack(self->pCall, MOTDRIVE, &sCall); + tracePar(self->name,"%f",sCall.fVal); + self->posCount = 0; + } } + /*-----------------------------------------------------------------------*/ - static int MotorStatus(void *sulf, SConnection *pCon) - { - pMotor self = NULL; - int status; +static int MotorStatus(void *sulf, SConnection * pCon) +{ + pMotor self = NULL; + int status; - assert(sulf); - self = (pMotor)sulf; + assert(sulf); + self = (pMotor) sulf; - status = evaluateStatus(self,pCon); - if (self->pDrivInt->drivableStatus!=status) { - ((SConnection *)pCon)->conEventType=STATUS; - ((SConnection *)pCon)->conStatus=status; - SCWrite(pCon, "", eEvent); - self->pDrivInt->drivableStatus=status; - } - if(status == HWBusy) - { - handleMoveCallback(self,pCon); - } - return status; + if(self->running != 1){ + return HWIdle; } + + status = evaluateStatus(self, pCon); + if (self->pDrivInt->drivableStatus != status) { + ((SConnection *) pCon)->conEventType = STATUS; + ((SConnection *) pCon)->conStatus = status; + SCWrite(pCon, "", eEvent); + self->pDrivInt->drivableStatus = status; + } + if (status == HWBusy) { + handleMoveCallback(self, pCon); + } + return status; +} + /*---------------------------------------------------------------------------*/ - pMotor MotorInit(char *drivername, char *name, MotorDriver *pDriv) - { - pMotor pM = NULL; - - assert(drivername); - assert(pDriv); - assert(name); - - /* get memory */ - pM = (pMotor)malloc(sizeof(Motor)); - if(!pM) - { - return NULL; - } - memset(pM, 0, sizeof(Motor)); /* DFC init all to zero */ - pM->pActionRoutine = NULL; /* DFC belt and braces */ - - /* create and initialize parameters */ - pM->ParArray = ObParCreate(MOTOBPARLENGTH); - if(!pM->ParArray) - { - free(pM); - return NULL; - } - ObParInit(pM->ParArray,SLOW,"softlowerlim",pDriv->fLower,usUser); - ObParInit(pM->ParArray,SUPP,"softupperlim",pDriv->fUpper,usUser); - ObParInit(pM->ParArray,SZERO,"softzero",ZEROINACTIVE,usUser); - ObParInit(pM->ParArray,FIX,"fixed",-1,usUser); - ObParInit(pM->ParArray,INT,"interruptmode",INTCONT,usMugger); - ObParInit(pM->ParArray,PREC,"precision",0.01,usMugger); - ObParInit(pM->ParArray,USRIGHTS,"accesscode",(float)usUser,usMugger); - ObParInit(pM->ParArray,SIGN,"sign",1.0,usMugger); - ObParInit(pM->ParArray,ECOUNT,"failafter",3.0,usMugger); - ObParInit(pM->ParArray,POSCOUNT,"maxretry",3.0,usMugger); - ObParInit(pM->ParArray,IGNOREFAULT,"ignorefault",0.0,usMugger); - ObParInit(pM->ParArray,MOVECOUNT,"movecount",10.0,usMugger); - pDriv->GetPosition(pDriv,&(pM->fPosition)); - pM->fTarget = pM->fPosition; - pM->endScriptID = 0; +int MotorGetPar(pMotor self, char *name, float *fVal) +{ + return self->MotorGetPar(self, name, fVal); +} - /* copy arguments */ - pM->pDriver = pDriv; - pM->drivername = strdup(drivername); - pM->name = strdup(name); - - - /* initialise object descriptor */ - pM->pDescriptor = CreateDescriptor("Motor"); - if(!pM->pDescriptor) - { - ObParDelete(pM->ParArray); - free(pM); - return NULL; - } - pM->pDescriptor->GetInterface = MotorGetInterface; - pM->pDescriptor->SaveStatus = MotorSaveStatus; - - /* initialise Drivable interface */ - pM->pDrivInt = CreateDrivableInterface(); - if(!pM->pDrivInt) - { - DeleteDescriptor(pM->pDescriptor); - ObParDelete(pM->ParArray); - free(pM); - return NULL; - } - pM->pDrivInt->SetValue = MotorRun; - pM->pDrivInt->CheckLimits = MotorLimits; - pM->pDrivInt->CheckStatus = MotorStatus; - pM->pDrivInt->GetValue = MotorGetValue; - pM->pDrivInt->Halt = MotorHalt; +/*---------------------------------------------------------------------------*/ +int MotorSetPar(pMotor self, SConnection * pCon, char *name, float fVal) +{ + return self->MotorSetPar(self, pCon, name, fVal); +} - /* initialise callback interface */ - pM->pCall = CreateCallBackInterface(); - if(!pM->pCall) - { - MotorKill(pM); - return NULL; - } - - /* done */ - return pM; +/*---------------------------------------------------------------------------*/ +int MotorGetHardPosition(pMotor self, SConnection * pCon, float *fVal) +{ + return self->MotorGetHardPosition(self, pCon, fVal); +} + +/*--------------------------------------------------------------------------*/ +static int MotorGetParImpl(pMotor self, char *name, float *fVal) +{ + ObPar *pPar = NULL; + assert(self); + + if (strcmp(name, "hardupperlim") == 0) { + *fVal = self->pDriver->fUpper; + return 1; + } + if (strcmp(name, "hardlowerlim") == 0) { + *fVal = self->pDriver->fLower; + return 1; } -/*--------------------------------------------------------------------------*/ -extern void KillPiPiezo(void *pData); - - void MotorKill(void *self) - { - pMotor pM; - assert(self); - - pM = (pMotor)self; - - /* MotorHalt(pM); */ - - if(pM->name) - free(pM->name); - - if(pM->pDrivInt) - { - free(pM->pDrivInt); - } - - if(pM->pCall) - { - DeleteCallBackInterface(pM->pCall); - } - - /* kill driver */ - if(pM->drivername) - { - if(pM->pDriver->KillPrivate != NULL) - { - pM->pDriver->KillPrivate(pM->pDriver); - if(pM->pDriver->name != NULL) - { - free(pM->pDriver->name); - } - free(pM->pDriver); - } - free(pM->drivername); - } - - /* get rid of parameter space */ - if(pM->ParArray) - { - ObParDelete(pM->ParArray); - } - - /* kill Descriptor */ - DeleteDescriptor(pM->pDescriptor); - - free(pM); - - } -/*--------------------------------------------------------------------------*/ - int MotorGetPar(pMotor self, char *name, float *fVal) - { - ObPar *pPar = NULL; - assert(self); - - if(strcmp(name,"hardupperlim") == 0) - { - *fVal = self->pDriver->fUpper; - return 1; - } - if(strcmp(name,"hardlowerlim") == 0) - { - *fVal = self->pDriver->fLower; - return 1; - } - if(strcmp(name,"position") == 0) - { + pPar = ObParFind(self->ParArray, name); + if (pPar) { + *fVal = pPar->fVal; + return 1; + } else { + /* can still be position */ + if (strcmp(name, "position") == 0) { *fVal = self->fPosition; return 1; - } - else if(strcmp(name,"target") == 0) - { + } else if (strcmp(name, "target") == 0) { *fVal = self->fTarget; return 1; + } else { + /* + check for a driver parameter + */ + if (self->pDriver->GetDriverPar != NULL) { + return self->pDriver->GetDriverPar(self->pDriver, name, fVal); + } else { + return 0; + } } + } +} - pPar = ObParFind(self->ParArray,name); - if(pPar) - { - *fVal = pPar->fVal; +/*---------------------------------------------------------------------------*/ +static int MotorSetParImpl(pMotor self, SConnection * pCon, char *name, + float fVal) +{ + ObPar *pPar = NULL; + char pBueffel[512]; + int iRet; + float fLimit, fOld, fChange; + + assert(self); + assert(pCon); + + /* + try set driver parameters + */ + if (self->pDriver->SetDriverPar != NULL) { + iRet = self->pDriver->SetDriverPar(self->pDriver, pCon, name, fVal); + if (iRet == 1) { + SCparChange(pCon); + InvokeCallBack(self->pCall, HDBVAL, self); + tracePar(self->name,"%s:%f",name, fVal); + return iRet; + + } + } + + + if (strcmp(name, "softzero") == 0) { + /* set it first, this also tests the necessary privileges */ + fOld = ObVal(self->ParArray, SZERO); + iRet = ObParSet(self->ParArray, self->name, name, fVal, pCon); + if (!iRet) { + return iRet; + } + /* shift the limits by the difference between old and new */ + fChange = fVal - fOld; + /* upper limit */ + fLimit = ObVal(self->ParArray, SUPP); + fLimit -= fChange; + ObParSet(self->ParArray, self->name, "softupperlim", fLimit, pCon); + /* lower limit */ + fLimit = ObVal(self->ParArray, SLOW); + fLimit -= fChange; + ObParSet(self->ParArray, self->name, "softlowerlim", fLimit, pCon); + SCparChange(pCon); + InvokeCallBack(self->pCall, HDBVAL, self); + tracePar(self->name,"%s:%f",name, fVal); + + return 1; + } + + iRet = ObParSet(self->ParArray, self->name, name, fVal, pCon); + if (strcmp(name, "sign") == 0) { + if ((absf(fVal) - 1.0) > 0.01) { + SCWrite(pCon, "ERROR: Invalid Sign Value", eError); + return 0; + } + if (fVal < 0.0) { + ObParInit(self->ParArray, SLOW, "softlowerlim", + self->pDriver->fUpper * fVal, usUser); + ObParInit(self->ParArray, SUPP, "softupperlim", + self->pDriver->fLower * fVal, usUser); + ObParInit(self->ParArray, SZERO, "softzero", ZEROINACTIVE, usUser); + } + } + InvokeCallBack(self->pCall, HDBVAL, self); + SCparChange(pCon); + tracePar(self->name,"%s:%f",name, fVal); + + return iRet; +} + +/*------------------------------------------------------------------------*/ +static int MotorGetHardPositionImpl(pMotor self, SConnection * pCon, + float *fHard) +{ + int iRet, iCode; + float fVal; + char pBueffel[512], pError[256]; + + assert(self); + assert(pCon); + + iRet = self->pDriver->GetPosition(self->pDriver, &fVal); + if (iRet == OKOK) { /* all went well, the exception */ + *fHard = fVal; + return 1; + } else { /* a problem, the usual case: try fix the problem */ + /* no point in trying this three times */ + self->pDriver->GetError(self->pDriver, &iCode, pError, 255); + iRet = self->pDriver->TryAndFixIt(self->pDriver, iCode, fVal); + snprintf(pBueffel,sizeof(pBueffel)-1, "WARNING: Trying to fix %s", pError); + SCWrite(pCon, pBueffel, eWarning); + switch (iRet) { + case MOTFAIL: + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: cannot fix motor %s", self->name); + SCWrite(pCon, pBueffel, eError); + SCSetInterrupt(pCon, (int) ObVal(self->ParArray, INT)); + *fHard = fVal; + return 0; + case MOTOK: + case MOTREDO: + iRet = self->pDriver->GetPosition(self->pDriver, &fVal); + if (iRet) { + *fHard = fVal * ObVal(self->ParArray, SIGN); + return 1; + } else { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: cannot fix motor %s", self->name); + SCSetInterrupt(pCon, (int) ObVal(self->ParArray, INT)); + SCWrite(pCon, pBueffel, eError); + *fHard = fVal; + return 0; + } + } + } + *fHard = fVal * ObVal(self->ParArray, SIGN); + return 0; +} + +/*---------------------------------------------------------------------------*/ +static long MotorRunImpl(void *sulf, SConnection * pCon, float fNew) +{ + float fHard; + int i, iRet, iCode; + char pBueffel[512]; + char pError[132]; + pMotor self; + long lTime; + float fDelta; + + self = (pMotor) (sulf); + assert(self); + assert(pCon); + + /* check if I'am allowed to move this motor */ + if (!SCMatchRights(pCon, (int) ObVal(self->ParArray, USRIGHTS))) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: You are not authorised to move motor %s", + self->name); + SCWrite(pCon, pBueffel, eError); + SCSetInterrupt(pCon, eAbortBatch); + return 0; + } + + /* check boundaries first */ + iRet = MotorCheckBoundaryImpl(self, fNew, &fHard, pError, 131); + if (!iRet) { + snprintf(pBueffel, 511, "ERROR: %s", pError); + SCWrite(pCon, pBueffel, eError); + SCSetInterrupt(pCon, eAbortOperation); + return 0; + } + + /* check if the bad motor flag is set */ + if ((int) ObVal(self->ParArray, IGNOREFAULT) > 0) { + snprintf(pBueffel, 511, "WARNING: motor %s is unreliable", self->name); + SCWrite(pCon, pBueffel, eWarning); + self->pDrivInt->iErrorCount = 0; + } + + /* check our error count and interrupt if to much */ + iCode = (int) ObVal(self->ParArray, ECOUNT); + if (self->pDrivInt->iErrorCount > iCode) { + /* big alarm */ + ServerWriteGlobal("ERROR: !!! MOTOR ALARM !!! MOTOR ALARM !!!", + eError); + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: too many position errors counted at motor %s", + self->name); + ServerWriteGlobal(pBueffel, eError); + SCSetInterrupt(pCon, eAbortBatch); + self->pDrivInt->iErrorCount = 0; + return 0; + } + + /* Boundaries OK, send command */ + self->posFaultCount = 0; + self->retryCount = 0; + self->stopped = 0; + self->fTarget = fHard; + InvokeCallBack(self->pCall, HDBVAL, self); + self->posCount = 0; + iRet = self->pDriver->RunTo(self->pDriver, fHard); + if (iRet != OKOK) { /* try three times to fix it */ + for (i = 0; (i < 3) && (iRet != OKOK); i++) { + self->pDriver->GetError(self->pDriver, &iCode, pError, 131); + snprintf(pBueffel,sizeof(pBueffel)-1, "WARNING: Trying to fix: %s", pError); + SCWrite(pCon, pBueffel, eWarning); + iRet = self->pDriver->TryAndFixIt(self->pDriver, iCode, fHard); + switch (iRet) { + case MOTFAIL: + SCWrite(pCon, pError, eError); + SCWrite(pCon, "\n", eError); + SCSetInterrupt(pCon, (int) ObVal(self->ParArray, INT)); + return HWFault; + case MOTREDO: + iRet = self->pDriver->RunTo(self->pDriver, fHard); + if (iRet == OKOK) { + self->running = 1; + return OKOK; + } + break; + case MOTOK: + self->running = 1; + return OKOK; + break; + } + } + /* tried three times, refuses to work */ + SCWrite(pCon, pError, eError); + SCWrite(pCon, "\n", eError); + SCSetInterrupt(pCon, (int) ObVal(self->ParArray, INT)); + return HWFault; + } + self->running = 1; + return OKOK; +} + +/*---------------------------------------------------------------------------*/ +pMotor MotorInit(char *drivername, char *name, MotorDriver * pDriv) +{ + pMotor pM = NULL; + + assert(drivername); + assert(pDriv); + assert(name); + + /* get memory */ + pM = (pMotor) malloc(sizeof(Motor)); + if (!pM) { + return NULL; + } + memset(pM,0,sizeof(Motor)); + + + /* create and initialize parameters */ + pM->ParArray = ObParCreate(MOTOBPARLENGTH); + if (!pM->ParArray) { + free(pM); + return NULL; + } + ObParInit(pM->ParArray, SLOW, "softlowerlim", pDriv->fLower, usUser); + ObParInit(pM->ParArray, SUPP, "softupperlim", pDriv->fUpper, usUser); + ObParInit(pM->ParArray, SZERO, "softzero", ZEROINACTIVE, usUser); + ObParInit(pM->ParArray, FIX, "fixed", -1, usUser); + ObParInit(pM->ParArray, INT, "interruptmode", INTCONT, usMugger); + ObParInit(pM->ParArray, PREC, "precision", 0.01, usMugger); + ObParInit(pM->ParArray, USRIGHTS, "accesscode", (float) usUser, + usMugger); + ObParInit(pM->ParArray, SIGN, "sign", 1.0, usMugger); + ObParInit(pM->ParArray, ECOUNT, "failafter", 3.0, usMugger); + ObParInit(pM->ParArray, POSCOUNT, "maxretry", 3.0, usMugger); + ObParInit(pM->ParArray, IGNOREFAULT, "ignorefault", 0.0, usMugger); + ObParInit(pM->ParArray, MOVECOUNT, "movecount", 10.0, usMugger); + pDriv->GetPosition(pDriv, &(pM->fPosition)); + pM->fTarget = pM->fPosition; + pM->endScriptID = 0; + + /* copy arguments */ + pM->pDriver = pDriv; + pM->drivername = strdup(drivername); + pM->name = strdup(name); + + + /* initialise object descriptor */ + pM->pDescriptor = CreateDescriptor("Motor"); + if (!pM->pDescriptor) { + ObParDelete(pM->ParArray); + free(pM); + return NULL; + } + pM->pDescriptor->GetInterface = MotorGetInterface; + pM->pDescriptor->SaveStatus = MotorSaveStatus; + + /* initialise Drivable interface */ + pM->pDrivInt = CreateDrivableInterface(); + if (!pM->pDrivInt) { + DeleteDescriptor(pM->pDescriptor); + ObParDelete(pM->ParArray); + free(pM); + return NULL; + } + pM->pDrivInt->SetValue = MotorRunImpl; + pM->pDrivInt->CheckLimits = MotorLimits; + pM->pDrivInt->CheckStatus = MotorStatus; + pM->pDrivInt->GetValue = MotorGetValue; + pM->pDrivInt->Halt = MotorHalt; + + /* initialize function pointers */ + pM->MotorGetPar = MotorGetParImpl; + pM->MotorSetPar = MotorSetParImpl; + pM->MotorGetHardPosition = MotorGetHardPositionImpl; + + /* initialise callback interface */ + pM->pCall = CreateCallBackInterface(); + if (!pM->pCall) { + MotorKill(pM); + return NULL; + } + + /* done */ + return pM; +} + +/*--------------------------------------------------------------------------*/ +long MotorRun(void *data, SConnection * pCon, float fNew) +{ + pMotor self = (pMotor) data; + + return self->pDrivInt->SetValue(data, pCon, fNew); +} + +/*--------------------------------------------------------------------------*/ +int MotorCheckBoundary(pMotor self, float fVal, float *fHard, + char *error, int iErrLen) +{ + return self->pDrivInt->CheckLimits(self, fVal, error, iErrLen); +} + +/*--------------------------------------------------------------------------*/ +int MotorGetSoftPosition(pMotor self, SConnection * pCon, float *fVal) +{ + float myVal; + myVal = self->pDrivInt->GetValue(self, pCon); + *fVal = myVal; + if (myVal <= -9999999.99) { + return 0; + } else { + return 1; + } +} + +/*--------------------------------------------------------------------------*/ +extern void KillPiPiezo(void *pData); + +void MotorKill(void *self) +{ + pMotor pM; + assert(self); + + pM = (pMotor) self; + + /* MotorHalt(pM); */ + + if (pM->name) + free(pM->name); + + if (pM->pDrivInt) { + free(pM->pDrivInt); + } + + if (pM->pCall) { + DeleteCallBackInterface(pM->pCall); + } + + /* kill driver */ + if (pM->drivername) { + if (pM->pDriver->KillPrivate != NULL) { + pM->pDriver->KillPrivate(pM->pDriver); + if (pM->pDriver->name != NULL) { + free(pM->pDriver->name); + } + free(pM->pDriver); + } + free(pM->drivername); + } + + /* get rid of parameter space */ + if (pM->ParArray) { + ObParDelete(pM->ParArray); + } + + /* kill Descriptor */ + DeleteDescriptor(pM->pDescriptor); + + free(pM); + +} + +/*------------------------------------------------------------------------*/ +float MotorHardToSoftPosition(pMotor self, float fValue) +{ + /* apply zeropoint */ + if (ObVal(self->ParArray, SIGN) < 0.) { + fValue += ObVal(self->ParArray, SZERO); + } else { + fValue -= ObVal(self->ParArray, SZERO); + } + /* apply sign */ + return fValue * ObVal(self->ParArray, SIGN); +} + +/*---------------------------------------------------------------------------*/ +int MotorCheckPosition(void *sulf, SConnection * pCon) +{ + float fHard; + int i, iRet, iCode; + char pBueffel[512]; + pMotor self; + + self = (pMotor) sulf; + assert(self); + assert(pCon); + + /* try to find current position */ + iRet = MotorGetHardPosition(self, pCon, &fHard); + if (iRet) { + if (absf(fHard - self->fTarget) < ObVal(self->ParArray, PREC)) { + self->fPosition = fHard; return 1; } else { - if(self->pDriver->GetDriverPar != NULL) - { - return self->pDriver->GetDriverPar(self->pDriver,name,fVal); - } - else - { - return 0; - } - } - } -/*---------------------------------------------------------------------------*/ - int MotorSetPar(pMotor self, SConnection *pCon, char *name, float fVal) - { - ObPar *pPar = NULL; - char pBueffel[512]; - int iRet; - float fLimit, fOld, fChange; - - assert(self); - assert(pCon); - - /* - try set driver parameters - */ - if(self->pDriver->SetDriverPar != NULL) - { - iRet = self->pDriver->SetDriverPar(self->pDriver,pCon,name,fVal); - if(iRet == 1) - { - SCparChange(pCon); - InvokeCallBack(self->pCall,HDBVAL,self); - return iRet; - } - } - - - if(strcmp(name,"softzero") == 0) - { - /* set it first, this also tests the necessary privileges */ - fOld = ObVal(self->ParArray,SZERO); - iRet = ObParSet(self->ParArray,self->name,name,fVal,pCon); - if(!iRet) - { - return iRet; - } - /* shift the limits by the difference between old and new */ - fChange = fVal - fOld; - /* upper limit */ - fLimit = ObVal(self->ParArray,SUPP); - fLimit -= fChange; - ObParSet(self->ParArray,self->name,"softupperlim",fLimit,pCon); - /* lower limit */ - fLimit = ObVal(self->ParArray,SLOW); - fLimit -= fChange; - ObParSet(self->ParArray,self->name,"softlowerlim",fLimit,pCon); - SCparChange(pCon); - InvokeCallBack(self->pCall,HDBVAL,self); - - return 1; - } - - iRet = ObParSet(self->ParArray,self->name,name,fVal,pCon); - if(strcmp(name,"sign") == 0) - { - if((absf(fVal)-1.0) > 0.01) - { - SCWrite(pCon,"ERROR: Invalid Sign Value",eError); - return 0; - } - if(fVal < 0.0) - { - ObParInit(self->ParArray,SLOW,"softlowerlim", - self->pDriver->fUpper*fVal,usUser); - ObParInit(self->ParArray,SUPP,"softupperlim", - self->pDriver->fLower*fVal,usUser); - ObParInit(self->ParArray,SZERO,"softzero",ZEROINACTIVE,usUser); - } - } - InvokeCallBack(self->pCall,HDBVAL,self); - SCparChange(pCon); - - return iRet; - } -/*--------------------------------------------------------------------------- - MotorCheckBoundary checks for violation of boundary conditions and - transforms from SoftCoordinates to hard coordinates. - */ - - int MotorCheckBoundary(pMotor self, float fVal, float *fNew, - char *pError, int iErrLen) - { - float fHard; - float fZero; - char pBueffel[512]; - - assert(self); - - /* check for fixed */ - if(ObVal(self->ParArray,FIX) >= 0) - { - sprintf(pBueffel,"Motor %s is Fixed",self->name); - strncpy(pError,pBueffel,iErrLen); - return 0; /* is this an error? */ - } - - /* check against software boundaries */ - if(fVal > ObVal(self->ParArray,SUPP)) - { - sprintf(pBueffel,"%f violates upper software limit %f on %s", - fVal, ObVal(self->ParArray,SUPP),self->name); - strncpy(pError,pBueffel,iErrLen); - return 0; - } - if(fVal < ObVal(self->ParArray,SLOW)) - { - sprintf(pBueffel,"%f violates lower software limit %f on %s", - fVal,ObVal(self->ParArray,SLOW),self->name ); - strncpy(pError,pBueffel,iErrLen); - return 0; - } - - /* correct for zero point */ - fZero = ObVal(self->ParArray,SZERO); - fZero = -fZero; - fHard = fVal - fZero; - - /* apply sign */ - fHard = fHard*ObVal(self->ParArray,SIGN); - - /* check for hardware limits */ - if(fHard > self->pDriver->fUpper) - { - sprintf(pBueffel,"%f violates upper hardware limit %f on %s", - fVal,self->pDriver->fUpper,self->name); - strncpy(pError,pBueffel,iErrLen); - return 0; - } - if(fHard < self->pDriver->fLower) - { - sprintf(pBueffel,"%f violates lower hardware limit %f on %s", - fVal,self->pDriver->fLower,self->name); - strncpy(pError,pBueffel,iErrLen); - return 0; - } - - *fNew = fHard; - return 1; - } -/*---------------------------------------------------------------------------*/ - long MotorRun(void *sulf, SConnection *pCon, float fNew) - { - float fHard; - int i, iRet, iCode; - char pBueffel[512]; - char pError[132]; - pMotor self; - long lTime; - float fDelta; - - self = (pMotor)(sulf); - assert(self); - assert(pCon); - - /* check if I'am allowed to move this motor */ - if(!SCMatchRights(pCon,(int)ObVal(self->ParArray,USRIGHTS))) - { - sprintf(pBueffel,"ERROR: You are not authorised to move motor %s", - self->name); - SCWrite(pCon,pBueffel,eError); - SCSetInterrupt(pCon,eAbortBatch); - return 0; - } - - /* check boundaries first */ - iRet = MotorCheckBoundary(self,fNew,&fHard,pError,131); - if(!iRet) - { - snprintf(pBueffel,511,"ERROR: %s",pError); - SCWrite(pCon,pBueffel,eError); - SCSetInterrupt(pCon,eAbortOperation); - return 0; - } - - /* check if the bad motor flag is set */ - if((int)ObVal(self->ParArray,IGNOREFAULT) > 0) - { - snprintf(pBueffel,511,"WARNING: motor %s is unreliable", - self->name); - SCWrite(pCon,pBueffel,eWarning); - self->pDrivInt->iErrorCount = 0; - } - - /* check our error count and interrupt if to much */ - iCode = (int)ObVal(self->ParArray,ECOUNT); - if(self->pDrivInt->iErrorCount > iCode) - { - /* big alarm */ - ServerWriteGlobal("ERROR: !!! MOTOR ALARM !!! MOTOR ALARM !!!",eError); - sprintf(pBueffel, - "ERROR: too many position errors counted at motor %s", - self->name); - ServerWriteGlobal(pBueffel,eError); - SCSetInterrupt(pCon,eAbortBatch); - self->pDrivInt->iErrorCount = 0; + /* Oooopppsss error */ return 0; } - - /* Boundaries OK, send command */ - self->posFaultCount = 0; - self->retryCount = 0; - self->stopped = 0; - self->moving = 1; - self->fTarget = fHard; - InvokeCallBack(self->pCall,HDBVAL,self); - self->last_report_time = 0.0; - self->posCount = 0; - iRet = self->pDriver->RunTo(self->pDriver,fHard); - if(iRet != OKOK) - { /* try three times to fix it */ - for(i = 0; (i < 3) && (iRet != OKOK); i++) - { - self->pDriver->GetError(self->pDriver,&iCode, pError,131); - sprintf(pBueffel,"WARNING: Trying to fix: %s",pError); - SCWrite(pCon,pBueffel,eWarning); - iRet = self->pDriver->TryAndFixIt(self->pDriver,iCode, fHard); - switch(iRet) - { - case MOTFAIL: - SCWrite(pCon,pError,eError); - SCWrite(pCon,"\n",eError); - SCSetInterrupt(pCon,(int)ObVal(self->ParArray,INT)); - return HWFault; - case MOTREDO: - iRet = self->pDriver->RunTo(self->pDriver,fHard); - if(iRet == OKOK) - { - return OKOK; - } - break; - case MOTOK: - return OKOK; - break; - } - } - /* tried three times, refuses to work */ - SCWrite(pCon,pError,eError); - SCWrite(pCon,"\n",eError); - SCSetInterrupt(pCon,(int)ObVal(self->ParArray,INT)); - return HWFault; - } - return OKOK; + } else { /* error getting hold of position, MotorGetHard already tried to + solve the problem and FAILED, the fucking bastard + even messaged the connection accordingly */ + return -1; } -/*------------------------------------------------------------------------*/ - int MotorGetHardPosition(pMotor self,SConnection *pCon, float *fHard) - { - int iRet, iCode; - float fVal; - char pBueffel[512],pError[256]; - - assert(self); - assert(pCon); +} - iRet = self->pDriver->GetPosition(self->pDriver,&fVal); - if(iRet == OKOK) /* all went well, the exception */ - { - *fHard = fVal; - return 1; - } - else /* a problem, the usual case: try fix the problem */ - { /* no point in trying this three times */ - self->pDriver->GetError(self->pDriver,&iCode, pError,255); - iRet = self->pDriver->TryAndFixIt(self->pDriver,iCode, fVal); - sprintf(pBueffel,"WARNING: Trying to fix %s",pError); - SCWrite(pCon,pBueffel,eWarning); - switch(iRet) - { - case MOTFAIL: - sprintf(pBueffel,"ERROR: cannot fix motor %s", - self->name); - SCWrite(pCon,pBueffel,eError); - SCSetInterrupt(pCon,(int)ObVal(self->ParArray,INT)); - *fHard = fVal; - return 0; - case MOTOK: - case MOTREDO: - iRet = self->pDriver->GetPosition(self->pDriver,&fVal); - if(iRet) - { - *fHard = fVal*ObVal(self->ParArray,SIGN); - return 1; - } - else - { - sprintf(pBueffel,"ERROR: cannot fix motor %s", - self->name); - SCSetInterrupt(pCon,(int)ObVal(self->ParArray,INT)); - SCWrite(pCon,pBueffel,eError); - *fHard = fVal; - return 0; - } - } - } - *fHard = fVal*ObVal(self->ParArray,SIGN); - return 0; - } -/*------------------------------------------------------------------------*/ - float MotorHardToSoftPosition(pMotor self, float fValue) - { - /* apply zeropoint */ - if(ObVal(self->ParArray,SIGN) < 0.) - { - fValue += ObVal(self->ParArray,SZERO); - } - else - { - fValue -= ObVal(self->ParArray,SZERO); - } - /* apply sign */ - return fValue*ObVal(self->ParArray,SIGN); - } -/* ------------------------------------------------------------------------*/ - int MotorGetSoftPosition(pMotor self, SConnection *pCon, float *fVal) - { - int iRet; - float fValue; - - assert(self); - assert(pCon); - - /* get the hard position */ - iRet = MotorGetHardPosition(self,pCon,&fValue); - if(!iRet) - { - *fVal = fValue; - return 0; - } - /* apply zeropoint */ - if(ObVal(self->ParArray,SIGN) < 0.) - { - fValue += ObVal(self->ParArray,SZERO); - } - else - { - fValue -= ObVal(self->ParArray,SZERO); - } - *fVal = fValue; - - /* apply sign */ - /* *fVal = MotorHardToSoftPosition(self,fValue); */ - - *fVal = fValue*ObVal(self->ParArray,SIGN); - - return 1; - } -/*---------------------------------------------------------------------------*/ - int MotorCheckPosition(void *sulf, SConnection *pCon) - { - float fHard; - int i, iRet, iCode; - char pBueffel[512]; - pMotor self; - - self = (pMotor)sulf; - assert(self); - assert(pCon); - - /* try to find current position */ - iRet = MotorGetHardPosition(self,pCon,&fHard); - if(iRet) - { - if(absf(fHard - self->fTarget) < ObVal(self->ParArray,PREC)) - { - self->fPosition = fHard; - return 1; - } - else - { - /* Oooopppsss error */ - return 0; - } - } - else /* error getting hold of position, MotorGetHard already tried to - solve the problem and FAILED, the fucking bastard - even messaged the connection accordingly */ - { - return -1; - } - } /* -------------------------------------------------------------------------- The Factory function for creating a motor. Usage: MotorCreate name DriverName. @@ -980,227 +990,212 @@ extern void KillPiPiezo(void *pData); PiPiezo Physik-Instrumente E-255 Piezo Controller SIM simulated motor */ - -extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray); - int MotorCreate(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - pMotor pNew = NULL; - MotorDriver *pDriver = NULL; - char pBueffel[512]; - int iD, iRet; - Tcl_Interp *pTcl = (Tcl_Interp *)pSics->pTcl; - pSite site = NULL; +extern MotorDriver *MakePiPiezo(Tcl_Interp * pTcl, char *pArray); - assert(pCon); - assert(pSics); - - /* a first check */ - if(argc < 3) - { - SCWrite(pCon,"Insufficient arguments for motor creation",eError); - return 0; - } - - /* create the driver */ - strtolower(argv[2]); - strtolower(argv[1]); - if (strcmp(argv[2],"sim") == 0) - { - iD = argc - 3; - pDriver = CreateSIM(pCon,iD,&argv[3]); - if(!pDriver) - { - return 0; - } - /* create the motor */ - pNew = MotorInit("SIM",argv[1],pDriver); - if(!pNew) - { - sprintf(pBueffel,"Failure to create motor %s",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - }else if (strcmp(argv[2],"tclmot") == 0) - { - pDriver = CreateTclMotDriv(pCon,argc,argv); - if(!pDriver) - { - return 0; - } - /* create the motor */ - pNew = MotorInit("TCLMOT",argv[1],pDriver); - if(!pNew) - { - sprintf(pBueffel,"Failure to create motor %s",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - } else if(strcmp(argv[2],"regress") == 0) - { - pDriver = RGMakeMotorDriver(); - if(!pDriver) - { - return 0; - } - /* create the motor */ - pNew = MotorInit("regress",argv[1],pDriver); - if(!pNew) - { - sprintf(pBueffel,"Failure to create motor %s",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - } - else - { - site = getSite(); - if(site != NULL) - { - pNew = site->CreateMotor(pCon,argc-1,&argv[1]); - } - if(pNew == NULL) - { - sprintf(pBueffel,"Motor Type %s not recognized for motor %s", - argv[2],argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - } - - /* create the interpreter command */ - if (pNew->pActionRoutine) - iRet = AddCommand(pSics,argv[1],pNew->pActionRoutine,MotorKill,pNew); - else - iRet = AddCommand(pSics,argv[1],MotorAction,MotorKill,pNew); - if(!iRet) - { - sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - return 1; - } -/* ----------------- some private functions used in MotorAction -------------*/ - void MotorListLL(pMotor self, SConnection *pCon) - { - char pBueffel[512]; - int i, iLen; - - iLen = ObParLength(self->ParArray); - sprintf(pBueffel,"Parameter Listing for motor %s",self->name); - SCWrite(pCon,pBueffel,eValue); - sprintf(pBueffel,"%s.Position = %f\n", self->name,self->fPosition); - SCWrite(pCon,pBueffel,eStatus); - sprintf(pBueffel,"%s.TargetPosition = %f\n", self->name,self->fTarget); - SCWrite(pCon,pBueffel,eStatus); - - snprintf(pBueffel,511,"%s.hardlowerlim = %f",self->name, - self->pDriver->fLower); - SCWrite(pCon,pBueffel,eValue); - snprintf(pBueffel,511,"%s.hardupperlim = %f",self->name, - self->pDriver->fUpper); - SCWrite(pCon,pBueffel,eValue); - for(i = 0; i < iLen; i++) - { - sprintf(pBueffel,"%s.%s = %f\n",self->name, - self->ParArray[i].name,self->ParArray[i].fVal); - SCWrite(pCon,pBueffel,eStatus); - } - - //list driver parameters when appropriate - if(self->pDriver->ListDriverPar != NULL) - { - self->pDriver->ListDriverPar(self->pDriver,self->name, pCon); - } - } -/*--------------------------------------------------------------------------*/ - void MotorReset(pMotor pM) - { - ObParInit(pM->ParArray,SLOW,"softlowerlim",pM->pDriver->fLower,usUser); - ObParInit(pM->ParArray,SUPP,"softupperlim",pM->pDriver->fUpper,usUser); - ObParInit(pM->ParArray,SZERO,"softzero",ZEROINACTIVE,usUser); - ObParInit(pM->ParArray,FIX,"fixed",-1,usUser); - } -/*------------------------------------------------------------------------*/ - typedef struct { - char *pName; - SConnection *pCon; - float lastValue; - } MotInfo, *pMotInfo; -/*-----------------------------------------------------------------------*/ - static void KillInfo(void *pData) - { - pMotInfo self = NULL; - - assert(pData); - self = (pMotInfo)pData; - if(self->pName) - { - free(self->pName); - } - free(self); - } -/*------------------- The CallBack function for interest ------------------*/ - static int InterestCallback(int iEvent, void *pEvent, void *pUser, - commandContext cc) - { - pMotInfo pInfo = NULL; - char pBueffel[80]; - MotCallback *psCall; - - assert(pEvent); - assert(pUser); - - psCall = (MotCallback *)pEvent; - pInfo = (MotInfo *)pUser; - - if (pInfo->lastValue != psCall->fVal) { - pInfo->lastValue = psCall->fVal; - (pInfo->pCon)->conEventType=POSITION; - sprintf(pBueffel,"%s.position = %f ", pInfo->pName, pInfo->lastValue); - SCWriteInContext(pInfo->pCon,pBueffel,eEvent,cc); - } - return 1; - } -/*------------------------------------------------------------------------*/ - static void KillScript(void *pData) - { - if(pData != NULL) - { - free(pData); - } - } -/*------------------------ The endscript callback function ----------------*/ - static int EndScriptCallback(int iEvent, void *pEvent, void *pUser, - commandContext cc) - { - char *pScript = NULL; - MotCallback *psCall; - char pCommand[1024]; - int iRet; - - assert(pEvent); - assert(pUser); - - psCall = (MotCallback *)pEvent; - pScript = (char *)pUser; - - sprintf(pCommand,"%s %f",pScript,psCall->fVal); - iRet = Tcl_Eval(pServ->pSics->pTcl,pCommand); - return iRet; - } - - int CheckMotiMatch(const void* context, const void* pUserData) +int MotorCreate(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) { - pMotInfo pMoti = (pMotInfo) pUserData; - SConnection *pCon = (SConnection*) context; - if (pMoti->pCon == pCon) + pMotor pNew = NULL; + MotorDriver *pDriver = NULL; + char pBueffel[512]; + int iD, iRet; + Tcl_Interp *pTcl = (Tcl_Interp *) pSics->pTcl; + pSite site = NULL; + + assert(pCon); + assert(pSics); + + /* a first check */ + if (argc < 3) { + SCWrite(pCon, "Insufficient arguments for motor creation", eLogError); return 0; + } + + /* create the driver */ + strtolower(argv[2]); + strtolower(argv[1]); + if (strcmp(argv[2], "sim") == 0) { + iD = argc - 3; + pDriver = CreateSIM(pCon, iD, &argv[3]); + if (!pDriver) { + return 0; + } + /* create the motor */ + pNew = MotorInit("SIM", argv[1], pDriver); + if (!pNew) { + snprintf(pBueffel,sizeof(pBueffel)-1, "Failure to create motor %s", argv[1]); + SCWrite(pCon, pBueffel, eLogError); + return 0; + } + } else if (strcmp(argv[2], "tclmot") == 0) { + pDriver = CreateTclMotDriv(pCon, argc, argv); + if (!pDriver) { + return 0; + } + /* create the motor */ + pNew = MotorInit("TCLMOT", argv[1], pDriver); + if (!pNew) { + snprintf(pBueffel,sizeof(pBueffel)-1, "Failure to create motor %s", argv[1]); + SCWrite(pCon, pBueffel, eLogError); + return 0; + } + } else if (strcmp(argv[2], "regress") == 0) { + pDriver = RGMakeMotorDriver(); + if (!pDriver) { + return 0; + } + /* create the motor */ + pNew = MotorInit("regress", argv[1], pDriver); + if (!pNew) { + snprintf(pBueffel,sizeof(pBueffel)-1, "Failure to create motor %s", argv[1]); + SCWrite(pCon, pBueffel, eLogError); + return 0; + } + } else { + site = getSite(); + if (site != NULL) { + pNew = site->CreateMotor(pCon, argc - 1, &argv[1]); + } + if (pNew == NULL) { + snprintf(pBueffel,sizeof(pBueffel)-1, "Motor Type %s not recognized for motor %s", + argv[2], argv[1]); + SCWrite(pCon, pBueffel, eLogError); + return 0; + } + } + + /* create the interpreter command */ + iRet = AddCommand(pSics, argv[1], MotorAction, MotorKill, pNew); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: duplicate command %s not created", argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } return 1; } +/* ----------------- some private functions used in MotorAction -------------*/ +void MotorListLL(pMotor self, SConnection * pCon) +{ + char pBueffel[512]; + int i, iLen; + + iLen = ObParLength(self->ParArray); + snprintf(pBueffel,sizeof(pBueffel)-1, "Parameter Listing for motor %s", self->name); + SCWrite(pCon, pBueffel, eValue); + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.Position = %f\n", self->name, self->fPosition); + SCWrite(pCon, pBueffel, eValue); + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.TargetPosition = %f\n", self->name, self->fTarget); + SCWrite(pCon, pBueffel, eValue); + + snprintf(pBueffel, 511, "%s.hardlowerlim = %f", self->name, + self->pDriver->fLower); + SCWrite(pCon, pBueffel, eValue); + snprintf(pBueffel, 511, "%s.hardupperlim = %f", self->name, + self->pDriver->fUpper); + SCWrite(pCon, pBueffel, eValue); + for (i = 0; i < iLen; i++) { + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.%s = %f\n", self->name, + self->ParArray[i].name, self->ParArray[i].fVal); + SCWrite(pCon, pBueffel, eValue); + } + + /* + list driver parameters when appropriate + */ + if (self->pDriver->ListDriverPar != NULL) { + self->pDriver->ListDriverPar(self->pDriver, self->name, pCon); + } +} + +/*--------------------------------------------------------------------------*/ +void MotorReset(pMotor pM) +{ + ObParInit(pM->ParArray, SLOW, "softlowerlim", pM->pDriver->fLower, + usUser); + ObParInit(pM->ParArray, SUPP, "softupperlim", pM->pDriver->fUpper, + usUser); + ObParInit(pM->ParArray, SZERO, "softzero", ZEROINACTIVE, usUser); + ObParInit(pM->ParArray, FIX, "fixed", -1, usUser); + pM->running = 0; +} + +/*------------------------------------------------------------------------*/ +typedef struct { + char *pName; + SConnection *pCon; + float lastValue; +} MotInfo, *pMotInfo; +/*-----------------------------------------------------------------------*/ +static void KillInfo(void *pData) +{ + pMotInfo self = NULL; + + assert(pData); + self = (pMotInfo) pData; + if (self->pName) { + free(self->pName); + } + if (self->pCon != NULL) { + SCDeleteConnection(self->pCon); + } + free(self); +} + +/*------------------- The CallBack function for interest ------------------*/ +static int InterestCallback(int iEvent, void *pEvent, void *pUser) +{ + pMotInfo pInfo = NULL; + char pBueffel[80]; + MotCallback *psCall; + + assert(pEvent); + assert(pUser); + + psCall = (MotCallback *) pEvent; + pInfo = (MotInfo *) pUser; + + if (!SCisConnected(pInfo->pCon)) { + return -1; + } + + if (pInfo->lastValue != psCall->fVal) { + pInfo->lastValue = psCall->fVal; + (pInfo->pCon)->conEventType = POSITION; + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.position = %f ", pInfo->pName, pInfo->lastValue); + SCWrite(pInfo->pCon, pBueffel, eEvent); + } + return 1; +} + +/*------------------------------------------------------------------------*/ +static void KillScript(void *pData) +{ + if (pData != NULL) { + free(pData); + } +} + +/*------------------------ The endscript callback function ----------------*/ +static int EndScriptCallback(int iEvent, void *pEvent, void *pUser) +{ + char *pScript = NULL; + MotCallback *psCall; + char pCommand[1024]; + int iRet; + + assert(pEvent); + assert(pUser); + + psCall = (MotCallback *) pEvent; + pScript = (char *) pUser; + + snprintf(pCommand,sizeof(pCommand)-1, "%s %f", pScript, psCall->fVal); + iRet = Tcl_Eval(pServ->pSics->pTcl, pCommand); + return iRet; +} + /*---------------------------------------------------------------------------- The wrapper function for a motor. Commands currently supported are: @@ -1213,217 +1208,177 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray); motorname endscript : script to call when motor finishes driving -----------------------------------------------------------------------------*/ - int MotorAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - char pBueffel[512]; - TokenList *pList = NULL; - TokenList *pCurrent; - TokenList *pName; - int iRet; - pMotor self; - float fValue; - long lID; - pMotInfo pMoti = NULL; - - assert(pCon); - assert(pSics); - assert(pData); - - self = (pMotor)pData; - - /* create Tokenlist */ - argtolower(argc,argv); - pList = SplitArguments(argc,argv); - if(!pList) - { - SCWrite(pCon,"Error parsing argument list in MotorAction",eError); - return 0; - } - - /* first argument can be one of list, reset or parameter name */ - pCurrent = pList->pNext; - if(!pCurrent) /* no argument, print value */ - { - iRet = MotorGetSoftPosition(self,pCon,&fValue); - if(!iRet) - { - sprintf(pBueffel,"Error obtaining position for %s",argv[0]); - SCWrite(pCon,pBueffel,eError); - DeleteTokenList(pList); - return 0; - } - sprintf(pBueffel,"%s = %f",argv[0],fValue); - SCWrite(pCon,pBueffel,eValue); - DeleteTokenList(pList); - return 1; - } - - /* check for list */ - if(strcmp(pCurrent->text,"list") == 0) - { - MotorListLL(self,pCon); - DeleteTokenList(pList); - return 1; - } /* check for reset */ - else if(strcmp(pCurrent->text,"reset") == 0) - { - if(!SCMatchRights(pCon,usUser)) - { - sprintf(pBueffel,"Insufficient privilege to reset %s", - argv[0]); - SCWrite(pCon,pBueffel,eError); - DeleteTokenList(pList); - return 0; - } - MotorReset(self); - DeleteTokenList(pList); - SCSendOK(pCon); - return 1; - } - else if(strcmp(pCurrent->text,"interest") == 0) /* interest */ - { - pMoti = (pMotInfo)malloc(sizeof(MotInfo)); - if(!pMoti) - { - SCWrite(pCon,"ERROR: out of memory in motor.c",eError); - return 0; - } - pMoti->pName = strdup(argv[0]); - pMoti->pCon = pCon; - iRet = MotorGetSoftPosition(self,pCon,&fValue); - if(!iRet) - { - sprintf(pBueffel,"Failed to register interest, Reason:Error obtaining current position for %s",argv[0]); - SCWrite(pCon,pBueffel,eError); - DeleteTokenList(pList); - return 0; - } - pMoti->lastValue = fValue; +int MotorAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + char pBueffel[512]; + TokenList *pList = NULL; + TokenList *pCurrent; + TokenList *pName; + int iRet; + pMotor self; + float fValue; + long lID; + pMotInfo pMoti = NULL; - RemoveCallback3(self->pCall, InterestCallback, CheckMotiMatch, pCon); /* only this one */ - lID = RegisterCallback(self->pCall, SCGetContext(pCon),MOTDRIVE, InterestCallback, - pMoti, KillInfo); - SCRegister(pCon,pSics, self->pCall,lID); - DeleteTokenList(pList); - SCSendOK(pCon); - return 1; - } - else if(strcmp(pCurrent->text,"uninterest") == 0) - { - RemoveCallback3(self->pCall, InterestCallback, CheckMotiMatch, pCon); - SCSendOK(pCon); - DeleteTokenList(pList); - return 1; - } - else if(strcmp(pCurrent->text,"endscript") == 0) /* endscript */ - { - if(!SCMatchRights(pCon,usMugger)) - { - return 0; - } - if(self->endScriptID != 0) - { - RemoveCallback(self->pCall, self->endScriptID); - self->endScriptID = 0; - } - pCurrent = pCurrent->pNext; - if(!pCurrent) - { - SCWrite(pCon,"ERROR: scriptname argument missing",eError); - return 0; - } - self->endScriptID = - RegisterCallback(self->pCall, SCGetContext(pCon),MOTEND, EndScriptCallback, - strdup(pCurrent->text), KillScript); - SCRegister(pCon,pSics, self->pCall,self->endScriptID); - DeleteTokenList(pList); - SCSendOK(pCon); - return 1; - } - else /* one of the parameter commands or error left now */ - { - pName = pCurrent; - pCurrent = pCurrent->pNext; - if(!pCurrent) /* no third par: print val */ - { - /* deal with position first */ - if(strcmp(pName->text,"position") == 0) - { - iRet = MotorGetSoftPosition(self,pCon,&fValue); - if(!iRet) - { - sprintf(pBueffel,"Error obtaining position for %s",argv[0]); - SCWrite(pCon,pBueffel,eValue); - DeleteTokenList(pList); - return 0; - } - sprintf(pBueffel,"%s.SoftPosition = %f",argv[0],fValue); - SCWrite(pCon,pBueffel,eValue); - DeleteTokenList(pList); - return 1; - } - else if(strcmp(pName->text,"hardposition") == 0) - { - iRet = MotorGetHardPosition(self,pCon,&fValue); - if(!iRet) { - sprintf(pBueffel,"Error obtaining position for %s",argv[0]); - SCWrite(pCon,pBueffel,eValue); - DeleteTokenList(pList); - return 0; - } - sprintf(pBueffel,"%s.HardPosition = %f",argv[0],fValue); - SCWrite(pCon,pBueffel,eValue); - DeleteTokenList(pList); - return 1; - } - iRet = MotorGetPar(self,pName->text,&fValue); - if(!iRet) - { - sprintf(pBueffel,"Parameter %s not found ",pName->text); - SCWrite(pCon,pBueffel,eValue); - DeleteTokenList(pList); - return 0; - } - else - { - sprintf(pBueffel, "%s.%s = %f",self->name,pName->text,fValue); - SCWrite(pCon,pBueffel,eValue); - DeleteTokenList(pList); - return 1; - } - } - else /* set */ - { /* set command */ - /* parameter must be numerical value */ - if(pCurrent->Type == eInt) - { - fValue = (float)pCurrent->iVal; - } - else if(pCurrent->Type == eFloat) - { - fValue = pCurrent->fVal; - } - else - { - sprintf(pBueffel,"Wrong argument type for %s %s set", - argv[0],pName->text); - SCWrite(pCon,pBueffel,eError); - DeleteTokenList(pList); - return 0; - } - iRet = MotorSetPar(self,pCon,pName->text,fValue); - DeleteTokenList(pList); - if(iRet) - SCSendOK(pCon); - return iRet; - } - } - return 0; + assert(pCon); + assert(pSics); + assert(pData); + + self = (pMotor) pData; + + /* create Tokenlist */ + argtolower(argc, argv); + pList = SplitArguments(argc, argv); + if (!pList) { + SCWrite(pCon, "Error parsing argument list in MotorAction", eError); + return 0; } + /* first argument can be one of list, reset or parameter name */ + pCurrent = pList->pNext; + if (!pCurrent) { /* no argument, print value */ + iRet = MotorGetSoftPosition(self, pCon, &fValue); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, "Error obtaining position for %s", argv[0]); + SCWrite(pCon, pBueffel, eError); + DeleteTokenList(pList); + return 0; + } + snprintf(pBueffel,sizeof(pBueffel)-1, "%s = %f", argv[0], fValue); + SCWrite(pCon, pBueffel, eValue); + DeleteTokenList(pList); + return 1; + } + /* check for list */ + if (strcmp(pCurrent->text, "list") == 0) { + MotorListLL(self, pCon); + DeleteTokenList(pList); + return 1; + } /* check for reset */ + else if (strcmp(pCurrent->text, "reset") == 0) { + if (!SCMatchRights(pCon, usUser)) { + snprintf(pBueffel,sizeof(pBueffel)-1, "Insufficient privilege to reset %s", argv[0]); + SCWrite(pCon, pBueffel, eError); + DeleteTokenList(pList); + return 0; + } + MotorReset(self); + DeleteTokenList(pList); + SCSendOK(pCon); + return 1; + } else if (strcmp(pCurrent->text, "interest") == 0) { /* interest */ + pMoti = (pMotInfo) malloc(sizeof(MotInfo)); + if (!pMoti) { + SCWrite(pCon, "ERROR: out of memory in motor.c", eError); + return 0; + } + pMoti->pName = strdup(argv[0]); + pMoti->pCon = SCCopyConnection(pCon); + iRet = MotorGetSoftPosition(self, pCon, &fValue); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "Failed to register interest, Reason:Error obtaining current position for %s", + argv[0]); + SCWrite(pCon, pBueffel, eError); + DeleteTokenList(pList); + return 0; + } + pMoti->lastValue = fValue; + lID = RegisterCallback(self->pCall, MOTDRIVE, InterestCallback, + pMoti, KillInfo); + DeleteTokenList(pList); + SCSendOK(pCon); + return 1; + } else if (strcmp(pCurrent->text, "uninterest") == 0) { + RemoveCallbackCon(self->pCall, pCon); + SCSendOK(pCon); + DeleteTokenList(pList); + return 1; + } else if (strcmp(pCurrent->text, "endscript") == 0) { /* endscript */ + if (!SCMatchRights(pCon, usMugger)) { + return 0; + } + if (self->endScriptID != 0) { + RemoveCallback(self->pCall, self->endScriptID); + self->endScriptID = 0; + } + pCurrent = pCurrent->pNext; + if (!pCurrent) { + SCWrite(pCon, "ERROR: scriptname argument missing", eError); + return 0; + } + self->endScriptID = + RegisterCallback(self->pCall, MOTEND, EndScriptCallback, + strdup(pCurrent->text), KillScript); + DeleteTokenList(pList); + SCSendOK(pCon); + return 1; + } else { /* one of the parameter commands or error left now */ - - + pName = pCurrent; + pCurrent = pCurrent->pNext; + if (!pCurrent) { /* no third par: print val */ + /* deal with position first */ + if (strcmp(pName->text, "position") == 0) { + iRet = MotorGetSoftPosition(self, pCon, &fValue); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, "Error obtaining position for %s", argv[0]); + SCWrite(pCon, pBueffel, eValue); + DeleteTokenList(pList); + return 0; + } + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.SoftPosition = %f", argv[0], fValue); + SCWrite(pCon, pBueffel, eValue); + DeleteTokenList(pList); + return 1; + } else if (strcmp(pName->text, "hardposition") == 0) { + iRet = MotorGetHardPosition(self, pCon, &fValue); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, "Error obtaining position for %s", argv[0]); + SCWrite(pCon, pBueffel, eValue); + DeleteTokenList(pList); + return 0; + } + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.HardPosition = %f", argv[0], fValue); + SCWrite(pCon, pBueffel, eValue); + DeleteTokenList(pList); + return 1; + } + iRet = MotorGetPar(self, pName->text, &fValue); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, "Parameter %s not found ", pName->text); + SCWrite(pCon, pBueffel, eValue); + DeleteTokenList(pList); + return 0; + } else { + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.%s = %f", self->name, pName->text, fValue); + SCWrite(pCon, pBueffel, eValue); + DeleteTokenList(pList); + return 1; + } + } else { /* set */ + /* set command */ + /* parameter must be numerical value */ + if (pCurrent->Type == eInt) { + fValue = (float) pCurrent->iVal; + } else if (pCurrent->Type == eFloat) { + fValue = pCurrent->fVal; + } else { + snprintf(pBueffel,sizeof(pBueffel)-1, "Wrong argument type for %s %s set", + argv[0], pName->text); + SCWrite(pCon, pBueffel, eError); + DeleteTokenList(pList); + return 0; + } + iRet = MotorSetPar(self, pCon, pName->text, fValue); + DeleteTokenList(pList); + if (iRet) + SCSendOK(pCon); + return iRet; + } + } + return 0; +} diff --git a/motor.h b/motor.h index f86530a4..f06bc2c6 100644 --- a/motor.h +++ b/motor.h @@ -13,65 +13,69 @@ #include "modriv.h" #include "obdes.h" #include "interface.h" +#include "hipadaba.h" #define MOTOBPARLENGTH 12 - typedef struct __Motor { - pObjectDescriptor pDescriptor; - ObPar *ParArray; - pIDrivable pDrivInt; - pICallBack pCall; - ObjectFunc pActionRoutine; - char *drivername; - char *name; - MotorDriver *pDriver; - float fTarget; - float fPosition; - long endScriptID; - int posCount; /* counter for calling the - motor callback */ - int retryCount; /* for retries in status */ - int posFaultCount; - int stopped; - int moving; /* for enabling MOTDRIVE/MOTEND reporting */ - double last_report_time; - } Motor; - typedef Motor *pMotor; +typedef struct __Motor { + pObjectDescriptor pDescriptor; + pHdb objectNode; + pIDrivable pDrivInt; + pICallBack pCall; + int (*MotorSetPar) (struct __Motor * self, SConnection * pCon, + char *name, float fVal); + int (*MotorGetPar) (struct __Motor * self, char *name, float *fVal); + int (*MotorGetHardPosition) (struct __Motor * self, SConnection * pCon, + float *fVal); + char *drivername; + char *name; + MotorDriver *pDriver; + float fTarget; + float fPosition; + long endScriptID; + int posCount; /* counter for calling the + motor callback */ + int retryCount; /* for retries in status */ + int posFaultCount; + int stopped; + int stopReported; + int errorCount; + int running; + ObPar *ParArray; + void *pPrivate; + void (*KillPrivate) (void *); +} Motor; +typedef Motor *pMotor; /*------------------------------------------------------------------------ a tiny structure used in CallBack work --------------------------------------------------------------------------*/ typedef struct { - float fVal; - char *pName; - } MotCallback; -/*-------------------------------------------------------------------------*/ + float fVal; + char *pName; +} MotCallback; +/*-------------------------------------------------------------------------*/ /* parameter management */ - int MotorGetPar(pMotor self, char *name, float *fVal); - int MotorSetPar(pMotor self, SConnection *pCon, char *name, float fVal); +int MotorGetPar(pMotor self, char *name, float *fVal); +int MotorSetPar(pMotor self, SConnection * pCon, char *name, float fVal); /* driving */ - long MotorRun(void *self, SConnection *pCon, float fNew); - int MotorCheckBoundary(pMotor self, float fVal, float *fHard, - char *error, int iErrLen); - int MotorCheckPosition(void *self, SConnection *pCon); - +long MotorRun(void *self, SConnection * pCon, float fNew); +int MotorCheckBoundary(pMotor self, float fVal, float *fHard, + char *error, int iErrLen); + /* Where are we ? */ - int MotorGetSoftPosition(pMotor self,SConnection *pCon, float *fVal); - int MotorGetHardPosition(pMotor self,SConnection *pCon, float *fVal); - float MotorHardToSoftPosition(pMotor self, float fHard); - +int MotorGetSoftPosition(pMotor self, SConnection * pCon, float *fVal); +int MotorGetHardPosition(pMotor self, SConnection * pCon, float *fVal); + /* creation */ - int MotorCreate(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - pMotor MotorInit(char *drivername,char *name, MotorDriver *pDriv); - void MotorKill(void *self); +int MotorCreate(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); +pMotor MotorInit(char *drivername, char *name, MotorDriver * pDriv); +void MotorKill(void *self); /* interface to interpreter */ - int MotorAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - pMotor FindMotor(SicsInterp *pSics, char *name); +int MotorAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); +pMotor FindMotor(SicsInterp * pSics, char *name); -/* Made available to oscillate.c to generate MOTEND event. Ferdi */ - void finishDriving(pMotor self, SConnection *pCon); #endif - diff --git a/motorlist.c b/motorlist.c index 60c3ff77..f5433864 100644 --- a/motorlist.c +++ b/motorlist.c @@ -11,54 +11,57 @@ #include "lld.h" #include "motor.h" /*---------------------------------------------------------------*/ -static void *MOLIGetInterface(void *data, int iD){ - return NULL; +static void *MOLIGetInterface(void *data, int iD) +{ + return NULL; } + /*---------------------------------------------------------------- This routine can return either OKOK or HWFault when thing go wrong. However, the return value of Halt is usually ignored! ------------------------------------------------------------------*/ -static int MOLIHalt(void *data) { - int self = 0, iRet; - MotControl tuktuk; - - self = *(int *)data; +static int MOLIHalt(void *data) +{ + int self = 0, iRet; + MotControl tuktuk; - iRet = LLDnodePtr2First(self); - while(iRet != 0) - { - LLDnodeDataTo(self,&tuktuk); - tuktuk.pDriv->Halt(tuktuk.data); - iRet = LLDnodePtr2Next(self); - } - return OKOK; + self = *(int *) data; + + iRet = LLDnodePtr2First(self); + while (iRet != 0) { + LLDnodeDataTo(self, &tuktuk); + tuktuk.pDriv->Halt(tuktuk.data); + iRet = LLDnodePtr2Next(self); + } + return OKOK; } + /*---------------------------------------------------------------- This routine can return either 1 or 0. 1 means the position can be reached, 0 NOT If 0, error shall contain up to errlen characters of information about which limit was violated ------------------------------------------------------------------*/ -static int MOLICheckLimits(void *data, float val, - char *error, int errlen){ - int self = 0, iRet, test, retVal = 1; - MotControl tuktuk; - - self = *(int *)data; +static int MOLICheckLimits(void *data, float val, char *error, int errlen) +{ + int self = 0, iRet, test, retVal = 1; + MotControl tuktuk; - iRet = LLDnodePtr2First(self); - while(iRet != 0) - { - LLDnodeDataTo(self,&tuktuk); - test = tuktuk.pDriv->CheckLimits(tuktuk.data,val, error, errlen); - if(test == 0){ - retVal = 0; - } - iRet = LLDnodePtr2Next(self); + self = *(int *) data; + + iRet = LLDnodePtr2First(self); + while (iRet != 0) { + LLDnodeDataTo(self, &tuktuk); + test = tuktuk.pDriv->CheckLimits(tuktuk.data, val, error, errlen); + if (test == 0) { + retVal = 0; } + iRet = LLDnodePtr2Next(self); + } - return retVal; + return retVal; } + /*---------------------------------------------------------------- This routine can return 0 when a limit problem occurred OKOK when the motor was successfully started @@ -68,27 +71,28 @@ static int MOLICheckLimits(void *data, float val, to start the motor in question val is the value to drive the motor too ------------------------------------------------------------------*/ -static long MOLISetValue(void *data, SConnection *pCon, float val){ - int self = 0, iRet, test; - MotControl tuktuk; - - self = *(int *)data; +static long MOLISetValue(void *data, SConnection * pCon, float val) +{ + int self = 0, iRet, test; + MotControl tuktuk; - iRet = LLDnodePtr2First(self); - while(iRet != 0) - { - LLDnodeDataTo(self,&tuktuk); - test = tuktuk.pDriv->SetValue(tuktuk.data,pCon,tuktuk.target); - if(test != 1) { - return test; - } else { - tuktuk.running = 1; - LLDnodeDataFrom(self,&tuktuk); - } - iRet = LLDnodePtr2Next(self); + self = *(int *) data; + + iRet = LLDnodePtr2First(self); + while (iRet != 0) { + LLDnodeDataTo(self, &tuktuk); + test = tuktuk.pDriv->SetValue(tuktuk.data, pCon, tuktuk.target); + if (test != 1) { + return test; + } else { + tuktuk.running = 1; + LLDnodeDataFrom(self, &tuktuk); } - return OKOK; + iRet = LLDnodePtr2Next(self); + } + return OKOK; } + /*---------------------------------------------------------------- Checks the status of a running motor. Possible return values HWBusy The motor is still running @@ -99,167 +103,222 @@ static long MOLISetValue(void *data, SConnection *pCon, float val){ For real motors CheckStatus again shall try hard to fix any issues with the motor ------------------------------------------------------------------*/ -static int MOLICheckStatus(void *data, SConnection *pCon){ - int self = 0, iRet, status, result = HWIdle; - MotControl tuktuk; - - self = *(int *)data; +static int MOLICheckStatus(void *data, SConnection * pCon) +{ + int self = 0, iRet, status, result = HWIdle; + MotControl tuktuk; - iRet = LLDnodePtr2First(self); - while(iRet != 0) - { - LLDnodeDataTo(self,&tuktuk); - if(tuktuk.running == 1){ - status = tuktuk.pDriv->CheckStatus(tuktuk.data, pCon); - switch(status){ - case HWIdle: - tuktuk.running = 0; - LLDnodeDataFrom(self,&tuktuk); - break; - case HWBusy: - result = HWBusy; - break; - case HWFault: - case HWPosFault: - return status; - break; - default: - /* - this is a programming error and has to be fixed - */ - assert(0); - } + self = *(int *) data; + + iRet = LLDnodePtr2First(self); + while (iRet != 0) { + LLDnodeDataTo(self, &tuktuk); + if (tuktuk.running == 1) { + status = tuktuk.pDriv->CheckStatus(tuktuk.data, pCon); + switch (status) { + case HWIdle: + tuktuk.running = 0; + LLDnodeDataFrom(self, &tuktuk); + break; + case HWBusy: + result = HWBusy; + break; + case HWFault: + case HWPosFault: + /** + * It is questionable if one should not set a flag here + * and keep polling: it is not clear if this error is a + * communication problem or that the motor really + * has stopped. + */ + return status; + break; + default: + /* + this is a programming error and has to be fixed + */ + assert(0); } - iRet = LLDnodePtr2Next(self); } - return result; + iRet = LLDnodePtr2Next(self); + } + return result; } +/*--------------------------------------------------------- + A special version for EIGER. I am cautious: I have problems + with this at EIGER but I do not want to propagate the fix + elsewhere even if it may be the right thing to do. + -----------------------------------------------------------*/ +int MOLIEigerStatus(void *data, SConnection * pCon) +{ + int self = 0, iRet, status, result = HWIdle; + MotControl tuktuk; + + self = *(int *) data; + + iRet = LLDnodePtr2First(self); + while (iRet != 0) { + LLDnodeDataTo(self, &tuktuk); + if (tuktuk.running == 1) { + status = tuktuk.pDriv->CheckStatus(tuktuk.data, pCon); + switch (status) { + case HWIdle: + tuktuk.running = 0; + LLDnodeDataFrom(self, &tuktuk); + break; + case HWBusy: + result = HWBusy; + break; + case HWFault: + case HWPosFault: + tuktuk.running = 0; + LLDnodeDataFrom(self, &tuktuk); + break; + default: + /* + this is a programming error and has to be fixed + */ + assert(0); + } + } + iRet = LLDnodePtr2Next(self); + } + return result; +} + /*---------------------------------------------------------------- GetValue is supposed to read a motor position On errors, -99999999.99 is returned and messages printed to pCon ------------------------------------------------------------------*/ -static float MOLIGetValue(void *data, SConnection *pCon){ - int self = 0, iRet; - MotControl tuktuk; - float value, result = 1; - - self = *(int *)data; +static float MOLIGetValue(void *data, SConnection * pCon) +{ + int self = 0, iRet; + MotControl tuktuk; + float value, result = 1; - iRet = LLDnodePtr2First(self); - while(iRet != 0) - { - LLDnodeDataTo(self,&tuktuk); - if(MotorGetSoftPosition(tuktuk.data,pCon,&value) == 1){ - tuktuk.position = value; - } else { - tuktuk.position = -9999999.99; - } - LLDnodeDataFrom(self,&tuktuk); - iRet = LLDnodePtr2Next(self); + self = *(int *) data; + + iRet = LLDnodePtr2First(self); + while (iRet != 0) { + LLDnodeDataTo(self, &tuktuk); + if (MotorGetSoftPosition(tuktuk.data, pCon, &value) == 1) { + tuktuk.position = value; + } else { + tuktuk.position = -9999999.99; } - return OKOK; + LLDnodeDataFrom(self, &tuktuk); + iRet = LLDnodePtr2Next(self); + } + return OKOK; } + /*======================== interface functions ========================*/ -pIDrivable makeMotListInterface(){ - pIDrivable pDriv = NULL; +pIDrivable makeMotListInterface() +{ + pIDrivable pDriv = NULL; + pDriv = CreateDrivableInterface(); + if (pDriv == NULL) { + return NULL; + } + pDriv->Halt = MOLIHalt; + pDriv->CheckLimits = MOLICheckLimits; + pDriv->SetValue = MOLISetValue; + pDriv->CheckStatus = MOLICheckStatus; + pDriv->GetValue = MOLIGetValue; - pDriv = CreateDrivableInterface(); - if(pDriv == NULL){ - return NULL; - } - pDriv->Halt = MOLIHalt; - pDriv->CheckLimits = MOLICheckLimits; - pDriv->SetValue = MOLISetValue; - pDriv->CheckStatus = MOLICheckStatus; - pDriv->GetValue = MOLIGetValue; - - return pDriv; + return pDriv; } + /*----------------------------------------------------------------------*/ -int addMotorToList(int listHandle, char *name, float targetValue){ - pMotor pMot = NULL; - MotControl tuktuk; - - pMot = FindMotor(pServ->pSics,name); - if(pMot == NULL){ - return 0; - } - tuktuk.data = pMot; - strncpy(tuktuk.name,name,79); - tuktuk.pDriv = pMot->pDrivInt; - tuktuk.target = targetValue; - tuktuk.running = 0; - tuktuk.position = -9999999.999; - LLDnodeAppendFrom(listHandle,&tuktuk); - return 1; +int addMotorToList(int listHandle, char *name, float targetValue) +{ + pMotor pMot = NULL; + MotControl tuktuk; + + pMot = FindMotor(pServ->pSics, name); + if (pMot == NULL) { + return 0; + } + tuktuk.data = pMot; + strlcpy(tuktuk.name, name, 79); + tuktuk.pDriv = pMot->pDrivInt; + tuktuk.target = targetValue; + tuktuk.running = 0; + tuktuk.position = -9999999.999; + LLDnodeAppendFrom(listHandle, &tuktuk); + return 1; } + /*---------------------------------------------------------------------*/ -int setNewMotorTarget(int listHandle, char *name, float value){ - int iRet; - MotControl tuktuk; - - iRet = LLDnodePtr2First(listHandle); - while(iRet != 0) - { - LLDnodeDataTo(listHandle,&tuktuk); - if(strcmp(tuktuk.name,name) == 0){ - tuktuk.target = value; - tuktuk.running = 0; - LLDnodeDataFrom(listHandle, &tuktuk); - return 1; - } - iRet = LLDnodePtr2Next(listHandle); +int setNewMotorTarget(int listHandle, char *name, float value) +{ + int iRet; + MotControl tuktuk; + + iRet = LLDnodePtr2First(listHandle); + while (iRet != 0) { + LLDnodeDataTo(listHandle, &tuktuk); + if (strcmp(tuktuk.name, name) == 0) { + tuktuk.target = value; + tuktuk.running = 0; + LLDnodeDataFrom(listHandle, &tuktuk); + return 1; } - return 0; + iRet = LLDnodePtr2Next(listHandle); + } + return 0; } + /*-----------------------------------------------------------------*/ -int getMotorFromList(int listHandle, char *name,pMotControl tuk){ - int iRet; - MotControl tuktuk; - - iRet = LLDnodePtr2First(listHandle); - while(iRet != 0) - { - LLDnodeDataTo(listHandle,&tuktuk); - if(strcmp(tuktuk.name,name) == 0){ - memcpy(tuk,&tuktuk,sizeof(MotControl)); - return 1; - } - iRet = LLDnodePtr2Next(listHandle); +int getMotorFromList(int listHandle, char *name, pMotControl tuk) +{ + int iRet; + MotControl tuktuk; + + iRet = LLDnodePtr2First(listHandle); + while (iRet != 0) { + LLDnodeDataTo(listHandle, &tuktuk); + if (strcmp(tuktuk.name, name) == 0) { + memcpy(tuk, &tuktuk, sizeof(MotControl)); + return 1; } - return 0; + iRet = LLDnodePtr2Next(listHandle); + } + return 0; } + /*-----------------------------------------------------------------*/ -float getListMotorPosition(int listHandle, char *name){ - int iRet; - MotControl tuktuk; - - iRet = LLDnodePtr2First(listHandle); - while(iRet != 0) - { - LLDnodeDataTo(listHandle,&tuktuk); - if(strcmp(tuktuk.name,name) == 0){ - return tuktuk.position; - } - iRet = LLDnodePtr2Next(listHandle); +float getListMotorPosition(int listHandle, char *name) +{ + int iRet; + MotControl tuktuk; + + iRet = LLDnodePtr2First(listHandle); + while (iRet != 0) { + LLDnodeDataTo(listHandle, &tuktuk); + if (strcmp(tuktuk.name, name) == 0) { + return tuktuk.position; } - return -999999.99; + iRet = LLDnodePtr2Next(listHandle); + } + return -999999.99; } + /*--------------------------------------------------------------------*/ -void printMotorList(int listHandle, SConnection *pCon){ - int iRet; - MotControl tuktuk; - char pBueffel[132]; - - MOLIGetValue(&listHandle,pCon); - - iRet = LLDnodePtr2First(listHandle); - while(iRet != 0) - { - LLDnodeDataTo(listHandle,&tuktuk); - snprintf(pBueffel,131,"Driving %20s from %8.3f to %8.3f", - tuktuk.name, tuktuk.position, tuktuk.target); - SCWrite(pCon,pBueffel,eValue); - iRet = LLDnodePtr2Next(listHandle); - } +void printMotorList(int listHandle, SConnection * pCon) +{ + int iRet; + MotControl tuktuk; + char pBueffel[132]; + + MOLIGetValue(&listHandle, pCon); + + iRet = LLDnodePtr2First(listHandle); + while (iRet != 0) { + LLDnodeDataTo(listHandle, &tuktuk); + snprintf(pBueffel, 131, "Driving %20s from %8.3f to %8.3f", + tuktuk.name, tuktuk.position, tuktuk.target); + SCWrite(pCon, pBueffel, eValue); + iRet = LLDnodePtr2Next(listHandle); + } } diff --git a/motorlist.h b/motorlist.h index 963d0e3b..4821dbd2 100644 --- a/motorlist.h +++ b/motorlist.h @@ -12,14 +12,14 @@ #define SICSMOTLIST #include "sics.h" -typedef struct{ - char name[80]; - float target; - float position; - pIDrivable pDriv; - void *data; - int running; -}MotControl, *pMotControl; +typedef struct { + char name[80]; + float target; + float position; + pIDrivable pDriv; + void *data; + int running; +} MotControl, *pMotControl; /*======================================================================*/ @@ -27,8 +27,7 @@ pIDrivable makeMotListInterface(); int addMotorToList(int listHandle, char *name, float targetValue); int setNewMotorTarget(int listHandle, char *name, float value); int getMotorFromList(int listHandle, char *name, pMotControl tuk); -float getListMotorPosition(int listHandle, char *name); -void printMotorList(int listHandle, SConnection *pCon); +float getListMotorPosition(int listHandle, char *name); +void printMotorList(int listHandle, SConnection * pCon); #endif - diff --git a/motorsec.c b/motorsec.c new file mode 100644 index 00000000..e0822c3b --- /dev/null +++ b/motorsec.c @@ -0,0 +1,823 @@ +/** + * This is the implementation of a second generation motor. A second + * generation motor differs in various aspects from a first generation + * motor though it is functionally equivalent and even adheres to the + * same interface. The differing aspects are: + * - The second generation motor deos not use the ObPar array for parameter storage + * but the Hipadaba parameter system rooted in self->pDes->objectNode. + * - The second generation motor does not use the driver. The second generation motor + * implements some functionality but is largely a shell. Scripts are supposed to add + * more parameters and link to a corresponding ScriptContext object which takes care + * of actual talking to the hardware. + * - The old callback system is also not implemented: third parties which are interested + * to be notified of changes to the motor position shall register a callback. + * + * This also means that many of the fields in the motor data structure are not used in + * this module but are present to support first generation motors. This must be so as we cannot + * replace all existing driver with new ones quickly. Here a list of fields which have no use: + * - pDriver + * - ParArray + * + * We need three different position parameters to keep this under control: + * - the physical value which is the main motor node + * - the targetposition which is is the hardware target where the motor is supposed + * to be + * - The hardposition which is the actual hardware position. This is also the + * one which is responsible for talking to the motor. + * + * Then we need a status parameter which is some text which says what the motor + * is up to. + * + * A less obvious use of a callback is the HardUpdateCallback. It automatically + * updates the physical motor position, too. + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, December 2008 + */ +#include +#include +#include +#include +#include "sics.h" +#include "sicshipadaba.h" +#include "sicsobj.h" +#include "motor.h" +#include "splitter.h" + +#define ABS(x) (x < 0 ? -(x) : (x)) + +/*--------------------------------------------------------------------------*/ +static int SecMotorGetPar(pMotor self, char *name, float *fVal) +{ + char pBueffel[512]; + hdbValue value;; + int status; + + snprintf(pBueffel, 511, "%s ", name); + status = SICSHdbGetPar(self, NULL, pBueffel, &value); + *fVal = (float) value.v.doubleValue; + return status; +} + +/*---------------------------------------------------------------------------*/ +static int SecMotorSetPar(pMotor self, SConnection * pCon, char *name, + float fVal) +{ + int status; + hdbValue value; + value = MakeHdbFloat(fVal); + status = SICSHdbSetPar(self, pCon, name, value); + if (status == 1) { + SCparChange(pCon); + return 1; + } else { + return 0; + } +} + +/*-------------------------------------------------------------------------*/ +static void *MotorGetInterfaceSec(void *pData, int iID) +{ + pMotor self = NULL; + + self = (pMotor) pData; + assert(self); + if (iID == DRIVEID) { + return self->pDrivInt; + } else if (iID == CALLBACKINTERFACE) { + return self->pCall; + } + return NULL; +} + +/*---------------------------------------------------------------------------*/ +static long SecMotorRun(void *sulf, SConnection * pCon, float fNew) +{ + pMotor self = (pMotor) sulf; + hdbValue v; + int accesscode, status; + pHdb node = NULL; + + assert(SICSHdbGetPar(self, NULL, "accesscode", &v) == 1); + accesscode = (int)v.v.doubleValue; + if(!SCMatchRights(pCon, accesscode)){ + return 0; + } + self->stopped = 0; + self->stopReported = 0; + + v = MakeHdbFloat(fNew); + status = SetHipadabaPar(self->pDescriptor->parNode, v, pCon); + node = GetHipadabaNode(self->pDescriptor->parNode, "status"); + if(node != NULL){ + v = MakeHdbText(strdup("run")); + UpdateHipadabaPar(node,v,pCon); + ReleaseHdbValue(&v); + } + + return status; +} + +/*--------------------------------------------------------------------------*/ +static int SecMotorCheckBoundary(pMotor self, float fVal, float *fTarget, + char *pError, int iErrLen) +{ + double fZero, fixed, lowerlim, upperlim, sign, offset; + float fHard, hupper, hlower; + char pBueffel[512]; + hdbValue v; + + assert(self); + + assert(SICSHdbGetPar(self, NULL, "fixed", &v) == 1); + fixed = v.v.doubleValue; + assert(SICSHdbGetPar(self, NULL, "softzero", &v) == 1); + fZero = v.v.doubleValue; + assert(SICSHdbGetPar(self, NULL, "staticoffset", &v) == 1); + offset = v.v.doubleValue; + assert(SICSHdbGetPar(self, NULL, "softlowerlim", &v) == 1); + lowerlim = v.v.doubleValue; + assert(SICSHdbGetPar(self, NULL, "softupperlim", &v) == 1); + upperlim = v.v.doubleValue; + assert(SICSHdbGetPar(self, NULL, "sign", &v) == 1); + sign = v.v.doubleValue; + + *fTarget = fVal; + + /* check for fixed */ + if (fixed >= 0) { + snprintf(pBueffel,sizeof(pBueffel)-1, "Motor %s is Fixed", self->name); + strlcpy(pError, pBueffel, iErrLen); + return 0; /* is this an error? */ + } + + /* check against software boundaries */ + if (fVal > upperlim) { + snprintf(pBueffel,sizeof(pBueffel)-1, "%f violates upper software limit %f on %s", + fVal, upperlim, self->name); + strlcpy(pError, pBueffel, iErrLen); + return 0; + } + if (fVal < lowerlim) { + snprintf(pBueffel,sizeof(pBueffel)-1, "%f violates lower software limit %f on %s", + fVal, lowerlim, self->name); + strlcpy(pError, pBueffel, iErrLen); + return 0; + } + + /* correct for zero point */ + fZero += offset; + fZero = -fZero; + fHard = fVal - fZero; + + /* apply sign */ + fHard = fHard * sign; + + + /* check for hardware limits */ + SecMotorGetPar(self, "hardlowerlim", &hlower); + SecMotorGetPar(self, "hardupperlim", &hupper); + if (fHard > hupper) { + snprintf(pBueffel,sizeof(pBueffel)-1, "%f violates upper hardware limit %f on %s", + fVal, hupper, self->name); + strlcpy(pError, pBueffel, iErrLen); + return 0; + } + if (fHard < hlower) { + snprintf(pBueffel,sizeof(pBueffel)-1, "%f violates lower hardware limit %f on %s", + fVal, hlower, self->name); + strlcpy(pError, pBueffel, iErrLen); + return 0; + } + + *fTarget = fHard; + return 1; +} + +/*--------------------------------------------------------------------------*/ +static int SecMotorLimits(void *sulf, float fVal, char *error, int iErrLen) +{ + float fHard; + pMotor self; + + assert(sulf); + + self = (pMotor) sulf; + + return SecMotorCheckBoundary(self, fVal, &fHard, error, iErrLen); +} + +/*-----------------------------------------------------------------------*/ +static int checkPosition(pMotor self, SConnection * pCon) +{ + float precision, hard, target, maxretry; + pHdb node = NULL; + + if (self->stopped) { + if(self->stopReported == 0){ + SCPrintf(pCon, eLog, "WARNING: %s stopped", self->name); + self->stopReported = 1; + } + return HWFault; + } + if (SCGetInterrupt(pCon) != eContinue) { + return HWFault; + } + SecMotorGetPar(self, "hardposition", &hard); + SecMotorGetPar(self, "targetposition", &target); + SecMotorGetPar(self, "precision", &precision); + SecMotorGetPar(self, "maxretry", &maxretry); + if (ABS(target - hard) > precision) { + if (self->retryCount >= (int) maxretry) { + SCPrintf(pCon, eLogError, + "ERROR: Aborting %s after %d retries, off position by %f", + self->name, (int) maxretry, target - hard); + node = GetHipadabaNode(self->pDescriptor->parNode, "status"); + assert(node != NULL); + UpdateHipadabaPar(node, MakeHdbText("error"), pCon); + return HWFault; + } + self->retryCount++; + SCPrintf(pCon, eLog, "WARNING: %s off position by %f, restarting", + self->name, target - hard); + node = GetHipadabaNode(self->pDescriptor->parNode, "status"); + assert(node != NULL); + UpdateHipadabaPar(node, MakeHdbText("run"), pCon); + node = GetHipadabaNode(self->pDescriptor->parNode, "hardposition"); + assert(node != NULL); + SetHipadabaPar(node, MakeHdbFloat(target), pCon); + return HWBusy; + } + return HWIdle; +} + +/*-----------------------------------------------------------------------*/ +static void handleMoveCallback(pMotor self, SConnection * pCon) +{ + float movecount; + pHdb node = NULL; + hdbValue v; + + SecMotorGetPar(self, "movecount", &movecount); + self->posCount++; + if (self->posCount > (int) movecount) { + node = GetHipadabaNode(self->pDescriptor->parNode, "hardposition"); + GetHipadabaPar(node, &v, pCon); + UpdateHipadabaPar(node, v, pCon); + self->posCount = 0; + } +} + +/*-----------------------------------------------------------------------*/ +static int SecMotorStatus(void *sulf, SConnection * pCon) +{ + pMotor self = NULL; + int status; + pHdb node = NULL; + hdbValue v; + float interrupt; + + assert(sulf); + self = (pMotor) sulf; + + node = GetHipadabaNode(self->pDescriptor->parNode, "status"); + assert(node != NULL); + status = GetHipadabaPar(node, &v, pCon); + + if (status != 1) { + return HWFault; + } + + if (v.v.text == NULL) { + return HWBusy; + } + if (strstr(v.v.text, "idle") != NULL) { + status = checkPosition(self, pCon); + } else if (strstr(v.v.text, "run") != NULL) { + handleMoveCallback(self, pCon); + status = HWBusy; + } else if (strstr(v.v.text, "poserror") != NULL) { + status = checkPosition(self, pCon); + } else if (strstr(v.v.text, "error") != NULL) { + status = HWFault; + } else { + SCPrintf(pCon, eError, "ERROR: unknown motor status %s found", + v.v.text); + status = HWFault; + } + ReleaseHdbValue(&v); + + /* + * when terminating: force an update of the position. + */ + switch (status) { + case HWFault: + self->posCount = 10000; + handleMoveCallback(self, pCon); + SecMotorGetPar(self, "interrupt", &interrupt); + if (SCGetInterrupt(pCon) < (int) interrupt) { + SCSetInterrupt(pCon, (int) interrupt); + } + break; + case HWIdle: + self->posCount = 10000; + handleMoveCallback(self, pCon); + break; + } + return status; +} + +/*---------------------------------------------------------------------------*/ +static float SecMotorGetValue(void *pData, SConnection * pCon) +{ + int status; + pMotor self = (pMotor) pData; + hdbValue v; + + assert(pData); + status = GetHipadabaPar(self->pDescriptor->parNode, &v, pCon); + if (status != 1) { + return -9999999.99; + } else { + return (float) v.v.doubleValue; + } +} + +/*------------------------------------------------------------------------*/ +static int SecMotorHalt(void *sulf) +{ + pMotor self; + pHdb node = NULL, par[0]; + SICSOBJFunc haltFunc = NULL; + int status; + + assert(sulf); + self = (pMotor) sulf; + + node = GetHipadabaNode(self->pDescriptor->parNode, "halt"); + assert(node != NULL); + + haltFunc = (SICSOBJFunc) node->value.v.func; + assert(haltFunc != NULL); + self->stopped = 1; + self->pDrivInt->iErrorCount--; + if(self->pDrivInt->iErrorCount < 0){ + self->pDrivInt->iErrorCount = 0; + } + return haltFunc((pSICSOBJ) self, pServ->dummyCon, node, par, 0); +} + +/*--------------------------------------------------------------------------*/ +static int SecMotorGetHardPosition(struct __Motor *self, + SConnection * pCon, float *fVal) +{ + hdbValue v; + int status; + pHdb node = NULL; + + node = GetHipadabaNode(self->pDescriptor->parNode, "hardposition"); + assert(node != NULL); + status = GetHipadabaPar(node, &v, pCon); + *fVal = (float) v.v.doubleValue; + return status; +} + +/*---------------------------------------------------------------------------*/ +static void AddMotorPar(pHdb node, int priv, char *name) +{ + pHdb child = NULL; + + child = MakeSICSHdbPar(name, priv, MakeHdbFloat(.0)); + if (child != NULL) { + SetHdbProperty(child, "__save", "true"); + AddHipadabaChild(node, child, NULL); + } +} + +/*---------------------------------------------------------------------------*/ +static float hardToSoftPosition(pMotor self, float hard) +{ + float sign, zero, fVal, offset; + + SecMotorGetPar(self, "sign", &sign); + SecMotorGetPar(self, "softzero", &zero); + SecMotorGetPar(self, "staticoffset", &offset); + fVal = hard; + if (sign < 0) { + fVal += zero + offset; + } else { + fVal -= zero + offset; + } + fVal *= sign; + return fVal; +} + +/*---------------------------------------------------------------------------*/ +static hdbCallbackReturn SecMotorCallback(pHdb node, void *userData, + pHdbMessage message) +{ + SConnection *pCon = NULL; + pHdbDataMessage mm = NULL; + hdbValue v; + pHdb child = NULL; + pMotor self = NULL; + float fHard, fVal, sign, zero; + char pBueffel[512], pError[132]; + int status; + + self = (pMotor) userData; + assert(self != NULL); + + mm = GetHdbSetMessage(message); + if (mm != NULL) { + pCon = (SConnection *) mm->callData; + v = *(mm->v); + + /* + * check permission + */ + SecMotorGetPar(self, "accesscode", &fVal); + if (!SCMatchRights(pCon, (int) fVal)) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: You are not authorised to move motor %s", + self->name); + SCWrite(pCon, pBueffel, eError); + SCSetInterrupt(pCon, eAbortBatch); + return hdbAbort; + } + + /* + * check limits + */ + status = SecMotorCheckBoundary(self, (float) v.v.doubleValue, + &fHard, pError, 131); + if (status != 1) { + snprintf(pBueffel, 511, "ERROR: %s", pError); + SCWrite(pCon, pBueffel, eWarning); + SCSetInterrupt(pCon, eAbortOperation); + return hdbAbort; + } + + /* + * check the motor bad flag + */ + SecMotorGetPar(self, "ignorefault", &fVal); + if ((int) fVal > 0) { + snprintf(pBueffel, 511, "WARNING: motor %s is unreliable", + self->name); + SCWrite(pCon, pBueffel, eWarning); + self->errorCount = 0; + } + + /* + * check for alarm condition + */ + SecMotorGetPar(self, "failafter", &fVal); + if (self->pDrivInt->iErrorCount > (int) fVal) { + /* big alarm */ + ServerWriteGlobal("ERROR: !!! MOTOR ALARM !!! MOTOR ALARM !!!", + eError); + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: too many position errors counted at motor %s", + self->name); + ServerWriteGlobal(pBueffel, eError); + SCSetInterrupt(pCon, eAbortBatch); + self->pDrivInt->iErrorCount = 0; + return hdbAbort; + } + + self->posFaultCount = 0; + self->retryCount = 0; + self->stopped = 0; + self->posCount = 0; + child = GetHipadabaNode(self->pDescriptor->parNode, "targetposition"); + UpdateHipadabaPar(child, MakeHdbFloat(fHard), pCon); + child = GetHipadabaNode(self->pDescriptor->parNode, "status"); + UpdateHipadabaPar(child, MakeHdbText("run"), pCon); + child = GetHipadabaNode(self->pDescriptor->parNode, "hardposition"); + SetHipadabaPar(child, MakeHdbFloat(fHard), pCon); + + return hdbContinue; + } + + mm = GetHdbGetMessage(message); + if (mm != NULL) { + pCon = (SConnection *) mm->callData; + SecMotorGetPar(self, "hardposition", &fVal); + fVal = hardToSoftPosition(self, fVal); + node->value.v.doubleValue = fVal; + mm->v->v.doubleValue = fVal; + return hdbContinue; + } + + return hdbContinue; +} + +/*--------------------------------------------------------------------------*/ +static hdbCallbackReturn HardUpdateCallback(pHdb node, void *userData, + pHdbMessage message) +{ + pHdbDataMessage mm = NULL; + pMotor self = (pMotor) userData; + float fVal; + hdbValue v; + + assert(self != NULL); + + mm = GetHdbUpdateMessage(message); + if (mm != NULL) { + v = *mm->v; + fVal = hardToSoftPosition(self, (float) v.v.doubleValue); + v.v.doubleValue = fVal; + UpdateHipadabaPar(self->pDescriptor->parNode, v, mm->callData); + return hdbContinue; + } + return hdbContinue; +} + +/*--------------------------------------------------------------------------*/ +static hdbCallbackReturn SecMotorSignCallback(pHdb node, void *userData, + pHdbMessage message) +{ + pMotor self = NULL; + SConnection *pCon = NULL; + pHdb zero = NULL; + double value; + pHdbDataMessage mm = NULL; + float limit; + hdbValue v; + + self = (pMotor) userData; + + mm = GetHdbSetMessage(message); + if (mm != NULL) { + pCon = (SConnection *) mm->callData; + if (!SCMatchRights(pCon, usMugger)) { + return hdbAbort; + } + v = *mm->v; + if (ABS(v.v.doubleValue) - 1. > .01) { + if (pCon != NULL) { + SCWrite(pCon, "ERROR: invalid sign value", eError); + return hdbAbort; + } + } + SecMotorGetPar(self, "softlowerlim", &limit); + limit *= v.v.doubleValue; + SecMotorSetPar(self, pCon, "softupperlim", limit); + SecMotorGetPar(self, "softupperlim", &limit); + limit *= v.v.doubleValue; + SecMotorSetPar(self, pCon, "softlowerlim", limit); + SecMotorSetPar(self, pCon, "softzero", .0); + UpdateHipadabaPar(node, v, pCon); + return hdbContinue; + } + return hdbContinue; +} + +/*---------------------------------------------------------------------------*/ +static hdbCallbackReturn SecMotorZeroCallback(pHdb node, void *userData, + pHdbMessage message) +{ + pMotor self = NULL; + float limit, oldZero, diff; + SConnection *pCon = NULL; + pHdbDataMessage mm = NULL; + hdbValue v; + + self = (pMotor) userData; + assert(self != NULL); + + mm = GetHdbSetMessage(message); + if (mm != NULL) { + pCon = (SConnection *) mm->callData; + if (!SCMatchRights(pCon, usUser)) { + return hdbAbort; + } + v = *mm->v; + SecMotorGetPar(self, "softzero", &oldZero); + diff = v.v.doubleValue - oldZero; + + SecMotorGetPar(self, "softupperlim", &limit); + limit -= diff; + SecMotorSetPar(self, pCon, "softupperlim", limit); + + SecMotorGetPar(self, "softlowerlim", &limit); + limit -= diff; + SecMotorSetPar(self, pCon, "softlowerlim", limit); + UpdateHipadabaPar(node, v, pCon); + return hdbContinue; + } + return hdbContinue; +} + +/*---------------------------------------------------------------------------*/ +pMotor SecMotorInit(char *name) +{ + pMotor pM = NULL; + pHdb node = NULL, child = NULL; + hdbValue v; + + assert(name); + + /* get memory */ + pM = (pMotor) malloc(sizeof(Motor)); + if (!pM) { + return NULL; + } + memset(pM, 0, sizeof(Motor)); + + /* initialise object descriptor */ + pM->pDescriptor = CreateDescriptor("Motor"); + if (!pM->pDescriptor) { + free(pM); + return NULL; + } + pM->pDescriptor->GetInterface = MotorGetInterfaceSec; + pM->pDescriptor->SaveStatus = SaveSICSOBJ; + pM->pDescriptor->parNode = MakeSICSHdbPar(name, usSpy, MakeHdbFloat(.0)); + if (pM->pDescriptor->parNode == NULL) { + free(pM); + return NULL; + } + node = pM->pDescriptor->parNode; + SetHdbProperty(node,"type","drivable"); + SetHdbProperty(node,"sicsdev", name); + pM->objectNode = node; + AppendHipadabaCallback(pM->pDescriptor->parNode, + MakeHipadabaCallback(SecMotorCallback, pM, NULL)); + + /* copy arguments */ + pM->name = strdup(name); + + /* + * install parameters + */ + child = MakeSICSHdbPar("targetposition", usInternal, MakeHdbFloat(.0)); + if (child == NULL) { + return (NULL); + } + SetHdbProperty(child, "__save", "true"); + + AddHipadabaChild(node, child, NULL); + child = MakeHipadabaNode("hardposition", HIPFLOAT, 1); + if (child == NULL) { + return (NULL); + } + AddHipadabaChild(node, child, NULL); + SetHdbProperty(child, "motname", name); + AppendHipadabaCallback(child, + MakeHipadabaCallback(HardUpdateCallback, pM, + NULL)); + + child = MakeHipadabaNode("sign", HIPFLOAT, 1); + SetHdbProperty(child, "__save", "true"); + AddHipadabaChild(node, child, NULL); + AppendHipadabaCallback(child, + MakeHipadabaCallback(SecMotorSignCallback, pM, + NULL)); + UpdateHipadabaPar(child, MakeHdbFloat(1.), NULL); + + child = MakeHipadabaNode("softzero", HIPFLOAT, 1); + SetHdbProperty(child, "__save", "true"); + AddHipadabaChild(node, child, NULL); + AppendHipadabaCallback(child, + MakeHipadabaCallback(SecMotorZeroCallback, pM, + NULL)); + + child = MakeHipadabaNode("hardlowerlim", HIPFLOAT, 1); + AddHipadabaChild(node, child, NULL); + + child = MakeHipadabaNode("hardupperlim", HIPFLOAT, 1); + AddHipadabaChild(node, child, NULL); + + child = MakeSICSHdbPar("softlowerlim", usUser, MakeHdbFloat(.0)); + SetHdbProperty(child, "__save", "true"); + AddHipadabaChild(node, child, NULL); + + child = MakeSICSHdbPar("softupperlim", usUser, MakeHdbFloat(.0)); + SetHdbProperty(child, "__save", "true"); + AddHipadabaChild(node, child, NULL); + + child = MakeSICSHdbPar("fixed", usUser, MakeHdbFloat(-1.)); + SetHdbProperty(child, "__save", "true"); + AddHipadabaChild(node, child, NULL); + + child = MakeSICSHdbPar("interruptmode", usMugger, MakeHdbFloat(.0)); + SetHdbProperty(child, "__save", "true"); + AddHipadabaChild(node, child, NULL); + + child = MakeSICSHdbPar("precision", usMugger, MakeHdbFloat(.01)); + SetHdbProperty(child, "__save", "true"); + AddHipadabaChild(node, child, NULL); + + child = MakeSICSHdbPar("accesscode", usMugger, + MakeHdbFloat((double) usUser)); + SetHdbProperty(child, "__save", "true"); + AddHipadabaChild(node, child, NULL); + + child = MakeSICSHdbPar("failafter", usMugger, + MakeHdbFloat((double) 3.0)); + SetHdbProperty(child, "__save", "true"); + AddHipadabaChild(node, child, NULL); + + child = MakeSICSHdbPar("maxretry", usMugger, MakeHdbFloat((double) 3.0)); + SetHdbProperty(child, "__save", "true"); + AddHipadabaChild(node, child, NULL); + + child = MakeSICSHdbPar("ignorefault", usMugger, + MakeHdbFloat((double) .0)); + SetHdbProperty(child, "__save", "true"); + AddHipadabaChild(node, child, NULL); + + child = MakeSICSHdbPar("movecount", usMugger, + MakeHdbFloat((double) 10.0)); + SetHdbProperty(child, "__save", "true"); + AddHipadabaChild(node, child, NULL); + + child = MakeSICSHdbPar("staticoffset", usMugger, + MakeHdbFloat((double) 0.0)); + SetHdbProperty(child, "__save", "true"); + AddHipadabaChild(node, child, NULL); + + child = MakeHipadabaNode("status", HIPTEXT, 1); + SetHdbProperty(child, "motname", name); + AddHipadabaChild(node, child, NULL); + + pM->endScriptID = 0; + + /* initialise Drivable interface */ + pM->pDrivInt = CreateDrivableInterface(); + if (!pM->pDrivInt) { + DeleteDescriptor(pM->pDescriptor); + free(pM); + return NULL; + } + pM->pDrivInt->SetValue = SecMotorRun; + pM->pDrivInt->CheckLimits = SecMotorLimits; + pM->pDrivInt->CheckStatus = SecMotorStatus; + pM->pDrivInt->GetValue = SecMotorGetValue; + pM->pDrivInt->Halt = SecMotorHalt; + + /* + * initialize motor function pointers + */ + pM->MotorGetPar = SecMotorGetPar; + pM->MotorSetPar = SecMotorSetPar; + pM->MotorGetHardPosition = SecMotorGetHardPosition; + + /* initialise callback interface */ + pM->pCall = CreateCallBackInterface(); + if (!pM->pCall) { + MotorKill(pM); + return NULL; + } + + /* done */ + return pM; +} + +/*--------------------------------------------------------------------------*/ +static void SecMotorKill(void *data) +{ + pMotor self = (pMotor) data; + if (self == NULL) { + return; + } + if (self->name) + free(self->name); + + if (self->pDrivInt) { + free(self->pDrivInt); + } + + if (self->pCall) { + DeleteCallBackInterface(self->pCall); + } + + /* kill Descriptor */ + DeleteDescriptor(self->pDescriptor); + + free(self); +} + +/*--------------------------------------------------------------------------*/ +int SecMotorFactory(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pMotor pNew = NULL; + + if (argc < 2) { + SCWrite(pCon, "ERROR: need name for new motor", eError); + return 0; + } + + pNew = SecMotorInit(argv[1]); + if (pNew == NULL) { + SCWrite(pCon, "ERROR: out of memory creating motor", eError); + return 0; + } + return AddCommand(pSics, argv[1], InterInvokeSICSOBJ, + SecMotorKill, pNew); + +} diff --git a/motorsec.h b/motorsec.h new file mode 100644 index 00000000..b2ff76b9 --- /dev/null +++ b/motorsec.h @@ -0,0 +1,14 @@ +/** + * This is the header file for the second generation motor object. + * More details in the header of the implementation file. + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, December 2008 + */ +#ifndef MOTORSEC_H_ +#define MOTORSEC_H_ +int SecMotorFactory(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); + +#endif /*MOTORSEC_H_ */ diff --git a/motreg.c b/motreg.c index 92e024a1..6408130d 100644 --- a/motreg.c +++ b/motreg.c @@ -10,39 +10,41 @@ Mark Koennecke, August 2002 -----------------------------------------------------------------------*/ #include -#include +#include #include "fortify.h" #include "motreg.h" /*--------------------------------------------------------------------*/ -pMotReg RegisterMotor(char *name, SicsInterp *pSics, - long (*NewSetValue)(void *pData, SConnection *pCon, - float farget), - int (*NewCheckStatus)(void *pData,SConnection *pCon) ){ +pMotReg RegisterMotor(char *name, SicsInterp * pSics, + long (*NewSetValue) (void *pData, SConnection * pCon, + float farget), + int (*NewCheckStatus) (void *pData, + SConnection * pCon)) +{ CommandList *pCom = NULL; pIDrivable pDriv = NULL; pMotReg pNew = NULL; /* - find motor data structures - */ - pCom = FindCommand(pSics,name); - if(pCom == NULL){ + find motor data structures + */ + pCom = FindCommand(pSics, name); + if (pCom == NULL) { return NULL; } pDriv = GetDrivableInterface(pCom->pData); - if(pDriv == NULL){ + if (pDriv == NULL) { return NULL; } /* - everything seems OK. Allocate data structure and initialize - */ - pNew = (pMotReg)malloc(sizeof(MotReg)); - if(pNew == NULL){ + everything seems OK. Allocate data structure and initialize + */ + pNew = (pMotReg) malloc(sizeof(MotReg)); + if (pNew == NULL) { return NULL; } - memset(pNew,0,sizeof(MotReg)); + memset(pNew, 0, sizeof(MotReg)); pNew->motorData = pCom->pData; pNew->motorName = strdup(name); @@ -55,45 +57,56 @@ pMotReg RegisterMotor(char *name, SicsInterp *pSics, return pNew; } -/*---------------------------------------------------------------------*/ -void KillRegMot(void *pData){ - pMotReg self = (pMotReg)pData; - if(self == NULL){ +/*---------------------------------------------------------------------*/ +void KillRegMot(void *pData) +{ + pMotReg self = (pMotReg) pData; + + if (self == NULL) { return; } - if(self->motorName != NULL){ + if (self->motorName != NULL) { free(self->motorName); } free(self); } + /*------------------------------------------------------------------------*/ -void SetRegMotTarget(pMotReg self, float fValue){ +void SetRegMotTarget(pMotReg self, float fValue) +{ assert(self); self->targetPosition = fValue; self->iActive = 1; } + /*------------------------------------------------------------------------*/ -void CreateTargetString(pMotReg self, char pBueffel[80]) { +void CreateTargetString(pMotReg self, char pBueffel[80]) +{ assert(self); - if(strlen(self->motorName) + 20 < 80) { - sprintf(pBueffel," %s %12.4f ", self->motorName, self->targetPosition); + if (strlen(self->motorName) + 20 < 80) { + sprintf(pBueffel, " %s %12.4f ", self->motorName, + self->targetPosition); } } + /*-----------------------------------------------------------------------*/ -int RegMotMatch(pMotReg self, char *name){ +int RegMotMatch(pMotReg self, char *name) +{ assert(self); - if(strcmp(self->motorName, name) == 0) { + if (strcmp(self->motorName, name) == 0) { return 1; } return 0; } + /*----------------------------------------------------------------------*/ -int StartRegMot(pMotReg self, SConnection *pCon, float fValue){ +int StartRegMot(pMotReg self, SConnection * pCon, float fValue) +{ int ret; - long (*oldSet)(void *pmotorData, SConnection *pCon, float fValue); + long (*oldSet) (void *pmotorData, SConnection * pCon, float fValue); pIDrivable pDriv = NULL; char pBueffel[132]; @@ -104,35 +117,35 @@ int StartRegMot(pMotReg self, SConnection *pCon, float fValue){ oldSet = pDriv->SetValue; pDriv->SetValue = self->originalSetValue; ret = StartDevice(pServ->pExecutor, self->motorName, - FindDescriptor(self->motorData), - self->motorData, - pCon, - fValue); + FindDescriptor(self->motorData), + self->motorData, pCon, pCon->runLevel, fValue); /* - sprintf(pBueffel,"anticollision started %s to %f",self->motorName, - fValue); - SCWrite(pCon,pBueffel,eValue); - */ + snprintf(pBueffel,sizeof(pBueffel)-1,"anticollision started %s to %f",self->motorName, + fValue); + SCWrite(pCon,pBueffel,eValue); + */ pDriv->SetValue = oldSet; - if(ret == 1){ - self->iActive = 1; + if (ret == 1) { + self->iActive = 1; } else { - snprintf(pBueffel,131,"ERROR: failed to start motor %s", - self->motorName); - SCWrite(pCon,pBueffel,eError); - self->iActive = 0; + snprintf(pBueffel, 131, "ERROR: failed to start motor %s", + self->motorName); + SCWrite(pCon, pBueffel, eError); + self->iActive = 0; } return ret; } + /*----------------------------------------------------------------------*/ -int CheckRegMot(pMotReg self, SConnection *pCon){ +int CheckRegMot(pMotReg self, SConnection * pCon) +{ int stat; assert(self); - if(self->iActive){ - stat = self->originalCheckStatus(self->motorData,pCon); - if(stat != HWBusy){ + if (self->iActive) { + stat = self->originalCheckStatus(self->motorData, pCon); + if (stat != HWBusy) { self->iActive = 0; } return stat; @@ -140,4 +153,3 @@ int CheckRegMot(pMotReg self, SConnection *pCon){ return HWIdle; } } - diff --git a/motreg.h b/motreg.h index 457abb97..7b61e21a 100644 --- a/motreg.h +++ b/motreg.h @@ -17,36 +17,34 @@ typedef struct __MOTREG { - void *motorData; - char *motorName; - float targetPosition; - long (*originalSetValue)(void *motorData, - SConnection *pCon, - float fTarget); - int (*originalCheckStatus)(void *motorData, - SConnection *pCon); - int iActive; - } MotReg, *pMotReg; + void *motorData; + char *motorName; + float targetPosition; + long (*originalSetValue) (void *motorData, + SConnection * pCon, float fTarget); + int (*originalCheckStatus) (void *motorData, SConnection * pCon); + int iActive; +} MotReg, *pMotReg; /*----------------------------------------------------------------------*/ - pMotReg RegisterMotor(char *name, SicsInterp *pSics, - long (*SetValue)(void *pData, SConnection *pCon, float - fTarget), - int (*CheckStatus)(void *pData, SConnection *pCon)); - void KillRegMot(void *self); +pMotReg RegisterMotor(char *name, SicsInterp * pSics, + long (*SetValue) (void *pData, SConnection * pCon, + float fTarget), + int (*CheckStatus) (void *pData, + SConnection * pCon)); +void KillRegMot(void *self); - void SetRegMotTarget(pMotReg self, float target); - void CreateTargetString(pMotReg self, char pBueffel[80]); +void SetRegMotTarget(pMotReg self, float target); +void CreateTargetString(pMotReg self, char pBueffel[80]); - int RegMotMatch(pMotReg self, char *name); +int RegMotMatch(pMotReg self, char *name); - int StartRegMot(pMotReg self, SConnection *pCon, float fValue); +int StartRegMot(pMotReg self, SConnection * pCon, float fValue); + +int CheckRegMot(pMotReg self, SConnection * pCon); - int CheckRegMot(pMotReg self, SConnection *pCon); - #endif - diff --git a/motreglist.c b/motreglist.c index ff7ba7cb..6badef39 100644 --- a/motreglist.c +++ b/motreglist.c @@ -14,106 +14,119 @@ #include "motreglist.h" /*-----------------------------------------------------------------------*/ -int MakeMotList(){ +int MakeMotList() +{ return LLDcreate(sizeof(pMotReg)); } + /*----------------------------------------------------------------------*/ -pMotReg FindMotEntry(int iList, char *name){ +pMotReg FindMotEntry(int iList, char *name) +{ int iRet; pMotReg pMot = NULL; iRet = LLDnodePtr2First(iList); - while(iRet != 0){ - LLDnodeDataTo(iList,&pMot); - if(pMot != NULL){ - if(RegMotMatch(pMot,name)){ - return pMot; + while (iRet != 0) { + LLDnodeDataTo(iList, &pMot); + if (pMot != NULL) { + if (RegMotMatch(pMot, name)) { + return pMot; } } iRet = LLDnodePtr2Next(iList); } return NULL; } + /*-----------------------------------------------------------------------*/ -pMotReg FindMotFromDataStructure(int iList, void *pData){ +pMotReg FindMotFromDataStructure(int iList, void *pData) +{ int iRet; pMotReg pMot = NULL; iRet = LLDnodePtr2First(iList); - while(iRet != 0){ - LLDnodeDataTo(iList,&pMot); - if(pMot != NULL){ - if(pMot->motorData == pData){ - return pMot; + while (iRet != 0) { + LLDnodeDataTo(iList, &pMot); + if (pMot != NULL) { + if (pMot->motorData == pData) { + return pMot; } } iRet = LLDnodePtr2Next(iList); } return NULL; } + /*----------------------------------------------------------------------*/ -int CheckAllMotors(int iList, SConnection *pCon){ +int CheckAllMotors(int iList, SConnection * pCon) +{ int iRet, count = 0; pMotReg pMot = NULL; iRet = LLDnodePtr2First(iList); - while(iRet != 0){ - LLDnodeDataTo(iList,&pMot); - if(pMot != NULL){ - CheckRegMot(pMot,pCon); - if(pMot->iActive){ - count++; + while (iRet != 0) { + LLDnodeDataTo(iList, &pMot); + if (pMot != NULL) { + CheckRegMot(pMot, pCon); + if (pMot->iActive) { + count++; } } iRet = LLDnodePtr2Next(iList); } return count; } + /*----------------------------------------------------------------------*/ -void StopAllMotors(int iList){ +void StopAllMotors(int iList) +{ int iRet, count = 0; pMotReg pMot = NULL; pIDrivable pDriv; iRet = LLDnodePtr2First(iList); - while(iRet != 0){ - LLDnodeDataTo(iList,&pMot); - if(pMot != NULL){ - if(pMot->iActive){ - pDriv = (pIDrivable)GetDrivableInterface(pMot->motorData); - if(pDriv){ - pDriv->Halt(pMot->motorData); - } - pMot->iActive = 0; + while (iRet != 0) { + LLDnodeDataTo(iList, &pMot); + if (pMot != NULL) { + if (pMot->iActive) { + pDriv = (pIDrivable) GetDrivableInterface(pMot->motorData); + if (pDriv) { + pDriv->Halt(pMot->motorData); + } + pMot->iActive = 0; } } iRet = LLDnodePtr2Next(iList); } } + /*----------------------------------------------------------------------*/ -void DeactivateAllMotors(int iList){ +void DeactivateAllMotors(int iList) +{ int iRet, count = 0; pMotReg pMot = NULL; pIDrivable pDriv; iRet = LLDnodePtr2First(iList); - while(iRet != 0){ - LLDnodeDataTo(iList,&pMot); - if(pMot != NULL){ + while (iRet != 0) { + LLDnodeDataTo(iList, &pMot); + if (pMot != NULL) { pMot->iActive = 0; } iRet = LLDnodePtr2Next(iList); } } + /*----------------------------------------------------------------------*/ -void KillMotList(int iList){ +void KillMotList(int iList) +{ int iRet; pMotReg pMot = NULL; iRet = LLDnodePtr2First(iList); - while(iRet != 0){ - LLDnodeDataTo(iList,&pMot); - if(pMot != NULL){ + while (iRet != 0) { + LLDnodeDataTo(iList, &pMot); + if (pMot != NULL) { KillRegMot(pMot); } iRet = LLDnodePtr2Next(iList); diff --git a/motreglist.h b/motreglist.h index dd887a53..5aaca947 100644 --- a/motreglist.h +++ b/motreglist.h @@ -14,17 +14,15 @@ #include "motreg.h" - int MakeMotList(); - pMotReg FindMotEntry(int iList,char *name); - pMotReg FindMotFromDataStructure(int iList, void *pData); - int CheckAllMotors(int iList, SConnection *pCon); - void KillMotList(int iList); - void StopAllMotors(int iList); - void DeactivateAllMotors(int iList); - +int MakeMotList(); +pMotReg FindMotEntry(int iList, char *name); +pMotReg FindMotFromDataStructure(int iList, void *pData); +int CheckAllMotors(int iList, SConnection * pCon); +void KillMotList(int iList); +void StopAllMotors(int iList); +void DeactivateAllMotors(int iList); + #endif - - diff --git a/multicounter.c b/multicounter.c index 266d121f..ed129a69 100644 --- a/multicounter.c +++ b/multicounter.c @@ -14,6 +14,10 @@ * copyright: see file COPYRIGHT * * Mark Koennecke, September 2006 + * + * extended to forward parameter setting requests to the single counter driver + * + * Mark Koennecke, February 2009 */ #include #include @@ -28,222 +32,188 @@ #define MAXSLAVE 16 #define NOCOUNTERS -2727 /*=============== code for the driver ======================================*/ -typedef struct { - void *slaveData[MAXSLAVE]; - pICountable slaves[MAXSLAVE]; - char *transferScript; - int nSlaves; -}MultiCounter, *pMultiCounter; +typedef struct { + void *slaveData[MAXSLAVE]; + pICountable slaves[MAXSLAVE]; + char *transferScript; + int nSlaves; +} MultiCounter, *pMultiCounter; /*--------------------------------------------------------------------------*/ -static void KillMultiDriver(struct __COUNTER *data){ - pMultiCounter self = (pMultiCounter)data->pData; - if(self == NULL){ - return; - } - if(self->transferScript != NULL){ - free(self->transferScript); - } - free(self); +static void KillMultiDriver(struct __COUNTER *data) +{ + pMultiCounter self = (pMultiCounter) data->pData; + if (self == NULL) { + return; + } + if (self->transferScript != NULL) { + free(self->transferScript); + } + free(self); } + /*============== countable interface functions ============================*/ -static int MMCCHalt(void *pData){ +static int MMCCHalt(void *pData) +{ int i, retVal = OKOK, status; pCounter pCount = NULL; pMultiCounter self = NULL; - pCount = (pCounter)pData; - if(pCount != NULL){ - self = (pMultiCounter)pCount->pDriv->pData; + pCount = (pCounter) pData; + if (pCount != NULL) { + self = (pMultiCounter) pCount->pDriv->pData; } assert(self); - for(i = 0; i < self->nSlaves; i++){ + for (i = 0; i < self->nSlaves; i++) { status = self->slaves[i]->Halt(self->slaveData[i]); - if(status != OKOK) + ReleaseCountLock(self->slaves[i]); + if (status != OKOK) retVal = status; } + ReleaseCountLock(pCount->pCountInt); return retVal; } + /*-------------------------------------------------------------------------*/ -static int MMCCStart(void *pData, SConnection *pCon) +static int MMCCStart(void *pData, SConnection * pCon) { - int i, status, controlMonitor; - int slavePreset, oneYear=32000000; + int i, status; pCounter pCount = NULL; pMultiCounter self = NULL; - char buffer[128]; - CounterMode slaveMode; - pCount = (pCounter)pData; - if(pCount != NULL){ - self = (pMultiCounter)pCount->pDriv->pData; + pCount = (pCounter) pData; + if (pCount != NULL) { + self = (pMultiCounter) pCount->pDriv->pData; } assert(self); - controlMonitor = GetControlMonitor((pCounter)pCount); - if (pCount->pDriv->eMode == ePreset) { - slaveMode = eTimer; - slavePreset = oneYear; - } else { - slaveMode = pCount->pDriv->eMode; - slavePreset = pCount->pDriv->fPreset; + + if (!GetCountLock(pCount->pCountInt, pCon)) { + return HWFault; } - for(i = 0; i < self->nSlaves; i++){ - if (i == controlMonitor) { - self->slaves[i]->SetCountParameters(self->slaveData[i], - pCount->pDriv->fPreset, pCount->pDriv->eMode); - } else { - self->slaves[i]->SetCountParameters(self->slaveData[i], - slavePreset, slaveMode); - } - status = self->slaves[i]->StartCount(self->slaveData[i],pCon); - if(status != OKOK){ + + for (i = 0; i < self->nSlaves; i++) { + ReleaseCountLock(self->slaves[i]); + self->slaves[i]->SetCountParameters(self->slaveData[i], + pCount->pDriv->fPreset, + pCount->pDriv->eMode); + status = self->slaves[i]->StartCount(self->slaveData[i], pCon); + if (status != OKOK) { MMCCHalt(pData); + ReleaseCountLock(pCount->pCountInt); return status; } } pCount->isUpToDate = 0; pCount->tStart = time(NULL); - InvokeCallBack(pCount->pCall,COUNTSTART,pCon); + InvokeCallBack(pCount->pCall, COUNTSTART, pCon); return OKOK; } + /*-------------------------------------------------------------------------*/ -static int MMCCStatus(void *pData, SConnection *pCon){ - int status, ctrStatus, i, controlMonitor; - pCounter pCountController = NULL, pSlaveCounter = NULL; - pCounter pCount = NULL; +static int MMCCStatus(void *pData, SConnection * pCon) +{ + int status, i; + pCounter pCount = NULL, pMaster = NULL;; pMultiCounter self = NULL; pDummy pDum = NULL; - enum { - eIdle, - eBusy, - ePause, - eNoBeam, - eFault - } statusLevel; - pCount = (pCounter)pData; - if(pCount != NULL){ - self = (pMultiCounter)pCount->pDriv->pData; + pCount = (pCounter) pData; + if (pCount != NULL) { + self = (pMultiCounter) pCount->pDriv->pData; } assert(self); - if(self->nSlaves == 0) { + if (self->nSlaves == 0) { pCount->pDriv->iErrorCode = NOCOUNTERS; + ReleaseCountLock(pCount->pCountInt); return HWFault; } - controlMonitor = GetControlMonitor((pCounter)pCount); - pCountController = (pCounter)self->slaveData[controlMonitor]; - - /* counter states = HWIdle, HWBusy, HWPause, HWNoBeam, HWFault */ - status = HWIdle; - statusLevel = eIdle; - for (i = 0; i < self->nSlaves; i++) { - pSlaveCounter = (pCounter)self->slaveData[i]; - ctrStatus = self->slaves[i]->CheckCountStatus(pSlaveCounter,pCon); - if (statusLevel >= eFault) - continue; - switch (ctrStatus) { - case HWFault: - statusLevel = eFault; - status = HWFault; - break; - case HWNoBeam: - if (statusLevel < eNoBeam) - statusLevel = eNoBeam; - status = HWNoBeam; - break; - case HWPause: - if (statusLevel < ePause) - statusLevel = ePause; - status = HWPause; - break; - default: - if ( pCountController->pDriv->eMode == ePreset && i == controlMonitor && ctrStatus == HWIdle) { - statusLevel = eBusy; /* Allow transition to HWPause or higher */ - status = HWIdle; - } else if (statusLevel < eBusy && ctrStatus != HWIdle) { - /* ffr: We expect !HWIdle means HWBusy, if not the existing code should handle the exception */ - statusLevel = eBusy; - status = ctrStatus; - } - } - } - if(status == HWIdle || status == HWFault){ + status = self->slaves[0]->CheckCountStatus(self->slaveData[0], pCon); + pMaster = (pCounter)self->slaveData[0]; + pCount->pDriv->fLastCurrent = GetControlValue(pMaster); + if (status == HWIdle || status == HWFault) { /* - stop counting on slaves when finished or when an error - occurred. - */ - InvokeCallBack(pCount->pCall,COUNTEND,pCon); + stop counting on slaves when finished or when an error + occurred. + */ + InvokeCallBack(pCount->pCall, COUNTEND, pCon); MMCCHalt(pCount); } - for(i = 1; i < MAXSLAVE; i++){ - if(self->slaves[i] != NULL){ - pDum = (pDummy)self->slaveData[i]; - if(strcmp(pDum->pDescriptor->name,"HistMem") == 0){ - HistDirty((pHistMem)self->slaveData[i]); + for (i = 1; i < MAXSLAVE; i++) { + if (self->slaves[i] != NULL) { + pDum = (pDummy) self->slaveData[i]; + if (strcmp(pDum->pDescriptor->name, "HistMem") == 0) { + HistDirty((pHistMem) self->slaveData[i]); } + ReleaseCountLock(self->slaves[i]); } } return status; } + /*-------------------------------------------------------------------------*/ -static int MMCCPause(void *pData, SConnection *pCon){ +static int MMCCPause(void *pData, SConnection * pCon) +{ int i, status; pCounter pCount = NULL; pMultiCounter self = NULL; - pCount = (pCounter)pData; - if(pCount != NULL){ - self = (pMultiCounter)pCount->pDriv->pData; + pCount = (pCounter) pData; + if (pCount != NULL) { + self = (pMultiCounter) pCount->pDriv->pData; } assert(self); - for(i = 0; i < self->nSlaves; i++){ - status = self->slaves[i]->Pause(self->slaveData[i],pCon); - if(status != OKOK){ + for (i = 0; i < self->nSlaves; i++) { + status = self->slaves[i]->Pause(self->slaveData[i], pCon); + if (status != OKOK) { MMCCHalt(pCount); return status; } } return OKOK; } + /*--------------------------------------------------------------------------*/ -static int MMCCContinue(void *pData, SConnection *pCon){ +static int MMCCContinue(void *pData, SConnection * pCon) +{ int i, status; pCounter pCount = NULL; pMultiCounter self = NULL; - pCount = (pCounter)pData; - if(pCount != NULL){ - self = (pMultiCounter)pCount->pDriv->pData; + pCount = (pCounter) pData; + if (pCount != NULL) { + self = (pMultiCounter) pCount->pDriv->pData; } assert(self); - for(i = 0; i < self->nSlaves; i++){ - status = self->slaves[i]->Continue(self->slaveData[i],pCon); - if(status != OKOK){ + for (i = 0; i < self->nSlaves; i++) { + status = self->slaves[i]->Continue(self->slaveData[i], pCon); + if (status != OKOK) { MMCCHalt(pCount); return status; } } return OKOK; } + /*------------------------------------------------------------------------*/ -static char *getNextMMCCNumber(char *pStart, char pNumber[80]){ +static char *getNextMMCCNumber(char *pStart, char pNumber[80]) +{ int charCount = 0; pNumber[0] = '\0'; /* advance to first digit */ - while(isspace(*pStart) && *pStart != '\0'){ + while (isspace(*pStart) && *pStart != '\0') { pStart++; } - if(*pStart == '\0'){ + if (*pStart == '\0') { return NULL; } /* copy */ - while(!isspace(*pStart) && *pStart != '\0' && charCount < 78){ + while (!isspace(*pStart) && *pStart != '\0' && charCount < 78) { pNumber[charCount] = *pStart; pStart++; charCount++; @@ -251,160 +221,214 @@ static char *getNextMMCCNumber(char *pStart, char pNumber[80]){ pNumber[charCount] = '\0'; return pStart; } + /*-------------------------------------------------------------------------*/ -static void loadCountData(pCounter pCount, const char *data){ - char *pPtr = NULL; - char pNumber[80]; - int i = 0; - - pPtr = (char *)data; - pPtr = getNextMMCCNumber(pPtr,pNumber); - // SICS-195 get time from controlling monitor - // pCount->pDriv->fTime = atof(pNumber); - while(pPtr != NULL && i < MAXCOUNT){ - pPtr = getNextMMCCNumber(pPtr,pNumber); - pCount->pDriv->lCounts[i] = atoi(pNumber); - i++; - } +static void loadCountData(pCounter pCount, const char *data) +{ + char *pPtr = NULL; + char pNumber[80]; + int i = 0; + + pPtr = (char *) data; + pPtr = getNextMMCCNumber(pPtr, pNumber); + pCount->pDriv->fTime = atof(pNumber); + while (pPtr != NULL && i < MAXCOUNT) { + pPtr = getNextMMCCNumber(pPtr, pNumber); + pCount->pDriv->lCounts[i] = atoi(pNumber); + i++; + } } + /*--------------------------------------------------------------------------*/ -static int MMCCTransfer(void *pData, SConnection *pCon){ +static int MMCCTransfer(void *pData, SConnection * pCon) +{ int i, retVal = OKOK, status; char pBueffel[132]; pCounter pCount = NULL; - pCounter pCountController = NULL, pCountSlave; pMultiCounter self = NULL; int tclStatus; - int controlMonitor; - double avCntRt; - pCount = (pCounter)pData; - if(pCount != NULL){ - self = (pMultiCounter)pCount->pDriv->pData; + pCount = (pCounter) pData; + if (pCount != NULL) { + self = (pMultiCounter) pCount->pDriv->pData; } assert(self); - controlMonitor = GetControlMonitor(pCount); - pCountController = (pCounter)self->slaveData[controlMonitor]; - for(i = 0; i < self->nSlaves; i++){ + for (i = 0; i < self->nSlaves; i++) { status = self->slaves[i]->TransferData(self->slaveData[i], pCon); - if(status != OKOK){ + if (status != OKOK) { retVal = status; - sprintf(pBueffel,"WARNING: slave histogram %d failed to transfer data", - i); - SCWrite(pCon,pBueffel,eWarning); - } else if (pCountController->pDriv->eMode == ePreset) { - if (i != controlMonitor) { - pCountSlave = (pCounter) self->slaveData[i]; - avCntRt = pCountSlave->pDriv->lCounts[0] / pCountSlave->pDriv->fTime; - pCountSlave->pDriv->lCounts[0] = avCntRt * pCountController->pDriv->fTime; - pCountSlave->pDriv->fTime = pCountController->pDriv->fTime; - } + snprintf(pBueffel,sizeof(pBueffel)-1, + "WARNING: slave histogram %d failed to transfer data", i); + SCWrite(pCon, pBueffel, eWarning); } } - pCount->pDriv->fTime = pCountController->pDriv->fTime; - if(self->transferScript != NULL){ + if (self->transferScript != NULL) { MacroPush(pCon); tclStatus = Tcl_Eval(InterpGetTcl(pServ->pSics), self->transferScript); - if(tclStatus != TCL_OK){ - snprintf(pBueffel,131,"ERROR: TransferScript returned: %s", - Tcl_GetStringResult(InterpGetTcl(pServ->pSics))); - SCWrite(pCon,pBueffel,eError); - MacroPop(); - return HWFault; + if (tclStatus != TCL_OK) { + snprintf(pBueffel, 131, "ERROR: TransferScript returned: %s", + Tcl_GetStringResult(InterpGetTcl(pServ->pSics))); + SCWrite(pCon, pBueffel, eError); + MacroPop(); + return HWFault; } MacroPop(); - loadCountData(pCount,Tcl_GetStringResult(InterpGetTcl(pServ->pSics))); + loadCountData(pCount, Tcl_GetStringResult(InterpGetTcl(pServ->pSics))); } return retVal; } + /*-------------------------------------------------------------------------*/ -static void MMCCParameter(void *pData, float fPreset, CounterMode eMode ){ +static void MMCCParameter(void *pData, float fPreset, CounterMode eMode) +{ int i; pCounter pCount = NULL; pMultiCounter self = NULL; - pCount = (pCounter)pData; - if(pCount != NULL){ - self = (pMultiCounter)pCount->pDriv->pData; + pCount = (pCounter) pData; + if (pCount != NULL) { + self = (pMultiCounter) pCount->pDriv->pData; } assert(self); - for(i = 0; i < self->nSlaves; i++){ + for (i = 0; i < self->nSlaves; i++) { self->slaves[i]->SetCountParameters(self->slaveData[i], fPreset, eMode); } } + /*======================= Driver Interface ==============================*/ -static int MultiCounterSet(struct __COUNTER *self, char *name, - int iCter, float fVal){ - - return 0; +static int MultiCounterSet(struct __COUNTER *pCount, char *name, + int iCter, float fVal) +{ + pDummy pDum; + int i; + pMultiCounter self = NULL; + pCounter pCter; + + self = (pMultiCounter) pCount->pData; + assert(self); + + for (i = 0; i < self->nSlaves; i++) { + pDum = (pDummy)self->slaveData[i]; + if(strcmp(pDum->pDescriptor->name, "SingleCounter") == 0){ + pCter = (pCounter)self->slaveData[i]; + if(pCter->pDriv != NULL){ + return pCter->pDriv->Set(pCter->pDriv, name, iCter, fVal); + } else { + return 0; + } + } + } + return 0; } /*-----------------------------------------------------------------------*/ -static int MultiCounterGet(struct __COUNTER *self, char *name, - int iCter, float *fVal){ - - return 0; +static int MultiCounterGet(struct __COUNTER *pCount, char *name, + int iCter, float *fVal) +{ + pDummy pDum; + int i; + pMultiCounter self = NULL; + pCounter pCter; + pHdb node; + hdbValue v; + + self = (pMultiCounter) pCount->pData; + assert(self); + + for (i = 0; i < self->nSlaves; i++) { + pDum = (pDummy)self->slaveData[i]; + if(strcmp(pDum->pDescriptor->name, "SingleCounter") == 0){ + pCter = (pCounter)self->slaveData[i]; + if(pCter->pDriv != NULL){ + return pCter->pDriv->Get(pCter->pDriv, name, iCter, fVal); + } else { + return 0; + } + } + } + return 0; } /*-----------------------------------------------------------------------*/ -static int MultiCounterSend(struct __COUNTER *self, char *pText, - char *reply, int replylen){ - - strncpy(reply,"NOT Implemented",replylen); - return 0; +static int MultiCounterSend(struct __COUNTER *pCount, char *pText, + char *reply, int replylen) +{ + pDummy pDum; + int i; + pMultiCounter self = NULL; + pCounter pCter; + + self = (pMultiCounter) pCount->pData; + assert(self); + + for (i = 0; i < self->nSlaves; i++) { + pDum = (pDummy)self->slaveData[i]; + if(strcmp(pDum->pDescriptor->name, "SingleCounter") == 0){ + pCter = (pCounter)self->slaveData[i]; + return pCter->pDriv->Send(pCter->pDriv,pText, reply, replylen); + } + } + return 0; } /*---------------------------------------------------------------------*/ static int MultiCounterError(struct __COUNTER *pDriv, int *iCode, - char *error, int errlen){ - + char *error, int errlen) +{ - if(pDriv->iErrorCode == NOCOUNTERS){ - strncpy(error,"NO counters configured!",errlen); - } else { - strncpy(error,"Not Implemented", errlen); - } - return COTERM; -} -/*----------------------------------------------------------------------*/ -static int MultiCounterFix(struct __COUNTER *self, int iCode){ + + if (pDriv->iErrorCode == NOCOUNTERS) { + strlcpy(error, "NO counters configured!", errlen); + } else { + strlcpy(error, "Not Implemented", errlen); + } return COTERM; } -/*=============== Interpreter Interface ================================ */ -int MultiCounterAction(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]){ - pMultiCounter self = NULL; - pCounter pCount = NULL; - char buffer[256]; - - if(argc > 1){ - strtolower(argv[1]); - if(strcmp(argv[1],"transferscript") == 0){ - pCount = (pCounter)pData; - self = (pMultiCounter)pCount->pDriv->pData; - if(argc < 3){ - SCPrintf(pCon,eValue,"%s.transferscript = %s", - argv[0],self->transferScript); - return 1; - } else { - if(!SCMatchRights(pCon,usUser)){ - return 0; - } - if(self->transferScript != NULL){ - free(self->transferScript); - } - Arg2Text(argc-2,&argv[2],buffer,255); - self->transferScript = strdup(buffer); - SCSendOK(pCon); - return 1; - } - } - } - return CountAction(pCon,pSics,pData,argc,argv); + +/*----------------------------------------------------------------------*/ +static int MultiCounterFix(struct __COUNTER *self, int iCode) +{ + return COTERM; } + +/*=============== Interpreter Interface ================================ */ +int MultiCounterAction(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]) +{ + pMultiCounter self = NULL; + pCounter pCount = NULL; + char buffer[256]; + + if (argc > 1) { + strtolower(argv[1]); + if (strcmp(argv[1], "transferscript") == 0) { + pCount = (pCounter) pData; + self = (pMultiCounter) pCount->pDriv->pData; + if (argc < 3) { + SCPrintf(pCon, eValue, "%s.transferscript = %s", + argv[0], self->transferScript); + return 1; + } else { + if (!SCMatchRights(pCon, usUser)) { + return 0; + } + if (self->transferScript != NULL) { + free(self->transferScript); + } + Arg2Text(argc - 2, &argv[2], buffer, 255); + self->transferScript = strdup(buffer); + SCSendOK(pCon); + return 1; + } + } + } + return CountAction(pCon, pSics, pData, argc, argv); +} + /*------------------------------------------------------------------------*/ -int MakeMultiCounter(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]){ +int MakeMultiCounter(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]) +{ int i, status; pCounter pNew = NULL; char pBueffel[132]; @@ -414,67 +438,43 @@ int MakeMultiCounter(SConnection *pCon, SicsInterp *pSics, pCounterDriver pDriv = NULL; /* - need at least two parameters - */ - if(argc < 3){ - SCWrite(pCon,"ERROR: insufficient number of arguments to MakeMultiCounter", - eError); + need at least two parameters + */ + if (argc < 3) { + SCWrite(pCon, + "ERROR: insufficient number of arguments to MakeMultiCounter", + eError); return 0; } /* allocate our data structure - */ + */ self = malloc(sizeof(MultiCounter)); pDriv = malloc(sizeof(CounterDriver)); - if(self == NULL || pDriv == NULL){ - SCWrite(pCon,"ERROR: out of memory in MakeMultiCounter",eError); + if (self == NULL || pDriv == NULL) { + SCWrite(pCon, "ERROR: out of memory in MakeMultiCounter", eError); return 0; } - memset(self,0,sizeof(MultiCounter)); - memset(pDriv,0,sizeof(CounterDriver)); + memset(self, 0, sizeof(MultiCounter)); + memset(pDriv, 0, sizeof(CounterDriver)); pDriv->pData = self; pDriv->KillPrivate = KillMultiDriver; - - /* - now loop through the remaining arguments, thereby entering them into - the slave list. - */ - for(i = 2, self->nSlaves = 0; i < argc; i++){ - pCom = FindCommand(pSics,argv[i]); - if(!pCom){ - sprintf(pBueffel,"ERROR: object %s not found in MakeMultiCounter", - argv[i]); - SCWrite(pCon,pBueffel,eError); - continue; - } - pCount = GetCountableInterface(pCom->pData); - if(!pCount){ - sprintf(pBueffel,"ERROR: object %s is NOT countable", - argv[i]); - SCWrite(pCon,pBueffel,eError); - continue; - } - self->slaves[self->nSlaves] = pCount; - self->slaveData[self->nSlaves] = pCom->pData; - self->nSlaves++; - } - pDriv->iNoOfMonitors = self->nSlaves; - pNew = CreateCounter(argv[1],pDriv); - if(pNew == NULL){ - SCWrite(pCon,"ERROR: out of memory in MakeMultiCounter",eError); + pDriv->iNoOfMonitors = MAXCOUNT; + pNew = CreateCounter(argv[1], pDriv); + if (pNew == NULL) { + SCWrite(pCon, "ERROR: out of memory in MakeMultiCounter", eError); return 0; } - pDriv->Get = MultiCounterGet; - pDriv->GetError = MultiCounterError; + pDriv->Get = MultiCounterGet; + pDriv->GetError = MultiCounterError; pDriv->TryAndFixIt = MultiCounterFix; - pDriv->Set = MultiCounterSet; - pDriv->Send -= MultiCounterSend; - + pDriv->Set = MultiCounterSet; + pDriv->Send = MultiCounterSend; + /* - assign interface functions - */ + assign interface functions + */ pNew->pCountInt->Halt = MMCCHalt; pNew->pCountInt->StartCount = MMCCStart; pNew->pCountInt->CheckCountStatus = MMCCStatus; @@ -484,17 +484,39 @@ int MakeMultiCounter(SConnection *pCon, SicsInterp *pSics, pNew->pCountInt->SetCountParameters = MMCCParameter; /* - now install our action command and we are done - */ - status = AddCommand(pSics,argv[1],MultiCounterAction,DeleteCounter, - pNew); - if(!status){ - sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[1]); - SCWrite(pCon,pBueffel,eError); + now loop through the remaining arguments, thereby entering them into + the slave list. + */ + for (i = 2; i < argc; i++) { + pCom = FindCommand(pSics, argv[i]); + if (!pCom) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: object %s not found in MakeMultiCounter", + argv[i]); + SCWrite(pCon, pBueffel, eError); + continue; + } + pCount = GetCountableInterface(pCom->pData); + if (!pCount) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: object %s is NOT countable", argv[i]); + SCWrite(pCon, pBueffel, eError); + continue; + } + self->slaves[self->nSlaves] = pCount; + self->slaveData[self->nSlaves] = pCom->pData; + self->nSlaves++; + } + + /* + now install our action command and we are done + */ + status = AddCommand(pSics, argv[1], MultiCounterAction, DeleteCounter, + pNew); + if (!status) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: duplicate command %s not created", argv[1]); + SCWrite(pCon, pBueffel, eError); DeleteCounter(pNew); return 0; - } - + } + return 1; } - diff --git a/multicounter.h b/multicounter.h index 400e36f6..ba3434b3 100644 --- a/multicounter.h +++ b/multicounter.h @@ -14,6 +14,6 @@ #define MULTICOUNTER_H_ #include -int MakeMultiCounter(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]); -#endif /*MULTICOUNTER_H_*/ +int MakeMultiCounter(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]); +#endif /*MULTICOUNTER_H_ */ diff --git a/mumo.c b/mumo.c index d3b8c406..94ae6139 100644 --- a/mumo.c +++ b/mumo.c @@ -64,115 +64,108 @@ #include "mumo.h" #include "mumo.i" /*-------------------------------------------------------------------------*/ -static int SaveMumo(void *pData, char *name, FILE *fd) +static int SaveMumo(void *pData, char *name, FILE * fd) { pMulMot self = NULL; char pCommand[512]; const char *pName = NULL; - self = (pMulMot)pData; - if(self == NULL) - { + self = (pMulMot) pData; + if (self == NULL) { return 0; } - fprintf(fd,"#----- MultiMotor %s\n", name); - while((pName = StringDictGetNext(self->pNamPos,pCommand, 511)) != NULL) - { - if(strcmp(pName,"back") != 0) - { - fprintf(fd,"%s recovernampos %s %s\n",name,pName,pCommand); + fprintf(fd, "#----- MultiMotor %s\n", name); + while ((pName = StringDictGetNext(self->pNamPos, pCommand, 511)) != NULL) { + if (strcmp(pName, "back") != 0) { + fprintf(fd, "%s recovernampos %s %s\n", name, pName, pCommand); } } return 1; } + /*--------------------------------------------------------------------------*/ - pMulMot MakeMultiMotor(void) - { - pMulMot pNew = NULL; - - pNew = (pMulMot)malloc(sizeof(MulMot)); - if(!pNew) - { - return NULL; - } - memset(pNew,0,sizeof(MulMot)); +pMulMot MakeMultiMotor(void) +{ + pMulMot pNew = NULL; - /* the string Dictionaries */ - pNew->pAlias = CreateStringDict(); - pNew->pNamPos = CreateStringDict(); - if( (!pNew->pAlias) || (!pNew->pNamPos)) - { - free(pNew); - return NULL; - } - - pNew->pDes = CreateDescriptor("MulMot"); - if(!pNew->pDes) - { - DeleteStringDict(pNew->pAlias); - DeleteStringDict(pNew->pNamPos); - free(pNew); - return NULL; - } - pNew->pDes->SaveStatus = SaveMumo; - - /* the parameter array */ - pNew->pParam = ObParCreate(1); - ObParInit(pNew->pParam,ACCESS,"accesscode",usUser,usMugger); - - - pNew->name = NULL; - return pNew; + pNew = (pMulMot) malloc(sizeof(MulMot)); + if (!pNew) { + return NULL; + } + memset(pNew, 0, sizeof(MulMot)); + + /* the string Dictionaries */ + pNew->pAlias = CreateStringDict(); + pNew->pNamPos = CreateStringDict(); + if ((!pNew->pAlias) || (!pNew->pNamPos)) { + free(pNew); + return NULL; + } + + pNew->pDes = CreateDescriptor("MulMot"); + if (!pNew->pDes) { + DeleteStringDict(pNew->pAlias); + DeleteStringDict(pNew->pNamPos); + free(pNew); + return NULL; + } + pNew->pDes->SaveStatus = SaveMumo; + + /* the parameter array */ + pNew->pParam = ObParCreate(1); + ObParInit(pNew->pParam, ACCESS, "accesscode", usUser, usMugger); + + + pNew->name = NULL; + return pNew; +} + +/*-------------------------------------------------------------------------*/ +void KillMultiMotor(void *pData) +{ + pMulMot self; + int i; + + assert(pData); + + self = (pMulMot) pData; + assert(strcmp(self->pDes->name, "MulMot") == 0); + + /* remove string dictionaries */ + if (self->pAlias) { + DeleteStringDict(self->pAlias); + } + if (self->pNamPos) { + DeleteStringDict(self->pNamPos); + } + + /* free descriptor */ + if (self->pDes) { + DeleteDescriptor(self->pDes); } -/*-------------------------------------------------------------------------*/ - void KillMultiMotor(void *pData) - { - pMulMot self; - int i; - - assert(pData); - - self = (pMulMot)pData; - assert(strcmp(self->pDes->name,"MulMot") == 0); - /* remove string dictionaries */ - if(self->pAlias) - { - DeleteStringDict(self->pAlias); - } - if(self->pNamPos) - { - DeleteStringDict(self->pNamPos); - } - - /* free descriptor */ - if(self->pDes) - { - DeleteDescriptor(self->pDes); - } - /* kill parameter array */ - ObParDelete(self->pParam); + ObParDelete(self->pParam); /* free name and myself */ - if(self->name) - { - free(self->name); - } - free(self); + if (self->name) { + free(self->name); } + free(self); +} + /*--------------------------------------------------------------------------- Multiple Motors have a funny and flexible syntax. Analysing the argc, argv[] set will not do. Therefore this is done by some recursive descent parsing. */ - - typedef struct __MYTOKEN { - char *pCommand; - char *pPtr; - int iCurrentToken; - char Token[80]; - } sParser, *psParser; + +typedef struct __MYTOKEN { + char *pCommand; + char *pPtr; + int iCurrentToken; + char Token[80]; +} sParser, *psParser; /* define some TokenTypes */ #define END 0 #define INCREMENT 1 @@ -181,7 +174,7 @@ static int SaveMumo(void *pData, char *name, FILE *fd) #define ALIAS 4 #define SYMBOL 5 #define NUMBER 6 -#define EQUALITY 7 +#define EQUALITY 7 #define PLUS 8 #define MINUS 9 #define UNKNOWN 10 @@ -191,314 +184,270 @@ static int SaveMumo(void *pData, char *name, FILE *fd) #define DEFPOS 14 #define RECOVERNAMPOS 15 #define GETPOS 16 -/*-------------------------------------------------------------------------*/ - static int GetNextToken(psParser self, pMulMot pDings) - { - char *pPtr; - int i; - - pPtr = self->pPtr; - - /* skip whitespace */ - while( (*pPtr == ' ') || (*pPtr == '\t') ) - { - pPtr++; - } - - /* check for end */ - if( (*pPtr == '\n') || (*pPtr == '\0') || (*pPtr == '\r') ) - { - self->pPtr = pPtr; - self->Token[0] = *pPtr; - self->Token[1] = '\0'; - self->iCurrentToken = END; - return END; - } - - /* check equaL SIGN */ - if(*pPtr == '=') - { - strcpy(self->Token,"="); - self->iCurrentToken = EQUALITY; - self->pPtr = pPtr +1; - return EQUALITY; - } - - /* check + */ - if(*pPtr == '+') - { - if(*(pPtr+1) == '+') /* increment */ - { - strcpy(self->Token,"++"); - self->iCurrentToken = INCREMENT; - self->pPtr = pPtr+2; - return INCREMENT; - } - else /* silly plus */ - { - strcpy(self->Token,"+"); - self->iCurrentToken = PLUS; - self->pPtr = pPtr + 1; - return PLUS; - } - } - - /* check - */ - if(*pPtr == '-') - { - if(*(pPtr+1) == '-') /* Decrement */ - { - strcpy(self->Token,"--"); - self->iCurrentToken = DECREMENT; - self->pPtr = pPtr+2; - return DECREMENT; - } - else /* silly minus */ - { - strcpy(self->Token,"-"); - self->iCurrentToken = MINUS; - self->pPtr = pPtr + 1; - return MINUS; - } - } - - /* number */ - if( (isdigit((int)*pPtr)) || (*pPtr == '.') ) - { - i = 0; - while (isdigit((int)*pPtr) || (*pPtr == '.') ) - { - self->Token[i] = *pPtr; - i++; - pPtr++; - } - self->Token[i] = '\0'; - self->iCurrentToken = NUMBER; - self->pPtr = pPtr; - return NUMBER; - } - - /* a Symbol ? */ - if(isalnum((int)*pPtr)) - { - i = 0; - while( (!isspace((int)*pPtr)) && (*pPtr != '=') - && (*pPtr != '+') && (*pPtr != '-') &&(*pPtr != '\0') - && (*pPtr != '\n') ) - { - self->Token[i] = *pPtr; - i++; - pPtr++; - } - self->Token[i] = '\0'; - self->pPtr = pPtr; - /* now it can be a named position, a motor alias or a keyword */ - if(StringDictExists(pDings->pNamPos,self->Token)) - { - self->iCurrentToken = NAMPOS; - return NAMPOS; - } - else if(StringDictExists(pDings->pAlias,self->Token)) - { - self->iCurrentToken = ALIAS; - return ALIAS; - } - else if(strcmp(self->Token,"all") == 0) - { - self->iCurrentToken = NAMALL; - return NAMALL; - } - else if(strcmp(self->Token,"list") == 0) - { - self->iCurrentToken = LIST; - return LIST; - } - else if(strcmp(self->Token,"defpos") ==0) - { - self->iCurrentToken = DEFPOS; - return DEFPOS; - } - else if(strcmp(self->Token,"getpos") ==0) - { - self->iCurrentToken = GETPOS; - return GETPOS; - } - else if(strcmp(self->Token,"recovernampos") ==0) - { - self->iCurrentToken = RECOVERNAMPOS; - return RECOVERNAMPOS; - } - else - { - self->iCurrentToken = SYMBOL; - return SYMBOL; - } - } - return UNKNOWN; - } /*-------------------------------------------------------------------------*/ - static void ListMulMot(char *name, SConnection *pCon, pMulMot self) - { - int i, iRet; - char pBueffel[512]; - float fVal; - OutCode eOut = eValue; - const char *pNam = NULL; - char pMotName[132]; - pMotor pMot = NULL; - - sprintf(pBueffel,"Status listing for %s",name); - SCWrite(pCon,pBueffel,eValue); +static int GetNextToken(psParser self, pMulMot pDings) +{ + char *pPtr; + int i; - /* scan through all aliases */ - pNam = StringDictGetNext(self->pAlias,pMotName, 131); - while(pNam != NULL) - { - pMot = FindMotor(GetInterpreter(), pMotName); - assert(pMot); /* has been tested on definition */ - iRet = MotorGetSoftPosition(pMot,pCon,&fVal); - if(!iRet) - { - sprintf(pBueffel,"ERROR: Cannot read motor %s\n", - pMotName); - eOut = eError; - } - else - { - eOut = eValue; - sprintf(pBueffel,"%s.%s = %f\n",name,pNam, fVal); - } - SCWrite(pCon,pBueffel,eValue); - pNam = StringDictGetNext(self->pAlias, pMotName, 131); + pPtr = self->pPtr; + + /* skip whitespace */ + while ((*pPtr == ' ') || (*pPtr == '\t')) { + pPtr++; + } + + /* check for end */ + if ((*pPtr == '\n') || (*pPtr == '\0') || (*pPtr == '\r')) { + self->pPtr = pPtr; + self->Token[0] = *pPtr; + self->Token[1] = '\0'; + self->iCurrentToken = END; + return END; + } + + /* check equaL SIGN */ + if (*pPtr == '=') { + strcpy(self->Token, "="); + self->iCurrentToken = EQUALITY; + self->pPtr = pPtr + 1; + return EQUALITY; + } + + /* check + */ + if (*pPtr == '+') { + if (*(pPtr + 1) == '+') { /* increment */ + strcpy(self->Token, "++"); + self->iCurrentToken = INCREMENT; + self->pPtr = pPtr + 2; + return INCREMENT; + } else { /* silly plus */ + + strcpy(self->Token, "+"); + self->iCurrentToken = PLUS; + self->pPtr = pPtr + 1; + return PLUS; } } + + /* check - */ + if (*pPtr == '-') { + if (*(pPtr + 1) == '-') { /* Decrement */ + strcpy(self->Token, "--"); + self->iCurrentToken = DECREMENT; + self->pPtr = pPtr + 2; + return DECREMENT; + } else { /* silly minus */ + + strcpy(self->Token, "-"); + self->iCurrentToken = MINUS; + self->pPtr = pPtr + 1; + return MINUS; + } + } + + /* number */ + if ((isdigit((int) *pPtr)) || (*pPtr == '.')) { + i = 0; + while (isdigit((int) *pPtr) || (*pPtr == '.')) { + self->Token[i] = *pPtr; + i++; + pPtr++; + } + self->Token[i] = '\0'; + self->iCurrentToken = NUMBER; + self->pPtr = pPtr; + return NUMBER; + } + + /* a Symbol ? */ + if (isalnum((int) *pPtr)) { + i = 0; + while ((!isspace((int) *pPtr)) && (*pPtr != '=') + && (*pPtr != '+') && (*pPtr != '-') && (*pPtr != '\0') + && (*pPtr != '\n')) { + self->Token[i] = *pPtr; + i++; + pPtr++; + } + self->Token[i] = '\0'; + self->pPtr = pPtr; + /* now it can be a named position, a motor alias or a keyword */ + if (StringDictExists(pDings->pNamPos, self->Token)) { + self->iCurrentToken = NAMPOS; + return NAMPOS; + } else if (StringDictExists(pDings->pAlias, self->Token)) { + self->iCurrentToken = ALIAS; + return ALIAS; + } else if (strcmp(self->Token, "all") == 0) { + self->iCurrentToken = NAMALL; + return NAMALL; + } else if (strcmp(self->Token, "list") == 0) { + self->iCurrentToken = LIST; + return LIST; + } else if (strcmp(self->Token, "defpos") == 0) { + self->iCurrentToken = DEFPOS; + return DEFPOS; + } else if (strcmp(self->Token, "getpos") == 0) { + self->iCurrentToken = GETPOS; + return GETPOS; + } else if (strcmp(self->Token, "recovernampos") == 0) { + self->iCurrentToken = RECOVERNAMPOS; + return RECOVERNAMPOS; + } else { + self->iCurrentToken = SYMBOL; + return SYMBOL; + } + } + return UNKNOWN; +} + +/*-------------------------------------------------------------------------*/ +static void ListMulMot(char *name, SConnection * pCon, pMulMot self) +{ + int i, iRet; + char pBueffel[512]; + float fVal; + OutCode eOut = eValue; + const char *pNam = NULL; + char pMotName[132]; + pMotor pMot = NULL; + + snprintf(pBueffel,sizeof(pBueffel)-1, "Status listing for %s", name); + SCWrite(pCon, pBueffel, eValue); + + /* scan through all aliases */ + pNam = StringDictGetNext(self->pAlias, pMotName, 131); + while (pNam != NULL) { + pMot = FindMotor(GetInterpreter(), pMotName); + assert(pMot); /* has been tested on definition */ + iRet = MotorGetSoftPosition(pMot, pCon, &fVal); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Cannot read motor %s\n", pMotName); + eOut = eError; + } else { + eOut = eValue; + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.%s = %f\n", name, pNam, fVal); + } + SCWrite(pCon, pBueffel, eValue); + pNam = StringDictGetNext(self->pAlias, pMotName, 131); + } +} + /*--------------------------------------------------------------------------*/ - static int ParseAlias(psParser pParse, SConnection *pCon, - pMulMot self) - { - int i, iToken, iRet; - int iSign = 1; - int iInc = 0; - char pBueffel[132]; - char pCommand[1064]; - float fVal = 0, fIn = 0; - int iComplete; - pMotor pMot = NULL; - - /* Okay first find the alias, the current token must still be - its name - */ - strcpy(pCommand,"run "); - iRet = StringDictGet(self->pAlias,pParse->Token,pBueffel,131); - /* that it is alias has been tested earlier */ - assert(iRet == 1); - strcat(pCommand, pBueffel); +static int ParseAlias(psParser pParse, SConnection * pCon, pMulMot self) +{ + int i, iToken, iRet; + int iSign = 1; + int iInc = 0; + char pBueffel[132]; + char pCommand[1064]; + float fVal = 0, fIn = 0; + int iComplete; + pMotor pMot = NULL; + + /* Okay first find the alias, the current token must still be + its name + */ + strcpy(pCommand, "run "); + iRet = StringDictGet(self->pAlias, pParse->Token, pBueffel, 131); + /* that it is alias has been tested earlier */ + assert(iRet == 1); + strlcat(pCommand, pBueffel,1024); /* now find the value to handle */ - iToken = GetNextToken(pParse,self); - iComplete = 0; - while(iToken != END) - { - switch(iToken) - { - case PLUS: - iSign = 1; - break; - case MINUS: - iSign = -1; - break; - case EQUALITY: - break; - case INCREMENT: - iInc = 1; - break; - case DECREMENT: - iSign = -1; - iInc = 1; - break; - case NUMBER:/* ey! Do some real work */ - fIn = (float)atof(pParse->Token); - iComplete = 0; - if(iInc) - { - pMot = FindMotor(GetInterpreter(), pBueffel); - assert(pMot); /* existence shoul have been verified earlier */ - MotorGetSoftPosition(pMot,pCon,&fVal); - fVal += iSign * fIn; - sprintf(pBueffel," %f ",fVal); - strcat(pCommand, pBueffel); - InterpExecute(GetInterpreter(),pCon,pCommand); - return 1; - } - else - { - sprintf(pBueffel," %f ",iSign*fIn); - strcat(pCommand, pBueffel); - InterpExecute(GetInterpreter(),pCon,pCommand); - return 1; - } - return 1; - break; - default: - sprintf(pBueffel,"ERROR: Unexpected symbol %s", - pParse->Token); - SCWrite(pCon,pBueffel,eError); - return 0; + iToken = GetNextToken(pParse, self); + iComplete = 0; + while (iToken != END) { + switch (iToken) { + case PLUS: + iSign = 1; + break; + case MINUS: + iSign = -1; + break; + case EQUALITY: + break; + case INCREMENT: + iInc = 1; + break; + case DECREMENT: + iSign = -1; + iInc = 1; + break; + case NUMBER: /* ey! Do some real work */ + fIn = (float) atof(pParse->Token); + iComplete = 0; + if (iInc) { + pMot = FindMotor(GetInterpreter(), pBueffel); + assert(pMot); /* existence shoul have been verified earlier */ + MotorGetSoftPosition(pMot, pCon, &fVal); + fVal += iSign * fIn; + snprintf(pBueffel,sizeof(pBueffel)-1, " %f ", fVal); + strlcat(pCommand, pBueffel,1024); + InterpExecute(GetInterpreter(), pCon, pCommand); + return 1; + } else { + snprintf(pBueffel,sizeof(pBueffel)-1, " %f ", iSign * fIn); + strlcat(pCommand, pBueffel,1024); + InterpExecute(GetInterpreter(), pCon, pCommand); + return 1; } - iToken = GetNextToken(pParse,self); - } - if(!iComplete) - { - SCWrite(pCon,"ERROR: Incomplete command",eError); + return 1; + break; + default: + snprintf(pBueffel,1024, "ERROR: Unexpected symbol %s", pParse->Token); + SCWrite(pCon, pBueffel, eError); return 0; } - return 1; - } - + iToken = GetNextToken(pParse, self); + } + if (!iComplete) { + SCWrite(pCon, "ERROR: Incomplete command", eError); + return 0; + } + return 1; +} + /*-------------------------------------------------------------------------- */ - static int MakeCurrentNamPos(char *name, SConnection *pCon, - pMulMot self) - { - const char *pAlias = NULL; - char pMotort[132]; - char pCommand[1064]; - pMotor pMot = NULL; - float fVal; - int iRet; +static int MakeCurrentNamPos(char *name, SConnection * pCon, pMulMot self) +{ + const char *pAlias = NULL; + char pMotort[132]; + char pCommand[1064]; + pMotor pMot = NULL; + float fVal; + int iRet; + + assert(self); + assert(pCon); + + pCommand[0] = '\0'; + pAlias = StringDictGetNext(self->pAlias, pMotort, 131); + while (pAlias != NULL) { + strlcat(pCommand, pMotort,1024); + pMot = FindMotor(GetInterpreter(), pMotort); + assert(pMot); /* validity of alias has already been checked */ + iRet = MotorGetSoftPosition(pMot, pCon, &fVal); + if (!iRet) { + snprintf(pCommand,1024, "ERROR: failure to read motor %s, %s", + pMotort, " named position not created"); + SCWrite(pCon, pCommand, eError); + return 0; + } + snprintf(pMotort,sizeof(pMotort)-1, " %f ", fVal); + strlcat(pCommand, pMotort,1024); + pAlias = StringDictGetNext(self->pAlias, pMotort, 131); + } + if (StringDictExists(self->pNamPos, name)) { + StringDictUpdate(self->pNamPos, name, pCommand); + } else { + StringDictAddPair(self->pNamPos, name, pCommand); + } + return 1; +} - assert(self); - assert(pCon); - - pCommand[0] = '\0'; - pAlias = StringDictGetNext(self->pAlias, pMotort, 131); - while(pAlias != NULL) - { - strcat(pCommand, pMotort); - pMot = FindMotor(GetInterpreter(),pMotort); - assert(pMot); /* validity of alias has already been checked */ - iRet = MotorGetSoftPosition(pMot,pCon,&fVal); - if(!iRet) - { - sprintf(pCommand,"ERROR: failure to read motor %s, %s", - pMotort," named position not created"); - SCWrite(pCon,pCommand,eError); - return 0; - } - sprintf(pMotort," %f ", fVal); - strcat(pCommand,pMotort); - pAlias = StringDictGetNext(self->pAlias, pMotort, 131); - } - if(StringDictExists(self->pNamPos,name)) - { - StringDictUpdate(self->pNamPos,name,pCommand); - } - else - { - StringDictAddPair(self->pNamPos,name,pCommand); - } - return 1; - } /*-------------------------------------------------------------------------- FindNamPos: checks if the current position is identical to a named position. The comparison is done by getting the motors @@ -506,245 +455,224 @@ static int SaveMumo(void *pData, char *name, FILE *fd) all currently stored named positions. -------------------------------------------------------------------------*/ - const char *FindNamPos(pMulMot self, SConnection *pCon) - { - int iRet, iTest; - char pCurrCommand[1064], pTestCommand[1064]; - const char *pAlias; - char *pName, *pVal; - float f1, f2; - pMotor pMot = NULL; - pStringDict motCache = NULL; - - /* - * create cache of motor positions - */ - motCache = CreateStringDict(); - if(motCache == NULL){ - SCWrite(pCon,"ERROR: out of memory in FindNamPos",eError); - return NULL; - } - StringDictKillScan(self->pAlias); - pAlias = StringDictGetNext(self->pAlias,pCurrCommand,1023); - while(pAlias != NULL){ - pMot = FindMotor(pServ->pSics,pCurrCommand); - if(pMot != NULL){ - iRet = MotorGetSoftPosition(pMot,pCon,&f1); - if(!iRet){ - sprintf(pTestCommand, - "ERROR: failed to get motor position for %s", pName); - SCWrite(pCon,pTestCommand,eError); - return NULL; - } - snprintf(pTestCommand,1023,"%f",f1); - StringDictAddPair(motCache,pCurrCommand,pTestCommand); - } - pAlias = StringDictGetNext(self->pAlias,pCurrCommand,1023); - } - - /* scan named position list */ - StringDictKillScan(self->pNamPos); - pAlias = StringDictGetNext(self->pNamPos,pTestCommand,1063); - while(pAlias != NULL) - { - strcpy(pCurrCommand,pTestCommand); - pName = strtok(pCurrCommand," "); - iTest = 1; - while(pName != NULL) - { - pVal = strtok(NULL," "); - StringDictGetAsNumber(motCache,pName,&f1); - sscanf(pVal,"%f",&f2); - f1 = f1 - f2; - if(f1 < 0.) - f1 = - f1; - if(f1 > 0.03) - { - iTest--; - break; - } - pName = strtok(NULL," "); - } - if(iTest == 1 && (strcmp(pAlias,"back") != 0) ) { - DeleteStringDict(motCache); - return pAlias; - } - pAlias = StringDictGetNext(self->pNamPos,pTestCommand,1063); - } - DeleteStringDict(motCache); - /* not found */ - return NULL; - } -/*--------------------------------------------------------------------------*/ - static int ParseDropPos(psParser pParse, SConnection *pCon, - pMulMot self) - { - int i, iToken, iRet; - char pBueffel[256]; - float fVal = 0; - char pName[80]; - char *pPtr = NULL; - - iToken = GetNextToken(pParse,self); - while(iToken != END) - { - switch(iToken) - { - case EQUALITY: - break; - case NAMPOS: - /* we never want back to be killed ..... */ - if(strcmp(pParse->Token,"back") == 0) - { - SCWrite(pCon, - "ERROR: You are NOT allowed to deleted system position BACK", - eError); - return 0; - } - /* find NamPos and kill it */ - iRet = StringDictDelete(self->pNamPos,pParse->Token); - return 1; - break; - case NAMALL: - /* kill all named positions except back */ - iRet = StringDictGet(self->pNamPos,"back",pBueffel,256); - DeleteStringDict(self->pNamPos); - self->pNamPos = CreateStringDict(); - if(!self->pNamPos) - { - SCWrite(pCon, - "ERROR: severe! out of memory in mumo drop", - eError); - return 0; - } - if(iRet) - { - StringDictAddPair(self->pNamPos,"back",pBueffel); - } - return 1; - break; - default: - sprintf(pBueffel,"ERROR: Unexpected symbol %s", - pParse->Token); - SCWrite(pCon,pBueffel,eError); - return 0; - } - } - return 1; - } -/*-------------------------------------------------------------------------*/ - static int CheckPermission(SConnection *pCon, pMulMot self) - { - int iAccess; - char pBueffel[132]; - - iAccess = (int)ObVal(self->pParam,ACCESS); - if(SCMatchRights(pCon, iAccess)) - { - return 1; - } - else - { - sprintf(pBueffel,"ERROR: NO permission to drive %s", - self->name); - SCWrite(pCon,pBueffel,eError); - return 0; - } - } -/* ------------------------------------------------------------------------*/ - static int ParseNamPos(psParser pParse, SConnection *pCon, - SicsInterp *pSics, pMulMot self) - { - int iToken, iRet; - char pBueffel[256]; - char pCommand[1064]; - char *pPtr; +const char *FindNamPos(pMulMot self, SConnection * pCon) +{ + int iRet, iTest; + char pCurrCommand[1064], pTestCommand[1064]; + const char *pAlias; + char *pVal, *pName; + float f1, f2; + pMotor pMot = NULL; + pStringDict motCache = NULL; - /* is the user allowed to do ANYTHING ? */ - iRet = CheckPermission(pCon,self); - if(!iRet) - { - return 0; + /* + * create cache of motor positions + */ + motCache = CreateStringDict(); + if (motCache == NULL) { + SCWrite(pCon, "ERROR: out of memory in FindNamPos", eError); + return NULL; + } + StringDictKillScan(self->pAlias); + pAlias = StringDictGetNext(self->pAlias, pCurrCommand, 1023); + while (pAlias != NULL) { + pMot = FindMotor(pServ->pSics, pCurrCommand); + if (pMot != NULL) { + iRet = MotorGetSoftPosition(pMot, pCon, &f1); + if (!iRet) { + snprintf(pTestCommand,sizeof(pTestCommand)-1, + "ERROR: failed to get motor position for %s", pMot->name); + SCWrite(pCon, pTestCommand, eError); + return NULL; } - - strcpy(pCommand,"run "); - pPtr = pCommand + strlen("run "); - iRet = StringDictGet(self->pNamPos,pParse->Token,pPtr, 1050); - if(iRet) - { - InterpExecute(GetInterpreter(),pCon,pCommand); - return 1; + snprintf(pTestCommand, 1023, "%f", f1); + StringDictAddPair(motCache, pCurrCommand, pTestCommand); + } + pAlias = StringDictGetNext(self->pAlias, pCurrCommand, 1023); + } + + /* scan named position list */ + StringDictKillScan(self->pNamPos); + pAlias = StringDictGetNext(self->pNamPos, pTestCommand, 1063); + while (pAlias != NULL) { + strcpy(pCurrCommand, pTestCommand); + pName = strtok(pCurrCommand, " "); + iTest = 1; + while (pName != NULL) { + pVal = strtok(NULL, " "); + StringDictGetAsNumber(motCache, pName, &f1); + sscanf(pVal, "%f", &f2); + f1 = f1 - f2; + if (f1 < 0.) + f1 = -f1; + if (f1 > 0.03) { + iTest--; + break; } - else - { - sprintf(pCommand,"ERROR: named position %s NOT found",pParse->Token); - SCWrite(pCon,pCommand,eError); + pName = strtok(NULL, " "); + } + if (iTest == 1 && (strcmp(pAlias, "back") != 0)) { + DeleteStringDict(motCache); + return pAlias; + } + pAlias = StringDictGetNext(self->pNamPos, pTestCommand, 1063); + } + DeleteStringDict(motCache); + /* not found */ + return NULL; +} + +/*--------------------------------------------------------------------------*/ +static int ParseDropPos(psParser pParse, SConnection * pCon, pMulMot self) +{ + int i, iToken, iRet; + char pBueffel[256]; + float fVal = 0; + char pName[80]; + char *pPtr = NULL; + + iToken = GetNextToken(pParse, self); + while (iToken != END) { + switch (iToken) { + case EQUALITY: + break; + case NAMPOS: + /* we never want back to be killed ..... */ + if (strcmp(pParse->Token, "back") == 0) { + SCWrite(pCon, + "ERROR: You are NOT allowed to deleted system position BACK", + eError); return 0; } - return 0; /* not reached */ + /* find NamPos and kill it */ + iRet = StringDictDelete(self->pNamPos, pParse->Token); + return 1; + break; + case NAMALL: + /* kill all named positions except back */ + iRet = StringDictGet(self->pNamPos, "back", pBueffel, 256); + DeleteStringDict(self->pNamPos); + self->pNamPos = CreateStringDict(); + if (!self->pNamPos) { + SCWrite(pCon, "ERROR: severe! out of memory in mumo drop", eError); + return 0; + } + if (iRet) { + StringDictAddPair(self->pNamPos, "back", pBueffel); + } + return 1; + break; + default: + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Unexpected symbol %s", pParse->Token); + SCWrite(pCon, pBueffel, eError); + return 0; + } } -/*-------------------------------------------------------------------------*/ - static int ParseDefPos(SicsInterp *pSics,psParser pPP, - pMulMot self, SConnection *pCon) - { - pMotor pMot = NULL; - char pError[132], motorName[80], command[1024], namPos[80]; - int iToken, status; - float fVal; - - - iToken = GetNextToken(pPP,self); - if(iToken != SYMBOL) /* we want a name here */ - { - sprintf(pError,"ERROR: Invalid Token %s in ParsePos",pPP->Token); - SCWrite(pCon,pError,eError); - return 0; - } - - strncpy(namPos,pPP->Token,79); - iToken = GetNextToken(pPP,self); - command[0] = '\0'; - while(iToken != END) - { - if(iToken != ALIAS) - { - sprintf(command,"ERROR: expected motor alias, got: %s", pPP->Token); - SCWrite(pCon,command,eError); - return 0; - } - StringDictGet(self->pAlias,pPP->Token,motorName,79); - strcat(command, motorName); - strcat(command," "); - iToken = GetNextToken(pPP,self); - if(iToken != NUMBER) - { - sprintf(command,"ERROR: expected number, got: %s", pPP->Token); - SCWrite(pCon,command,eError); - return 0; - } - strcat(command,pPP->Token); - strcat(command," "); - iToken = GetNextToken(pPP,self); - } + return 1; +} - StringDictAddPair(self->pNamPos,namPos,command); +/*-------------------------------------------------------------------------*/ +static int CheckPermission(SConnection * pCon, pMulMot self) +{ + int iAccess; + char pBueffel[132]; + + iAccess = (int) ObVal(self->pParam, ACCESS); + if (SCMatchRights(pCon, iAccess)) { return 1; - } + } else { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: NO permission to drive %s", self->name); + SCWrite(pCon, pBueffel, eError); + return 0; + } +} + +/* ------------------------------------------------------------------------*/ +static int ParseNamPos(psParser pParse, SConnection * pCon, + SicsInterp * pSics, pMulMot self) +{ + int iToken, iRet; + char pBueffel[256]; + char pCommand[1064]; + char *pPtr; + + /* is the user allowed to do ANYTHING ? */ + iRet = CheckPermission(pCon, self); + if (!iRet) { + return 0; + } + + strcpy(pCommand, "run "); + pPtr = pCommand + strlen("run "); + iRet = StringDictGet(self->pNamPos, pParse->Token, pPtr, 1050); + if (iRet) { + InterpExecute(GetInterpreter(), pCon, pCommand); + return 1; + } else { + snprintf(pCommand,sizeof(pCommand)-1, "ERROR: named position %s NOT found", pParse->Token); + SCWrite(pCon, pCommand, eError); + return 0; + } + return 0; /* not reached */ +} + +/*-------------------------------------------------------------------------*/ +static int ParseDefPos(SicsInterp * pSics, psParser pPP, + pMulMot self, SConnection * pCon) +{ + pMotor pMot = NULL; + char pError[132], motorName[80], command[1024], namPos[80]; + int iToken, status; + float fVal; + + + iToken = GetNextToken(pPP, self); + if (iToken != SYMBOL) { /* we want a name here */ + snprintf(pError,sizeof(pError)-1, "ERROR: Invalid Token %s in ParsePos", pPP->Token); + SCWrite(pCon, pError, eError); + return 0; + } + + strlcpy(namPos, pPP->Token, 79); + iToken = GetNextToken(pPP, self); + command[0] = '\0'; + while (iToken != END) { + if (iToken != ALIAS) { + snprintf(command,sizeof(command)-1, "ERROR: expected motor alias, got: %s", pPP->Token); + SCWrite(pCon, command, eError); + return 0; + } + StringDictGet(self->pAlias, pPP->Token, motorName, 79); + strlcat(command, motorName,1024); + strlcat(command, " ",1024); + iToken = GetNextToken(pPP, self); + if (iToken != NUMBER) { + snprintf(command,sizeof(command)-1, "ERROR: expected number, got: %s", pPP->Token); + SCWrite(pCon, command, eError); + return 0; + } + strlcat(command, pPP->Token,1024); + strlcat(command, " ",1024); + iToken = GetNextToken(pPP, self); + } + + StringDictAddPair(self->pNamPos, namPos, command); + return 1; +} + /*-----------------------------------------------------------------------*/ static void RecoverNamPos(pMulMot self, int argc, char *argv[]) { char pCommand[512]; - Arg2Text(argc-1,&argv[1],pCommand, 511); - if(StringDictExists(self->pNamPos,argv[0])) - { - StringDictUpdate(self->pNamPos,argv[0],pCommand); + Arg2Text(argc - 1, &argv[1], pCommand, 511); + if (StringDictExists(self->pNamPos, argv[0])) { + StringDictUpdate(self->pNamPos, argv[0], pCommand); + } else { + StringDictAddPair(self->pNamPos, argv[0], pCommand); } - else - { - StringDictAddPair(self->pNamPos,argv[0],pCommand); - } -} +} + /*--------------------------------------------------------------------------- MultiWrapper is the user interface to a multi motor unit. It supports the following syntax, where DingsBums is the name of the unit: @@ -764,198 +692,165 @@ static void RecoverNamPos(pMulMot self, int argc, char *argv[]) saved named positions -*/ - - - int MultiWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - char pBueffel[512]; - char pError[132]; - sParser MyParser; - int iToken; - int iRet; - pMulMot self; - int iAlias = 0; - const char *pPtr; - Tcl_DString tString; - - assert(pCon); - assert(pSics); - assert(pData); - - self = (pMulMot)pData; - assert(strcmp(self->pDes->name,"MulMot")== 0); - - /* setup */ - argtolower(argc,argv); - iRet = Arg2Text(argc,argv,pBueffel,511); - if(!iRet) - { - SCWrite(pCon,"Command line to long",eError); +*/ + + +int MultiWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + char pBueffel[512]; + char pError[132]; + sParser MyParser; + int iToken; + int iRet; + pMulMot self; + int iAlias = 0; + const char *pPtr; + Tcl_DString tString; + + assert(pCon); + assert(pSics); + assert(pData); + + self = (pMulMot) pData; + assert(strcmp(self->pDes->name, "MulMot") == 0); + + /* setup */ + argtolower(argc, argv); + iRet = Arg2Text(argc, argv, pBueffel, 511); + if (!iRet) { + SCWrite(pCon, "Command line to long", eError); + return 0; + } + MyParser.pPtr = &pBueffel[0]; + MyParser.pCommand = pBueffel; + + /* ignore first Token: that is my name ! */ + iToken = GetNextToken(&MyParser, self); + + /* now loop through my Tokens */ + iToken = GetNextToken(&MyParser, self); + if (iToken == END) { + ListMulMot(argv[0], pCon, self); + return 1; + } + while (iToken != END) { + switch (iToken) { + case END: + SCSendOK(pCon); + return 1; + case NAMPOS: + /* do a named position, current token is it */ + if (strcmp(MyParser.Token, "back") != 0) { + MakeCurrentNamPos("back", pCon, self); + } + iRet = ParseNamPos(&MyParser, pCon, pSics, self); + if (iRet) { + SCSendOK(pCon); + SCparChange(pCon); + return 1; + } else { + return 0; + } + break; + case ALIAS: + iRet = CheckPermission(pCon, self); + if (iAlias == 0) { + MakeCurrentNamPos("back", pCon, self); + iAlias = 1; + } + if (!iRet) { + return 0; + } + iRet = ParseAlias(&MyParser, pCon, self); + if (!iRet) { + return 0; + } + break; + case GETPOS: + pPtr = FindNamPos(self, pCon); + if (pPtr != NULL) { + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.nampos = %s", argv[0], pPtr); + } else { + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.nampos = undefined", argv[0]); + } + SCWrite(pCon, pBueffel, eValue); + return 1; + case DEFPOS: + SCparChange(pCon); + return ParseDefPos(pSics, &MyParser, self, pCon); + break; + case LIST: + pPtr = NULL; + Tcl_DStringInit(&tString); + snprintf(pBueffel,sizeof(pBueffel)-1, "%s list of known named positions \n", argv[0]); + Tcl_DStringAppend(&tString, pBueffel, strlen(pBueffel)); + StringDictKillScan(self->pNamPos); + pPtr = StringDictGetNext(self->pNamPos, pError, 131); + while (pPtr != NULL) { + Tcl_DStringAppend(&tString, (char *) pPtr, -1); + Tcl_DStringAppend(&tString, " \n", -1); + pPtr = StringDictGetNext(self->pNamPos, pError, 131); + } + SCWrite(pCon, Tcl_DStringValue(&tString), eValue); + Tcl_DStringFree(&tString); + return 1; + break; + case SYMBOL: + if (strcmp(MyParser.Token, "pos") == 0) { + iRet = CheckPermission(pCon, self); + if (!iRet) { + return 0; + } else { + iToken = GetNextToken(&MyParser, self); + if ((iToken == SYMBOL) || (iToken == NAMPOS)) { + MakeCurrentNamPos(MyParser.Token, pCon, self); + SCparChange(pCon); + return 1; + } else { + snprintf(pError,sizeof(pError)-1, "ERROR: %s no valid named position name", + MyParser.Token); + SCWrite(pCon, pError, eError); + return 0; + } + } + } + if (strcmp(MyParser.Token, "drop") == 0) { + iRet = CheckPermission(pCon, self); + if (!iRet) { + return 0; + } else { + SCparChange(pCon); + return ParseDropPos(&MyParser, pCon, self); + } + } + if (strcmp(MyParser.Token, "find") == 0) { + pPtr = NULL; + pPtr = FindNamPos(self, pCon); + if (pPtr) { + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.namedposition = %s", argv[0], pPtr); + } else { + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.namedposition = UNKNOWN", argv[0]); + } + SCWrite(pCon, pBueffel, eValue); + return 1; + } + snprintf(pError,sizeof(pError)-1, "ERROR: Unknown Token %s", MyParser.Token); + SCWrite(pCon, pError, eError); + return 0; + case RECOVERNAMPOS: + /* + This is not meant to be user command but a facility to read + back data from sattus file. This is why the error checking + is not happening + */ + RecoverNamPos(self, argc - 2, &argv[2]); + return 1; + default: + SCWrite(pCon, "ERROR: Parse Error", eError); return 0; } - MyParser.pPtr = &pBueffel[0]; - MyParser.pCommand = pBueffel; - - /* ignore first Token: that is my name ! */ - iToken = GetNextToken(&MyParser,self); - - /* now loop through my Tokens */ - iToken = GetNextToken(&MyParser,self); - if(iToken == END) - { - ListMulMot(argv[0],pCon,self); - return 1; - } - while( iToken != END) - { - switch(iToken) - { - case END: - SCSendOK(pCon); - return 1; - case NAMPOS: - /* do a named position, current token is it */ - if(strcmp(MyParser.Token,"back")!= 0) - { - MakeCurrentNamPos("back",pCon,self); - } - iRet = ParseNamPos(&MyParser,pCon,pSics,self); - if(iRet) - { - SCSendOK(pCon); - SCparChange(pCon); - return 1; - } - else - { - return 0; - } - break; - case ALIAS: - iRet = CheckPermission(pCon, self); - if(iAlias == 0) - { - MakeCurrentNamPos("back",pCon,self); - iAlias = 1; - } - if(!iRet) - { - return 0; - } - iRet = ParseAlias(&MyParser,pCon,self); - if(!iRet) - { - return 0; - } - break; - case GETPOS: - pPtr = FindNamPos(self,pCon); - if(pPtr != NULL) - { - sprintf(pBueffel,"%s.nampos = %s",argv[0], pPtr); - } - else - { - sprintf(pBueffel,"%s.nampos = undefined",argv[0]); - } - SCWrite(pCon,pBueffel,eValue); - return 1; - case DEFPOS: - SCparChange(pCon); - return ParseDefPos(pSics,&MyParser,self,pCon); - break; - case LIST: - pPtr = NULL; - Tcl_DStringInit(&tString); - sprintf(pBueffel,"%s list of known named positions \n", - argv[0]); - Tcl_DStringAppend(&tString,pBueffel,strlen(pBueffel)); - StringDictKillScan(self->pNamPos); - pPtr = StringDictGetNext(self->pNamPos,pError,131); - while(pPtr != NULL) - { - Tcl_DStringAppend(&tString,(char *)pPtr,-1); - Tcl_DStringAppend (&tString," \n",-1); - pPtr = StringDictGetNext(self->pNamPos, - pError,131); - } - SCWrite(pCon,Tcl_DStringValue(&tString),eValue); - Tcl_DStringFree(&tString); - return 1; - break; - case SYMBOL: - if(strcmp(MyParser.Token,"pos") == 0) - { - iRet = CheckPermission(pCon,self); - if(!iRet) - { - return 0; - } - else - { - iToken = GetNextToken(&MyParser, self); - if((iToken == SYMBOL) || (iToken == NAMPOS)) - { - MakeCurrentNamPos(MyParser.Token,pCon,self); - SCparChange(pCon); - return 1; - } - else - { - sprintf(pError,"ERROR: %s no valid named position name", - MyParser.Token); - SCWrite(pCon,pError,eError); - return 0; - } - } - } - if(strcmp(MyParser.Token,"drop") == 0) - { - iRet = CheckPermission(pCon,self); - if(!iRet) - { - return 0; - } - else - { - SCparChange(pCon); - return ParseDropPos(&MyParser, pCon, self); - } - } - if(strcmp(MyParser.Token,"find") == 0) - { - pPtr = NULL; - pPtr = FindNamPos(self,pCon); - if(pPtr) - { - sprintf(pBueffel,"%s.namedposition = %s",argv[0],pPtr); - } - else - { - sprintf(pBueffel,"%s.namedposition = UNKNOWN",argv[0]); - } - SCWrite(pCon,pBueffel,eValue); - return 1; - } - sprintf(pError,"ERROR: Unknown Token %s",MyParser.Token); - SCWrite(pCon,pError,eError); - return 0; - case RECOVERNAMPOS: - /* - This is not meant to be user command but a facility to read - back data from sattus file. This is why the error checking - is not happening - */ - RecoverNamPos(self,argc-2,&argv[2]); - return 1; - default: - SCWrite(pCon,"ERROR: Parse Error",eError); - return 0; - } - iToken = GetNextToken(&MyParser,self); - } - return 1; - } - + iToken = GetNextToken(&MyParser, self); + } + return 1; +} diff --git a/mumo.h b/mumo.h index 84983a76..d1f9d999 100644 --- a/mumo.h +++ b/mumo.h @@ -15,22 +15,21 @@ #ifndef SICSMUMO #define SICSMUMO /*-------------------------------------------------------------------------*/ - typedef struct __MULMOT *pMulMot; +typedef struct __MULMOT *pMulMot; - pMulMot MakeMultiMotor(void); - void KillMultiMotor(void *pData); - - const char *FindNamPos(pMulMot self, SConnection *pCon); - - int MultiWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); +pMulMot MakeMultiMotor(void); +void KillMultiMotor(void *pData); - int MakeMulti(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - - int ConfigMulti(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - - -#endif +const char *FindNamPos(pMulMot self, SConnection * pCon); +int MultiWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); + +int MakeMulti(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); + +int ConfigMulti(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); + + +#endif diff --git a/mumoconf.c b/mumoconf.c index 305a7417..d0f08643 100644 --- a/mumoconf.c +++ b/mumoconf.c @@ -62,13 +62,13 @@ Once again, the demands for command evaluation are high. Therefore a recursice descent parser. */ - - typedef struct __MYTOKEN { - char *pCommand; - char *pPtr; - int iCurrentToken; - char Token[80]; - } sParser, *psParser; + +typedef struct __MYTOKEN { + char *pCommand; + char *pPtr; + int iCurrentToken; + char Token[80]; +} sParser, *psParser; /* define Token Types */ #define UNKNOWN 0 @@ -80,295 +80,271 @@ #define NUMBER 6 #define ENDCONFIG 7 -/*-------------------------------------------------------------------------*/ - static int GetNextToken(psParser self) - { - char *pPtr; - int i; - - pPtr = self->pPtr; - - /* skip whitespace */ - while( (*pPtr == ' ') || (*pPtr == '\t') ) - { - pPtr++; - } +/*-------------------------------------------------------------------------*/ +static int GetNextToken(psParser self) +{ + char *pPtr; + int i; - /* check for end */ - if( (*pPtr == '\n') || (*pPtr == '\0') || (*pPtr == '\r') ) - { - self->pPtr = pPtr; - self->Token[0] = *pPtr; - self->Token[1] = '\0'; - self->iCurrentToken = END; - return END; - } + pPtr = self->pPtr; + + /* skip whitespace */ + while ((*pPtr == ' ') || (*pPtr == '\t')) { + pPtr++; + } + + /* check for end */ + if ((*pPtr == '\n') || (*pPtr == '\0') || (*pPtr == '\r')) { + self->pPtr = pPtr; + self->Token[0] = *pPtr; + self->Token[1] = '\0'; + self->iCurrentToken = END; + return END; + } - - /* check equaL SIGN */ - if(*pPtr == '=') - { - strcpy(self->Token,"="); - self->iCurrentToken = EQUALITY; - self->pPtr = pPtr +1; - return EQUALITY; - } - - /* number */ - if( (isdigit((int)*pPtr)) || (*pPtr == '.') - ||(*pPtr == '+') || (*pPtr == '-') ) - { - i = 0; - while (isdigit((int)*pPtr) || (*pPtr == '.') - ||(*pPtr == '+') || (*pPtr == '-') ) - { - self->Token[i] = *pPtr; - i++; - pPtr++; - } - self->Token[i] = '\0'; - self->iCurrentToken = NUMBER; - self->pPtr = pPtr; - return NUMBER; - } - - /* a Symbol ? */ - if(isalnum((int)*pPtr)) - { - i = 0; - while( (!isspace((int)*pPtr)) && (*pPtr != '=') - && (*pPtr != '+') && (*pPtr != '-') - && (*pPtr != '\0') && (*pPtr != '\n') ) - { - self->Token[i] = *pPtr; - i++; - pPtr++; - } - self->Token[i] = '\0'; - self->pPtr = pPtr; - /* now it can be one of the keywords, a motor or a symbol */ - if(strcmp(self->Token,"alias") == 0) - { - self->iCurrentToken = ALIAS; - return ALIAS; - } - else if(strcmp(self->Token,"pos") == 0) - { - self->iCurrentToken = POS; - return POS; - } - else if(strcmp(self->Token,"endconfig") == 0) - { - self->iCurrentToken = ENDCONFIG; - return ENDCONFIG; - } - else - { - self->iCurrentToken = SYMBOL; - return SYMBOL; - } - } - return UNKNOWN; - } + + /* check equaL SIGN */ + if (*pPtr == '=') { + strcpy(self->Token, "="); + self->iCurrentToken = EQUALITY; + self->pPtr = pPtr + 1; + return EQUALITY; + } + + /* number */ + if ((isdigit((int) *pPtr)) || (*pPtr == '.') + || (*pPtr == '+') || (*pPtr == '-')) { + i = 0; + while (isdigit((int) *pPtr) || (*pPtr == '.') + || (*pPtr == '+') || (*pPtr == '-')) { + self->Token[i] = *pPtr; + i++; + pPtr++; + } + self->Token[i] = '\0'; + self->iCurrentToken = NUMBER; + self->pPtr = pPtr; + return NUMBER; + } + + /* a Symbol ? */ + if (isalnum((int) *pPtr)) { + i = 0; + while ((!isspace((int) *pPtr)) && (*pPtr != '=') + && (*pPtr != '+') && (*pPtr != '-') + && (*pPtr != '\0') && (*pPtr != '\n')) { + self->Token[i] = *pPtr; + i++; + pPtr++; + } + self->Token[i] = '\0'; + self->pPtr = pPtr; + /* now it can be one of the keywords, a motor or a symbol */ + if (strcmp(self->Token, "alias") == 0) { + self->iCurrentToken = ALIAS; + return ALIAS; + } else if (strcmp(self->Token, "pos") == 0) { + self->iCurrentToken = POS; + return POS; + } else if (strcmp(self->Token, "endconfig") == 0) { + self->iCurrentToken = ENDCONFIG; + return ENDCONFIG; + } else { + self->iCurrentToken = SYMBOL; + return SYMBOL; + } + } + return UNKNOWN; +} + /*-------------------------------------------------------------------------- in this code we need to find a motor for a name quite frequently....... */ - pMotor FindMotor(SicsInterp *pSics, char *name) - { - CommandList *pC; - pMotor pMot; - - pC = FindCommand(pSics,name); - if(!pC) - { - return NULL; - } - pMot = (pMotor)pC->pData; - if(!pMot) - { - return NULL; - } - if(strcmp(pMot->pDescriptor->name,"Motor") != 0) - { - return NULL; - } - return pMot; +pMotor FindMotor(SicsInterp * pSics, char *name) +{ + CommandList *pC; + pMotor pMot; + + pC = FindCommand(pSics, name); + if (!pC) { + return NULL; } + pMot = (pMotor) pC->pData; + if (!pMot) { + return NULL; + } + if (strcmp(pMot->pDescriptor->name, "Motor") != 0) { + return NULL; + } + return pMot; +} + /*--------------------------------------------------------------------------*/ - int MakeMulti(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - /* this does not do much, just installs the configuration command */ - pMulMot pNew = NULL; - int iRet; - char pBueffel[512]; - - if(argc < 2) - { - SCWrite(pCon,"You need to specify a name for a MultiMotor",eError); - return 0; - } +int MakeMulti(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + /* this does not do much, just installs the configuration command */ + pMulMot pNew = NULL; + int iRet; + char pBueffel[512]; - /* check rights */ - if(!SCMatchRights(pCon,usMugger)) - { - SCWrite(pCon,"ERROR: you are not permitted to do this",eError); - return 0; - } - - pNew = MakeMultiMotor(); - if(!pNew) - { - SCWrite(pCon,"No Memory for creating MultiMot",eError); - return 0; - } - pNew->name = strdup(argv[1]); - iRet = AddCommand(pSics,argv[1],ConfigMulti,NULL,pNew); - if(!iRet) - { - sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - return 1; - } -/*-------------------------------------------------------------------------*/ - static int ParseAlias(SicsInterp *pSics,psParser pPP, pMulMot self, SConnection *pCon) - { - int iToken; - char pError[132]; - pMotor pMot; - - /* next token should be a motor name */ - iToken = GetNextToken(pPP); - if(iToken != SYMBOL) - { - sprintf(pError,"ERROR: Token %s not recognized in MulMot alias", - pPP->Token); - SCWrite(pCon,pError,eError); - return 0; - } - /* try find the motor and verify that it is a motor */ - pMot = FindMotor(pSics,pPP->Token); - if(!pMot) - { - sprintf(pError,"ERROR: Motor %s not found, no alias created", - pPP->Token); - SCWrite(pCon,pError,eError); - return 0; - } - - /* now pMot holds all info ever needed about the motor */ - /* the next Token should be a symbol giving the alias */ - iToken = GetNextToken(pPP); - if(iToken == EQUALITY) /* tolerate Equality */ - { - iToken = GetNextToken(pPP); - } - if(iToken != SYMBOL) - { - sprintf(pError,"ERROR: Token %s not recognized in MulMot alias", - pPP->Token); - SCWrite(pCon,pError,eError); - return 0; - } - - /* now we have all that is ever needed to create an alias. We have done - so much work in order to get here, that it will be done, here and - now! - */ - StringDictAddPair(self->pAlias,pPP->Token,pMot->name); - return 1; - } - -/*-------------------------------------------------------------------------*/ - static int ParsePos(SicsInterp *pSics,psParser pPP, - pMulMot self, SConnection *pCon) - { - pMotor pMot = NULL; - char pError[132]; - int iToken; - float fVal; - - iToken = GetNextToken(pPP); - if(iToken != SYMBOL) /* we want a name here */ - { - sprintf(pError,"ERROR: Invalid Token %s in ParsePos",pPP->Token); - SCWrite(pCon,pError,eError); - return 0; - } - - /* The rest of the stuff should be the motors to drive until - we are there - */ - StringDictAddPair(self->pNamPos,pPP->Token,pPP->pPtr); - return 1; - } -/*--------------------------------------------------------------------------*/ - int ConfigMulti(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - pMulMot self; - char pBueffel[512]; - char pError[132]; - int i, iToken, iRet; - sParser PP; - CommandList *pCom = NULL; - - assert(pCon); - assert(pSics); - assert(pData); - - self = (pMulMot)pData; - - iRet = Arg2Text(argc,argv,pBueffel,511); - if(!iRet) - { - sprintf(pBueffel,"Argument string to long for %s configuration",argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - strtolower(pBueffel); - - /* first token is name, ignore */ - PP.pCommand = pBueffel; - PP.pPtr = pBueffel; - iToken = GetNextToken(&PP); - iToken = GetNextToken(&PP); - while(iToken != END) - { - switch(iToken) - { - case END: - return 1; /* ignored */ - break; - case ENDCONFIG: - /* reconfigure command to final state */ - pCom = FindCommand(pSics,argv[0]); - assert(pCom != NULL); - pCom->OFunc = MultiWrapper; - pCom->KFunc = KillMultiMotor; - return 1; - break; - case ALIAS: - return ParseAlias(pSics,&PP,self,pCon); - break; - case POS: - return ParsePos(pSics,&PP,self,pCon); - break; - default: - sprintf(pError,"ERROR: Invalid Token %s found in %s", - PP.Token, argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - iToken = GetNextToken(&PP); - } - /* should never end here */ - sprintf(pError,"ERROR: %s was NOT understood in mumoconf",pBueffel); - SCWrite(pCon,pError,eError); + if (argc < 2) { + SCWrite(pCon, "You need to specify a name for a MultiMotor", eError); return 0; - } + } + /* check rights */ + if (!SCMatchRights(pCon, usMugger)) { + SCWrite(pCon, "ERROR: you are not permitted to do this", eError); + return 0; + } + + pNew = MakeMultiMotor(); + if (!pNew) { + SCWrite(pCon, "No Memory for creating MultiMot", eError); + return 0; + } + pNew->name = strdup(argv[1]); + iRet = AddCommand(pSics, argv[1], ConfigMulti, NULL, pNew); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: duplicate command %s not created", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + return 1; +} + +/*-------------------------------------------------------------------------*/ +static int ParseAlias(SicsInterp * pSics, psParser pPP, pMulMot self, + SConnection * pCon) +{ + int iToken; + char pError[132]; + pMotor pMot; + + /* next token should be a motor name */ + iToken = GetNextToken(pPP); + if (iToken != SYMBOL) { + snprintf(pError,sizeof(pError)-1, "ERROR: Token %s not recognized in MulMot alias", + pPP->Token); + SCWrite(pCon, pError, eError); + return 0; + } + /* try find the motor and verify that it is a motor */ + pMot = FindMotor(pSics, pPP->Token); + if (!pMot) { + snprintf(pError,sizeof(pError)-1, "ERROR: Motor %s not found, no alias created", + pPP->Token); + SCWrite(pCon, pError, eError); + return 0; + } + + /* now pMot holds all info ever needed about the motor */ + /* the next Token should be a symbol giving the alias */ + iToken = GetNextToken(pPP); + if (iToken == EQUALITY) { /* tolerate Equality */ + iToken = GetNextToken(pPP); + } + if (iToken != SYMBOL) { + snprintf(pError,sizeof(pError)-1, "ERROR: Token %s not recognized in MulMot alias", + pPP->Token); + SCWrite(pCon, pError, eError); + return 0; + } + + /* now we have all that is ever needed to create an alias. We have done + so much work in order to get here, that it will be done, here and + now! + */ + StringDictAddPair(self->pAlias, pPP->Token, pMot->name); + return 1; +} + +/*-------------------------------------------------------------------------*/ +static int ParsePos(SicsInterp * pSics, psParser pPP, + pMulMot self, SConnection * pCon) +{ + pMotor pMot = NULL; + char pError[132]; + int iToken; + float fVal; + + iToken = GetNextToken(pPP); + if (iToken != SYMBOL) { /* we want a name here */ + snprintf(pError,sizeof(pError)-1, "ERROR: Invalid Token %s in ParsePos", pPP->Token); + SCWrite(pCon, pError, eError); + return 0; + } + + /* The rest of the stuff should be the motors to drive until + we are there + */ + StringDictAddPair(self->pNamPos, pPP->Token, pPP->pPtr); + return 1; +} + +/*--------------------------------------------------------------------------*/ +int ConfigMulti(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pMulMot self; + char pBueffel[512]; + char pError[132]; + int i, iToken, iRet; + sParser PP; + CommandList *pCom = NULL; + + assert(pCon); + assert(pSics); + assert(pData); + + self = (pMulMot) pData; + + iRet = Arg2Text(argc, argv, pBueffel, 511); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, "Argument string to long for %s configuration", + argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + strtolower(pBueffel); + + /* first token is name, ignore */ + PP.pCommand = pBueffel; + PP.pPtr = pBueffel; + iToken = GetNextToken(&PP); + iToken = GetNextToken(&PP); + while (iToken != END) { + switch (iToken) { + case END: + return 1; /* ignored */ + break; + case ENDCONFIG: + /* reconfigure command to final state */ + pCom = FindCommand(pSics, argv[0]); + assert(pCom != NULL); + pCom->OFunc = MultiWrapper; + pCom->KFunc = KillMultiMotor; + return 1; + break; + case ALIAS: + return ParseAlias(pSics, &PP, self, pCon); + break; + case POS: + return ParsePos(pSics, &PP, self, pCon); + break; + default: + snprintf(pError,sizeof(pError)-1, "ERROR: Invalid Token %s found in %s", + PP.Token, argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + iToken = GetNextToken(&PP); + } + /* should never end here */ + snprintf(pError,sizeof(pError)-1, "ERROR: %s was NOT understood in mumoconf", pBueffel); + SCWrite(pCon, pError, eError); + return 0; +} diff --git a/napi.c b/napi.c index 3de6d75a..197f1250 100644 --- a/napi.c +++ b/napi.c @@ -19,7 +19,7 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - For further information, see + For further information, see ----------------------------------------------------------------------------*/ @@ -32,6 +32,9 @@ static const char* rscid = "$Id$"; /* Revision inserted by CVS */ #include #include #include +#include + +#include "nxconfig.h" #include "napi.h" #include "nxstack.h" @@ -49,11 +52,151 @@ static int iFortifyScope; #ifdef _WIN32 #define LIBSEP ";" #define PATHSEP "\\" +#define THREAD_LOCAL __declspec(thread) #else #define LIBSEP ":" #define PATHSEP "/" +#define THREAD_LOCAL __thread #endif -extern char *stptok(char *s, char *tok, size_t toklen, char *brk); + +#ifdef _MSC_VER +#define snprintf _snprintf +#endif /* _MSC_VER */ + +#include "nx_stptok.h" + +#if defined(_WIN32) +/* + * HDF5 on windows does not do locking for multiple threads conveniently so we will implement it ourselves. + * Freddie Akeroyd, 16/06/2011 + */ +#include + + +static CRITICAL_SECTION nx_critical; + +static int nxilock() +{ + static int first_call = 1; + if (first_call) + { + first_call = 0; + InitializeCriticalSection(&nx_critical); + } + EnterCriticalSection(&nx_critical); + return NX_OK; +} + +static int nxiunlock(int ret) +{ + LeaveCriticalSection(&nx_critical); + return ret; +} + +#define LOCKED_CALL(__call) \ + ( nxilock() , nxiunlock(__call) ) + +#elif HAVE_LIBPTHREAD + +#include + +static pthread_mutex_t nx_mutex; + +#ifdef PTHREAD_MUTEX_RECURSIVE +#define RECURSIVE_LOCK PTHREAD_MUTEX_RECURSIVE +#else +#define RECURSIVE_LOCK PTHREAD_MUTEX_RECURSIVE_NP +#endif /* PTHREAD_MUTEX_RECURSIVE */ + +static void nx_pthread_init() +{ + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, RECURSIVE_LOCK); + pthread_mutex_init(&nx_mutex, &attr); +} + +static int nxilock() +{ + static pthread_once_t once_control = PTHREAD_ONCE_INIT; + if (pthread_once(&once_control, nx_pthread_init) != 0) + { + NXReportError("pthread_once failed"); + return NX_ERROR; + } + if (pthread_mutex_lock(&nx_mutex) != 0) + { + NXReportError("pthread_mutex_lock failed"); + return NX_ERROR; + } + return NX_OK; +} + +static int nxiunlock(int ret) +{ + if (pthread_mutex_unlock(&nx_mutex) != 0) + { + NXReportError("pthread_mutex_unlock failed"); + return NX_ERROR; + } + return ret; +} + +#define LOCKED_CALL(__call) \ + ( nxilock() , nxiunlock(__call) ) + +#else + +#define LOCKED_CALL(__call) \ + __call + +#endif /* _WIN32 */ + +/** + * valid NeXus names + */ +int validNXName(const char* name, int allow_colon) +{ + int i; + if (name == NULL) + { + return 0; + } + for(i=0; i= 'a' && name[i] <= 'z') || + (name[i] >= 'A' && name[i] <= 'Z') || + (name[i] >= '0' && name[i] <= '9') || + (name[i] == '_') ) + { + ; + } + else if (allow_colon && name[i] == ':') + { + ; + } + else + { + return 0; + } + } + return 1; +} + +static int64_t* dupDimsArray(int* dims_array, int rank) +{ + int i; + int64_t* dims64 = (int64_t*)malloc(rank * sizeof(int64_t)); + if (dims64 != NULL) + { + for(i=0; istripFlag = 1; if(am & NXACC_NOSTRIP){ fHandle->stripFlag = 0; - am -= NXACC_NOSTRIP; + am = (NXaccess)(am & ~NXACC_NOSTRIP); + } + fHandle->checkNameSyntax = 0; + if (am & NXACC_CHECKNAMESYNTAX) { + fHandle->checkNameSyntax = 1; + am = (NXaccess)(am & ~NXACC_CHECKNAMESYNTAX); } - if (am==NXACC_CREATE) { + + if (my_am==NXACC_CREATE) { /* HDF4 will be used ! */ hdf_type=1; filename = strdup(userfilename); - } else if (am==NXACC_CREATE4) { + } else if (my_am==NXACC_CREATE4) { /* HDF4 will be used ! */ hdf_type=1; filename = strdup(userfilename); - } else if (am==NXACC_CREATE5) { + } else if (my_am==NXACC_CREATE5) { /* HDF5 will be used ! */ hdf_type=2; filename = strdup(userfilename); - } else if (am==NXACC_CREATEXML) { + } else if (my_am==NXACC_CREATEXML) { /* XML will be used ! */ hdf_type=3; filename = strdup(userfilename); } else { filename = locateNexusFileInPath((char *)userfilename); if(filename == NULL){ - NXIReportError(NXpData,"Out of memory in NeXus-API"); + NXReportError("Out of memory in NeXus-API"); free(fHandle); return NX_ERROR; } @@ -327,14 +546,14 @@ static NXstatus NXinternalopen(CONSTCHAR *userfilename, NXaccess am, pFileStac if(iRet < 0) { snprintf(error,1023,"failed to open %s for reading", filename); - NXIReportError(NXpData,error); + NXReportError(error); free(filename); return NX_ERROR; } if(iRet == 0){ snprintf(error,1023,"failed to determine filetype for %s ", filename); - NXIReportError(NXpData,error); + NXReportError(error); free(filename); free(fHandle); return NX_ERROR; @@ -342,7 +561,7 @@ static NXstatus NXinternalopen(CONSTCHAR *userfilename, NXaccess am, pFileStac hdf_type = iRet; } if(filename == NULL){ - NXIReportError(NXpData,"Out of memory in NeXus-API"); + NXReportError("Out of memory in NeXus-API"); return NX_ERROR; } @@ -359,7 +578,7 @@ static NXstatus NXinternalopen(CONSTCHAR *userfilename, NXaccess am, pFileStac NX4assignFunctions(fHandle); pushFileStack(fileStack,fHandle,filename); #else - NXIReportError (NXpData, + NXReportError( "ERROR: Attempt to create HDF4 file when not linked with HDF4"); retstat = NX_ERROR; #endif /* HDF4 */ @@ -378,7 +597,7 @@ static NXstatus NXinternalopen(CONSTCHAR *userfilename, NXaccess am, pFileStac NX5assignFunctions(fHandle); pushFileStack(fileStack,fHandle, filename); #else - NXIReportError (NXpData, + NXReportError( "ERROR: Attempt to create HDF5 file when not linked with HDF5"); retstat = NX_ERROR; #endif /* HDF5 */ @@ -399,12 +618,12 @@ static NXstatus NXinternalopen(CONSTCHAR *userfilename, NXaccess am, pFileStac NXXassignFunctions(fHandle); pushFileStack(fileStack,fHandle, filename); #else - NXIReportError (NXpData, + NXReportError( "ERROR: Attempt to create XML file when not linked with XML"); retstat = NX_ERROR; #endif } else { - NXIReportError (NXpData, + NXReportError( "ERROR: Format not readable by this NeXus library"); retstat = NX_ERROR; } @@ -414,6 +633,47 @@ static NXstatus NXinternalopen(CONSTCHAR *userfilename, NXaccess am, pFileStac return retstat; } +static NXstatus NXinternalopen(CONSTCHAR *userfilename, NXaccess am, pFileStack fileStack) +{ + return LOCKED_CALL(NXinternalopenImpl(userfilename, am, fileStack)); +} + + +NXstatus NXreopen(NXhandle pOrigHandle, NXhandle* pNewHandle) +{ + pFileStack newFileStack; + pFileStack origFileStack = (pFileStack)pOrigHandle; + pNexusFunction fOrigHandle = NULL, fNewHandle = NULL; + *pNewHandle = NULL; + newFileStack = makeFileStack(); + if(newFileStack == NULL){ + NXReportError ("ERROR: no memory to create filestack"); + return NX_ERROR; + } + // The code below will only open the last file on a stack + // for the moment raise an error, but this behaviour may be OK + if (fileStackDepth(origFileStack) > 0) + { + NXReportError ( + "ERROR: handle stack referes to many files - cannot reopen"); + return NX_ERROR; + } + fOrigHandle = peekFileOnStack(origFileStack); + if (fOrigHandle->nxreopen == NULL) + { + NXReportError ( + "ERROR: NXreopen not implemented for this underlying file format"); + return NX_ERROR; + } + fNewHandle = (NexusFunction*)malloc(sizeof(NexusFunction)); + memcpy(fNewHandle, fOrigHandle, sizeof(NexusFunction)); + LOCKED_CALL(fNewHandle->nxreopen( fOrigHandle->pNexusData, &(fNewHandle->pNexusData) )); + pushFileStack( newFileStack, fNewHandle, peekFilenameOnStack(origFileStack) ); + *pNewHandle = newFileStack; + return NX_OK; +} + + /* ------------------------------------------------------------------------- */ NXstatus NXclose (NXhandle *fid) @@ -421,21 +681,27 @@ static NXstatus NXinternalopen(CONSTCHAR *userfilename, NXaccess am, pFileStac NXhandle hfil; int status; pFileStack fileStack = NULL; - pNexusFunction pFunc=NULL; + if (*fid == NULL) + { + return NX_OK; + } fileStack = (pFileStack)*fid; pFunc = peekFileOnStack(fileStack); hfil = pFunc->pNexusData; - status = pFunc->nxclose(&hfil); + status = LOCKED_CALL(pFunc->nxclose(&hfil)); pFunc->pNexusData = hfil; free(pFunc); popFileStack(fileStack); if(fileStackDepth(fileStack) < 0){ killFileStack(fileStack); + *fid = NULL; } + /* we can't set fid to NULL always as the handle points to a stack of files for external file support */ /* Fortify_CheckAllMemory(); */ + return status; } @@ -443,8 +709,15 @@ static NXstatus NXinternalopen(CONSTCHAR *userfilename, NXaccess am, pFileStac NXstatus NXmakegroup (NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass) { + char buffer[256]; pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxmakegroup(pFunc->pNexusData, name, nxclass); + if ( pFunc->checkNameSyntax && (nxclass != NULL) /* && !strncmp("NX", nxclass, 2) */ && !validNXName(name, 0) ) + { + sprintf(buffer, "ERROR: invalid characters in group name \"%s\"", name); + NXReportError(buffer); + return NX_ERROR; + } + return LOCKED_CALL(pFunc->nxmakegroup(pFunc->pNexusData, name, nxclass)); } /*------------------------------------------------------------------------*/ static int analyzeNapimount(char *napiMount, char *extFile, int extFileLen, @@ -462,7 +735,7 @@ static int analyzeNapimount(char *napiMount, char *extFile, int extFileLen, if(path == NULL){ length = strlen(napiMount) - 9; if(length > extFileLen){ - NXIReportError(NXpData,"ERROR: internal errro with external linking"); + NXReportError("ERROR: internal errro with external linking"); return NXBADURL; } memcpy(extFile,pPtr+9,length); @@ -472,13 +745,13 @@ static int analyzeNapimount(char *napiMount, char *extFile, int extFileLen, pPtr += 9; length = path - pPtr; if(length > extFileLen){ - NXIReportError(NXpData,"ERROR: internal errro with external linking"); + NXReportError("ERROR: internal errro with external linking"); return NXBADURL; } memcpy(extFile,pPtr,length); length = strlen(path-1); if(length > extPathLen){ - NXIReportError(NXpData,"ERROR: internal error with external linking"); + NXReportError("ERROR: internal error with external linking"); return NXBADURL; } strcpy(extPath,path+1); @@ -491,21 +764,22 @@ static int analyzeNapimount(char *napiMount, char *extFile, int extFileLen, NXstatus NXopengroup (NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass) { int status, attStatus, type = NX_CHAR, length = 1023; - NXaccess access = NXACC_RDWR; + NXaccess access = NXACC_READ; NXlink breakID; pFileStack fileStack; char nxurl[1024], exfile[512], expath[512]; - ErrFunc oldError; pNexusFunction pFunc = NULL; fileStack = (pFileStack)fid; pFunc = handleToNexusFunc(fid); - status = pFunc->nxopengroup(pFunc->pNexusData, name, nxclass); - oldError = NXMGetError(); - NXIReportError = NXNXNoReport; + status = LOCKED_CALL(pFunc->nxopengroup(pFunc->pNexusData, name, nxclass)); + if(status == NX_OK){ + pushPath(fileStack,name); + } + NXMDisableErrorReporting(); attStatus = NXgetattr(fid,"napimount",nxurl,&length, &type); - NXIReportError = oldError; + NXMEnableErrorReporting(); if(attStatus == NX_OK){ /* this is an external linking group @@ -514,11 +788,11 @@ static int analyzeNapimount(char *napiMount, char *extFile, int extFileLen, if(status == NXBADURL){ return NX_ERROR; } - status = NXinternalopen(exfile,access, fileStack); + status = NXinternalopen(exfile, access, fileStack); if(status == NX_ERROR){ return status; } - status = NXopenpath(fid,expath); + status = NXopenpath(fid, expath); NXgetgroupID(fid,&breakID); setCloseID(fileStack,breakID); } @@ -537,7 +811,11 @@ static int analyzeNapimount(char *napiMount, char *extFile, int extFileLen, pNexusFunction pFunc = handleToNexusFunc(fid); fileStack = (pFileStack)fid; if(fileStackDepth(fileStack) == 0){ - return pFunc->nxclosegroup(pFunc->pNexusData); + status = LOCKED_CALL(pFunc->nxclosegroup(pFunc->pNexusData)); + if(status == NX_OK){ + popPath(fileStack); + } + return status; } else { /* we have to check for leaving an external file */ NXgetgroupID(fid,¤tID); @@ -546,7 +824,10 @@ static int analyzeNapimount(char *napiMount, char *extFile, int extFileLen, NXclose(&fid); status = NXclosegroup(fid); } else { - status = pFunc->nxclosegroup(pFunc->pNexusData); + status = LOCKED_CALL(pFunc->nxclosegroup(pFunc->pNexusData)); + if(status == NX_OK){ + popPath(fileStack); + } } return status; } @@ -557,27 +838,61 @@ static int analyzeNapimount(char *napiMount, char *extFile, int extFileLen, NXstatus NXmakedata (NXhandle fid, CONSTCHAR *name, int datatype, int rank, int dimensions[]) { - pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxmakedata(pFunc->pNexusData, name, datatype, rank, dimensions); + int status; + int64_t* dims64 = dupDimsArray(dimensions, rank); + status = NXmakedata64(fid, name, datatype, rank, dims64); + free(dims64); + return status; } + NXstatus NXmakedata64 (NXhandle fid, CONSTCHAR *name, int datatype, + int rank, int64_t dimensions[]) + { + char buffer[256]; + pNexusFunction pFunc = handleToNexusFunc(fid); + if ( pFunc->checkNameSyntax && !validNXName(name, 0) ) + { + sprintf(buffer, "ERROR: invalid characters in dataset name \"%s\"", name); + NXReportError(buffer); + return NX_ERROR; + } + return LOCKED_CALL(pFunc->nxmakedata64(pFunc->pNexusData, name, datatype, rank, dimensions)); + } /* --------------------------------------------------------------------- */ NXstatus NXcompmakedata (NXhandle fid, CONSTCHAR *name, int datatype, - int rank, int dimensions[],int compress_type, int chunk_size[]) + int rank, int dimensions[], int compress_type, int chunk_size[]) { - pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxcompmakedata (pFunc->pNexusData, name, datatype, rank, dimensions, compress_type, chunk_size); + int status; + int64_t* dims64 = dupDimsArray(dimensions, rank); + int64_t* chunk64 = dupDimsArray(chunk_size, rank); + status = NXcompmakedata64(fid, name, datatype, rank, dims64, compress_type, chunk64); + free(dims64); + free(chunk64); + return status; } + NXstatus NXcompmakedata64 (NXhandle fid, CONSTCHAR *name, int datatype, + int rank, int64_t dimensions[], int compress_type, int64_t chunk_size[]) + { + char buffer[256]; + pNexusFunction pFunc = handleToNexusFunc(fid); + if ( pFunc->checkNameSyntax && !validNXName(name, 0) ) + { + sprintf(buffer, "ERROR: invalid characters in dataset name \"%s\"", name); + NXReportError(buffer); + return NX_ERROR; + } + return LOCKED_CALL(pFunc->nxcompmakedata64 (pFunc->pNexusData, name, datatype, rank, dimensions, compress_type, chunk_size)); + } /* --------------------------------------------------------------------- */ NXstatus NXcompress (NXhandle fid, int compress_type) { pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxcompress (pFunc->pNexusData, compress_type); + return LOCKED_CALL(pFunc->nxcompress (pFunc->pNexusData, compress_type)); } @@ -585,42 +900,129 @@ static int analyzeNapimount(char *napiMount, char *extFile, int extFileLen, NXstatus NXopendata (NXhandle fid, CONSTCHAR *name) { - pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxopendata(pFunc->pNexusData, name); - } + int status, attStatus, type = NX_CHAR, length = 1023; + NXaccess access = NXACC_READ; + NXlink breakID; + pFileStack fileStack; + char nxurl[1024], exfile[512], expath[512]; + pNexusFunction pFunc = NULL; + fileStack = (pFileStack)fid; + pFunc = handleToNexusFunc(fid); + status = LOCKED_CALL(pFunc->nxopendata(pFunc->pNexusData, name)); + + if(status == NX_OK){ + pushPath(fileStack,name); + } + + NXMDisableErrorReporting(); + attStatus = NXgetattr(fid,"napimount",nxurl,&length, &type); + NXMEnableErrorReporting(); + if(attStatus == NX_OK){ + /* + this is an external linking group + */ + status = analyzeNapimount(nxurl,exfile,511,expath,511); + if(status == NXBADURL){ + return NX_ERROR; + } + status = NXinternalopen(exfile, access, fileStack); + if(status == NX_ERROR){ + return status; + } + status = NXopenpath(fid,expath); + NXgetdataID(fid,&breakID); + setCloseID(fileStack,breakID); + } + + return status; + } /* ----------------------------------------------------------------- */ - NXstatus NXclosedata (NXhandle fid) + NXstatus NXclosedata (NXhandle fid) { + int status; + pFileStack fileStack = NULL; + NXlink closeID, currentID; + pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxclosedata(pFunc->pNexusData); + fileStack = (pFileStack)fid; + + if(fileStackDepth(fileStack) == 0){ + status = LOCKED_CALL(pFunc->nxclosedata(pFunc->pNexusData)); + if(status == NX_OK){ + popPath(fileStack); + } + return status; + } else { + /* we have to check for leaving an external file */ + NXgetdataID(fid,¤tID); + peekIDOnStack(fileStack,&closeID); + if(NXsameID(fid,&closeID,¤tID) == NX_OK){ + NXclose(&fid); + status = NXclosedata(fid); + } else { + status = LOCKED_CALL(pFunc->nxclosedata(pFunc->pNexusData)); + if(status == NX_OK){ + popPath(fileStack); + } + } + return status; + } } /* ------------------------------------------------------------------- */ - NXstatus NXputdata (NXhandle fid, void *data) + NXstatus NXputdata (NXhandle fid, const void *data) { pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxputdata(pFunc->pNexusData, data); + return LOCKED_CALL(pFunc->nxputdata(pFunc->pNexusData, data)); } /* ------------------------------------------------------------------- */ - NXstatus NXputattr (NXhandle fid, CONSTCHAR *name, void *data, + NXstatus NXputattr (NXhandle fid, CONSTCHAR *name, const void *data, int datalen, int iType) { + char buffer[256]; pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxputattr(pFunc->pNexusData, name, data, datalen, iType); + if (datalen > 1 && iType != NX_CHAR) + { + NXReportError("NXputattr: numeric arrays are not allowed as attributes - only character strings and single numbers"); + return NX_ERROR; + } + if ( pFunc->checkNameSyntax && !validNXName(name, 0) ) + { + sprintf(buffer, "ERROR: invalid characters in attribute name \"%s\"", name); + NXReportError(buffer); + return NX_ERROR; + } + return LOCKED_CALL(pFunc->nxputattr(pFunc->pNexusData, name, data, datalen, iType)); } /* ------------------------------------------------------------------- */ - NXstatus NXputslab (NXhandle fid, void *data, int iStart[], int iSize[]) + NXstatus NXputslab (NXhandle fid, const void *data, const int iStart[], const int iSize[]) + { + int i, iType, rank; + int64_t iStart64[NX_MAXRANK], iSize64[NX_MAXRANK]; + if (NXgetinfo64(fid, &rank, iStart64, &iType) != NX_OK) + { + return NX_ERROR; + } + for(i=0; i < rank; ++i) + { + iStart64[i] = iStart[i]; + iSize64[i] = iSize[i]; + } + return NXputslab64(fid, data, iStart64, iSize64); + } + + NXstatus NXputslab64 (NXhandle fid, const void *data, const int64_t iStart[], const int64_t iSize[]) { pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxputslab(pFunc->pNexusData, data, iStart, iSize); + return LOCKED_CALL(pFunc->nxputslab64(pFunc->pNexusData, data, iStart, iSize)); } /* ------------------------------------------------------------------- */ @@ -628,7 +1030,7 @@ static int analyzeNapimount(char *napiMount, char *extFile, int extFileLen, NXstatus NXgetdataID (NXhandle fid, NXlink* sRes) { pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxgetdataID(pFunc->pNexusData, sRes); + return LOCKED_CALL(pFunc->nxgetdataID(pFunc->pNexusData, sRes)); } @@ -637,14 +1039,21 @@ static int analyzeNapimount(char *napiMount, char *extFile, int extFileLen, NXstatus NXmakelink (NXhandle fid, NXlink* sLink) { pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxmakelink(pFunc->pNexusData, sLink); + return LOCKED_CALL(pFunc->nxmakelink(pFunc->pNexusData, sLink)); } /* ------------------------------------------------------------------- */ NXstatus NXmakenamedlink (NXhandle fid, CONSTCHAR *newname, NXlink* sLink) { + char buffer[256]; pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxmakenamedlink(pFunc->pNexusData, newname, sLink); + if ( pFunc->checkNameSyntax && !validNXName(newname, 0) ) + { + sprintf(buffer, "ERROR: invalid characters in link name \"%s\"", newname); + NXReportError(buffer); + return NX_ERROR; + } + return LOCKED_CALL(pFunc->nxmakenamedlink(pFunc->pNexusData, newname, sLink)); } /* --------------------------------------------------------------------*/ NXstatus NXopensourcegroup(NXhandle fid) @@ -655,7 +1064,7 @@ static int analyzeNapimount(char *napiMount, char *extFile, int extFileLen, status = NXgetattr(fid,"target",target_path,&length,&type); if(status != NX_OK) { - NXIReportError(NXpData,"ERROR: item not linked"); + NXReportError("ERROR: item not linked"); return NX_ERROR; } return NXopengrouppath(fid,target_path); @@ -672,7 +1081,7 @@ static int analyzeNapimount(char *napiMount, char *extFile, int extFileLen, fileStack = (pFileStack)*pHandle; pFunc = peekFileOnStack(fileStack); hfil = pFunc->pNexusData; - status = pFunc->nxflush(&hfil); + status = LOCKED_CALL(pFunc->nxflush(&hfil)); pFunc->pNexusData = hfil; return status; } @@ -680,16 +1089,29 @@ static int analyzeNapimount(char *napiMount, char *extFile, int extFileLen, /*-------------------------------------------------------------------------*/ + NXstatus NXmalloc (void** data, int rank, int dimensions[], int datatype) + { + int status; + int64_t* dims64 = dupDimsArray(dimensions, rank); + status = NXmalloc64(data, rank, dims64, datatype); + free(dims64); + return status; + } + + NXstatus NXmalloc64 (void** data, int rank, + int64_t dimensions[], int datatype) { int i; size_t size = 1; *data = NULL; for(i=0; inxgetnextentry(pFunc->pNexusData, name, nxclass, datatype); + return LOCKED_CALL(pFunc->nxgetnextentry(pFunc->pNexusData, name, nxclass, datatype)); } /*----------------------------------------------------------------------*/ /* @@ -751,8 +1173,8 @@ static int analyzeNapimount(char *napiMount, char *extFile, int extFileLen, char *nxitrim(char *str) { - char *ibuf = str, *obuf = str; - int i = 0, cnt = 0; + char *ibuf = str; + int i = 0; /* ** Trap NULL @@ -785,38 +1207,72 @@ char *nxitrim(char *str) NXstatus NXgetdata (NXhandle fid, void *data) { - int status, type, rank, iDim[NX_MAXRANK]; + int status, type, rank; + int64_t iDim[NX_MAXRANK]; char *pPtr, *pPtr2; pNexusFunction pFunc = handleToNexusFunc(fid); - status = pFunc->nxgetinfo(pFunc->pNexusData, &rank, iDim, &type); /* unstripped size if string */ + status = LOCKED_CALL(pFunc->nxgetinfo64(pFunc->pNexusData, &rank, iDim, &type)); /* unstripped size if string */ /* only strip one dimensional strings */ if ( (type == NX_CHAR) && (pFunc->stripFlag == 1) && (rank == 1) ) { - pPtr = (char*)malloc(iDim[0]+5); + pPtr = (char*)malloc(iDim[0]+5); memset(pPtr, 0, iDim[0]+5); - status = pFunc->nxgetdata(pFunc->pNexusData, pPtr); - pPtr2 = nxitrim(pPtr); - strncpy((char*)data, pPtr2, strlen(pPtr2)); /* not NULL terminated by default */ - free(pPtr); + status = LOCKED_CALL(pFunc->nxgetdata(pFunc->pNexusData, pPtr)); + pPtr2 = nxitrim(pPtr); + strncpy((char*)data, pPtr2, strlen(pPtr2)); /* not NULL terminated by default */ + free(pPtr); } else { - status = pFunc->nxgetdata(pFunc->pNexusData, data); + status = LOCKED_CALL(pFunc->nxgetdata(pFunc->pNexusData, data)); } return status; } - +/*---------------------------------------------------------------------------*/ + NXstatus NXgetrawinfo64 (NXhandle fid, int *rank, + int64_t dimension[], int *iType) + { + pNexusFunction pFunc = handleToNexusFunc(fid); + return LOCKED_CALL(pFunc->nxgetinfo64(pFunc->pNexusData, rank, dimension, iType)); + } + + NXstatus NXgetrawinfo (NXhandle fid, int *rank, + int dimension[], int *iType) + { + int i, status; + int64_t dims64[NX_MAXRANK]; + pNexusFunction pFunc = handleToNexusFunc(fid); + status = LOCKED_CALL(pFunc->nxgetinfo64(pFunc->pNexusData, rank, dims64, iType)); + for(i=0; i < *rank; ++i) + { + dimension[i] = dims64[i]; + } + return status; + } /*-------------------------------------------------------------------------*/ NXstatus NXgetinfo (NXhandle fid, int *rank, int dimension[], int *iType) + { + int i, status; + int64_t dims64[NX_MAXRANK]; + status = NXgetinfo64(fid, rank, dims64, iType); + for(i=0; i < *rank; ++i) + { + dimension[i] = dims64[i]; + } + return status; + } + + NXstatus NXgetinfo64 (NXhandle fid, int *rank, + int64_t dimension[], int *iType) { int status; char *pPtr = NULL; - pNexusFunction pFunc = handleToNexusFunc(fid); - status = pFunc->nxgetinfo(pFunc->pNexusData, rank, dimension, iType); + *rank = 0; + status = LOCKED_CALL(pFunc->nxgetinfo64(pFunc->pNexusData, rank, dimension, iType)); /* the length of a string may be trimmed.... */ @@ -825,7 +1281,7 @@ char *nxitrim(char *str) pPtr = (char *)malloc((dimension[0]+1)*sizeof(char)); if(pPtr != NULL){ memset(pPtr,0,(dimension[0]+1)*sizeof(char)); - pFunc->nxgetdata(pFunc->pNexusData, pPtr); + LOCKED_CALL(pFunc->nxgetdata(pFunc->pNexusData, pPtr)); dimension[0] = strlen(nxitrim(pPtr)); free(pPtr); } @@ -838,10 +1294,26 @@ char *nxitrim(char *str) NXstatus NXgetslab (NXhandle fid, void *data, int iStart[], int iSize[]) { - pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxgetslab(pFunc->pNexusData, data, iStart, iSize); + int i, iType, rank; + int64_t iStart64[NX_MAXRANK], iSize64[NX_MAXRANK]; + if (NXgetinfo64(fid, &rank, iStart64, &iType) != NX_OK) + { + return NX_ERROR; + } + for(i=0; i < rank; ++i) + { + iStart64[i] = iStart[i]; + iSize64[i] = iSize[i]; + } + return NXgetslab64(fid, data, iStart64, iSize64); } + NXstatus NXgetslab64 (NXhandle fid, void *data, + const int64_t iStart[], const int64_t iSize[]) + { + pNexusFunction pFunc = handleToNexusFunc(fid); + return LOCKED_CALL(pFunc->nxgetslab64(pFunc->pNexusData, data, iStart, iSize)); + } /*-------------------------------------------------------------------------*/ @@ -849,7 +1321,7 @@ char *nxitrim(char *str) int *iLength, int *iType) { pNexusFunction pFunc = handleToNexusFunc(fileid); - return pFunc->nxgetnextattr(pFunc->pNexusData, pName, iLength, iType); + return LOCKED_CALL(pFunc->nxgetnextattr(pFunc->pNexusData, pName, iLength, iType)); } @@ -858,7 +1330,7 @@ char *nxitrim(char *str) NXstatus NXgetattr (NXhandle fid, char *name, void *data, int* datalen, int* iType) { pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxgetattr(pFunc->pNexusData, name, data, datalen, iType); + return LOCKED_CALL(pFunc->nxgetattr(pFunc->pNexusData, name, data, datalen, iType)); } @@ -867,7 +1339,7 @@ char *nxitrim(char *str) NXstatus NXgetattrinfo (NXhandle fid, int *iN) { pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxgetattrinfo(pFunc->pNexusData, iN); + return LOCKED_CALL(pFunc->nxgetattrinfo(pFunc->pNexusData, iN)); } @@ -876,7 +1348,7 @@ char *nxitrim(char *str) NXstatus NXgetgroupID (NXhandle fileid, NXlink* sRes) { pNexusFunction pFunc = handleToNexusFunc(fileid); - return pFunc->nxgetgroupID(pFunc->pNexusData, sRes); + return LOCKED_CALL(pFunc->nxgetgroupID(pFunc->pNexusData, sRes)); } /*-------------------------------------------------------------------------*/ @@ -884,7 +1356,7 @@ char *nxitrim(char *str) NXstatus NXgetgroupinfo (NXhandle fid, int *iN, NXname pName, NXname pClass) { pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxgetgroupinfo(pFunc->pNexusData, iN, pName, pClass); + return LOCKED_CALL(pFunc->nxgetgroupinfo(pFunc->pNexusData, iN, pName, pClass)); } @@ -893,7 +1365,7 @@ char *nxitrim(char *str) NXstatus NXsameID (NXhandle fileid, NXlink* pFirstID, NXlink* pSecondID) { pNexusFunction pFunc = handleToNexusFunc(fileid); - return pFunc->nxsameID(pFunc->pNexusData, pFirstID, pSecondID); + return LOCKED_CALL(pFunc->nxsameID(pFunc->pNexusData, pFirstID, pSecondID)); } /*-------------------------------------------------------------------------*/ @@ -901,7 +1373,7 @@ char *nxitrim(char *str) NXstatus NXinitattrdir (NXhandle fid) { pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxinitattrdir(pFunc->pNexusData); + return LOCKED_CALL(pFunc->nxinitattrdir(pFunc->pNexusData)); } /*-------------------------------------------------------------------------*/ @@ -911,7 +1383,7 @@ char *nxitrim(char *str) pNexusFunction pFunc = handleToNexusFunc(fid); if(pFunc->nxsetnumberformat != NULL) { - return pFunc->nxsetnumberformat(pFunc->pNexusData,type,format); + return LOCKED_CALL(pFunc->nxsetnumberformat(pFunc->pNexusData,type,format)); } else { @@ -929,14 +1401,26 @@ char *nxitrim(char *str) NXstatus NXinitgroupdir (NXhandle fid) { pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxinitgroupdir(pFunc->pNexusData); + return LOCKED_CALL(pFunc->nxinitgroupdir(pFunc->pNexusData)); } /*----------------------------------------------------------------------*/ NXstatus NXinquirefile(NXhandle handle, char *filename, int filenameBufferLength){ pFileStack fileStack; char *pPtr = NULL; - int length; + int length, status; + + pNexusFunction pFunc = handleToNexusFunc(handle); + if (pFunc->nxnativeinquirefile != NULL) { + + status = LOCKED_CALL(pFunc->nxnativeinquirefile(pFunc->pNexusData, filename, filenameBufferLength)); + if (status < 0) { + return NX_ERROR; + } else { + return NX_OK; + } + + } fileStack = (pFileStack)handle; pPtr = peekFilenameOnStack(fileStack); @@ -953,26 +1437,32 @@ char *nxitrim(char *str) } } /*------------------------------------------------------------------------*/ -NXstatus NXisexternalgroup(NXhandle fid, CONSTCHAR *name, CONSTCHAR *class, +NXstatus NXisexternalgroup(NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass, char *url, int urlLen){ int status, attStatus, length = 1023, type = NX_CHAR; - ErrFunc oldError; char nxurl[1024]; pNexusFunction pFunc = handleToNexusFunc(fid); - status = pFunc->nxopengroup(pFunc->pNexusData, name,class); + if (pFunc->nxnativeisexternallink != NULL) { + status = LOCKED_CALL(pFunc->nxnativeisexternallink(pFunc->pNexusData, name, url, urlLen)); + if (status == NX_OK) { + return NX_OK; + } + // need to continue, could still be old style link + } + + status = LOCKED_CALL(pFunc->nxopengroup(pFunc->pNexusData, name, nxclass)); if(status != NX_OK){ return status; } - oldError = NXMGetError(); - NXIReportError = NXNXNoReport; + NXMDisableErrorReporting(); attStatus = NXgetattr(fid,"napimount",nxurl,&length, &type); - NXIReportError = oldError; - pFunc->nxclosegroup(pFunc->pNexusData); + NXMEnableErrorReporting(); + LOCKED_CALL(pFunc->nxclosegroup(pFunc->pNexusData)); if(attStatus == NX_OK){ length = strlen(nxurl); - if(length > urlLen){ + if(length >= urlLen){ length = urlLen - 1; } memset(url,0,urlLen); @@ -983,25 +1473,131 @@ NXstatus NXisexternalgroup(NXhandle fid, CONSTCHAR *name, CONSTCHAR *class, } } /*------------------------------------------------------------------------*/ -NXstatus NXlinkexternal(NXhandle fid, CONSTCHAR *name, CONSTCHAR *class, - CONSTCHAR *url){ - int status, type = NX_CHAR, length; +NXstatus NXisexternaldataset(NXhandle fid, CONSTCHAR *name, + char *url, int urlLen){ + int status, attStatus, length = 1023, type = NX_CHAR; + char nxurl[1024]; + pNexusFunction pFunc = handleToNexusFunc(fid); - status = pFunc->nxopengroup(pFunc->pNexusData,name,class); + if (pFunc->nxnativeisexternallink != NULL) { + status = LOCKED_CALL(pFunc->nxnativeisexternallink(pFunc->pNexusData, name, url, urlLen)); + if (status == NX_OK) { + return NX_OK; + } + // need to continue, could still be old style link + } + + status = LOCKED_CALL(pFunc->nxopendata(pFunc->pNexusData, name)); + if(status != NX_OK){ + return status; + } + NXMDisableErrorReporting(); + attStatus = NXgetattr(fid,"napimount",nxurl,&length, &type); + NXMEnableErrorReporting(); + LOCKED_CALL(pFunc->nxclosedata(pFunc->pNexusData)); + if(attStatus == NX_OK){ + length = strlen(nxurl); + if(length >= urlLen){ + length = urlLen - 1; + } + memset(url,0,urlLen); + memcpy(url,nxurl,length); + return attStatus; + } else { + return NX_ERROR; + } +} +/*------------------------------------------------------------------------*/ +NXstatus NXlinkexternal(NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass, CONSTCHAR *url) { + int status, type = NX_CHAR, length=1024, urllen; + char nxurl[1024], exfile[512], expath[512]; + pNexusFunction pFunc = handleToNexusFunc(fid); + + // in HDF5 we support external linking natively + if (pFunc->nxnativeexternallink != NULL) { + urllen = strlen(url); + memset(nxurl, 0, length); + if(urllen >= length){ + urllen = length - 1; + } + memcpy(nxurl, url, urllen); + status = analyzeNapimount(nxurl,exfile,511,expath,511); + if(status != NX_OK){ + return status; + } + status = LOCKED_CALL(pFunc->nxnativeexternallink(pFunc->pNexusData, name, exfile, expath)); + if(status != NX_OK){ + return status; + } + return NX_OK; + } + + NXMDisableErrorReporting(); + LOCKED_CALL(pFunc->nxmakegroup(pFunc->pNexusData,name,nxclass)); + NXMEnableErrorReporting(); + + status = LOCKED_CALL(pFunc->nxopengroup(pFunc->pNexusData,name,nxclass)); if(status != NX_OK){ return status; } length = strlen(url); - status = NXputattr(fid, "napimount",(void *)url,length, type); + status = NXputattr(fid, "napimount",url,length, type); if(status != NX_OK){ return status; } - pFunc->nxclosegroup(pFunc->pNexusData); + LOCKED_CALL(pFunc->nxclosegroup(pFunc->pNexusData)); + return NX_OK; +} +/*------------------------------------------------------------------------*/ +NXstatus NXlinkexternaldataset(NXhandle fid, CONSTCHAR *name, + CONSTCHAR *url){ + int status, type = NX_CHAR, length=1024, urllen; + char nxurl[1024], exfile[512], expath[512]; + pNexusFunction pFunc = handleToNexusFunc(fid); + int rank = 1; + int64_t dims[1] = {1}; + + //TODO cut and paste + + // in HDF5 we support external linking natively + if (pFunc->nxnativeexternallink != NULL) { + urllen = strlen(url); + memset(nxurl, 0, length); + if(urllen > length){ + urllen = length - 1; + } + memcpy(nxurl, url, urllen); + status = analyzeNapimount(nxurl,exfile,511,expath,511); + if(status != NX_OK){ + return status; + } + status = LOCKED_CALL(pFunc->nxnativeexternallink(pFunc->pNexusData, name, exfile, expath)); + if(status != NX_OK){ + return status; + } + return NX_OK; + } + + + status = LOCKED_CALL(pFunc->nxmakedata64(pFunc->pNexusData, name, NX_CHAR, rank, dims)); + if(status != NX_OK){ + return status; + } + status = LOCKED_CALL(pFunc->nxopendata(pFunc->pNexusData, name)); + if(status != NX_OK){ + return status; + } + length = strlen(url); + status = NXputattr(fid, "napimount",url,length, type); + if(status != NX_OK){ + return status; + } + LOCKED_CALL(pFunc->nxclosedata(pFunc->pNexusData)); return NX_OK; } /*------------------------------------------------------------------------ - Implementation of NXopenpath. + Implementation of NXopenpath --------------------------------------------------------------------------*/ static int isDataSetOpen(NXhandle hfil) { @@ -1124,7 +1720,6 @@ static NXstatus moveOneDown(NXhandle hfil) static char *moveDown(NXhandle hfil, char *path, int *code) { int status; - NXname pathElem; char *pPtr; *code = NX_OK; @@ -1153,7 +1748,7 @@ static char *moveDown(NXhandle hfil, char *path, int *code) /*--------------------------------------------------------------------*/ static NXstatus stepOneUp(NXhandle hfil, char *name) { - int status, datatype; + int datatype; NXname name2, xclass; char pBueffel[256]; @@ -1161,35 +1756,32 @@ static NXstatus stepOneUp(NXhandle hfil, char *name) catch the case when we are there: i.e. no further stepping necessary. This can happen with paths like ../ */ - if(strlen(name) < 1) - { + if (strlen(name) < 1) { return NX_OK; } NXinitgroupdir(hfil); - while(NXgetnextentry(hfil,name2,xclass,&datatype) != NX_EOD) + + while(NXgetnextentry(hfil, name2, xclass, &datatype) != NX_EOD) { - if(strcmp(name2,name) == 0) { if(strcmp(xclass,"SDS") == 0) { return NXopendata(hfil,name); - } - else - { + } else { return NXopengroup(hfil,name,xclass); } } } snprintf(pBueffel,255,"ERROR: NXopenpath cannot step into %s",name); - NXIReportError (NXpData, pBueffel); + NXReportError( pBueffel); return NX_ERROR; } /*--------------------------------------------------------------------*/ static NXstatus stepOneGroupUp(NXhandle hfil, char *name) { - int status, datatype; + int datatype; NXname name2, xclass; char pBueffel[256]; @@ -1208,8 +1800,7 @@ static NXstatus stepOneGroupUp(NXhandle hfil, char *name) if(strcmp(name2,name) == 0) { - if(strcmp(xclass,"SDS") == 0) - { + if(strcmp(xclass,"SDS") == 0) { return NX_EOD; } else @@ -1219,7 +1810,7 @@ static NXstatus stepOneGroupUp(NXhandle hfil, char *name) } } snprintf(pBueffel,255,"ERROR: NXopenpath cannot step into %s",name); - NXIReportError (NXpData, pBueffel); + NXReportError( pBueffel); return NX_ERROR; } /*---------------------------------------------------------------------*/ @@ -1231,7 +1822,7 @@ NXstatus NXopenpath(NXhandle hfil, CONSTCHAR *path) if(hfil == NULL || path == NULL) { - NXIReportError(NXpData, + NXReportError( "ERROR: NXopendata needs both a file handle and a path string"); return NX_ERROR; } @@ -1239,7 +1830,7 @@ NXstatus NXopenpath(NXhandle hfil, CONSTCHAR *path) pPtr = moveDown(hfil,(char *)path,&status); if(status != NX_OK) { - NXIReportError (NXpData, + NXReportError( "ERROR: NXopendata failed to move down in hierarchy"); return status; } @@ -1268,7 +1859,7 @@ NXstatus NXopengrouppath(NXhandle hfil, CONSTCHAR *path) if(hfil == NULL || path == NULL) { - NXIReportError(NXpData, + NXReportError( "ERROR: NXopendata needs both a file handle and a path string"); return NX_ERROR; } @@ -1276,7 +1867,7 @@ NXstatus NXopengrouppath(NXhandle hfil, CONSTCHAR *path) pPtr = moveDown(hfil,(char *)path,&status); if(status != NX_OK) { - NXIReportError (NXpData, + NXReportError( "ERROR: NXopendata failed to move down in hierarchy"); return status; } @@ -1296,18 +1887,29 @@ NXstatus NXopengrouppath(NXhandle hfil, CONSTCHAR *path) } return NX_OK; } - +/*---------------------------------------------------------------------*/ NXstatus NXIprintlink(NXhandle fid, NXlink* link) { pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxprintlink(pFunc->pNexusData, link); + return LOCKED_CALL(pFunc->nxprintlink(pFunc->pNexusData, link)); +} +/*----------------------------------------------------------------------*/ +NXstatus NXgetpath(NXhandle fid, char *path, int pathlen){ + int status; + pFileStack fileStack = NULL; + + fileStack = (pFileStack)fid; + status = buildPath(fileStack,path,pathlen); + if(status != 1){ + return NX_ERROR; + } + return NX_OK; } /*-------------------------------------------------------------------- format NeXus time. Code needed in every NeXus file driver ---------------------------------------------------------------------*/ char *NXIformatNeXusTime(){ - char *timeData; time_t timer; char* time_buffer = NULL; struct tm *time_info; @@ -1319,7 +1921,7 @@ char *NXIformatNeXusTime(){ time_buffer = (char *)malloc(64*sizeof(char)); if(!time_buffer){ - NXIReportError(NXpData,"Failed to allocate buffer for time data"); + NXReportError("Failed to allocate buffer for time data"); return NULL; } @@ -1342,7 +1944,7 @@ char *NXIformatNeXusTime(){ } else { - NXIReportError (NXpData, + NXReportError( "Your gmtime() function does not work ... timezone information will be incorrect\n"); gmt_offset = 0; } @@ -1352,11 +1954,11 @@ char *NXIformatNeXusTime(){ { if (gmt_offset < 0) { - time_format = "%04d-%02d-%02d %02d:%02d:%02d-%02d%02d"; + time_format = "%04d-%02d-%02dT%02d:%02d:%02d-%02d:%02d"; } else { - time_format = "%04d-%02d-%02d %02d:%02d:%02d+%02d%02d"; + time_format = "%04d-%02d-%02dT%02d:%02d:%02d+%02d:%02d"; } sprintf(time_buffer, time_format, 1900 + time_info->tm_year, @@ -1371,7 +1973,7 @@ char *NXIformatNeXusTime(){ } else { - strcpy(time_buffer, "1970-01-01 00:00:00+0000"); + strcpy(time_buffer, "1970-01-01T00:00:00+00:00"); } return time_buffer; } @@ -1385,18 +1987,18 @@ char *NXIformatNeXusTime(){ * instead, but that would mean writing far more wrappers */ NXstatus NXfopen(char * filename, NXaccess* am, - NexusFunction* pHandle) + NXhandle pHandle) { NXstatus ret; NXhandle fileid = NULL; ret = NXopen(filename, *am, &fileid); if (ret == NX_OK) { - memcpy(pHandle, fileid, sizeof(NexusFunction)); + memcpy(pHandle, fileid, getFileStackSize()); } else { - memset(pHandle, 0, sizeof(NexusFunction)); + memset(pHandle, 0, getFileStackSize()); } if (fileid != NULL) { @@ -1409,26 +2011,26 @@ char *NXIformatNeXusTime(){ * array holding the NexusFunction structure. We need to malloc() * a temporary copy as NXclose will try to free() this */ - NXstatus NXfclose (NexusFunction* pHandle) + NXstatus NXfclose (NXhandle pHandle) { NXhandle h; NXstatus ret; - h = (NXhandle)malloc(sizeof(NexusFunction)); - memcpy(h, pHandle, sizeof(NexusFunction)); + h = (NXhandle)malloc(getFileStackSize()); + memcpy(h, pHandle, getFileStackSize()); ret = NXclose(&h); /* does free(h) */ - memset(pHandle, 0, sizeof(NexusFunction)); + memset(pHandle, 0, getFileStackSize()); return ret; } /*---------------------------------------------------------------------*/ - NXstatus NXfflush(NexusFunction* pHandle) + NXstatus NXfflush(NXhandle pHandle) { NXhandle h; NXstatus ret; - h = (NXhandle)malloc(sizeof(NexusFunction)); - memcpy(h, pHandle, sizeof(NexusFunction)); + h = (NXhandle)malloc(getFileStackSize()); + memcpy(h, pHandle, getFileStackSize()); ret = NXflush(&h); /* modifies and reallocates h */ - memcpy(pHandle, h, sizeof(NexusFunction)); + memcpy(pHandle, h, getFileStackSize()); return ret; } /*----------------------------------------------------------------------*/ @@ -1444,7 +2046,7 @@ char *NXIformatNeXusTime(){ sprintf (buffer, "ERROR: Cannot allocate space for array rank of %d in NXfmakedata", *pRank); - NXIReportError (NXpData, buffer); + NXReportError( buffer); return NX_ERROR; } /* @@ -1459,7 +2061,7 @@ char *NXIformatNeXusTime(){ return ret; } - +/*-----------------------------------------------------------------------*/ NXstatus NXfcompmakedata(NXhandle fid, char *name, int *pDatatype, int *pRank, int dimensions[], @@ -1475,7 +2077,7 @@ char *NXIformatNeXusTime(){ sprintf (buffer, "ERROR: Cannot allocate space for array rank of %d in NXfcompmakedata", *pRank); - NXIReportError (NXpData, buffer); + NXReportError( buffer); return NX_ERROR; } /* @@ -1498,7 +2100,7 @@ char *NXIformatNeXusTime(){ return NXcompress(fid,*compr_type); } /*-----------------------------------------------------------------------*/ - NXstatus NXfputattr(NXhandle fid, char *name, void *data, + NXstatus NXfputattr(NXhandle fid, const char *name, const void *data, int *pDatalen, int *pIType) { return NXputattr(fid, name, data, *pDatalen, *pIType); @@ -1518,3 +2120,14 @@ char *NXIformatNeXusTime(){ return ret; } +/*--------------------------------------------------------------------------*/ +NXstatus NXfgetpath(NXhandle fid, char *path, int *pathlen) +{ + return NXgetpath(fid,path,*pathlen); +} + +const char* NXgetversion() +{ + return NEXUS_VERSION ; +} + diff --git a/napi.h b/napi.h index b2b18bb1..3118dcfa 100644 --- a/napi.h +++ b/napi.h @@ -3,7 +3,7 @@ Application Program Interface Header File - Copyright (C) 2000-2007 Mark Koennecke, Uwe Filges + Copyright (C) 2000-2011 Mark Koennecke, Uwe Filges This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -24,33 +24,46 @@ $Id$ ----------------------------------------------------------------------------*/ +/** \file + * Documentation for the NeXus-API version 4.3 + * 2000-2011, the NeXus International Advisory Commitee + * \defgroup c_main C API + * \defgroup c_types Data Types + * \ingroup c_main + * \defgroup c_init General Initialisation and shutdown + * \ingroup c_main + * \defgroup c_group Reading and Writing Groups + * \ingroup c_main + * \defgroup c_readwrite Reading and Writing Data + * \ingroup c_main + * \defgroup c_navigation General File navigation + * \ingroup c_main + * \defgroup c_metadata Meta data routines + * \ingroup c_main + * \defgroup c_linking Linking + * \ingroup c_main + * \defgroup c_memory Memory allocation + * \ingroup c_main + * \defgroup c_external External linking + * \ingroup c_main + */ #ifndef NEXUSAPI #define NEXUSAPI +#include + /* NeXus HDF45 */ -#define NEXUS_VERSION "4.1.0" /* major.minor.patch */ -#define H5Eset_auto_vers 1 -#define H5Dopen_vers 1 -#define H5Gopen_vers 1 -#define H5Acreate_vers 1 -#define H5Dcreate_vers 1 -#define H5Gcreate_vers 1 -#define H5Aiterate_vers 1 +#define NEXUS_VERSION "4.3.0" /* major.minor.patch */ #define CONSTCHAR const char -#ifdef _MSC_VER -#define snprintf nxisnprintf -extern int nxisnprintf(char* buffer, int len, const char* format, ... ); -#endif /* _MSC_VER */ - typedef void* NXhandle; /* really a pointer to a NexusFile structure */ typedef int NXstatus; typedef char NXname[128]; /* - * Any new NXaccess options should be numbered in 2^n format + * Any new NXaccess_mode options should be numbered in 2^n format * (8, 16, 32, etc) so that they can be bit masked and tested easily. * * To test older non bit masked options (values below 8) use e.g. @@ -64,8 +77,23 @@ typedef char NXname[128]; */ #define NXACCMASK_REMOVEFLAGS (0x7) /* bit mask to remove higher flag options */ +/** \enum NXaccess_mode + * NeXus file access codes. + * \li NXACC_READ read-only + * \li NXACC_RDWR open an existing file for reading and writing. + * \li NXACC_CREATE create a NeXus HDF-4 file + * \li NXACC_CREATE4 create a NeXus HDF-4 file + * \li NXACC_CREATE5 create a NeXus HDF-5 file. + * \li NXACC_CREATEXML create a NeXus XML file. + * \li NXACC_CHECKNAMESYNTAX Check names conform to NeXus allowed characters. + */ typedef enum {NXACC_READ=1, NXACC_RDWR=2, NXACC_CREATE=3, NXACC_CREATE4=4, - NXACC_CREATE5=5, NXACC_CREATEXML=6, NXACC_NOSTRIP=128} NXaccess; + NXACC_CREATE5=5, NXACC_CREATEXML=6, NXACC_TABLE=8, NXACC_NOSTRIP=128, NXACC_CHECKNAMESYNTAX=256 } NXaccess_mode; + +/** + * A combination of options from #NXaccess_mode + */ +typedef int NXaccess; typedef struct { char *iname; @@ -80,23 +108,33 @@ typedef struct { #define NX_MAXRANK 32 #define NX_MAXNAMELEN 64 +#define NX_MAXPATHLEN 1024 -/*------------------------------------------------------------------------- - HDF Datatype values for datatype parameters - in the Nexus API - NX_FLOAT32 32 bit float - NX_FLOAT64 64 nit float == double - NX_INT8 8 bit integer == byte - NX_UINT8 8 bit unsigned integer - NX_INT16 16 bit integer - NX_UINT16 16 bit unsigned integer - NX_INT32 32 bit integer - NX_UINT32 32 bit unsigned integer - NX_CHAR 8 bit character - NX_BINARY lump of binary data == NX_UINT8 - ---------------------------------------------------------------------------*/ +/** + * \ingroup c_types + * \def NX_FLOAT32 + * 32 bit float + * \def NX_FLOAT64 + * 64 bit float == double + * \def NX_INT8 + * 8 bit integer == byte + * \def NX_UINT8 + * 8 bit unsigned integer + * \def NX_INT16 + * 16 bit integer + * \def NX_UINT16 + * 16 bit unsigned integer + * \def NX_INT32 + * 32 bit integer + * \def NX_UINT32 + * 32 bit unsigned integer + * \def NX_CHAR + * 8 bit character + * \def NX_BINARY + * lump of binary data == NX_UINT8 +*/ +/*--------------------------------------------------------------------------*/ /* Map NeXus to HDF types */ #define NX_FLOAT32 5 @@ -114,11 +152,24 @@ typedef struct { #define NX_BINARY 21 /* Map NeXus compression methods to HDF compression methods */ +#define NX_CHUNK 0 #define NX_COMP_NONE 100 #define NX_COMP_LZW 200 #define NX_COMP_RLE 300 #define NX_COMP_HUF 400 +/* to test for these we use ((value / 100) == NX_COMP_LZW) */ +#define NX_COMP_LZW_LVL0 (100*NX_COMP_LZW + 0) +#define NX_COMP_LZW_LVL1 (100*NX_COMP_LZW + 1) +#define NX_COMP_LZW_LVL2 (100*NX_COMP_LZW + 2) +#define NX_COMP_LZW_LVL3 (100*NX_COMP_LZW + 3) +#define NX_COMP_LZW_LVL4 (100*NX_COMP_LZW + 4) +#define NX_COMP_LZW_LVL5 (100*NX_COMP_LZW + 5) +#define NX_COMP_LZW_LVL6 (100*NX_COMP_LZW + 6) +#define NX_COMP_LZW_LVL7 (100*NX_COMP_LZW + 7) +#define NX_COMP_LZW_LVL8 (100*NX_COMP_LZW + 8) +#define NX_COMP_LZW_LVL9 (100*NX_COMP_LZW + 9) + typedef struct { long iTag; /* HDF4 variable */ long iRef; /* HDF4 variable */ @@ -137,33 +188,43 @@ typedef struct { # endif # define NXopen MANGLE(nxiopen) +# define NXreopen MANGLE(nxireopen) # define NXclose MANGLE(nxiclose) # define NXmakegroup MANGLE(nximakegroup) # define NXopengroup MANGLE(nxiopengroup) # define NXopenpath MANGLE(nxiopenpath) +# define NXgetpath MANGLE(nxigetpath) # define NXopengrouppath MANGLE(nxiopengrouppath) # define NXclosegroup MANGLE(nxiclosegroup) # define NXmakedata MANGLE(nximakedata) +# define NXmakedata64 MANGLE(nximakedata64) # define NXcompmakedata MANGLE(nxicompmakedata) +# define NXcompmakedata64 MANGLE(nxicompmakedata64) # define NXcompress MANGLE(nxicompress) # define NXopendata MANGLE(nxiopendata) # define NXclosedata MANGLE(nxiclosedata) # define NXputdata MANGLE(nxiputdata) # define NXputslab MANGLE(nxiputslab) +# define NXputslab64 MANGLE(nxiputslab64) # define NXputattr MANGLE(nxiputattr) # define NXgetdataID MANGLE(nxigetdataid) # define NXmakelink MANGLE(nximakelink) # define NXmakenamedlink MANGLE(nximakenamedlink) # define NXopensourcegroup MANGLE(nxiopensourcegroup) # define NXmalloc MANGLE(nximalloc) +# define NXmalloc64 MANGLE(nximalloc64) # define NXfree MANGLE(nxifree) # define NXflush MANGLE(nxiflush) # define NXgetinfo MANGLE(nxigetinfo) +# define NXgetinfo64 MANGLE(nxigetinfo64) +# define NXgetrawinfo MANGLE(nxigetrawinfo) +# define NXgetrawinfo64 MANGLE(nxigetrawinfo64) # define NXgetnextentry MANGLE(nxigetnextentry) # define NXgetdata MANGLE(nxigetdata) # define NXgetslab MANGLE(nxigetslab) +# define NXgetslab64 MANGLE(nxigetslab64) # define NXgetnextattr MANGLE(nxigetnextattr) # define NXgetattr MANGLE(nxigetattr) # define NXgetattrinfo MANGLE(nxigetattrinfo) @@ -174,9 +235,12 @@ typedef struct { # define NXinitattrdir MANGLE(nxiinitattrdir) # define NXsetnumberformat MANGLE(nxisetnumberformat) # define NXsetcache MANGLE(nxisetcache) -# define NXinquirefile MANGLE(nxiinquirefile) +# define NXinquirefile MANGLE(nxiinquirefile) # define NXisexternalgroup MANGLE(nxiisexternalgroup) +# define NXisexternaldataset MANGLE(nxiisexternaldataset) # define NXlinkexternal MANGLE(nxilinkexternal) +# define NXlinkexternaldataset MANGLE(nxilinkexternaldataset) +# define NXgetversion MANGLE(nxigetversion) /* * FORTRAN helpers - for NeXus internal use only @@ -188,7 +252,7 @@ typedef struct { # define NXfcompmakedata MANGLE(nxifcompmakedata) # define NXfcompress MANGLE(nxifcompress) # define NXfputattr MANGLE(nxifputattr) - +# define NXfgetpath MANGLE(nxifgetpath) /* * Standard interface @@ -202,98 +266,646 @@ typedef struct { #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ + /** + * Open a NeXus file. + * NXopen honours full path file names. But it also searches + * for files in all the paths given in the NX_LOAD_PATH environment variable. + * NX_LOAD_PATH is supposed to hold a list of path string separated by the platform + * specific path separator. For unix this is the : , for DOS the ; . Please note + * that crashing on an open NeXus file will result in corrupted data. Only after a NXclose + * or a NXflush will the data file be valid. + * \param filename The name of the file to open + * \param access_method The file access method. This can be: + * \li NXACC__READ read access + * \li NXACC_RDWR read write access + * \li NXACC_CREATE, NXACC_CREATE4 create a new HDF-4 NeXus file + * \li NXACC_CREATE5 create a new HDF-5 NeXus file + * \li NXACC_CREATEXML create an XML NeXus file. + * see #NXaccess_mode + * Support for HDF-4 is deprecated. + * \param pHandle A file handle which will be initialized upon successfull completeion of NXopen. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_init + */ extern NXstatus NXopen(CONSTCHAR * filename, NXaccess access_method, NXhandle* pHandle); + + /** + * Opens an existing NeXus file a second time for e.g. access from another thread. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_init + */ +extern NXstatus NXreopen(NXhandle pOrigHandle, NXhandle* pNewHandle); + + /** + * close a NeXus file + * \param pHandle A NeXus file handle as returned from NXopen. pHandle is invalid after this + * call. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_init + */ extern NXstatus NXclose(NXhandle* pHandle); + + /** + * flush data to disk + * \param pHandle A NeXus file handle as initialized by NXopen. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_readwrite + */ extern NXstatus NXflush(NXhandle* pHandle); - + + /** + * NeXus groups are NeXus way of structuring information into a hierarchy. + * This function creates a group but does not open it. + * \param handle A NeXus file handle as initialized NXopen. + * \param name The name of the group + * \param NXclass the class name of the group. Should start with the prefix NX + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_group + */ extern NXstatus NXmakegroup (NXhandle handle, CONSTCHAR *name, CONSTCHAR* NXclass); + + /** + * Step into a group. All further access will be within the opened group. + * \param handle A NeXus file handle as initialized by NXopen. + * \param name The name of the group + * \param NXclass the class name of the group. Should start with the prefix NX + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_group + */ extern NXstatus NXopengroup (NXhandle handle, CONSTCHAR *name, CONSTCHAR* NXclass); + + /** + * Open the NeXus object with the path specified + * \param handle A NeXus file handle as returned from NXopen. + * \param path A unix like path string to a NeXus group or dataset. The path string + * is a list of group names and SDS names separated with / (slash). + * Example: /entry1/sample/name + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_navigation + */ extern NXstatus NXopenpath (NXhandle handle, CONSTCHAR *path); + + /** + * Opens the group in which the NeXus object with the specified path exists + * \param handle A NeXus file handle as initialized by NXopen. + * \param path A unix like path string to a NeXus group or dataset. The path string + * is a list of group names and SDS names separated with / (slash). + * Example: /entry1/sample/name + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_navigation + */ extern NXstatus NXopengrouppath (NXhandle handle, CONSTCHAR *path); + /** + * Retrieve the current path in the NeXus file + * \param handle a NeXus file handle + * \param path A buffer to copy the path too + * \param pathlen The maximum number of characters to copy into path + * \return NX_OK or NX_ERROR + * \ingroup c_navigation + */ +extern NXstatus NXgetpath(NXhandle handle, char *path, int pathlen); + + /** + * Closes the currently open group and steps one step down in the NeXus file + * hierarchy. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_group + */ extern NXstatus NXclosegroup(NXhandle handle); - + + /** + * Create a multi dimensional data array or dataset. The dataset is NOT opened. + * \param handle A NeXus file handle as initialized by NXopen. + * \param label The name of the dataset + * \param datatype The data type of this data set. + * \param rank The number of dimensions this dataset is going to have + * \param dim An array of size rank holding the size of the dataset in each dimension. The first dimension + * can be NX_UNLIMITED. Data can be appended to such a dimension using NXputslab. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_readwrite + */ extern NXstatus NXmakedata (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int dim[]); + + + /** + * @copydoc NXmakedata() + */ +extern NXstatus NXmakedata64 (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int64_t dim[]); + + +/** + * Create a compressed dataset. The dataset is NOT opened. Data from this set will automatically be compressed when + * writing and decompressed on reading. + * \param handle A NeXus file handle as initialized by NXopen. + * \param label The name of the dataset + * \param datatype The data type of this data set. + * \param rank The number of dimensions this dataset is going to have + * \param comp_typ The compression scheme to use. Possible values: + * \li NX_COMP_NONE no compression + * \li NX_COMP_LZW lossless Lempel Ziv Welch compression (recommended) + * \li NX_COMP_RLE run length encoding (only HDF-4) + * \li NX_COMP_HUF Huffmann encoding (only HDF-4) + * \param dim An array of size rank holding the size of the dataset in each dimension. The first dimension + * can be NX_UNLIMITED. Data can be appended to such a dimension using NXputslab. + * \param bufsize The dimensions of the subset of the data which usually be writen in one go. + * This is a parameter used by HDF for performance optimisations. If you write your data in one go, this + * should be the same as the data dimension. If you write it in slabs, this is your preferred slab size. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_readwrite + */ extern NXstatus NXcompmakedata (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int dim[], int comp_typ, int bufsize[]); + + +/** + * @copydoc NXcompmakedata() + */ +extern NXstatus NXcompmakedata64 (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int64_t dim[], int comp_typ, int64_t chunk_size[]); + + + /** + * Switch compression on. This routine is superseeded by NXcompmakedata and thus + * is deprecated. + * \param handle A NeXus file handle as initialized by NXopen. + * \param compr_type The compression scheme to use. Possible values: + * \li NX_COMP_NONE no compression + * \li NX_COMP_LZW lossless Lempel Ziv Welch compression (recommended) + * \li NX_COMP_RLE run length encoding (only HDF-4) + * \li NX_COMP_HUF Huffmann encoding (only HDF-4) + * \ingroup c_readwrite + */ extern NXstatus NXcompress (NXhandle handle, int compr_type); + + /** + * Open access to a dataset. After this call it is possible to write and read data or + * attributes to and from the dataset. + * \param handle A NeXus file handle as initialized by NXopen. + * \param label The name of the dataset + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_readwrite + */ extern NXstatus NXopendata (NXhandle handle, CONSTCHAR* label); + + /** + * Close access to a dataset. + * \param handle A NeXus file handle as initialized by NXopen. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_readwrite + */ extern NXstatus NXclosedata(NXhandle handle); -extern NXstatus NXputdata(NXhandle handle, void* data); -extern NXstatus NXputattr(NXhandle handle, CONSTCHAR* name, void* data, int iDataLen, int iType); -extern NXstatus NXputslab(NXhandle handle, void* data, int start[], int size[]); + /** + * Write data to a datset which has previouly been opened with NXopendata. + * This writes all the data in one go. Data should be a pointer to a memory + * area matching the datatype and dimensions of the dataset. + * \param handle A NeXus file handle as initialized by NXopen. + * \param data Pointer to data to write. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_readwrite + */ +extern NXstatus NXputdata(NXhandle handle, const void* data); + /** + * Write an attribute. The kind of attribute written depends on the + * poistion in the file: at root level, a global attribute is written, if + * agroup is open but no dataset, a group attribute is written, if a dataset is + * open, a dataset attribute is written. + * \param handle A NeXus file handle as initialized by NXopen. + * \param name The name of the attribute. + * \param data A pointer to the data to write for the attribute. + * \param iDataLen The length of the data in data in bytes. + * \param iType The NeXus data type of the attribute. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_readwrite + */ +extern NXstatus NXputattr(NXhandle handle, CONSTCHAR* name, const void* data, int iDataLen, int iType); + + /** + * Write a subset of a multi dimensional dataset. + * \param handle A NeXus file handle as initialized by NXopen. + * \param data A pointer to a memory area holding the data to write. + * \param start An array holding the start indices where to start the data subset. + * \param size An array holding the size of the data subset to write in each dimension. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_readwrite + */ +extern NXstatus NXputslab(NXhandle handle, const void* data, const int start[], const int size[]); + + /** + * @copydoc NXputdata() + */ +extern NXstatus NXputslab64(NXhandle handle, const void* data, const int64_t start[], const int64_t size[]); + + /** + * Retrieve link data for a dataset. This link data can later on be used to link this + * dataset into a different group. + * \param handle A NeXus file handle as initialized by NXopen. + * \param pLink A link data structure which will be initialized with the required information + * for linking. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_linking + */ extern NXstatus NXgetdataID(NXhandle handle, NXlink* pLink); + + /** + * Create a link to the group or dataset described by pLink in the currently open + * group. + * \param handle A NeXus file handle as initialized by NXopen. + * \param pLink A link data structure describing the object to link. This must have been initialized + * by either a call to NXgetdataID or NXgetgroupID. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_linking + */ extern NXstatus NXmakelink(NXhandle handle, NXlink* pLink); + + /** + * Create a link to the group or dataset described by pLink in the currently open + * group. But give the linked item a new name. + * \param handle A NeXus file handle as initialized by NXopen. + * \param newname The new name of the item in the currently open group. + * \param pLink A link data structure describing the object to link. This must have been initialized + * by either a call to NXgetdataID or NXgetgroupID. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_linking + */ extern NXstatus NXmakenamedlink(NXhandle handle, CONSTCHAR* newname, NXlink* pLink); + + /** + * Open the source group of a linked group or dataset. Returns an error when the item is + * not a linked item. + * \param handle A NeXus file handle as initialized by NXopen. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_navigation + */ extern NXstatus NXopensourcegroup(NXhandle handle); + /** + * Read a complete dataset from the currently open dataset into memory. + * \param handle A NeXus file handle as initialized by NXopen. + * \param data A pointer to the memory area where to read the data, too. Data must point to a memory + * area large enough to accomodate the data read. Otherwise your program may behave in unexpected + * and unwelcome ways. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_readwrite + */ extern NXstatus NXgetdata(NXhandle handle, void* data); + + /** + * Retrieve information about the curretly open dataset. + * \param handle A NeXus file handle as initialized by NXopen. + * \param rank A pointer to an integer which will be filled with the rank of + * the dataset. + * \param dimension An array which will be initialized with the size of the dataset in any of its + * dimensions. The array must have at least the size of rank. + * \param datatype A pointer to an integer which be set to the NeXus data type code for this dataset. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_metadata + */ extern NXstatus NXgetinfo(NXhandle handle, int* rank, int dimension[], int* datatype); + + /** + * @copydoc NXgetinfo() + */ +extern NXstatus NXgetinfo64(NXhandle handle, int* rank, int64_t dimension[], int* datatype); + + /** + * Get the next entry in the currently open group. This is for retrieving infromation about the + * content of a NeXus group. In order to search a group #NXgetnextentry is called in a loop until + * #NXgetnextentry returns NX_EOD which indicates that there are no further items in the group. + * Reset search using #NXinitgroupdir + * \param handle A NeXus file handle as initialized by NXopen. + * \param name The name of the object + * \param nxclass The NeXus class name for a group or the string SDS for a dataset. + * \param datatype The NeXus data type if the item is a SDS. + * \return NX_OK on success, NX_ERROR in the case of an error, NX_EOD when there are no more items. + * \ingroup c_navigation + */ extern NXstatus NXgetnextentry(NXhandle handle, NXname name, NXname nxclass, int* datatype); + /** + * Read a subset of data from file into memory. + * \param handle A NeXus file handle as initialized by NXopen. + * \param data A pointer to the memory data where to copy the data too. The pointer must point + * to a memory area large enough to accomodate the size of the data read. + * \param start An array holding the start indices where to start reading the data subset. + * \param size An array holding the size of the data subset to read for each dimension. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_readwrite + */ extern NXstatus NXgetslab(NXhandle handle, void* data, int start[], int size[]); + + + /** + * @copydoc NXgetslab() + */ +extern NXstatus NXgetslab64(NXhandle handle, void* data, const int64_t start[], const int64_t size[]); + +/** + * Iterate over global, group or dataset attributes depending on the currently open group or + * dataset. In order to search attributes multiple calls to #NXgetnextattr are performed in a loop + * until #NXgetnextattr returns NX_EOD which indicates that there are no further attributes. + * reset search using #NXinitattrdir + * \param handle A NeXus file handle as initialized by NXopen. + * \param pName The name of the attribute + * \param iLength A pointer to an integer which be set to the length of the attribute data. + * \param iType A pointer to an integer which be set to the NeXus data type of the attribute. + * \return NX_OK on success, NX_ERROR in the case of an error, NX_EOD when there are no more items. + * \ingroup c_readwrite + */ extern NXstatus NXgetnextattr(NXhandle handle, NXname pName, int *iLength, int *iType); + + /** + * Read an attribute. + * \param handle A NeXus file handle as initialized by NXopen. + * \param name The name of the atrribute to read. + * \param data A pointer to a memory area large enough to hold the attributes value. + * \param iDataLen The length of data in bytes. + * \param iType A pointer to an integer which will had been set to the NeXus data type of the attribute. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_readwrite + */ extern NXstatus NXgetattr(NXhandle handle, char* name, void* data, int* iDataLen, int* iType); + + /** + * Get the count of attributes in the currently open dataset, group or global attributes when at root level. + * \param handle A NeXus file handle as initialized by NXopen. + * \param no_items A pointer to an integer which be set to the number of attributes available. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_metadata + */ extern NXstatus NXgetattrinfo(NXhandle handle, int* no_items); + + /** + * Retrieve link data for the currently open group. This link data can later on be used to link this + * group into a different group. + * \param handle A NeXus file handle as initialized by NXopen. + * \param pLink A link data structure which will be initialized with the required information + * for linking. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_linking + */ extern NXstatus NXgetgroupID(NXhandle handle, NXlink* pLink); + + /** + * Retrieve information about the currently open group. + * \param handle A NeXus file handle as initialized by NXopen. + * \param no_items A pointer to an integer which will be set to the count + * of group elements available. This is the count of other groups and + * data sets in this group. + * \param name The name of the group. + * \param nxclass The NeXus class name of the group. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_metadata + */ extern NXstatus NXgetgroupinfo(NXhandle handle, int* no_items, NXname name, NXname nxclass); + + /** + * Tests if two link data structures describe the same item. + * \param handle A NeXus file handle as initialized by NXopen. + * \param pFirstID The first link data for the test. + * \param pSecondID The second link data structure. + * \return NX_OK when both link data structures describe the same item, NX_ERROR else. + * \ingroup c_linking + */ extern NXstatus NXsameID(NXhandle handle, NXlink* pFirstID, NXlink* pSecondID); + /** + * Resets a pending group search to the start again. To be called in a #NXgetnextentry loop when + * a group search has to be restarted. + * \param handle A NeXus file handle as initialized by NXopen. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_navigation + */ extern NXstatus NXinitgroupdir(NXhandle handle); + + /** + * Resets a pending attribute search to the start again. To be called in a #NXgetnextattr loop when + * an attribute search has to be restarted. + * \param handle A NeXus file handle as initialized by NXopen. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_navigation + */ extern NXstatus NXinitattrdir(NXhandle handle); -extern NXstatus NXsetnumberformat(NXhandle handle, - int type, char *format); + /** + * Sets the format for number printing. This call has only an effect when using the XML physical file + * format. + * \param handle A NeXus file handle as initialized by NXopen. + * \param type The NeXus data type to set the format for. + * \param format The C-language format string to use for this data type. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_readwrite + */ +extern NXstatus NXsetnumberformat(NXhandle handle, int type, char *format); + + /** + * Inquire the filename of the currently open file. FilenameBufferLength of the file name + * will be copied into the filename buffer. + * \param handle A NeXus file handle as initialized by NXopen. + * \param filename The buffer to hold the filename. + * \param filenameBufferLength The length of the filename buffer. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_metadata + */ extern NXstatus NXinquirefile(NXhandle handle, char *filename, int filenameBufferLength); -extern NXstatus NXisexternalgroup(NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass, char *url, int urlLen); -extern NXstatus NXlinkexternal(NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass, CONSTCHAR *url); + /** + * Test if a group is actually pointing to an external file. If so, retrieve the URL of the + * external file. + * \param handle A NeXus file handle as initialized by NXopen. + * \param name The name of the group to test. + * \param nxclass The class name of the group to test. + * \param url A buffer to copy the URL too. + * \param urlLen The length of the Url buffer. At maximum urlLen bytes will be copied to url. + * \return NX_OK when the group is pointing to an external file, NX_ERROR else. + * \ingroup c_external + */ +extern NXstatus NXisexternalgroup(NXhandle handle, CONSTCHAR *name, CONSTCHAR *nxclass, char *url, int urlLen); + + + /** + * Test if a dataset is actually pointing to an external file. If so, retrieve the URL of the + * external file. + * \param handle A NeXus file handle as initialized by NXopen. + * \param name The name of the dataset to test. + * \param url A buffer to copy the URL too. + * \param urlLen The length of the Url buffer. At maximum urlLen bytes will be copied to url. + * \return NX_OK when the dataset is pointing to an external file, NX_ERROR else. + * \ingroup c_external + */ +extern NXstatus NXisexternaldataset(NXhandle handle, CONSTCHAR *name, char *url, int urlLen); + + /** + * Create a link to a group in an external file. This works by creating a NeXus group under the current level in + * the hierarchy which actually points to a group in another file. + * \param handle A NeXus file handle as initialized by NXopen. + * \param name The name of the group which points to the external file. + * \param nxclass The class name of the group which points to the external file. + * \param url The URL of the external file. Currently only one URL format is supported: nxfile://path-tofile\#path-in-file. + * This consists of two parts: the first part is of course the path to the file. The second part, path-in-file, is the + * path to the group in the external file which appears in the first file. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_external + */ +extern NXstatus NXlinkexternal(NXhandle handle, CONSTCHAR *name, CONSTCHAR *nxclass, CONSTCHAR *url); + + + /** + * Create a link to a dataset in an external file. This works by creating a dataset under the current level in + * the hierarchy which actually points to a dataset in another file. + * \param handle A NeXus file handle as initialized by NXopen. + * \param name The name of the dataset which points to the external file. + * \param url The URL of the external file. Currently only one URL format is supported: nxfile://path-tofile\#path-in-file. + * This consists of two parts: the first part is of course the path to the file. The second part, path-in-file, is the + * path to the dataset in the external file which appears in the first file. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_external + */ +extern NXstatus NXlinkexternaldataset(NXhandle handle, CONSTCHAR *name, CONSTCHAR *url); + + /** + * Utility function which allocates a suitably sized memory area for the dataset characteristics specified. + * \param data A pointer to a pointer which will be initialized with a pointer to a suitably sized memory area. + * \param rank the rank of the data. + * \param dimensions An array holding the size of the data in each dimension. + * \param datatype The NeXus data type of the data. + * \return NX_OK when allocation succeeds, NX_ERROR in the case of an error. + * \ingroup c_memory + */ extern NXstatus NXmalloc(void** data, int rank, int dimensions[], int datatype); + + /** + * @copydoc NXmalloc() + */ +extern NXstatus NXmalloc64(void** data, int rank, int64_t dimensions[], int datatype); + + + /** + * Utility function to return NeXus version + * \return pointer to string in static storage. Version in + * same format as NEXUS_VERSION string in napi.h i.e. "major.minor.patch" + * \ingroup c_metadata + */ +extern const char* NXgetversion(); + + /** + * Utility function to release the memory for data. + * \param data A pointer to a pointer to free. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_memory + */ extern NXstatus NXfree(void** data); /*----------------------------------------------------------------------- NAPI internals ------------------------------------------------------------------------*/ + /** + * Retrieve information about the currently open dataset. In contrast to the main function below, + * this function does not try to find out about the size of strings properly. + * \param handle A NeXus file handle as initialized by NXopen. + * \param rank A pointer to an integer which will be filled with the rank of + * the dataset. + * \param dimension An array which will be initialized with the size of the dataset in any of its + * dimensions. The array must have at least the size of rank. + * \param datatype A pointer to an integer which be set to the NeXus data type code for this dataset. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_metadata + */ +extern NXstatus NXgetrawinfo(NXhandle handle, int* rank, int dimension[], int* datatype); + + /** + * @copydoc NXgetrawinfo + */ +extern NXstatus NXgetrawinfo64(NXhandle handle, int* rank, int64_t dimension[], int* datatype); + +/** \typedef void (*ErrFunc)(void *data, char *text) + * All NeXus error reporting happens through this special function, the + * ErrFunc. The NeXus-API allows to replace this error reporting function + * through a user defined implementation. The default error function prints to stderr. User + * defined ones may pop up dialog boxes or whatever. + * \param data A pointer to some user defined data structure + * \param text The text of the error message to display. + */ typedef void (*ErrFunc)(void *data, char *text); -extern void NXMSetError(void *pData, ErrFunc); + + /** + * Set a global error function. + * Not threadsafe. + * \param pData A pointer to a user defined data structure which be passed to + * the error display function. + * \param newErr The new error display function. + */ +extern void NXMSetError(void *pData, ErrFunc newErr); + + /** + * Set an error function for the current thread. + * When used this overrides anything set in NXMSetError (for the current thread). + * Use this method in threaded applications. + * \param pData A pointer to a user defined data structure which be passed to + * the error display function. + * \param newErr The new error display function. + */ +extern void NXMSetTError(void *pData, ErrFunc newErr); + + /** + * Retrieve the current error display function + * \return The current error display function. + */ extern ErrFunc NXMGetError(); + + /** + * Suppress error reports from the NeXus-API + */ extern void NXMDisableErrorReporting(); + + /** + * Enable error reports from the NeXus-API + */ extern void NXMEnableErrorReporting(); -extern void (*NXIReportError)(void *pData,char *text); -extern void *NXpData; + + /** + * Dispatches the error message to the error function defined by NXMSetTError + */ +extern void NXReportError(char *text); + + /** + * Do not use, first parameter should be set by NXMSetTError + */ +extern void NXIReportError(void *pData,char *text); +/* extern void *NXpData; */ extern char *NXIformatNeXusTime(); extern NXstatus NXIprintlink(NXhandle fid, NXlink* link); -/* - another special function for setting the default cache size for HDF-5 -*/ +/** + * A function for setting the default cache size for HDF-5 + * \ingroup c_init + */ extern NXstatus NXsetcache(long newVal); typedef struct { - NXhandle *pNexusData; - int stripFlag; + NXhandle pNexusData; + NXstatus ( *nxreopen)(NXhandle pOrigHandle, NXhandle* pNewHandle); NXstatus ( *nxclose)(NXhandle* pHandle); NXstatus ( *nxflush)(NXhandle* pHandle); NXstatus ( *nxmakegroup) (NXhandle handle, CONSTCHAR *name, CONSTCHAR* NXclass); NXstatus ( *nxopengroup) (NXhandle handle, CONSTCHAR *name, CONSTCHAR* NXclass); NXstatus ( *nxclosegroup)(NXhandle handle); - NXstatus ( *nxmakedata) (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int dim[]); - NXstatus ( *nxcompmakedata) (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int dim[], int comp_typ, int bufsize[]); + NXstatus ( *nxmakedata64) (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int64_t dim[]); + NXstatus ( *nxcompmakedata64) (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int64_t dim[], int comp_typ, int64_t bufsize[]); NXstatus ( *nxcompress) (NXhandle handle, int compr_type); NXstatus ( *nxopendata) (NXhandle handle, CONSTCHAR* label); NXstatus ( *nxclosedata)(NXhandle handle); - NXstatus ( *nxputdata)(NXhandle handle, void* data); - NXstatus ( *nxputattr)(NXhandle handle, CONSTCHAR* name, void* data, int iDataLen, int iType); - NXstatus ( *nxputslab)(NXhandle handle, void* data, int start[], int size[]); + NXstatus ( *nxputdata)(NXhandle handle, const void* data); + NXstatus ( *nxputattr)(NXhandle handle, CONSTCHAR* name, const void* data, int iDataLen, int iType); + NXstatus ( *nxputslab64)(NXhandle handle, const void* data, const int64_t start[], const int64_t size[]); NXstatus ( *nxgetdataID)(NXhandle handle, NXlink* pLink); NXstatus ( *nxmakelink)(NXhandle handle, NXlink* pLink); NXstatus ( *nxmakenamedlink)(NXhandle handle, CONSTCHAR *newname, NXlink* pLink); NXstatus ( *nxgetdata)(NXhandle handle, void* data); - NXstatus ( *nxgetinfo)(NXhandle handle, int* rank, int dimension[], int* datatype); + NXstatus ( *nxgetinfo64)(NXhandle handle, int* rank, int64_t dimension[], int* datatype); NXstatus ( *nxgetnextentry)(NXhandle handle, NXname name, NXname nxclass, int* datatype); - NXstatus ( *nxgetslab)(NXhandle handle, void* data, int start[], int size[]); + NXstatus ( *nxgetslab64)(NXhandle handle, void* data, const int64_t start[], const int64_t size[]); NXstatus ( *nxgetnextattr)(NXhandle handle, NXname pName, int *iLength, int *iType); NXstatus ( *nxgetattr)(NXhandle handle, char* name, void* data, int* iDataLen, int* iType); NXstatus ( *nxgetattrinfo)(NXhandle handle, int* no_items); @@ -304,6 +916,11 @@ extern NXstatus NXsetcache(long newVal); NXstatus ( *nxinitattrdir)(NXhandle handle); NXstatus ( *nxsetnumberformat)(NXhandle handle, int type, char *format); NXstatus ( *nxprintlink)(NXhandle handle, NXlink* link); + NXstatus ( *nxnativeexternallink)(NXhandle handle, CONSTCHAR* name, CONSTCHAR* externalfile, CONSTCHAR* remotetarget); + NXstatus ( *nxnativeinquirefile)(NXhandle handle, char* externalfile, const int filenamelength); + NXstatus ( *nxnativeisexternallink)(NXhandle handle, CONSTCHAR* name, char* url, int urllen); + int stripFlag; + int checkNameSyntax; } NexusFunction, *pNexusFunction; /*---------------------*/ extern long nx_cacheSize; @@ -311,9 +928,9 @@ extern NXstatus NXsetcache(long newVal); /* FORTRAN internals */ extern NXstatus NXfopen(char * filename, NXaccess* am, - NexusFunction* pHandle); - extern NXstatus NXfclose (NexusFunction* pHandle); - extern NXstatus NXfputattr(NXhandle fid, char *name, void *data, + NXhandle pHandle); + extern NXstatus NXfclose (NXhandle pHandle); + extern NXstatus NXfputattr(NXhandle fid, const char *name, const void *data, int *pDatalen, int *pIType); extern NXstatus NXfcompress(NXhandle fid, int *compr_type); extern NXstatus NXfcompmakedata(NXhandle fid, char *name, @@ -322,11 +939,21 @@ extern NXstatus NXsetcache(long newVal); int *compression_type, int chunk[]); extern NXstatus NXfmakedata(NXhandle fid, char *name, int *pDatatype, int *pRank, int dimensions[]); - extern NXstatus NXfflush(NexusFunction* pHandle); - + extern NXstatus NXfflush(NXhandle pHandle); + extern NXstatus NXfgetpath(NXhandle fid, char *path, int *pathlen); #ifdef __cplusplus } #endif /* __cplusplus */ -#endif /*NEXUSAPI*/ +/** + * Freddie Akeroyd 11/8/2009 + * Add NeXus schema support - this uses BASE.xsd as the initial file + */ +#define NEXUS_SCHEMA_VERSION "3.1" /**< version of NeXus definition schema */ +#define NEXUS_SCHEMA_ROOT "http://definition.nexusformat.org/schema/" /**< XML schema namespace specified by xmlns */ +#define NEXUS_SCHEMA_NAMESPACE NEXUS_SCHEMA_ROOT NEXUS_SCHEMA_VERSION /**< XML schema namespace specified by xmlns */ +#define NEXUS_SCHEMA_BASE "BASE" +#define NEXUS_SCHEMA_FILE NEXUS_SCHEMA_BASE ".xsd" /**< default schema file for namespace */ +#define NEXUS_SCHEMA_URL NEXUS_SCHEMA_NAMESPACE "/" NEXUS_SCHEMA_FILE /**< location of default schema file for namespace */ +#endif /*NEXUSAPI*/ diff --git a/napi4.c b/napi4.c index ff9f8b79..06924f7e 100644 --- a/napi4.c +++ b/napi4.c @@ -19,11 +19,14 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - For further information, see + For further information, see $Id$ ----------------------------------------------------------------------------*/ + +#ifdef HDF4 + #include #include #include @@ -52,8 +55,7 @@ extern void *NXpData; int iStackPtr; char iAccess[2]; } NexusFile, *pNexusFile; - - /*--------------------------------------------------------------------*/ + /*-------------------------------------------------------------------*/ static pNexusFile NXIassert(NXhandle fid) { @@ -107,7 +109,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) static int32 NXIFindVgroup (pNexusFile pFile, CONSTCHAR *name, CONSTCHAR *nxclass) { int32 iNew, iRef, iTag; - int iN, i, status; + int iN, i; int32 *pArray = NULL; NXname pText; @@ -121,7 +123,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) } pArray = (int32 *) malloc (iN * sizeof (int32)); if (!pArray) { - NXIReportError (NXpData, "ERROR: out of memory in NXIFindVgroup"); + NXReportError( "ERROR: out of memory in NXIFindVgroup"); return NX_EOD; } Vlone (pFile->iVID, pArray, iN); @@ -173,7 +175,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) int32 iNew, iRet, iTag, iRef; int32 i, iN, iA, iD1, iD2; NXname pNam; - int32 iDim[MAX_VAR_DIMS]; + int32 iDim[H4_MAX_VAR_DIMS]; self = NXIassert (fid); @@ -181,7 +183,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) if (self->iCurrentVG == 0) { i = SDfileinfo (self->iSID, &iN, &iA); if (i < 0) { - NXIReportError (NXpData, "ERROR: failure to read file information"); + NXReportError( "ERROR: failure to read file information"); return NX_EOD; } for (i = 0; i < iN; i++) { @@ -240,7 +242,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) self->iStack[iStackPtr].iRefDir = (int32 *) malloc (self->iStack[iStackPtr].iNDir * sizeof (int32) + 1); if (!self->iStack[iStackPtr].iRefDir) { - NXIReportError (NXpData, "ERROR: out of memory in NXIInitDir"); + NXReportError( "ERROR: out of memory in NXIInitDir"); return NX_EOD; } Vlone (self->iVID, @@ -255,7 +257,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) (int32 *) malloc (self->iStack[iStackPtr].iNDir * sizeof (int32) + 1); if ((!self->iStack[iStackPtr].iRefDir) || (!self->iStack[iStackPtr].iTagDir)) { - NXIReportError (NXpData, "ERROR: out of memory in NXIInitDir"); + NXReportError( "ERROR: out of memory in NXIInitDir"); return NX_EOD; } for (i = 0; i < self->iStack[self->iStackPtr].iNDir; i++) { @@ -291,7 +293,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) { int iRet; int32 iData, iAtt, iRank, iType; - int32 iDim[MAX_VAR_DIMS]; + int32 iDim[H4_MAX_VAR_DIMS]; NXname pNam; pFile->iAtt.iCurDir = 0; @@ -309,7 +311,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) } } if (iRet < 0) { - NXIReportError (NXpData, "ERROR: HDF cannot read attribute numbers"); + NXReportError( "ERROR: HDF cannot read attribute numbers"); pFile->iAtt.iNDir = 0; return NX_ERROR; } @@ -336,22 +338,36 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) static void NXIbuildPath(pNexusFile pFile, char *buffer, int bufLen) { int i; - int32 groupID, iA, iD1, iD2, iDim[MAX_VAR_DIMS]; + int32 groupID, iA, iD1, iD2, iDim[H4_MAX_VAR_DIMS]; NXname pText; buffer[0] = '\0'; - for(i = 0; i < pFile->iStackPtr; i++){ + for(i = 1; i <= pFile->iStackPtr; i++){ strncat(buffer,"/",bufLen-strlen(buffer)); - groupID = Vattach(pFile->iVID,pFile->iStack[pFile->iStackPtr].iVref, - "r"); - Vgetname(groupID, pText); - strncat(buffer,pText,bufLen-strlen(buffer)); - Vdetach(groupID); + groupID = Vattach(pFile->iVID,pFile->iStack[i].iVref, "r"); + if (groupID != -1) + { + if (Vgetname(groupID, pText) != -1) { + strncat(buffer,pText,bufLen-strlen(buffer)); + } else { + NXReportError( "ERROR: NXIbuildPath cannot get vgroup name"); + } + Vdetach(groupID); + } + else + { + NXReportError( "ERROR: NXIbuildPath cannot attach to vgroup"); + } } if(pFile->iCurrentSDS != 0){ - strncat(buffer,"/",bufLen-strlen(buffer)); - SDgetinfo(pFile->iCurrentSDS,pText,&iA,iDim,&iD1,&iD2); - strncat(buffer,pText,bufLen-strlen(buffer)); + if (SDgetinfo(pFile->iCurrentSDS,pText,&iA,iDim,&iD1,&iD2) != -1) { + strncat(buffer,"/",bufLen-strlen(buffer)); + strncat(buffer,pText,bufLen-strlen(buffer)); + } + else + { + NXReportError( "ERROR: NXIbuildPath cannot read SDS"); + } } } /* ---------------------------------------------------------------------- @@ -370,9 +386,11 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) char HDF_VERSION[64]; uint32 lmajor, lminor, lrelease; int32 am1=0; - int32 file_id=0, an_id=0, ann_id=0; *pHandle = NULL; + + /* mask off any options for now */ + am = (NXaccess)(am & NXACCMASK_REMOVEFLAGS); /* map Nexus NXaccess types to HDF4 types */ if (am == NXACC_CREATE) { am1 = DFACC_CREATE; @@ -386,7 +404,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) /* get memory */ pNew = (pNexusFile) malloc (sizeof (NexusFile)); if (!pNew) { - NXIReportError (NXpData, "ERROR: no memory to create File datastructure"); + NXReportError( "ERROR: no memory to create File datastructure"); return NX_ERROR; } memset (pNew, 0, sizeof (NexusFile)); @@ -399,7 +417,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) if (am == NXACC_CREATE || am == NXACC_CREATE4) { if ( (file_id = Hopen(filename, am1, 0)) == -1 ) { sprintf (pBuffer, "ERROR: cannot open file_a: %s", filename); - NXIReportError (NXpData, pBuffer); + NXReportError( pBuffer); free (pNew); return NX_ERROR; } @@ -410,7 +428,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) ANend(an_id); if (Hclose(file_id) == -1) { sprintf (pBuffer, "ERROR: cannot close file: %s", filename); - NXIReportError (NXpData, pBuffer); + NXReportError( pBuffer); free (pNew); return NX_ERROR; } @@ -422,7 +440,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) pNew->iSID = SDstart (filename, am1); if (pNew->iSID <= 0) { sprintf (pBuffer, "ERROR: cannot open file_b: %s", filename); - NXIReportError (NXpData, pBuffer); + NXReportError( pBuffer); free (pNew); return NX_ERROR; } @@ -432,12 +450,12 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) */ if (am != NXACC_READ) { if (SDsetattr(pNew->iSID, "NeXus_version", DFNT_CHAR8, strlen(NEXUS_VERSION), NEXUS_VERSION) < 0) { - NXIReportError (NXpData, "ERROR: HDF failed to store NeXus_version attribute "); + NXReportError( "ERROR: HDF failed to store NeXus_version attribute "); return NX_ERROR; } Hgetlibversion(&lmajor, &lminor, &lrelease, HDF_VERSION); if (SDsetattr(pNew->iSID, "HDF_version", DFNT_CHAR8, strlen(HDF_VERSION), HDF_VERSION) < 0) { - NXIReportError (NXpData, "ERROR: HDF failed to store HDF_version attribute "); + NXReportError( "ERROR: HDF failed to store HDF_version attribute "); return NX_ERROR; } } @@ -445,13 +463,13 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) time_puffer = NXIformatNeXusTime(); if (am == NXACC_CREATE || am == NXACC_CREATE4) { if (SDsetattr(pNew->iSID, "file_name", DFNT_CHAR8, strlen(filename), (char*)filename) < 0) { - NXIReportError (NXpData, "ERROR: HDF failed to store file_name attribute "); + NXReportError( "ERROR: HDF failed to store file_name attribute "); return NX_ERROR; } if(time_puffer != NULL){ if (SDsetattr(pNew->iSID, "file_time", DFNT_CHAR8, strlen(time_puffer), time_puffer) < 0) { - NXIReportError (NXpData, + NXReportError( "ERROR: HDF failed to store file_time attribute "); free(time_puffer); return NX_ERROR; @@ -483,7 +501,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) pNew->iVID = Hopen(filename, am1, 100); if (pNew->iVID <= 0) { sprintf (pBuffer, "ERROR: cannot open file_c: %s", filename); - NXIReportError (NXpData, pBuffer); + NXReportError( pBuffer); free (pNew); return NX_ERROR; } @@ -512,17 +530,17 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) iRet = SDendaccess (pFile->iCurrentSDS); } if (iRet < 0) { - NXIReportError (NXpData, "ERROR: ending access to SDS"); + NXReportError( "ERROR: ending access to SDS"); } /* close the SDS and Vgroup API's */ Vend (pFile->iVID); iRet = SDend (pFile->iSID); if (iRet < 0) { - NXIReportError (NXpData, "ERROR: HDF cannot close SDS interface"); + NXReportError( "ERROR: HDF cannot close SDS interface"); } iRet = Hclose (pFile->iVID); if (iRet < 0) { - NXIReportError (NXpData, "ERROR: HDF cannot close HDF file"); + NXReportError( "ERROR: HDF cannot close HDF file"); } /* release memory */ NXIKillDir (pFile); @@ -549,14 +567,14 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) if ((iRet = NXIFindVgroup (pFile, (char*)name, nxclass)) >= 0) { sprintf (pBuffer, "ERROR: Vgroup %s, class %s already exists", name, nxclass); - NXIReportError (NXpData, pBuffer); + NXReportError( pBuffer); return NX_ERROR; } /* create and configure the group */ iNew = Vattach (pFile->iVID, -1, "w"); if (iNew < 0) { - NXIReportError (NXpData, "ERROR: HDF could not create Vgroup"); + NXReportError( "ERROR: HDF could not create Vgroup"); return NX_ERROR; } Vsetname (iNew, name); @@ -569,7 +587,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) } Vdetach (iNew); if (iRet < 0) { - NXIReportError (NXpData, "ERROR: HDF failed to insert Vgroup"); + NXReportError( "ERROR: HDF failed to insert Vgroup"); return NX_ERROR; } return NX_OK; @@ -587,8 +605,8 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) iRef = NXIFindVgroup (pFile, (char*)name, nxclass); if (iRef < 0) { - sprintf (pBuffer, "ERROR: Vgroup %s, class %s NOT found", name, nxclass); - NXIReportError (NXpData, pBuffer); + sprintf (pBuffer, "ERROR: Vgroup \"%s\", class \"%s\" NOT found", name, nxclass); + NXReportError( pBuffer); return NX_ERROR; } /* are we at root level ? */ @@ -643,14 +661,14 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) /* --------------------------------------------------------------------- */ - NXstatus NX4makedata (NXhandle fid, CONSTCHAR *name, int datatype, int rank, - int dimensions[]) + NXstatus NX4makedata64 (NXhandle fid, CONSTCHAR *name, int datatype, int rank, + int64_t dimensions[]) { pNexusFile pFile; int32 iNew; char pBuffer[256]; int i, iRet, type; - int32 myDim[MAX_VAR_DIMS]; + int32 myDim[H4_MAX_VAR_DIMS]; pFile = NXIassert (fid); @@ -661,7 +679,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) if ((iNew = NXIFindSDS (fid, name))>=0) { sprintf (pBuffer, "ERROR: SDS %s already exists at this level", name); - NXIReportError (NXpData, pBuffer); + NXReportError( pBuffer); return NX_ERROR; } @@ -703,14 +721,14 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) } else { - NXIReportError (NXpData, "ERROR: invalid type in NX4makedata"); + NXReportError( "ERROR: invalid type in NX4makedata"); return NX_ERROR; } if (rank <= 0) { sprintf (pBuffer, "ERROR: invalid rank specified for SDS %s", name); - NXIReportError (NXpData, pBuffer); + NXReportError( pBuffer); return NX_ERROR; } @@ -721,9 +739,9 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) for (i = 1; i < rank; i++) { if (dimensions[i] <= 0) { sprintf (pBuffer, - "ERROR: invalid dimension %d, value %d given for SDS %s", - i, dimensions[i], name); - NXIReportError (NXpData, pBuffer); + "ERROR: invalid dimension %d, value %lld given for SDS %s", + i, (long long)dimensions[i], name); + NXReportError( pBuffer); return NX_ERROR; } } @@ -744,7 +762,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) /* Do not allow creation of SDS's at the root level */ if (pFile->iCurrentVG == 0) { sprintf(pBuffer, "ERROR: SDS creation at root level is not permitted"); - NXIReportError(NXpData, pBuffer); + NXReportError( pBuffer); return NX_ERROR; } @@ -754,7 +772,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) if (iNew < 0) { sprintf (pBuffer, "ERROR: cannot create SDS %s, check arguments", name); - NXIReportError (NXpData, pBuffer); + NXReportError( pBuffer); return NX_ERROR; } /* link into Vgroup, if in one */ @@ -763,7 +781,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) } iRet = SDendaccess (iNew); if (iRet < 0) { - NXIReportError (NXpData, "ERROR: HDF cannot end access to SDS"); + NXReportError( "ERROR: HDF cannot end access to SDS"); return NX_ERROR; } return NX_OK; @@ -773,14 +791,14 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) /* --------------------------------------------------------------------- */ - NXstatus NX4compmakedata (NXhandle fid, CONSTCHAR *name, int datatype, int rank, - int dimensions[],int compress_type, int chunk_size[]) + NXstatus NX4compmakedata64 (NXhandle fid, CONSTCHAR *name, int datatype, int rank, + int64_t dimensions[],int compress_type, int64_t chunk_size[]) { pNexusFile pFile; int32 iNew, iRet, type; char pBuffer[256]; - int i; - int32 myDim[MAX_VAR_DIMS]; + int i, compress_level; + int32 myDim[H4_MAX_VAR_DIMS]; comp_info compstruct; pFile = NXIassert (fid); @@ -792,7 +810,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) if ((iNew = NXIFindSDS (fid, name))>=0) { sprintf (pBuffer, "ERROR: SDS %s already exists at this level", name); - NXIReportError (NXpData, pBuffer); + NXReportError( pBuffer); return NX_ERROR; } @@ -834,14 +852,14 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) } else { - NXIReportError (NXpData, "ERROR: invalid datatype in NX4compmakedata"); + NXReportError( "ERROR: invalid datatype in NX4compmakedata"); return NX_ERROR; } if (rank <= 0) { sprintf (pBuffer, "ERROR: invalid rank specified for SDS %s", name); - NXIReportError (NXpData, pBuffer); + NXReportError( pBuffer); return NX_ERROR; } @@ -852,9 +870,9 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) for (i = 1; i < rank; i++) { if (dimensions[i] <= 0) { sprintf (pBuffer, - "ERROR: invalid dimension %d, value %d given for SDS %s", - i, dimensions[i], name); - NXIReportError (NXpData, pBuffer); + "ERROR: invalid dimension %d, value %lld given for SDS %s", + i, (long long)dimensions[i], name); + NXReportError( pBuffer); return NX_ERROR; } } @@ -875,7 +893,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) /* Do not allow creation of SDS's at the root level */ if (pFile->iCurrentVG == 0) { sprintf(pBuffer, "ERROR: SDS creation at root level is not permitted"); - NXIReportError(NXpData, pBuffer); + NXReportError( pBuffer); return NX_ERROR; } @@ -885,19 +903,25 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) if (iNew < 0) { sprintf (pBuffer, "ERROR: cannot create SDS %s, check arguments", name); - NXIReportError (NXpData, pBuffer); + NXReportError( pBuffer); return NX_ERROR; } /* compress SD data set */ + compress_level = 6; + if( (compress_type / 100) == NX_COMP_LZW ) + { + compress_level = compress_type % 100; + compress_type = NX_COMP_LZW; + } if(compress_type == NX_COMP_LZW) { - compstruct.deflate.level = 6; + compstruct.deflate.level = compress_level; iRet = SDsetcompress(iNew, COMP_CODE_DEFLATE, &compstruct); if (iRet < 0) { - NXIReportError (NXpData, "LZW-Compression failure!"); + NXReportError( "LZW-Compression failure!"); return NX_ERROR; } } @@ -906,7 +930,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) iRet = SDsetcompress(iNew, COMP_CODE_RLE, &compstruct); if (iRet < 0) { - NXIReportError (NXpData, "RLE-Compression failure!"); + NXReportError( "RLE-Compression failure!"); return NX_ERROR; } } @@ -916,7 +940,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) iRet = SDsetcompress(iNew, COMP_CODE_SKPHUFF, &compstruct); if (iRet < 0) { - NXIReportError (NXpData, "HUF-Compression failure!"); + NXReportError( "HUF-Compression failure!"); return NX_ERROR; } } @@ -926,7 +950,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) } else { - NXIReportError (NXpData, "Unknown compression method!"); + NXReportError( "Unknown compression method!"); return NX_ERROR; } /* link into Vgroup, if in one */ @@ -935,7 +959,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) } iRet = SDendaccess (iNew); if (iRet < 0) { - NXIReportError (NXpData, "ERROR: HDF cannot end access to SDS"); + NXReportError( "ERROR: HDF cannot end access to SDS"); return NX_ERROR; } @@ -949,17 +973,18 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) { pNexusFile pFile; int32 iRank, iAtt, iType, iRet; - int32 iSize[MAX_VAR_DIMS]; - int compress_typei = COMP_CODE_NONE; + int32 iSize[H4_MAX_VAR_DIMS]; + comp_coder_t compress_typei = COMP_CODE_NONE; NXname pBuffer; char pError[512]; comp_info compstruct; + int compress_level = 6; pFile = NXIassert (fid); /* check if there is an SDS open */ if (pFile->iCurrentSDS == 0) { - NXIReportError (NXpData, "ERROR: no SDS open"); + NXReportError( "ERROR: no SDS open"); return NX_ERROR; } @@ -971,6 +996,12 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) { compress_typei = COMP_CODE_DEFLATE; } + else if ( (compress_type / 100) == NX_COMP_LZW ) + { + compress_typei = COMP_CODE_DEFLATE; + compress_level = compress_type % 100; + compress_type = NX_COMP_LZW; + } else if (compress_type == NX_COMP_RLE) { compress_typei = COMP_CODE_RLE; @@ -990,7 +1021,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) */ if(compress_type == NX_COMP_LZW) { - compstruct.deflate.level = 6; + compstruct.deflate.level = compress_level; } else if(compress_type == NX_COMP_HUF) { @@ -1000,7 +1031,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) iRet = SDsetcompress(pFile->iCurrentSDS, compress_typei, &compstruct); if (iRet < 0) { sprintf (pError, "ERROR: failure to compress data to %s", pBuffer); - NXIReportError (NXpData, pError); + NXReportError( pError); return NX_ERROR; } return NX_OK; @@ -1021,8 +1052,8 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) /* First find the reference number of the SDS */ iNew = NXIFindSDS (fid, name); if (iNew < 0) { - sprintf (pBuffer, "ERROR: SDS %s not found at this level", name); - NXIReportError (NXpData, pBuffer); + sprintf (pBuffer, "ERROR: SDS \"%s\" not found at this level", name); + NXReportError( pBuffer); return NX_ERROR; } /* Be nice: properly close the old open SDS silently if there is @@ -1031,7 +1062,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) if (pFile->iCurrentSDS) { iRet = SDendaccess (pFile->iCurrentSDS); if (iRet < 0) { - NXIReportError (NXpData, "ERROR: HDF cannot end access to SDS"); + NXReportError( "ERROR: HDF cannot end access to SDS"); } } /* clear pending attribute directories first */ @@ -1050,7 +1081,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) } if (pFile->iCurrentSDS < 0) { - NXIReportError (NXpData, "ERROR: HDF error opening SDS"); + NXReportError( "ERROR: HDF error opening SDS"); pFile->iCurrentSDS = 0; return NX_ERROR; } @@ -1071,11 +1102,11 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) iRet = SDendaccess (pFile->iCurrentSDS); pFile->iCurrentSDS = 0; if (iRet < 0) { - NXIReportError (NXpData, "ERROR: HDF cannot end access to SDS"); + NXReportError( "ERROR: HDF cannot end access to SDS"); return NX_ERROR; } } else { - NXIReportError (NXpData, "ERROR: no SDS open --> nothing to do"); + NXReportError( "ERROR: no SDS open --> nothing to do"); return NX_ERROR; } NXIKillAttDir (pFile); /* for attribute data */ @@ -1085,10 +1116,10 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) /* ------------------------------------------------------------------- */ - NXstatus NX4putdata (NXhandle fid, void *data) + NXstatus NX4putdata (NXhandle fid, const void *data) { pNexusFile pFile; - int32 iStart[MAX_VAR_DIMS], iSize[MAX_VAR_DIMS], iStride[MAX_VAR_DIMS]; + int32 iStart[H4_MAX_VAR_DIMS], iSize[H4_MAX_VAR_DIMS], iStride[H4_MAX_VAR_DIMS]; NXname pBuffer; int32 iRank, iAtt, iType, iRet, i; char pError[512]; @@ -1097,11 +1128,11 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) /* check if there is an SDS open */ if (pFile->iCurrentSDS == 0) { - NXIReportError (NXpData, "ERROR: no SDS open"); + NXReportError( "ERROR: no SDS open"); return NX_ERROR; } /* first read dimension information */ - memset (iStart, 0, MAX_VAR_DIMS * sizeof (int32)); + memset (iStart, 0, H4_MAX_VAR_DIMS * sizeof (int32)); SDgetinfo (pFile->iCurrentSDS, pBuffer, &iRank, iSize, &iType, &iAtt); /* initialise stride to 1 */ @@ -1110,10 +1141,11 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) } /* actually write */ - iRet = SDwritedata (pFile->iCurrentSDS, iStart, iStride, iSize, data); + iRet = SDwritedata (pFile->iCurrentSDS, iStart, iStride, iSize, (void*)data); if (iRet < 0) { + /* HEprint(stdout,0); */ sprintf (pError, "ERROR: failure to write data to %s", pBuffer); - NXIReportError (NXpData, pError); + NXReportError( pError); return NX_ERROR; } return NX_OK; @@ -1122,7 +1154,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) /* ------------------------------------------------------------------- */ NXstatus - NX4putattr (NXhandle fid, CONSTCHAR *name, void *data, int datalen, int iType) + NX4putattr (NXhandle fid, CONSTCHAR *name, const void *data, int datalen, int iType) { pNexusFile pFile; int iRet, type; @@ -1166,7 +1198,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) } else { - NXIReportError (NXpData, "ERROR: Invalid data type for HDF attribute"); + NXReportError( "ERROR: Invalid data type for HDF attribute"); return NX_ERROR; } if (pFile->iCurrentSDS != 0) { @@ -1186,7 +1218,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) } iType = type; if (iRet < 0) { - NXIReportError (NXpData, "ERROR: HDF failed to store attribute "); + NXReportError( "ERROR: HDF failed to store attribute "); return NX_ERROR; } return NX_OK; @@ -1195,12 +1227,12 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) /* ------------------------------------------------------------------- */ - NXstatus NX4putslab (NXhandle fid, void *data, int iStart[], int iSize[]) + NXstatus NX4putslab64 (NXhandle fid, const void *data, const int64_t iStart[], const int64_t iSize[]) { pNexusFile pFile; int iRet; - int32 iStride[MAX_VAR_DIMS]; - int32 myStart[MAX_VAR_DIMS], mySize[MAX_VAR_DIMS]; + int32 iStride[H4_MAX_VAR_DIMS]; + int32 myStart[H4_MAX_VAR_DIMS], mySize[H4_MAX_VAR_DIMS]; int32 i, iRank, iType, iAtt; NXname pBuffer; @@ -1209,19 +1241,14 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) /* check if there is an SDS open */ if (pFile->iCurrentSDS == 0) { - NXIReportError (NXpData, "ERROR: no SDS open"); + NXReportError( "ERROR: no SDS open"); return NX_ERROR; } /* initialise stride to 1 */ - for (i = 0; i < MAX_VAR_DIMS; i++) { + for (i = 0; i < H4_MAX_VAR_DIMS; i++) { iStride[i] = 1; } - /* if an int is not 32-bit we have to cast them properly in order - to kill a bug. - */ - if(sizeof(int) != 4) - { SDgetinfo (pFile->iCurrentSDS, pBuffer, &iRank, myStart, &iType, &iAtt); for(i = 0; i < iRank; i++) @@ -1231,19 +1258,12 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) } /* finally write */ iRet = SDwritedata (pFile->iCurrentSDS, myStart, - iStride, mySize, data); + iStride, mySize, (void*)data); - } - else - { - /* write directly */ - - iRet = SDwritedata (pFile->iCurrentSDS,(int32*)iStart, iStride, (int32*)iSize, data); - } /* deal with HDF errors */ if (iRet < 0) { - NXIReportError (NXpData, "ERROR: writing slab failed"); + NXReportError( "ERROR: writing slab failed"); return NX_ERROR; } return NX_OK; @@ -1255,7 +1275,8 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) NXstatus NX4getdataID (NXhandle fid, NXlink* sRes) { pNexusFile pFile; - + int datalen, type = NX_CHAR; + pFile = NXIassert (fid); if (pFile->iCurrentSDS == 0) { @@ -1264,7 +1285,14 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) } else { sRes->iTag = DFTAG_NDG; sRes->iRef = SDidtoref (pFile->iCurrentSDS); - NXIbuildPath(pFile,sRes->targetPath,1024); + NXMDisableErrorReporting(); + datalen = 1024; + memset(&sRes->targetPath,0,1024); + if(NX4getattr(fid,"target",&sRes->targetPath,&datalen,&type) != NX_OK) + { + NXIbuildPath(pFile,sRes->targetPath,1024); + } + NXMEnableErrorReporting(); return NX_OK; } sRes->iTag = NX_ERROR; @@ -1278,7 +1306,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) NXstatus NX4makelink (NXhandle fid, NXlink* sLink) { pNexusFile pFile; - int32 iVG, iRet, dataID, type = DFNT_CHAR8, length; + int32 dataID, type = DFNT_CHAR8, length; char name[] = "target"; pFile = NXIassert (fid); @@ -1310,9 +1338,9 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) NXstatus NX4makenamedlink (NXhandle fid, CONSTCHAR* newname, NXlink* sLink) { pNexusFile pFile; - int32 iVG, iRet, dataID, type = DFNT_CHAR8, length, dataType = NX_CHAR, + int32 dataID, type = DFNT_CHAR8, length, dataType = NX_CHAR, rank = 1, attType = NX_INT32; - int iDim[1]; + int64_t iDim[1]; char name[] = "target"; int tags[2]; @@ -1330,7 +1358,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) sLink->iTag == DFTAG_SDS) { iDim[0] = 1; - NX4makedata(fid,newname, dataType,rank,iDim); + NX4makedata64(fid,newname, dataType,rank,iDim); NX4opendata(fid,newname); NX4putattr(fid,"NAPIlink",tags, 2, attType); NX4closedata(fid); @@ -1354,8 +1382,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) NXstatus NX4printlink (NXhandle fid, NXlink* sLink) { - pNexusFile pFile; - pFile = NXIassert (fid); + NXIassert (fid); printf("HDF4 link: iTag = %ld, iRef = %ld, target=\"%s\"\n", sLink->iTag, sLink->iRef, sLink->targetPath); return NX_OK; } @@ -1383,7 +1410,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) */ iRet = Hfidinquire(pFile->iVID,&pFileName,&access,&dummy); if (iRet < 0) { - NXIReportError (NXpData, + NXReportError( "ERROR: Failed to inquire file name for HDF file"); return NX_ERROR; } @@ -1392,13 +1419,13 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) }else if(pFile->iAccess[0] == 'w') { ac = NXACC_RDWR; } else { - NXIReportError (NXpData, + NXReportError( "ERROR: NX4flush failed to determine file access mode"); return NX_ERROR; } pCopy = (char *)malloc((strlen(pFileName)+10)*sizeof(char)); if(!pCopy) { - NXIReportError (NXpData, + NXReportError( "ERROR: Failed to allocate data for filename copy"); return NX_ERROR; } @@ -1411,7 +1438,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) iStack = pFile->iStackPtr + 1; iRefs = (int *)malloc(iStack*sizeof(int)); if(!iRefs){ - NXIReportError (NXpData, + NXReportError( "ERROR: Failed to allocate data for hierarchy copy"); return NX_ERROR; } @@ -1452,7 +1479,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) pNexusFile pFile; int iRet, iStackPtr, iCurDir; int32 iTemp, iD1, iD2, iA; - int32 iDim[MAX_VAR_DIMS]; + int32 iDim[H4_MAX_VAR_DIMS]; pFile = NXIassert (fid); @@ -1463,7 +1490,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) if (pFile->iStack[pFile->iStackPtr].iRefDir == NULL) { iRet = NXIInitDir (pFile); if (iRet < 0) { - NXIReportError (NXpData, + NXReportError( "ERROR: no memory to store directory info"); return NX_EOD; } @@ -1480,7 +1507,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) iTemp = Vattach (pFile->iVID, pFile->iStack[iStackPtr].iRefDir[iCurDir], "r"); if (iTemp < 0) { - NXIReportError (NXpData, "ERROR: HDF cannot attach to Vgroup"); + NXReportError( "ERROR: HDF cannot attach to Vgroup"); return NX_ERROR; } Vgetname (iTemp, name); @@ -1494,7 +1521,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) iTemp = Vattach (pFile->iVID, pFile->iStack[iStackPtr].iRefDir[iCurDir], "r"); if (iTemp < 0) { - NXIReportError (NXpData, "ERROR: HDF cannot attach to Vgroup"); + NXReportError( "ERROR: HDF cannot attach to Vgroup"); return NX_ERROR; } Vgetname (iTemp, name); @@ -1535,7 +1562,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) NXstatus NX4getdata (NXhandle fid, void *data) { pNexusFile pFile; - int32 iStart[MAX_VAR_DIMS], iSize[MAX_VAR_DIMS]; + int32 iStart[H4_MAX_VAR_DIMS], iSize[H4_MAX_VAR_DIMS]; NXname pBuffer; int32 iRank, iAtt, iType; @@ -1543,11 +1570,11 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) /* check if there is an SDS open */ if (pFile->iCurrentSDS == 0) { - NXIReportError (NXpData, "ERROR: no SDS open"); + NXReportError( "ERROR: no SDS open"); return NX_ERROR; } /* first read dimension information */ - memset (iStart, 0, MAX_VAR_DIMS * sizeof (int32)); + memset (iStart, 0, H4_MAX_VAR_DIMS * sizeof (int32)); SDgetinfo (pFile->iCurrentSDS, pBuffer, &iRank, iSize, &iType, &iAtt); /* actually read */ SDreaddata (pFile->iCurrentSDS, iStart, NULL, iSize, data); @@ -1557,18 +1584,18 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) /*-------------------------------------------------------------------------*/ NXstatus - NX4getinfo (NXhandle fid, int *rank, int dimension[], + NX4getinfo64 (NXhandle fid, int *rank, int64_t dimension[], int *iType) { pNexusFile pFile; NXname pBuffer; - int32 iAtt, myDim[MAX_VAR_DIMS], i, iRank, mType; + int32 iAtt, myDim[H4_MAX_VAR_DIMS], i, iRank, mType; pFile = NXIassert (fid); /* check if there is an SDS open */ if (pFile->iCurrentSDS == 0) { - NXIReportError (NXpData, "ERROR: no SDS open"); + NXReportError( "ERROR: no SDS open"); return NX_ERROR; } /* read information */ @@ -1589,10 +1616,10 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) /*-------------------------------------------------------------------------*/ - NXstatus NX4getslab (NXhandle fid, void *data, int iStart[], int iSize[]) + NXstatus NX4getslab64 (NXhandle fid, void *data, const int64_t iStart[], const int64_t iSize[]) { pNexusFile pFile; - int32 myStart[MAX_VAR_DIMS], mySize[MAX_VAR_DIMS]; + int32 myStart[H4_MAX_VAR_DIMS], mySize[H4_MAX_VAR_DIMS]; int32 i, iRank, iType, iAtt; NXname pBuffer; @@ -1600,15 +1627,10 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) /* check if there is an SDS open */ if (pFile->iCurrentSDS == 0) { - NXIReportError (NXpData, "ERROR: no SDS open"); + NXReportError( "ERROR: no SDS open"); return NX_ERROR; } - /* if an int is not 32-bit we have to cast them properly in order - to kill a bug. - */ - if(sizeof(int) != 4) - { SDgetinfo (pFile->iCurrentSDS, pBuffer, &iRank, myStart, &iType, &iAtt); for(i = 0; i < iRank; i++) @@ -1620,14 +1642,6 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) SDreaddata (pFile->iCurrentSDS, myStart, NULL, mySize, data); return NX_OK; - } - else - { - /* read directly */ - SDreaddata (pFile->iCurrentSDS, (int32*)iStart, NULL, - (int32*)iSize, data); - return NX_OK; - } } /*-------------------------------------------------------------------------*/ @@ -1669,7 +1683,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) pName, &iPType, &iCount); } if (iRet < 0) { - NXIReportError (NXpData, "ERROR: HDF cannot read attribute info"); + NXReportError( "ERROR: HDF cannot read attribute info"); return NX_ERROR; } *iLength = iCount; @@ -1746,8 +1760,8 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) } } if (iNew < 0) { - sprintf (pBuffer, "ERROR: attribute %s not found", name); - NXIReportError (NXpData, pBuffer); + sprintf (pBuffer, "ERROR: attribute \"%s\" not found", name); + NXReportError( pBuffer); return NX_ERROR; } /* get more info, allocate temporary data space */ @@ -1764,14 +1778,17 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) } if (iRet < 0) { sprintf (pBuffer, "ERROR: HDF could not read attribute info"); - NXIReportError (NXpData, pBuffer); + NXReportError( pBuffer); return NX_ERROR; } *iType = (int)iType32; iLen = iLen * DFKNTsize (*iType); + if(*iType == NX_CHAR){ + iLen += 1; + } pData = (void *) malloc (iLen); if (!pData) { - NXIReportError (NXpData, "ERROR: allocating memory in NXgetattr"); + NXReportError( "ERROR: allocating memory in NXgetattr"); return NX_ERROR; } memset (pData, 0, iLen); @@ -1788,14 +1805,14 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) } if (iRet < 0) { sprintf (pBuffer, "ERROR: HDF could not read attribute data"); - NXIReportError (NXpData, pBuffer); + NXReportError( pBuffer); return NX_ERROR; } /* copy data to caller */ memset (data, 0, *datalen); if ((*datalen <= iLen) && (*iType == DFNT_UINT8 || *iType == DFNT_CHAR8 || *iType == DFNT_UCHAR8)) { - iLen = *datalen - 1; + iLen = *datalen - 1; /* this enforces NULL termination regardless of size of datalen */ } memcpy (data, pData, iLen); *datalen = iLen / DFKNTsize(*iType); @@ -1811,7 +1828,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) pNexusFile pFile; int iRet; int32 iData, iAtt, iRank, iType; - int32 iDim[MAX_VAR_DIMS]; + int32 iDim[H4_MAX_VAR_DIMS]; NXname pNam; pFile = NXIassert (fid); @@ -1828,7 +1845,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) } } if (iRet < 0) { - NXIReportError (NXpData, "NX_ERROR: HDF cannot read attribute numbers"); + NXReportError( "NX_ERROR: HDF cannot read attribute numbers"); *iN = 0; return NX_ERROR; } @@ -1884,9 +1901,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) NXstatus NX4sameID (NXhandle fileid, NXlink* pFirstID, NXlink* pSecondID) { - pNexusFile pFile; - - pFile = NXIassert (fileid); + NXIassert (fileid); if ((pFirstID->iTag == pSecondID->iTag) & (pFirstID->iRef == pSecondID->iRef)) { return NX_OK; } else { @@ -1903,7 +1918,7 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) int iRet; pFile = NXIassert (fid); - NXIKillAttDir (fid); + NXIKillAttDir (pFile); iRet = NXIInitAttDir (pFile); if (iRet == NX_ERROR) return NX_ERROR; @@ -1920,10 +1935,10 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) int iRet; pFile = NXIassert (fid); - NXIKillDir (fid); + NXIKillDir (pFile); iRet = NXIInitDir (pFile); if (iRet < 0) { - NXIReportError (NXpData,"NX_ERROR: no memory to store directory info"); + NXReportError("NX_ERROR: no memory to store directory info"); return NX_EOD; } return NX_OK; @@ -1933,25 +1948,26 @@ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) void NX4assignFunctions(pNexusFunction fHandle) { fHandle->nxclose=NX4close; + fHandle->nxreopen=NULL; fHandle->nxflush=NX4flush; fHandle->nxmakegroup=NX4makegroup; fHandle->nxopengroup=NX4opengroup; fHandle->nxclosegroup=NX4closegroup; - fHandle->nxmakedata=NX4makedata; - fHandle->nxcompmakedata=NX4compmakedata; + fHandle->nxmakedata64=NX4makedata64; + fHandle->nxcompmakedata64=NX4compmakedata64; fHandle->nxcompress=NX4compress; fHandle->nxopendata=NX4opendata; fHandle->nxclosedata=NX4closedata; fHandle->nxputdata=NX4putdata; fHandle->nxputattr=NX4putattr; - fHandle->nxputslab=NX4putslab; + fHandle->nxputslab64=NX4putslab64; fHandle->nxgetdataID=NX4getdataID; fHandle->nxmakelink=NX4makelink; fHandle->nxmakenamedlink=NX4makenamedlink; fHandle->nxgetdata=NX4getdata; - fHandle->nxgetinfo=NX4getinfo; + fHandle->nxgetinfo64=NX4getinfo64; fHandle->nxgetnextentry=NX4getnextentry; - fHandle->nxgetslab=NX4getslab; + fHandle->nxgetslab64=NX4getslab64; fHandle->nxgetnextattr=NX4getnextattr; fHandle->nxgetattr=NX4getattr; fHandle->nxgetattrinfo=NX4getattrinfo; @@ -1961,4 +1977,7 @@ void NX4assignFunctions(pNexusFunction fHandle) fHandle->nxinitgroupdir=NX4initgroupdir; fHandle->nxinitattrdir=NX4initattrdir; fHandle->nxprintlink=NX4printlink; + fHandle->nxnativeexternallink=NULL; } + +#endif /*HDF4*/ diff --git a/napi4.h b/napi4.h index f07cce9a..af354a57 100644 --- a/napi4.h +++ b/napi4.h @@ -1,3 +1,6 @@ +#ifndef NAPI4_H +#define NAPI4_H + #define NXSIGNATURE 959697 #include "mfhdf.h" @@ -15,22 +18,22 @@ extern NXstatus NX4makegroup (NXhandle handle, CONSTCHAR* Vgroup, CONSTCHAR* N extern NXstatus NX4opengroup (NXhandle handle, CONSTCHAR* Vgroup, CONSTCHAR* NXclass); extern NXstatus NX4closegroup(NXhandle handle); -extern NXstatus NX4makedata (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int dim[]); -extern NXstatus NX4compmakedata (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int dim[], int comp_typ, int bufsize[]); +extern NXstatus NX4makedata64 (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int64_t dim[]); +extern NXstatus NX4compmakedata64 (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int64_t dim[], int comp_typ, int64_t bufsize[]); extern NXstatus NX4compress (NXhandle handle, int compr_type); extern NXstatus NX4opendata (NXhandle handle, CONSTCHAR* label); extern NXstatus NX4closedata(NXhandle handle); extern NXstatus NX4getdata(NXhandle handle, void* data); -extern NXstatus NX4getslab(NXhandle handle, void* data, int start[], int size[]); +extern NXstatus NX4getslab64(NXhandle handle, void* data, const int64_t start[], const int64_t size[]); extern NXstatus NX4getattr(NXhandle handle, char* name, void* data, int* iDataLen, int* iType); -extern NXstatus NX4putdata(NXhandle handle, void* data); -extern NXstatus NX4putslab(NXhandle handle, void* data, int start[], int size[]); -extern NXstatus NX4putattr(NXhandle handle, CONSTCHAR* name, void* data, int iDataLen, int iType); +extern NXstatus NX4putdata(NXhandle handle, const void* data); +extern NXstatus NX4putslab64(NXhandle handle, const void* data, const int64_t start[], const int64_t size[]); +extern NXstatus NX4putattr(NXhandle handle, CONSTCHAR* name, const void* data, int iDataLen, int iType); -extern NXstatus NX4getinfo(NXhandle handle, int* rank, int dimension[], int* datatype); +extern NXstatus NX4getinfo64(NXhandle handle, int* rank, int64_t dimension[], int* datatype); extern NXstatus NX4getgroupinfo(NXhandle handle, int* no_items, NXname name, NXname nxclass); extern NXstatus NX4initgroupdir(NXhandle handle); extern NXstatus NX4getnextentry(NXhandle handle, NXname name, NXname nxclass, int* datatype); @@ -46,3 +49,12 @@ extern NXstatus NX4printlink(NXhandle handle, NXlink* pLink); void NX4assignFunctions(pNexusFunction fHandle); +/* + * HDF changed from MAX_VAR_DIMS to H4_MAX_VAR_DIMS aronud 9/5/2007 + * to avoid potential conflicts with NetCDF-3 library + */ +#ifndef H4_MAX_VAR_DIMS +#define H4_MAX_VAR_DIMS MAX_VAR_DIMS +#endif + +#endif /* NAPI4_H */ diff --git a/napi5.c b/napi5.c index 939b9972..810e1113 100644 --- a/napi5.c +++ b/napi5.c @@ -3,7 +3,7 @@ Application Program Interface (HDF5) Routines - Copyright (C) 1997-2006 Mark Koennecke, Przemek Klosowski + Copyright (C) 1997-2011 Mark Koennecke, Przemek Klosowski This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,12 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - For further information, see + For further information, see ----------------------------------------------------------------------------*/ + +#ifdef HDF5 + #include #include #include @@ -30,6 +33,16 @@ #include "napi.h" #include "napi5.h" +#ifdef H5_VERSION_GE +#if !H5_VERSION_GE(1,8,0) +#error HDF5 Version must be 1.8.0 or higher +#endif +#endif + +#ifdef _MSC_VER +#define snprintf _snprintf +#endif /* _MSC_VER */ + #define NX_UNKNOWN_GROUP "" /* for when no NX_class attr */ extern void *NXpData; @@ -38,7 +51,7 @@ extern void *NXpData; struct iStack5 { char irefn[1024]; int iVref; - int iCurrentIDX; + hsize_t iCurrentIDX; } iStack5[NXMAXSTACK]; struct iStack5 iAtt5; int iFID; @@ -63,9 +76,6 @@ extern void *NXpData; */ NXstatus NX5closegroup (NXhandle fid); /*-------------------------------------------------------------------*/ -static void ignoreError(void *data, char *text){ -} - /*--------------------------------------------------------------------*/ static pNexusFile5 NXI5assert(NXhandle fid) { @@ -93,7 +103,6 @@ static void ignoreError(void *data, char *text){ /*---------------------------------------------------------------------*/ static void buildCurrentPath(pNexusFile5 self, char *pathBuffer, int pathBufferLen){ - int length; memset(pathBuffer,0,pathBufferLen); if(self->iCurrentG != 0) { @@ -115,7 +124,31 @@ static void buildCurrentPath(pNexusFile5 self, char *pathBuffer, ---------------------------------------------------------------------*/ - NXstatus NX5open(CONSTCHAR *filename, NXaccess am, + NXstatus NX5reopen(NXhandle pOrigHandle, NXhandle* pNewHandle) +{ + pNexusFile5 pNew = NULL, pOrig = NULL; + *pNewHandle = NULL; + pOrig = (pNexusFile5)pOrigHandle; + pNew = (pNexusFile5) malloc (sizeof (NexusFile5)); + if (!pNew) { + NXReportError ("ERROR: no memory to create File datastructure"); + return NX_ERROR; + } + memset (pNew, 0, sizeof (NexusFile5)); + pNew->iFID = H5Freopen (pOrig->iFID); + if (pNew->iFID <= 0) { + NXReportError ("cannot clone file"); + free (pNew); + return NX_ERROR; + } + strcpy(pNew->iAccess, pOrig->iAccess); + pNew->iNXID = NX5SIGNATURE; + pNew->iStack5[0].iVref = 0; /* root! */ + *pNewHandle = (NXhandle)pNew; + return NX_OK; +} + +NXstatus NX5open(CONSTCHAR *filename, NXaccess am, NXhandle* pHandle) { hid_t attr1,aid1, aid2, iVID; @@ -123,29 +156,40 @@ static void buildCurrentPath(pNexusFile5 self, char *pathBuffer, char pBuffer[512]; char *time_buffer = NULL; char version_nr[10]; - int iRet; unsigned int vers_major, vers_minor, vers_release, am1 ; hid_t fapl = -1; int mdc_nelmts; -#ifdef H5_WANT_H5_V1_4_COMPAT - int rdcc_nelmts; -#else size_t rdcc_nelmts; -#endif size_t rdcc_nbytes; double rdcc_w0; + unsigned hdf5_majnum, hdf5_minnum, hdf5_relnum; + + *pHandle = NULL; + + if (H5get_libversion(&hdf5_majnum, &hdf5_minnum, &hdf5_relnum) < 0) + { + NXReportError("ERROR: cannot determine HDF5 library version"); + return NX_ERROR; + } + if (hdf5_majnum == 1 && hdf5_minnum < 8) + { + NXReportError("ERROR: HDF5 library 1.8.0 or higher required"); + return NX_ERROR; + } + + /* mask of any options for now */ + am = (NXaccess)(am & NXACCMASK_REMOVEFLAGS); /* turn off the automatic HDF error handling */ - H5Eset_auto(NULL,NULL); + H5Eset_auto(H5E_DEFAULT, NULL, NULL); #ifdef USE_FTIME struct timeb timeb_struct; #endif - *pHandle = NULL; pNew = (pNexusFile5) malloc (sizeof (NexusFile5)); if (!pNew) { - NXIReportError (NXpData,"ERROR: no memory to create File datastructure"); + NXReportError("ERROR: not enough memory to create file structure"); return NX_ERROR; } memset (pNew, 0, sizeof (NexusFile5)); @@ -154,14 +198,9 @@ static void buildCurrentPath(pNexusFile5 self, char *pathBuffer, /* start HDF5 interface */ if (am == NXACC_CREATE5) { fapl = H5Pcreate(H5P_FILE_ACCESS); - iRet=H5Pget_cache(fapl,&mdc_nelmts,&rdcc_nelmts,&rdcc_nbytes,&rdcc_w0); + H5Pget_cache(fapl,&mdc_nelmts,&rdcc_nelmts,&rdcc_nbytes,&rdcc_w0); rdcc_nbytes=(size_t)nx_cacheSize; - iRet = H5Pset_cache(fapl,mdc_nelmts,rdcc_nelmts,rdcc_nbytes,rdcc_w0); - /* - setting the close degree is absolutely necessary in HDF5 - versions > 1.6. If you use a lessere version and the compiler - complains, comment it out but keep this in mind. - */ + H5Pset_cache(fapl,mdc_nelmts,rdcc_nelmts,rdcc_nbytes,rdcc_w0); H5Pset_fclose_degree(fapl,H5F_CLOSE_STRONG); am1 = H5F_ACC_TRUNC; pNew->iFID = H5Fcreate (filename, am1, H5P_DEFAULT, fapl); @@ -175,15 +214,15 @@ static void buildCurrentPath(pNexusFile5 self, char *pathBuffer, H5Pset_fclose_degree(fapl,H5F_CLOSE_STRONG); pNew->iFID = H5Fopen (filename, am1, fapl); } - if (pNew->iFID <= 0) { - sprintf (pBuffer, "ERROR: cannot open file: %s", filename); - NXIReportError (NXpData, pBuffer); - free (pNew); - return NX_ERROR; - } if(fapl != -1) { H5Pclose(fapl); } + if (pNew->iFID <= 0) { + sprintf (pBuffer, "ERROR: cannot open file: %s", filename); + NXReportError( pBuffer); + free (pNew); + return NX_ERROR; + } /* * need to create global attributes file_name file_time NeXus_version @@ -191,7 +230,7 @@ static void buildCurrentPath(pNexusFile5 self, char *pathBuffer, */ if (am1 != H5F_ACC_RDONLY) { - iVID=H5Gopen(pNew->iFID,"/"); + iVID = H5Gopen(pNew->iFID,"/", H5P_DEFAULT); aid2 = H5Screate(H5S_SCALAR); aid1 = H5Tcopy(H5T_C_S1); H5Tset_size(aid1, strlen(NEXUS_VERSION)); @@ -199,96 +238,96 @@ static void buildCurrentPath(pNexusFile5 self, char *pathBuffer, { H5Adelete(iVID, "NeXus_version"); } - attr1= H5Acreate(iVID, "NeXus_version", aid1, aid2, H5P_DEFAULT); + attr1= H5Acreate(iVID, "NeXus_version", aid1, aid2, H5P_DEFAULT, H5P_DEFAULT); if (attr1<0) { - NXIReportError (NXpData, - "ERROR: HDF failed to store NeXus_version attribute "); + NXReportError( + "ERROR: failed to store NeXus_version attribute "); return NX_ERROR; } if (H5Awrite(attr1, aid1,NEXUS_VERSION)<0) { - NXIReportError (NXpData, - "ERROR: HDF failed to store NeXus_version attribute "); + NXReportError( + "ERROR: failed to store NeXus_version attribute "); return NX_ERROR; } /* Close attribute dataspace */ - iRet = H5Tclose(aid1); - iRet = H5Sclose(aid2); + H5Tclose(aid1); + H5Sclose(aid2); /* Close attribute */ - iRet = H5Aclose(attr1); + H5Aclose(attr1); H5Gclose(iVID); } if (am1 == H5F_ACC_TRUNC) { - iVID=H5Gopen(pNew->iFID,"/"); - aid2=H5Screate(H5S_SCALAR); + iVID = H5Gopen(pNew->iFID,"/", H5P_DEFAULT); + aid2 = H5Screate(H5S_SCALAR); aid1 = H5Tcopy(H5T_C_S1); H5Tset_size(aid1, strlen(filename)); - attr1= H5Acreate(iVID, "file_name", aid1, aid2, H5P_DEFAULT); + attr1= H5Acreate(iVID, "file_name", aid1, aid2, H5P_DEFAULT, H5P_DEFAULT); if (attr1 < 0) { - NXIReportError (NXpData, - "ERROR: HDF failed to store file_name attribute "); + NXReportError( + "ERROR: failed to store file_name attribute "); return NX_ERROR; } if (H5Awrite(attr1, aid1, (char*)filename) < 0) { - NXIReportError (NXpData, - "ERROR: HDF failed to store file_name attribute "); + NXReportError( + "ERROR: failed to store file_name attribute "); return NX_ERROR; } - iRet = H5Tclose(aid1); - iRet = H5Sclose(aid2); - iRet = H5Aclose(attr1); + H5Tclose(aid1); + H5Sclose(aid2); + H5Aclose(attr1); /* ------- library version ------*/ H5get_libversion(&vers_major, &vers_minor, &vers_release); sprintf (version_nr, "%d.%d.%d", vers_major,vers_minor,vers_release); aid2=H5Screate(H5S_SCALAR); aid1 = H5Tcopy(H5T_C_S1); H5Tset_size(aid1, strlen(version_nr)); - attr1= H5Acreate(iVID, "HDF5_Version", aid1, aid2, H5P_DEFAULT); + attr1= H5Acreate(iVID, "HDF5_Version", aid1, aid2, H5P_DEFAULT, H5P_DEFAULT); if (attr1 < 0) { - NXIReportError (NXpData, - "ERROR: HDF failed to store file_name attribute "); + NXReportError( + "ERROR: failed to store file_name attribute "); return NX_ERROR; } if (H5Awrite(attr1, aid1, (char*)version_nr) < 0) { - NXIReportError (NXpData, - "ERROR: HDF failed to store file_name attribute "); + NXReportError( + "ERROR: failed to store file_name attribute "); return NX_ERROR; } - iRet = H5Tclose(aid1); - iRet = H5Sclose(aid2); - iRet = H5Aclose(attr1); + H5Tclose(aid1); + H5Sclose(aid2); + H5Aclose(attr1); /*----------- file time */ time_buffer = NXIformatNeXusTime(); if(time_buffer != NULL){ aid2=H5Screate(H5S_SCALAR); aid1 = H5Tcopy(H5T_C_S1); H5Tset_size(aid1, strlen(time_buffer)); - attr1=H5Acreate(iVID, "file_time", aid1, aid2, H5P_DEFAULT); + attr1=H5Acreate(iVID, "file_time", aid1, aid2, H5P_DEFAULT, H5P_DEFAULT); if (attr1 < 0) { - NXIReportError (NXpData, - "ERROR: HDF failed to store file_time attribute "); + NXReportError( + "ERROR: failed to store file_time attribute "); free(time_buffer); return NX_ERROR; } if (H5Awrite(attr1, aid1, time_buffer) < 0) { - NXIReportError (NXpData, - "ERROR: HDF failed to store file_time attribute "); + NXReportError( + "ERROR: failed to store file_time attribute "); free(time_buffer); return NX_ERROR; } /* Close attribute dataspace */ - iRet = H5Tclose(aid1); - iRet = H5Sclose(aid2); + H5Tclose(aid1); + H5Sclose(aid2); /* Close attribute */ - iRet = H5Aclose(attr1); + H5Aclose(attr1); free(time_buffer); } H5Gclose(iVID); @@ -310,7 +349,7 @@ static void buildCurrentPath(pNexusFile5 self, char *pathBuffer, NXstatus NX5close (NXhandle* fid) { pNexusFile5 pFile = NULL; - int iRet; + herr_t iRet; pFile=NXI5assert(*fid); @@ -336,7 +375,7 @@ static void buildCurrentPath(pNexusFile5 self, char *pathBuffer, */ if (iRet < 0) { - NXIReportError (NXpData, "ERROR: HDF cannot close HDF file"); + NXReportError( "ERROR: cannot close HDF file"); } /* release memory */ NXI5KillDir (pFile); @@ -357,41 +396,36 @@ static void buildCurrentPath(pNexusFile5 self, char *pathBuffer, NXstatus NX5makegroup (NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass) { pNexusFile5 pFile; - hid_t iRet, iVID; + herr_t iRet; + hid_t iVID; hid_t attr1,aid1, aid2; char pBuffer[1024] = ""; pFile = NXI5assert (fid); /* create and configure the group */ - if (pFile->iCurrentG==0) - { - iRet = H5Gcreate(pFile->iFID,(const char*)name, 0); + if (pFile->iCurrentG==0) { snprintf(pBuffer,1023,"/%s",name); - } else - { + } else { snprintf(pBuffer,1023,"/%s/%s",pFile->name_ref,name); - iRet = H5Gcreate(pFile->iFID,(const char*)pBuffer, 0); } + iRet = H5Gcreate(pFile->iFID,(const char*)pBuffer, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); if (iRet < 0) { - NXIReportError (NXpData, "ERROR: HDF could not create Group"); + NXReportError( "ERROR: could not create Group"); return NX_ERROR; } iVID = iRet; - strncpy(pFile->name_ref,pBuffer,1023); aid2 = H5Screate(H5S_SCALAR); aid1 = H5Tcopy(H5T_C_S1); H5Tset_size(aid1, strlen(nxclass)); - attr1= H5Acreate(iVID, "NX_class", aid1, aid2, H5P_DEFAULT); - if (attr1 < 0) - { - NXIReportError (NXpData, "ERROR: HDF failed to store class name!"); + attr1= H5Acreate(iVID, "NX_class", aid1, aid2, H5P_DEFAULT, H5P_DEFAULT); + if (attr1 < 0) { + NXReportError( "ERROR: failed to store class name"); return NX_ERROR; - } - if (H5Awrite(attr1, aid1, (char*)nxclass) < 0) - { - NXIReportError (NXpData, "ERROR: HDF failed to store class name!"); + } + if (H5Awrite(attr1, aid1, (char*)nxclass) < 0) { + NXReportError( "ERROR: failed to store class name"); return NX_ERROR; - } + } /* close group */ iRet=H5Sclose(aid2); iRet=H5Tclose(aid1); @@ -402,7 +436,7 @@ static void buildCurrentPath(pNexusFile5 self, char *pathBuffer, /*------------------------------------------------------------------------*/ - herr_t attr_check (hid_t loc_id, const char *member_name, void *opdata) + herr_t attr_check (hid_t loc_id, const char *member_name, const H5A_info_t *unused, void *opdata) { char attr_name[8+1]; /* need to leave space for \0 as well */ @@ -410,61 +444,57 @@ static void buildCurrentPath(pNexusFile5 self, char *pathBuffer, return strstr(member_name, attr_name) ? 1 : 0; } /*------------------------------------------------------------------------*/ - NXstatus NX5opengroup (NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass) + NXstatus NX5opengroup(NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass) { pNexusFile5 pFile; - hid_t iRet, attr1, atype; + hid_t attr1, atype; + herr_t iRet; char pBuffer[1024]; char data[128]; pFile = NXI5assert (fid); - if (pFile->iCurrentG == 0) - { + if (pFile->iCurrentG == 0) { strcpy(pBuffer,name); - } - else - { + } else { sprintf(pBuffer,"%s/%s",pFile->name_tmp,name); } - iRet = H5Gopen (pFile->iFID,(const char *)pBuffer); + iRet = H5Gopen(pFile->iFID, (const char *)pBuffer, H5P_DEFAULT); if (iRet < 0) { - sprintf (pBuffer, "ERROR: Group %s does not exist!", pFile->name_tmp); - NXIReportError (NXpData, pBuffer); + sprintf (pBuffer, "ERROR: group %s does not exist", pFile->name_tmp); + NXReportError( pBuffer); return NX_ERROR; } pFile->iCurrentG = iRet; strcpy(pFile->name_tmp,pBuffer); strcpy(pFile->name_ref,pBuffer); - if ((nxclass != NULL) && (strcmp(nxclass, NX_UNKNOWN_GROUP) != 0)) - { + if ((nxclass != NULL) && (strcmp(nxclass, NX_UNKNOWN_GROUP) != 0)) { /* check group attribute */ - iRet=H5Aiterate(pFile->iCurrentG,NULL,attr_check,NULL); + iRet=H5Aiterate(pFile->iCurrentG,H5_INDEX_CRT_ORDER,H5_ITER_INC,0,attr_check,NULL); if (iRet < 0) { - NXIReportError (NXpData, "ERROR iterating through group!"); + NXReportError( "ERROR: iterating through attribute list"); return NX_ERROR; } else if (iRet == 1) { /* group attribute was found */ } else { /* no group attribute available */ - NXIReportError (NXpData, "No group attribute available"); + NXReportError( "ERROR: no group attribute available"); return NX_ERROR; } /* check contents of group attribute */ - attr1 = H5Aopen_name(pFile->iCurrentG, "NX_class"); - if (attr1 < 0) - { - NXIReportError (NXpData, "Error opening NX_class group attribute!"); + attr1 = H5Aopen_by_name(pFile->iCurrentG, ".", "NX_class", H5P_DEFAULT, H5P_DEFAULT); + if (attr1 < 0) { + NXReportError( "ERROR: opening NX_class group attribute"); return NX_ERROR; } atype=H5Tcopy(H5T_C_S1); - H5Tset_size(atype,128); + H5Tset_size(atype,sizeof(data)); iRet = H5Aread(attr1, atype, data); if (strcmp(data, nxclass) == 0) { /* test OK */ } else { - NXIReportError (NXpData, "Group class is not identical!"); + NXReportError( "ERROR: group class is not identical"); iRet = H5Tclose(atype); iRet = H5Aclose(attr1); return NX_ERROR; @@ -544,56 +574,33 @@ static void buildCurrentPath(pNexusFile5 self, char *pathBuffer, return NX_OK; } /*-----------------------------------------------------------------------*/ -static int nxToHDF5Type(int datatype) +static hid_t nxToHDF5Type(int datatype) { - int type; - if (datatype == NX_CHAR) - { + hid_t type; + if (datatype == NX_CHAR) { type=H5T_C_S1; - } - else if (datatype == NX_INT8) - { + } else if (datatype == NX_INT8) { type=H5T_NATIVE_CHAR; - } - else if (datatype == NX_UINT8) - { + } else if (datatype == NX_UINT8) { type=H5T_NATIVE_UCHAR; - } - else if (datatype == NX_INT16) - { + } else if (datatype == NX_INT16) { type=H5T_NATIVE_SHORT; - } - else if (datatype == NX_UINT16) - { + } else if (datatype == NX_UINT16) { type=H5T_NATIVE_USHORT; - } - else if (datatype == NX_INT32) - { + } else if (datatype == NX_INT32) { type=H5T_NATIVE_INT; - } - else if (datatype == NX_UINT32) - { + } else if (datatype == NX_UINT32) { type=H5T_NATIVE_UINT; - } - else if (datatype == NX_INT64) - { + } else if (datatype == NX_INT64) { type = H5T_NATIVE_INT64; - } - else if (datatype == NX_UINT64) - { + } else if (datatype == NX_UINT64) { type = H5T_NATIVE_UINT64; - } - else if (datatype == NX_FLOAT32) - { + } else if (datatype == NX_FLOAT32) { type=H5T_NATIVE_FLOAT; - } - else if (datatype == NX_FLOAT64) - { + } else if (datatype == NX_FLOAT64) { type=H5T_NATIVE_DOUBLE; - } - else - { - NXIReportError (NXpData, "ERROR: nxToHDF5Type: unknown type"); + } else { + NXReportError( "ERROR: nxToHDF5Type: unknown type"); type = -1; } return type; @@ -601,182 +608,219 @@ static int nxToHDF5Type(int datatype) /* --------------------------------------------------------------------- */ - NXstatus NX5compmakedata (NXhandle fid, CONSTCHAR *name, + NXstatus NX5compmakedata64 (NXhandle fid, CONSTCHAR *name, int datatype, - int rank, int dimensions[], - int compress_type, int chunk_size[]) + int rank, int64_t dimensions[], + int compress_type, int64_t chunk_size[]) { - hid_t datatype1, dataspace, iNew, iRet; - hid_t type, cparms = -1; - pNexusFile5 pFile; - char pBuffer[256]; - int i, byte_zahl = 0; - hsize_t chunkdims[H5S_MAX_RANK]; - hsize_t mydim[H5S_MAX_RANK], mydim1[H5S_MAX_RANK]; - hsize_t size[H5S_MAX_RANK]; - hsize_t maxdims[H5S_MAX_RANK]; + hid_t datatype1, dataspace, iNew; + herr_t iRet; + hid_t type, cparms = -1; + pNexusFile5 pFile; + char pBuffer[256]; + int i, byte_zahl = 0; + hsize_t chunkdims[H5S_MAX_RANK]; + hsize_t mydim[H5S_MAX_RANK], mydim1[H5S_MAX_RANK]; + hsize_t size[H5S_MAX_RANK]; + hsize_t maxdims[H5S_MAX_RANK]; + int compress_level; + int unlimiteddim = 0; - pFile = NXI5assert (fid); - - for (i = 0; i < rank; i++) - { - chunkdims[i]=chunk_size[i]; - mydim[i] = dimensions[i]; - maxdims[i] = dimensions[i]; - size[i] = dimensions[i]; - } + pFile = NXI5assert (fid); + if (pFile->iCurrentG <= 0) { + sprintf(pBuffer, "ERROR: no group open for makedata on %s", name); + NXReportError( pBuffer); + return NX_ERROR; + } - type = nxToHDF5Type(datatype); + if (rank <= 0) { + sprintf (pBuffer, "ERROR: invalid rank specified %s", name); + NXReportError( pBuffer); + return NX_ERROR; + } - if (rank <= 0) { - sprintf (pBuffer, "ERROR: invalid rank specified %s", - name); - NXIReportError (NXpData, pBuffer); - return NX_ERROR; - } - /* - Check dimensions for consistency. The first dimension may be -1 + type = nxToHDF5Type(datatype); + + /* + Check dimensions for consistency. Dimension may be -1 thus denoting an unlimited dimension. - */ - for (i = 1; i < rank; i++) { - if (dimensions[i] <= 0) { - sprintf (pBuffer, - "ERROR: invalid dimension %d, value %d given for Dataset %s", - i, dimensions[i], name); - NXIReportError (NXpData, pBuffer); - return NX_ERROR; - } - } - if (datatype == NX_CHAR) - { -/* - * This assumes string lenght is in the last dimensions and - * the logic must be the same as used in NX5getslab and NX5getinfo - * - * search for tests on H5T_STRING - */ - byte_zahl=dimensions[rank-1]; - for(i = 0; i < rank; i++) - { - mydim1[i] = dimensions[i]; - } - mydim1[rank-1] = 1; - if (dimensions[rank-1] > 1) - { - mydim[rank-1] = maxdims[rank-1] = size[rank-1] = 1; - } - if (chunkdims[rank-1] > 1) - { - chunkdims[rank-1] = 1; - } - if (dimensions[0] == NX_UNLIMITED) - { - mydim1[0] = 1; - maxdims[0] = H5S_UNLIMITED; - } - dataspace=H5Screate_simple(rank,mydim1,maxdims); - } else { - if (dimensions[0] == NX_UNLIMITED) + */ + for (i = 0; i < rank; i++) { - mydim[0] = 1; - maxdims[0] = H5S_UNLIMITED; - dataspace=H5Screate_simple(rank, mydim, maxdims); - } else { - /* dataset creation */ - dataspace=H5Screate_simple(rank, mydim, NULL); - } - } - datatype1=H5Tcopy(type); - if (datatype == NX_CHAR) - { - H5Tset_size(datatype1, byte_zahl); -/* H5Tset_strpad(H5T_STR_SPACEPAD); */ - } - if(compress_type == NX_COMP_LZW) - { - cparms = H5Pcreate(H5P_DATASET_CREATE); - iNew = H5Pset_chunk(cparms,rank,chunkdims); - if (iNew < 0) { - NXIReportError (NXpData, "ERROR: Size of chunks could not be set!"); - return NX_ERROR; + chunkdims[i] = chunk_size[i]; + mydim[i] = dimensions[i]; + maxdims[i] = dimensions[i]; + size[i] = dimensions[i]; + if (dimensions[i] <= 0) + { + mydim[i] = 1; + maxdims[i] = H5S_UNLIMITED; + size[i] = 1; + unlimiteddim = 1; + } else { + mydim[i] = dimensions[i]; + maxdims[i] = dimensions[i]; + size[i] = dimensions[i]; + } } - H5Pset_deflate(cparms,6); - iRet = H5Dcreate (pFile->iCurrentG, (char*)name, datatype1, - dataspace, cparms); - } else if (compress_type == NX_COMP_NONE) { - if (dimensions[0] == NX_UNLIMITED) { - cparms = H5Pcreate(H5P_DATASET_CREATE); - iNew = H5Pset_chunk(cparms,rank,chunkdims); - if (iNew < 0) { - NXIReportError (NXpData, - "ERROR: Size of chunks could not be set!"); - return NX_ERROR; - } - iRet = H5Dcreate (pFile->iCurrentG, (char*)name, datatype1, - dataspace, cparms); - } else { - iRet = H5Dcreate (pFile->iCurrentG, (char*)name, datatype1, - dataspace, H5P_DEFAULT); - } - } else { - NXIReportError (NXpData, - "HDF5 doesn't support selected compression method! Dataset was saved without compression"); - iRet = H5Dcreate (pFile->iCurrentG, (char*)name, datatype1, - dataspace, H5P_DEFAULT); - } - if (iRet < 0) { - NXIReportError (NXpData, "ERROR: Creating chunked dataset failed!"); - return NX_ERROR; - } else { - pFile->iCurrentD = iRet; - } - if (dimensions[0] == NX_UNLIMITED) - { - size[0] = 1; - iNew = H5Dextend (pFile->iCurrentD, size); - if (iNew < 0) { - sprintf (pBuffer, "ERROR: cannot create Dataset %s, check arguments", - name); - NXIReportError (NXpData, pBuffer); - return NX_ERROR; + + if (datatype == NX_CHAR) + { + /* + * This assumes string lenght is in the last dimensions and + * the logic must be the same as used in NX5getslab and NX5getinfo + * + * search for tests on H5T_STRING + */ + byte_zahl=mydim[rank-1]; + for(i = 0; i < rank; i++) + { + mydim1[i] = mydim[i]; + if (dimensions[i] <= 0) + { + mydim1[0] = 1; + maxdims[0] = H5S_UNLIMITED; + } + + } + mydim1[rank-1] = 1; + if (mydim[rank-1] > 1) + { + mydim[rank-1] = maxdims[rank-1] = size[rank-1] = 1; + } + if (chunkdims[rank-1] > 1) + { + chunkdims[rank-1] = 1; + } + dataspace=H5Screate_simple(rank,mydim1,maxdims); + } + else + { + if (unlimiteddim) + { + dataspace=H5Screate_simple(rank, mydim, maxdims); + } + else + { + /* dataset creation */ + dataspace=H5Screate_simple(rank, mydim, NULL); + } + } + datatype1=H5Tcopy(type); + if (datatype == NX_CHAR) + { + H5Tset_size(datatype1, byte_zahl); + /* H5Tset_strpad(H5T_STR_SPACEPAD); */ } - } - if (cparms != -1) { - iRet = H5Pclose(cparms); - } - iRet = H5Sclose(dataspace); - iRet = H5Tclose(datatype1); - iRet = H5Dclose(pFile->iCurrentD); - pFile->iCurrentD = 0; - if (iRet < 0) { - NXIReportError (NXpData, "ERROR: HDF cannot close Dataset"); - return NX_ERROR; - } - return NX_OK; + compress_level = 6; + if ( (compress_type / 100) == NX_COMP_LZW ) + { + compress_level = compress_type % 100; + compress_type = NX_COMP_LZW; + } + if(compress_type == NX_COMP_LZW) + { + cparms = H5Pcreate(H5P_DATASET_CREATE); + iNew = H5Pset_chunk(cparms,rank,chunkdims); + if (iNew < 0) + { + NXReportError( "ERROR: size of chunks could not be set"); + return NX_ERROR; + } + H5Pset_deflate(cparms,compress_level); + iRet = H5Dcreate(pFile->iCurrentG, (char*)name, datatype1, dataspace, H5P_DEFAULT, cparms, H5P_DEFAULT); + } + else if (compress_type == NX_COMP_NONE) + { + if (unlimiteddim) + { + cparms = H5Pcreate(H5P_DATASET_CREATE); + iNew = H5Pset_chunk(cparms,rank,chunkdims); + if (iNew < 0) + { + NXReportError( "ERROR: size of chunks could not be set"); + return NX_ERROR; + } + iRet = H5Dcreate(pFile->iCurrentG, (char*)name, datatype1, dataspace, H5P_DEFAULT, cparms, H5P_DEFAULT); + } + else + { + iRet = H5Dcreate(pFile->iCurrentG, (char*)name, datatype1, dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + } + } + else if (compress_type == NX_CHUNK) + { + cparms = H5Pcreate(H5P_DATASET_CREATE); + iNew = H5Pset_chunk(cparms,rank,chunkdims); + if (iNew < 0) + { + NXReportError("ERROR: size of chunks could not be set"); + return NX_ERROR; + } + iRet = H5Dcreate(pFile->iCurrentG, (char*)name, datatype1, dataspace, H5P_DEFAULT, cparms, H5P_DEFAULT); + + } + else + { + NXReportError( + "HDF5 doesn't support selected compression method! Dataset was saved without compression"); + iRet = H5Dcreate (pFile->iCurrentG, (char*)name, datatype1, dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + } + if (iRet < 0) + { + NXReportError( "ERROR: creating chunked dataset failed"); + return NX_ERROR; + } + else + { + pFile->iCurrentD = iRet; + } + if (unlimiteddim) + { + iNew = H5Dset_extent (pFile->iCurrentD, size); + if (iNew < 0) + { + sprintf (pBuffer, "ERROR: cannot create dataset %s", + name); + NXReportError( pBuffer); + return NX_ERROR; + } + } + if (cparms != -1) + { + iRet = H5Pclose(cparms); + } + iRet = H5Sclose(dataspace); + iRet = H5Tclose(datatype1); + iRet = H5Dclose(pFile->iCurrentD); + pFile->iCurrentD = 0; + if (iRet < 0) + { + NXReportError( "ERROR: HDF cannot close dataset"); + return NX_ERROR; + } + return NX_OK; } /* --------------------------------------------------------------------- */ - NXstatus NX5makedata (NXhandle fid, CONSTCHAR *name, int datatype, - int rank, int dimensions[]) + NXstatus NX5makedata64 (NXhandle fid, CONSTCHAR *name, int datatype, + int rank, int64_t dimensions[]) { - pNexusFile5 pFile; - int chunk_size[H5S_MAX_RANK]; + int64_t chunk_size[H5S_MAX_RANK]; int i; - - pFile = NXI5assert (fid); - memset(chunk_size,0,H5S_MAX_RANK*sizeof(int)); - if (dimensions[0] == NX_UNLIMITED) - { - for (i = 0; i < H5S_MAX_RANK; i++) - { - chunk_size[i]= 1; - } - } - return NX5compmakedata (fid, name, datatype, rank, dimensions, NX_COMP_NONE, chunk_size); + + NXI5assert(fid); - return NX_OK; + memset(chunk_size,0,H5S_MAX_RANK*sizeof(int64_t)); + memcpy(chunk_size,dimensions,rank*sizeof(int64_t)); + for(i = 0; i< rank; i++) { + if (dimensions[i] == NX_UNLIMITED || dimensions[i] <= 0){ + chunk_size[i]= 1; + } + } + return NX5compmakedata64 (fid, name, datatype, rank, dimensions, NX_COMP_NONE, chunk_size); } @@ -804,23 +848,23 @@ static int nxToHDF5Type(int datatype) /* find the ID number and open the dataset */ - pFile->iCurrentD = H5Dopen(pFile->iCurrentG, name); + pFile->iCurrentD = H5Dopen(pFile->iCurrentG, name, H5P_DEFAULT); if (pFile->iCurrentD < 0) { - sprintf (pBuffer, "ERROR: Dataset %s not found at this level", name); - NXIReportError (NXpData, pBuffer); + sprintf (pBuffer, "ERROR: dataset \"%s\" not found at this level", name); + NXReportError( pBuffer); return NX_ERROR; } /* find the ID number of datatype */ pFile->iCurrentT = H5Dget_type(pFile->iCurrentD); if (pFile->iCurrentT < 0) { - NXIReportError (NXpData, "ERROR:HDF error opening Dataset"); + NXReportError( "ERROR: error opening dataset"); pFile->iCurrentT=0; return NX_ERROR; } /* find the ID number of dataspace */ pFile->iCurrentS = H5Dget_space(pFile->iCurrentD); if (pFile->iCurrentS < 0) { - NXIReportError (NXpData, "ERROR:HDF error opening Dataset"); + NXReportError( "ERROR:HDF error opening dataset"); pFile->iCurrentS=0; return NX_ERROR; } @@ -836,14 +880,14 @@ static int nxToHDF5Type(int datatype) NXstatus NX5closedata (NXhandle fid) { pNexusFile5 pFile; - int iRet; + herr_t iRet; pFile = NXI5assert (fid); iRet = H5Sclose(pFile->iCurrentS); iRet = H5Tclose(pFile->iCurrentT); iRet = H5Dclose(pFile->iCurrentD); if (iRet < 0) { - NXIReportError (NXpData, "ERROR: HDF cannot end access to Dataset"); + NXReportError( "ERROR: cannot end access to dataset"); return NX_ERROR; } pFile->iCurrentD=0; @@ -854,22 +898,55 @@ static int nxToHDF5Type(int datatype) - NXstatus NX5putdata (NXhandle fid, void *data) + NXstatus NX5putdata (NXhandle fid, const void *data) { pNexusFile5 pFile; - hid_t iRet; + herr_t iRet; + int64_t myStart[H5S_MAX_RANK]; + int64_t mySize[H5S_MAX_RANK]; + hsize_t thedims[H5S_MAX_RANK],maxdims[H5S_MAX_RANK]; + int i, rank, unlimiteddim = 0; char pError[512] = ""; pFile = NXI5assert (fid); - - /* actually write */ - iRet = H5Dwrite (pFile->iCurrentD, pFile->iCurrentT, H5S_ALL, H5S_ALL, + rank = H5Sget_simple_extent_ndims(pFile->iCurrentS); + if (rank < 0) + { + NXReportError("ERROR: Cannot determine dataset rank"); + return NX_ERROR; + } + iRet = H5Sget_simple_extent_dims(pFile->iCurrentS, thedims, maxdims); + if (iRet < 0) + { + NXReportError("ERROR: Cannot determine dataset dimensions"); + return NX_ERROR; + } + for(i=0; iiCurrentD, pFile->iCurrentT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data); - if (iRet < 0) { - snprintf (pError,511, "ERROR: failure to write data"); - NXIReportError (NXpData, pError); - return NX_ERROR; + if (iRet < 0) { + snprintf (pError,sizeof(pError)-1, "ERROR: failure to write data"); + NXReportError( pError); + return NX_ERROR; + } } return NX_OK; } @@ -878,7 +955,7 @@ static int getAttVID(pNexusFile5 pFile){ int vid; if(pFile->iCurrentG == 0 && pFile->iCurrentD == 0){ /* global attribute */ - vid = H5Gopen(pFile->iFID,"/"); + vid = H5Gopen(pFile->iFID,"/", H5P_DEFAULT); } else if(pFile->iCurrentD != 0) { /* dataset attribute */ vid = pFile->iCurrentD; @@ -896,13 +973,14 @@ static void killAttVID(pNexusFile5 pFile, int vid){ } /* ------------------------------------------------------------------- */ - NXstatus NX5putattr (NXhandle fid, CONSTCHAR *name, void *data, - int datalen, int iType) + NXstatus NX5putattr (NXhandle fid, CONSTCHAR *name, const void *data, + + int datalen, int iType) { pNexusFile5 pFile; hid_t attr1, aid1, aid2; hid_t type; - int iRet; + herr_t iRet; int vid; pFile = NXI5assert (fid); @@ -916,24 +994,24 @@ static void killAttVID(pNexusFile5 pFile, int vid){ if (iType == NX_CHAR){ H5Tset_size(aid1,datalen); } - iRet = H5Aopen_name(vid, name); + iRet = H5Aopen_by_name(vid, ".", name, H5P_DEFAULT, H5P_DEFAULT); if (iRet>0) { H5Aclose(iRet); iRet=H5Adelete(vid,name); if (iRet<0) { - NXIReportError (NXpData, "ERROR: Old attribute cannot removed! "); + NXReportError( "ERROR: old attribute cannot be removed! "); killAttVID(pFile,vid); return NX_ERROR; } } - attr1 = H5Acreate(vid, name, aid1, aid2, H5P_DEFAULT); + attr1 = H5Acreate(vid, name, aid1, aid2, H5P_DEFAULT, H5P_DEFAULT); if (attr1 < 0) { - NXIReportError (NXpData, "ERROR: Attribute cannot created! "); + NXReportError( "ERROR: attribute cannot created! "); killAttVID(pFile,vid); return NX_ERROR; } if (H5Awrite(attr1,aid1,data) < 0) { - NXIReportError (NXpData, "ERROR: HDF failed to store attribute "); + NXReportError( "ERROR: failed to store attribute "); killAttVID(pFile,vid); return NX_ERROR; } @@ -948,43 +1026,61 @@ static void killAttVID(pNexusFile5 pFile, int vid){ /* ------------------------------------------------------------------- */ - NXstatus NX5putslab (NXhandle fid, void *data, int iStart[], int iSize[]) + NXstatus NX5putslab64 (NXhandle fid, const void *data, const int64_t iStart[], const int64_t iSize[]) { pNexusFile5 pFile; - int iRet, i; - int rank; + int iRet, rank, i; hsize_t myStart[H5S_MAX_RANK]; hsize_t mySize[H5S_MAX_RANK]; - hsize_t size[H5S_MAX_RANK],maxdims[H5S_MAX_RANK]; + hsize_t size[H5S_MAX_RANK],thedims[H5S_MAX_RANK],maxdims[H5S_MAX_RANK]; hid_t filespace,dataspace; + int unlimiteddim = 0; pFile = NXI5assert (fid); /* check if there is an Dataset open */ if (pFile->iCurrentD == 0) { - NXIReportError (NXpData, "ERROR: no dataset open"); + NXReportError( "ERROR: no dataset open"); return NX_ERROR; } rank = H5Sget_simple_extent_ndims(pFile->iCurrentS); - iRet = H5Sget_simple_extent_dims(pFile->iCurrentS, NULL, maxdims); + if (rank < 0) { + NXReportError( "ERROR: cannot get rank"); + return NX_ERROR; + } + iRet = H5Sget_simple_extent_dims(pFile->iCurrentS, thedims, maxdims); + if (iRet < 0) { + NXReportError( "ERROR: cannot get dimensions"); + return NX_ERROR; + } + for(i = 0; i < rank; i++) { myStart[i] = iStart[i]; mySize[i] = iSize[i]; - size[i] = iSize[i]; + size[i] = iStart[i] + iSize[i]; + if (maxdims[i] == H5S_UNLIMITED) { + unlimiteddim = 1; + } } if (H5Tget_class(pFile->iCurrentT) == H5T_STRING) { mySize[rank - 1] = 1; myStart[rank - 1] = 0; + size[rank - 1] = 1; } - dataspace = H5Screate_simple (rank, mySize, NULL); - if (maxdims[0] == NX_UNLIMITED) + dataspace = H5Screate_simple(rank, mySize, NULL); + if (unlimiteddim) { - size[0]=iStart[0] + iSize[0]; - iRet = H5Dextend(pFile->iCurrentD, size); + for(i = 0; i < rank; i++) + { + if (size[i] < thedims[i]) { + size[i] = thedims[i]; + } + } + iRet = H5Dset_extent(pFile->iCurrentD, size); if (iRet < 0) { - NXIReportError (NXpData, "ERROR: extend slab failed"); + NXReportError( "ERROR: extend slab failed"); return NX_ERROR; } @@ -993,20 +1089,22 @@ static void killAttVID(pNexusFile5 pFile, int vid){ /* define slab */ iRet = H5Sselect_hyperslab(filespace, H5S_SELECT_SET, myStart, NULL, mySize, NULL); - /* deal with HDF errors */ + /* deal with HDF errors */ if (iRet < 0) { - NXIReportError (NXpData, "ERROR: selecting slab failed"); + NXReportError( "ERROR: selecting slab failed"); return NX_ERROR; } /* write slab */ iRet = H5Dwrite(pFile->iCurrentD, pFile->iCurrentT, dataspace, - filespace, H5P_DEFAULT,data); + filespace, H5P_DEFAULT, data); if (iRet < 0) { - NXIReportError (NXpData, "ERROR: writing slab failed"); + NXReportError( "ERROR: writing slab failed"); } - iRet = H5Sclose(filespace); + /* update with new size */ + iRet = H5Sclose(pFile->iCurrentS); + pFile->iCurrentS = filespace; } else { /* define slab */ iRet = H5Sselect_hyperslab(pFile->iCurrentS, H5S_SELECT_SET, myStart, @@ -1014,22 +1112,22 @@ static void killAttVID(pNexusFile5 pFile, int vid){ /* deal with HDF errors */ if (iRet < 0) { - NXIReportError (NXpData, "ERROR: selecting slab failed"); + NXReportError( "ERROR: selecting slab failed"); return NX_ERROR; } /* write slab */ iRet = H5Dwrite(pFile->iCurrentD, pFile->iCurrentT, dataspace, - pFile->iCurrentS, H5P_DEFAULT,data); + pFile->iCurrentS, H5P_DEFAULT, data); if (iRet < 0) { - NXIReportError (NXpData, "ERROR: writing slab failed"); + NXReportError( "ERROR: writing slab failed"); } } /* deal with HDF errors */ iRet = H5Sclose(dataspace); if (iRet < 0) { - NXIReportError (NXpData, "ERROR: closing slab failed"); + NXReportError( "ERROR: closing slab failed"); return NX_ERROR; } return NX_OK; @@ -1040,7 +1138,6 @@ static void killAttVID(pNexusFile5 pFile, int vid){ NXstatus NX5getdataID (NXhandle fid, NXlink* sRes) { pNexusFile5 pFile; - ErrFunc oldErr; int datalen, type = NX_CHAR; pFile = NXI5assert (fid); @@ -1056,15 +1153,14 @@ static void killAttVID(pNexusFile5 pFile, int vid){ this means: if the item is already linked: use the target attribute else, the path to the current node */ - oldErr = NXMGetError(); - NXMSetError(NXpData, ignoreError); + NXMDisableErrorReporting(); datalen = 1024; memset(&sRes->targetPath,0,datalen*sizeof(char)); if(NX5getattr(fid,"target",&sRes->targetPath,&datalen,&type) != NX_OK) { buildCurrentPath(pFile, sRes->targetPath, 1024); } - NXMSetError(NXpData,oldErr); + NXMEnableErrorReporting(); sRes->linkType = 1; return NX_OK; } @@ -1073,34 +1169,32 @@ static void killAttVID(pNexusFile5 pFile, int vid){ NXstatus NX5printlink (NXhandle fid, NXlink* sLink) { - pNexusFile5 pFile; - pFile = NXI5assert (fid); - printf("HDF5 link: targetPath = \"%s\", linkType = \"%d\"\n", sLink->targetPath, sLink->linkType); + NXI5assert(fid); + printf("HDF5 link: targetPath = \"%s\", linkType = \"%d\"\n", sLink->targetPath, sLink->linkType); return NX_OK; } /*--------------------------------------------------------------------*/ static NXstatus NX5settargetattribute(pNexusFile5 pFile, NXlink *sLink) { - herr_t length, dataID, status, aid2, aid1, attID; - int type = NX_CHAR; + hid_t dataID, aid2, aid1, attID; + herr_t status; char name[] = "target"; - length = strlen(sLink->targetPath); /* set the target attribute */ if(sLink->linkType > 0) { - dataID = H5Dopen(pFile->iFID,sLink->targetPath); + dataID = H5Dopen(pFile->iFID,sLink->targetPath, H5P_DEFAULT); } else { - dataID = H5Gopen(pFile->iFID,sLink->targetPath); + dataID = H5Gopen(pFile->iFID,sLink->targetPath, H5P_DEFAULT); } if(dataID < 0) { - NXIReportError(NXpData,"Internal error, path to link does not exist"); + NXReportError("Internal error, path to link does not exist"); return NX_ERROR; } - status = H5Aopen_name(dataID,name); + status = H5Aopen_by_name(dataID,".", name, H5P_DEFAULT, H5P_DEFAULT); if(status > 0) { H5Aclose(status); @@ -1113,7 +1207,7 @@ static NXstatus NX5settargetattribute(pNexusFile5 pFile, NXlink *sLink) aid2 = H5Screate(H5S_SCALAR); aid1 = H5Tcopy(H5T_C_S1); H5Tset_size(aid1,strlen(sLink->targetPath)); - attID = H5Acreate(dataID,name,aid1,aid2,H5P_DEFAULT); + attID = H5Acreate(dataID,name,aid1,aid2,H5P_DEFAULT, H5P_DEFAULT); if(attID < 0) { return NX_OK; @@ -1133,9 +1227,7 @@ static NXstatus NX5settargetattribute(pNexusFile5 pFile, NXlink *sLink) NXstatus NX5makenamedlink(NXhandle fid, CONSTCHAR *name, NXlink *sLink) { pNexusFile5 pFile; - char linkTarget[1024]; - int type = NX_CHAR, length; - int status; + char linkTarget[1024]; pFile = NXI5assert (fid); if (pFile->iCurrentG == 0) { /* root level, can not link here */ @@ -1155,11 +1247,13 @@ NXstatus NX5makenamedlink(NXhandle fid, CONSTCHAR *name, NXlink *sLink) } else { - NXIReportError(NXpData,"Path string to long"); + NXReportError("ERROR: path string to long"); return NX_ERROR; } - status = H5Glink(pFile->iFID, H5G_LINK_HARD, sLink->targetPath, linkTarget); + //targetid = H5Oopen(pFile->iFID, sLink->targetPath, H5P_DEFAULT); + H5Lcreate_hard(pFile->iFID, sLink->targetPath, H5L_SAME_LOC, linkTarget, H5P_DEFAULT, H5P_DEFAULT); + //H5Oclose(targetid); return NX5settargetattribute(pFile,sLink); } @@ -1168,10 +1262,8 @@ NXstatus NX5makenamedlink(NXhandle fid, CONSTCHAR *name, NXlink *sLink) NXstatus NX5makelink (NXhandle fid, NXlink* sLink) { pNexusFile5 pFile; - char linkTarget[1024]; - int type = NX_CHAR, length; - char *itemName = NULL; - int status; + char linkTarget[1024]; + char *itemName = NULL; pFile = NXI5assert (fid); if (pFile->iCurrentG == 0) { /* root level, can not link here */ @@ -1183,7 +1275,7 @@ NXstatus NX5makenamedlink(NXhandle fid, CONSTCHAR *name, NXlink *sLink) */ itemName = strrchr(sLink->targetPath,'/'); if(itemName == NULL){ - NXIReportError(NXpData,"Bad link structure"); + NXReportError("ERROR: bad link structure"); return NX_ERROR; } itemName++; @@ -1201,11 +1293,13 @@ NXstatus NX5makenamedlink(NXhandle fid, CONSTCHAR *name, NXlink *sLink) } else { - NXIReportError(NXpData,"Path string to long"); + NXReportError("ERROR: path string to long"); return NX_ERROR; } - status = H5Glink(pFile->iFID, H5G_LINK_HARD, sLink->targetPath, linkTarget); + //targetid = H5Oopen(pFile->iFID, sLink->targetPath, H5P_DEFAULT); + H5Lcreate_hard(pFile->iFID, sLink->targetPath, H5L_SAME_LOC, linkTarget, H5P_DEFAULT, H5P_DEFAULT); + //H5Oclose(targetid); return NX5settargetattribute(pFile,sLink); } @@ -1215,7 +1309,7 @@ NXstatus NX5makenamedlink(NXhandle fid, CONSTCHAR *name, NXlink *sLink) NXstatus NX5flush(NXhandle *pHandle) { pNexusFile5 pFile = NULL; - int iRet; + herr_t iRet; pFile = NXI5assert (*pHandle); if (pFile->iCurrentD != 0) @@ -1231,7 +1325,7 @@ NXstatus NX5makenamedlink(NXhandle fid, CONSTCHAR *name, NXlink *sLink) iRet=H5Fflush(pFile->iFID,H5F_SCOPE_LOCAL); } if (iRet < 0){ - NXIReportError (NXpData, "ERROR: The object cannot be flushed"); + NXReportError( "ERROR: The object cannot be flushed"); return NX_ERROR; } return NX_OK; @@ -1241,24 +1335,22 @@ NXstatus NX5makenamedlink(NXhandle fid, CONSTCHAR *name, NXlink *sLink) /* Operator function. */ - herr_t nxgroup_info(hid_t loc_id, const char *name, void *op_data) + herr_t nxgroup_info(hid_t loc_id, const char *name, const H5L_info_t *statbuf, void *op_data) { - H5G_stat_t statbuf; - pinfo self; - - self = (pinfo)op_data; - H5Gget_objinfo(loc_id, name, 0, &statbuf); - switch (statbuf.type) - { - case H5G_GROUP: + pinfo self = (pinfo) op_data; + H5O_info_t object_info; + H5Oget_info_by_name(loc_id, name, &object_info, H5P_DEFAULT); + switch ((object_info).type) { + case H5O_TYPE_GROUP: self->iname = strdup(name); - self->type = H5G_GROUP; + self->type = H5O_TYPE_GROUP; break; - case H5G_DATASET: + case H5O_TYPE_DATASET: self->iname = strdup(name); - self->type = H5G_DATASET; + self->type = H5O_TYPE_DATASET; break; default: + // TODO defaults to group. not what we would want? self->type=0; break; } @@ -1268,22 +1360,19 @@ NXstatus NX5makenamedlink(NXhandle fid, CONSTCHAR *name, NXlink *sLink) /* Operator function. */ - herr_t group_info1(hid_t loc_id, const char *name, void *opdata) + herr_t group_info1(hid_t loc_id, const char *name, const H5L_info_t *statbuf, void *opdata) { - NexusFile5 self; - H5G_stat_t statbuf; - self.iNX = *((int*)opdata); - H5Gget_objinfo(loc_id, name, 0, &statbuf); - - switch (statbuf.type) - { - case H5G_GROUP: - self.iNX++; - *((int*)opdata)=self.iNX; + int iNX = *((int*)opdata); + H5O_info_t object_info; + H5Oget_info_by_name(loc_id, name, &object_info, H5P_DEFAULT); + switch ((object_info).type) { + case H5O_TYPE_GROUP: + iNX++; + *((int*)opdata)=iNX; break; - case H5G_DATASET: - self.iNX++; - *((int*)opdata)=self.iNX; + case H5O_TYPE_DATASET: + iNX++; + *((int*)opdata)=iNX; break; default: break; @@ -1293,12 +1382,11 @@ NXstatus NX5makenamedlink(NXhandle fid, CONSTCHAR *name, NXlink *sLink) /*-------------------------------------------------------------------------*/ - NXstatus NX5getgroupinfo (NXhandle fid, int *iN, NXname pName, NXname pClass) + NXstatus NX5getgroupinfo_recurse(NXhandle fid, int *iN, NXname pName, NXname pClass) { pNexusFile5 pFile; - hid_t atype,attr_id; - char data[64]; - int iRet; + hid_t atype, attr_id, grp; + char data[64]; pFile = NXI5assert (fid); /* check if there is a group open */ @@ -1306,173 +1394,246 @@ NXstatus NX5makenamedlink(NXhandle fid, CONSTCHAR *name, NXlink *sLink) strcpy (pName, "root"); strcpy (pClass, "NXroot"); pFile->iNX=0; - iRet=H5Giterate(pFile->iFID,"/",0,group_info1,&pFile->iNX); + grp = H5Gopen(pFile->iFID,"/",H5P_DEFAULT); + H5Literate(grp, H5_INDEX_NAME, H5_ITER_INC, 0, group_info1, &pFile->iNX); + H5Gclose(grp); *iN=pFile->iNX; } else { strcpy (pName,pFile->name_ref); - attr_id = H5Aopen_name(pFile->iCurrentG,"NX_class"); + attr_id = H5Aopen_by_name(pFile->iCurrentG,".", "NX_class", H5P_DEFAULT, H5P_DEFAULT); if (attr_id<0) { strcpy(pClass, NX_UNKNOWN_GROUP); } else { atype=H5Tcopy(H5T_C_S1); - H5Tset_size(atype,64); + H5Tset_size(atype,sizeof(data)); H5Aread(attr_id, atype, data); strcpy(pClass,data); pFile->iNX=0; - iRet=H5Giterate(pFile->iFID,pFile->name_ref,0,group_info1, &pFile->iNX); + grp = H5Gopen(pFile->iFID,pFile->name_ref,H5P_DEFAULT); + H5Literate(grp, H5_INDEX_NAME, H5_ITER_INC, 0, group_info1, &pFile->iNX); + H5Gclose(grp); *iN=pFile->iNX; H5Aclose(attr_id); } } return NX_OK; } - -/*------------------------------------------------------------------------*/ -static int hdf5ToNXType(int data_id, hid_t atype) +/*---------------------------------------------------------------------------*/ +static int countObjectsInGroup(hid_t loc_id) { - int iPtype = -1; - hid_t sign_id, size_id; + int count = 0; + H5G_info_t numobj; + + herr_t status; - if (data_id==H5T_STRING) - { - iPtype=NX_CHAR; - } - if (data_id==H5T_INTEGER) - { - size_id=H5Tget_size(atype); - sign_id=H5Tget_sign(atype); - if (size_id==1) - { - if (sign_id==H5T_SGN_2) - { - iPtype=NX_INT8; - } else { - iPtype=NX_UINT8; - } - } - else if (size_id==2) - { - if (sign_id==H5T_SGN_2) - { - iPtype=NX_INT16; - } else { - iPtype=NX_UINT16; - } - } - else if (size_id==4) - { - if (sign_id==H5T_SGN_2) - { - iPtype=NX_INT32; - } else { - iPtype=NX_UINT32; - } - } - else if(size_id == 8) - { - if (sign_id==H5T_SGN_2) - { - iPtype=NX_INT64; - } else { - iPtype=NX_UINT64; - } - } - } else if (data_id==H5T_FLOAT) - { - size_id=H5Tget_size(atype); - if (size_id==4) - { - iPtype=NX_FLOAT32; - } - else if (size_id==8) - { - iPtype=NX_FLOAT64; - } - } - if (iPtype == -1) - { - NXIReportError (NXpData, "ERROR: hdf5ToNXtype: invalid type"); - } + status = H5Gget_info(loc_id, &numobj); + if(status < 0) { + NXReportError("Internal error, failed to retrive no of objects"); + return 0; + } - return iPtype; + count = numobj.nlinks; + return count; } -/*--------------------------------------------------------------------------*/ -static int h5MemType(hid_t atype) -{ - hid_t data_id, size_id, sign_id, memtype_id = -1; - - data_id = H5Tget_class(atype); +/*----------------------------------------------------------------------------*/ + NXstatus NX5getgroupinfo (NXhandle fid, int *iN, NXname pName, NXname pClass) + { + pNexusFile5 pFile; + hid_t atype, attr_id, gid; + char data[64]; - if (data_id==H5T_INTEGER) - { - size_id=H5Tget_size(atype); - sign_id=H5Tget_sign(atype); - if (size_id==1) - { - if (sign_id==H5T_SGN_2) - { - memtype_id = H5T_NATIVE_INT8; - } else { - memtype_id = H5T_NATIVE_UINT8; - } - } - else if (size_id==2) - { - if (sign_id==H5T_SGN_2) - { - memtype_id = H5T_NATIVE_INT16; - } else { - memtype_id = H5T_NATIVE_UINT16; - } - } - else if (size_id==4) - { - if (sign_id==H5T_SGN_2) - { - memtype_id = H5T_NATIVE_INT32; - } else { - memtype_id = H5T_NATIVE_UINT32; - } - } - else if (size_id==8) - { - if (sign_id==H5T_SGN_2) - { - memtype_id = H5T_NATIVE_INT64; - } else { - memtype_id = H5T_NATIVE_UINT64; - } - } - } else if (data_id==H5T_FLOAT) - { - size_id=H5Tget_size(atype); - if (size_id==4) - { - memtype_id = H5T_NATIVE_FLOAT; - } else if (size_id==8) { - memtype_id = H5T_NATIVE_DOUBLE; - } + pFile = NXI5assert (fid); + /* check if there is a group open */ + if (pFile->iCurrentG == 0) { + strcpy (pName, "root"); + strcpy (pClass, "NXroot"); + gid = H5Gopen(pFile->iFID,"/", H5P_DEFAULT); + *iN = countObjectsInGroup(gid); + H5Gclose(gid); + } + else { + strcpy (pName,pFile->name_ref); + attr_id = H5Aopen_by_name(pFile->iCurrentG,".", "NX_class", H5P_DEFAULT, H5P_DEFAULT); + if (attr_id<0) { + strcpy(pClass, NX_UNKNOWN_GROUP); + } else { + atype=H5Tcopy(H5T_C_S1); + H5Tset_size(atype,sizeof(data)); + H5Aread(attr_id, atype, data); + strcpy(pClass,data); + pFile->iNX=0; + *iN = countObjectsInGroup(pFile->iCurrentG); + H5Aclose(attr_id); + } + } + return NX_OK; + } + + +/*------------------------------------------------------------------------- + * Function: hdf5ToNXType + * + * Purpose: Convert a HDF5 class to a NeXus type; it handles the following HDF5 classes + * H5T_STRING + * H5T_INTEGER + * H5T_FLOAT + * + * Return: the NeXus type + * + *------------------------------------------------------------------------- + */ + static int hdf5ToNXType(H5T_class_t tclass, hid_t atype) + { + int iPtype = -1; + size_t size; + H5T_sign_t sign; + + if (tclass==H5T_STRING) + { + iPtype=NX_CHAR; + } + else if (tclass==H5T_INTEGER) + { + size=H5Tget_size(atype); + sign=H5Tget_sign(atype); + if (size==1) + { + if (sign==H5T_SGN_2) + { + iPtype=NX_INT8; + } else { + iPtype=NX_UINT8; + } + } + else if (size==2) + { + if (sign==H5T_SGN_2) + { + iPtype=NX_INT16; + } else { + iPtype=NX_UINT16; + } + } + else if (size==4) + { + if (sign==H5T_SGN_2) + { + iPtype=NX_INT32; + } else { + iPtype=NX_UINT32; + } + } + else if(size == 8) + { + if (sign==H5T_SGN_2) + { + iPtype=NX_INT64; + } else { + iPtype=NX_UINT64; + } + } + } + else if (tclass==H5T_FLOAT) + { + size=H5Tget_size(atype); + if (size==4) + { + iPtype=NX_FLOAT32; + } + else if (size==8) + { + iPtype=NX_FLOAT64; + } + } + if (iPtype == -1) + { + NXReportError( "ERROR: hdf5ToNXtype: invalid type"); + } + + return iPtype; + } +/*--------------------------------------------------------------------------*/ + static hid_t h5MemType(hid_t atype) + { + hid_t memtype_id = -1; + size_t size; + H5T_sign_t sign; + H5T_class_t tclass; + + tclass = H5Tget_class(atype); + + if (tclass==H5T_INTEGER) + { + size=H5Tget_size(atype); + sign=H5Tget_sign(atype); + if (size==1) + { + if (sign==H5T_SGN_2) + { + memtype_id = H5T_NATIVE_INT8; + } else { + memtype_id = H5T_NATIVE_UINT8; + } + } + else if (size==2) + { + if (sign==H5T_SGN_2) + { + memtype_id = H5T_NATIVE_INT16; + } else { + memtype_id = H5T_NATIVE_UINT16; + } + } + else if (size==4) + { + if (sign==H5T_SGN_2) + { + memtype_id = H5T_NATIVE_INT32; + } else { + memtype_id = H5T_NATIVE_UINT32; + } + } + else if (size==8) + { + if (sign==H5T_SGN_2) + { + memtype_id = H5T_NATIVE_INT64; + } else { + memtype_id = H5T_NATIVE_UINT64; + } + } + } else if (tclass==H5T_FLOAT) + { + size=H5Tget_size(atype); + if (size==4) + { + memtype_id = H5T_NATIVE_FLOAT; + } else if (size==8) { + memtype_id = H5T_NATIVE_DOUBLE; + } } if (memtype_id == -1) { - NXIReportError (NXpData, "ERROR: h5MemType: invalid type"); + NXReportError( "ERROR: h5MemType: invalid type"); } return memtype_id; -} + } /*-------------------------------------------------------------------------*/ - NXstatus NX5getnextentry (NXhandle fid,NXname name, NXname nxclass, int *datatype) + NXstatus NX5getnextentry(NXhandle fid, NXname name, NXname nxclass, int *datatype) { pNexusFile5 pFile; - hid_t grp, attr1,type,atype; - int iRet,iPtype, i; - int idx,data_id,size_id, sign_id; - char data[128]; - char ph_name[1024]; - info_type op_data; - int iRet_iNX=-1; - char pBuffer[256]; + hid_t grp, attr1,type,atype; + herr_t iRet; + int iPtype, i; + hsize_t idx; + H5T_class_t tclass; + char data[128]; + char ph_name[1024]; + info_type op_data; + herr_t iRet_iNX=-1; + char pBuffer[256]; pFile = NXI5assert (fid); op_data.iname = NULL; @@ -1485,7 +1646,10 @@ static int h5MemType(hid_t atype) /* root group */ strcpy(pFile->name_ref,"/"); } - iRet=H5Giterate(pFile->iFID,pFile->name_ref,&idx,nxgroup_info,&op_data); + grp = H5Gopen(pFile->iFID, pFile->name_ref, H5P_DEFAULT); + // index can be wrong here + iRet=H5Literate(grp, H5_INDEX_NAME, H5_ITER_INC, &idx, nxgroup_info, &op_data); + H5Gclose(grp); strcpy(nxclass, NX_UNKNOWN_GROUP); /* @@ -1493,13 +1657,20 @@ static int h5MemType(hid_t atype) find out if we are at the end of the search. */ if (pFile->iCurrentG == 0) { + // if pFile->iCurrentG == 0 would not pFile->name_ref be "/" already, so we could skip that if statement ? pFile->iNX=0; - iRet_iNX = H5Giterate(pFile->iFID,"/",0,group_info1,&pFile->iNX); + grp = H5Gopen(pFile->iFID, "/", H5P_DEFAULT); + iRet_iNX=H5Literate(grp, H5_INDEX_NAME, H5_ITER_INC, 0, group_info1, &pFile->iNX); + H5Gclose(grp); } else { pFile->iNX=0; - iRet_iNX = H5Giterate(pFile->iFID,pFile->name_ref,0,group_info1, &pFile->iNX); + grp = H5Gopen(pFile->iFID, pFile->name_ref, H5P_DEFAULT); + // index can be wrong here + iRet_iNX=H5Literate(grp, H5_INDEX_NAME, H5_ITER_INC, 0, group_info1, &pFile->iNX); + H5Gclose(grp); } if (idx == pFile->iNX) { + // why 2? iRet_iNX = 2; } @@ -1513,8 +1684,7 @@ static int h5MemType(hid_t atype) pFile->iStack5[pFile->iStackPtr].iCurrentIDX = 0; return NX_EOD; } - if (op_data.type == H5G_GROUP) - { + if (op_data.type == H5O_TYPE_GROUP) { /* open group and find class name attribute */ @@ -1525,35 +1695,34 @@ static int h5MemType(hid_t atype) strcat(ph_name,"/"); } strcat(ph_name,name); - grp=H5Gopen(pFile->iFID,ph_name); + grp = H5Gopen(pFile->iFID,ph_name, H5P_DEFAULT); if (grp < 0) { - sprintf (pBuffer, "ERROR: Group %s does not exist!", ph_name); - NXIReportError (NXpData, pBuffer); + sprintf(pBuffer, "ERROR: group %s does not exist", ph_name); + NXReportError(pBuffer); return NX_ERROR; } - attr1 = H5Aopen_name(grp, "NX_class"); + attr1 = H5Aopen_by_name(grp,".", "NX_class", H5P_DEFAULT, H5P_DEFAULT); if (attr1 < 0) { strcpy(nxclass, NX_UNKNOWN_GROUP); } else { type=H5T_C_S1; atype=H5Tcopy(type); - H5Tset_size(atype,128); + H5Tset_size(atype,sizeof(data)); iRet = H5Aread(attr1, atype, data); strcpy(nxclass,data); H5Tclose(atype); H5Aclose(attr1); } H5Gclose(grp); - } else if (op_data.type==H5G_DATASET) - { + } else if (op_data.type==H5O_TYPE_DATASET) { /* open dataset and find type */ - grp=H5Dopen(pFile->iCurrentG,name); + grp=H5Dopen(pFile->iCurrentG,name, H5P_DEFAULT); type=H5Dget_type(grp); atype=H5Tcopy(type); - data_id = H5Tget_class(atype); - iPtype = hdf5ToNXType(data_id, atype); + tclass = H5Tget_class(atype); + iPtype = hdf5ToNXType(tclass, atype); *datatype=iPtype; strcpy(nxclass, "SDS"); H5Tclose(atype); @@ -1561,9 +1730,7 @@ static int h5MemType(hid_t atype) H5Dclose(grp); } return NX_OK; - } - else - { + } else { /* we are at the end of the search: clear the data structure and reset iCurrentIDX to 0 @@ -1578,8 +1745,7 @@ static int h5MemType(hid_t atype) if (op_data.iname != NULL) { free(op_data.iname); } - NXIReportError (NXpData, - "ERROR: Iteration (directory) was not successful"); + NXReportError("ERROR: iterating through group not successful"); return NX_ERROR; } } @@ -1590,20 +1756,21 @@ static int h5MemType(hid_t atype) { pNexusFile5 pFile; int iStart[H5S_MAX_RANK], status; - hid_t data_id, memtype_id, size_id, sign_id; + hid_t memtype_id; + H5T_class_t tclass; int dims; pFile = NXI5assert (fid); /* check if there is an Dataset open */ if (pFile->iCurrentD == 0) { - NXIReportError (NXpData, "ERROR: no Dataset open"); + NXReportError( "ERROR: no dataset open"); return NX_ERROR; } memset (iStart, 0, H5S_MAX_RANK * sizeof(int)); /* map datatypes of other plateforms */ - data_id = H5Tget_class(pFile->iCurrentT); - if (data_id==H5T_STRING) + tclass = H5Tget_class(pFile->iCurrentT); + if (tclass==H5T_STRING) { dims = H5Tget_size(pFile->iCurrentT); memtype_id = H5Tcopy(H5T_C_S1); @@ -1617,13 +1784,13 @@ static int h5MemType(hid_t atype) /* actually read */ status = H5Dread (pFile->iCurrentD, memtype_id, H5S_ALL, H5S_ALL,H5P_DEFAULT, data); - if(data_id == H5T_STRING) + if(tclass == H5T_STRING) { H5Tclose(memtype_id); } if(status < 0) { - NXIReportError (NXpData, "ERROR: failed to transfer dataset"); + NXReportError( "ERROR: failed to transfer dataset"); return NX_ERROR; } @@ -1632,28 +1799,28 @@ static int h5MemType(hid_t atype) /*-------------------------------------------------------------------------*/ - NXstatus NX5getinfo (NXhandle fid, int *rank, int dimension[], int *iType) + NXstatus NX5getinfo64 (NXhandle fid, int *rank, int64_t dimension[], int *iType) { pNexusFile5 pFile; - int i, iRank, mType, iRet; + int i, iRank, mType; hsize_t myDim[H5S_MAX_RANK]; - hid_t data_id,size_id,sign_id; + H5T_class_t tclass; pFile = NXI5assert (fid); /* check if there is an Dataset open */ if (pFile->iCurrentD == 0) { - NXIReportError (NXpData, "ERROR: no Dataset open"); + NXReportError( "ERROR: no dataset open"); return NX_ERROR; } /* read information */ - data_id = H5Tget_class(pFile->iCurrentT); - mType = hdf5ToNXType(data_id,pFile->iCurrentT); + tclass = H5Tget_class(pFile->iCurrentT); + mType = hdf5ToNXType(tclass,pFile->iCurrentT); iRank = H5Sget_simple_extent_ndims(pFile->iCurrentS); - iRet = H5Sget_simple_extent_dims(pFile->iCurrentS, myDim, NULL); + H5Sget_simple_extent_dims(pFile->iCurrentS, myDim, NULL); /* conversion to proper ints for the platform */ *iType = (int)mType; - if (data_id==H5T_STRING && myDim[iRank-1] == 1) { + if (tclass==H5T_STRING && myDim[iRank-1] == 1) { myDim[iRank-1] = H5Tget_size(pFile->iCurrentT); } *rank = (int)iRank; @@ -1666,14 +1833,15 @@ static int h5MemType(hid_t atype) /*-------------------------------------------------------------------------*/ - NXstatus NX5getslab (NXhandle fid, void *data, int iStart[], int iSize[]) + NXstatus NX5getslab64 (NXhandle fid, void *data, const int64_t iStart[], const int64_t iSize[]) { pNexusFile5 pFile; hsize_t myStart[H5S_MAX_RANK]; hsize_t mySize[H5S_MAX_RANK]; hsize_t mStart[H5S_MAX_RANK]; - hid_t memspace, iRet, data_id; - hid_t memtype_id, size_id, sign_id; + hid_t memspace, iRet; + H5T_class_t tclass; + hid_t memtype_id; char *tmp_data = NULL; char *data1; int i, dims, iRank, mtype = 0; @@ -1682,7 +1850,7 @@ static int h5MemType(hid_t atype) /* check if there is an Dataset open */ if (pFile->iCurrentD == 0) { - NXIReportError (NXpData, "ERROR: no Dataset open"); + NXReportError( "ERROR: no dataset open"); return NX_ERROR; } iRank = H5Sget_simple_extent_ndims(pFile->iCurrentS); @@ -1692,8 +1860,8 @@ static int h5MemType(hid_t atype) mySize[i] = (hsize_t)iSize[i]; mStart[i] = (hsize_t)0; } - data_id = H5Tget_class(pFile->iCurrentT); - if (data_id == H5T_STRING) { + tclass = H5Tget_class(pFile->iCurrentT); + if (tclass == H5T_STRING) { /* * FAA 24/1/2007: I don't think this will work for multidimensional * string arrays. @@ -1715,7 +1883,7 @@ static int h5MemType(hid_t atype) /* deal with HDF errors */ if (iRet < 0) { - NXIReportError (NXpData, "ERROR: selecting slab failed"); + NXReportError( "ERROR: selecting slab failed"); return NX_ERROR; } @@ -1724,11 +1892,11 @@ static int h5MemType(hid_t atype) NULL, mySize, NULL); if (iRet < 0) { - NXIReportError (NXpData, "ERROR: Select memspace failed"); + NXReportError( "ERROR: selecting memspace failed"); return NX_ERROR; } /* map datatypes of other plateforms */ - if (data_id==H5T_STRING) + if (tclass == H5T_STRING) { dims = H5Tget_size(pFile->iCurrentT); memtype_id = H5Tcopy(H5T_C_S1); @@ -1744,16 +1912,22 @@ static int h5MemType(hid_t atype) iRet = H5Dread(pFile->iCurrentD, memtype_id, H5S_ALL, H5S_ALL, H5P_DEFAULT,tmp_data); data1 = tmp_data + myStart[0]; - strncpy(data,data1,(hsize_t)iSize[0]); + strncpy((char*)data,data1,(hsize_t)iSize[0]); free(tmp_data); } else { iRet = H5Dread(pFile->iCurrentD, memtype_id, memspace, pFile->iCurrentS, H5P_DEFAULT,data); } + /* cleanup */ + if (tclass == H5T_STRING) { /* we used H5Tcopy */ + H5Tclose(memtype_id); + } + H5Sclose(memspace); if (iRet < 0) + { - NXIReportError (NXpData, "ERROR: Reading slab failed"); + NXReportError( "ERROR: reading slab failed"); return NX_ERROR; } return NX_OK; @@ -1763,45 +1937,47 @@ static int h5MemType(hid_t atype) /* Operator function. */ - herr_t attr_info(hid_t loc_id, const char *name, void *opdata) + herr_t attr_info(hid_t loc_id, const char *name, const H5A_info_t *unused, void *opdata) { *((char**)opdata)=strdup(name); return 1; } - NXstatus NX5getnextattr (NXhandle fileid, NXname pName, - int *iLength, int *iType) + NXstatus NX5getnextattr (NXhandle fileid, NXname pName, int *iLength, int *iType) { pNexusFile5 pFile; - hid_t attr_id,size_id,sign_id; - hid_t iRet, atype, aspace; + hid_t attr_id; + hid_t atype, aspace; + herr_t iRet; int iPType,rank; char *iname = NULL; - unsigned int idx; - int intern_idx=-1; + hsize_t idx, intern_idx=-1; int vid; - + H5O_info_t oinfo; pFile = NXI5assert (fileid); vid = getAttVID(pFile); + pName[0] = '\0'; idx=pFile->iAtt5.iCurrentIDX; iRet=0; - intern_idx=H5Aget_num_attrs(vid); + + H5Oget_info(vid, &oinfo); + intern_idx=oinfo.num_attrs; if(intern_idx == idx) { killAttVID(pFile,vid); return NX_EOD; } if (intern_idx > idx) { - iRet=H5Aiterate(vid,&idx,attr_info,&iname); + iRet=H5Aiterate(vid,H5_INDEX_CRT_ORDER,H5_ITER_INC,&idx,attr_info,&iname); } else { iRet=0; } intern_idx=-1; if (iRet < 0) { - NXIReportError (NXpData, "ERROR iterating through attribute list!"); + NXReportError( "ERROR: iterating through attribute list"); killAttVID(pFile,vid); return NX_ERROR; } @@ -1820,7 +1996,7 @@ static int h5MemType(hid_t atype) } else { strcpy(pName,"What is this?"); } - pFile->iCurrentA = H5Aopen_name(vid, pName); + pFile->iCurrentA = H5Aopen_by_name(vid, ".", pName, H5P_DEFAULT, H5P_DEFAULT); atype = H5Aget_type(pFile->iCurrentA); aspace = H5Aget_space(pFile->iCurrentA); rank = H5Sget_simple_extent_ndims(aspace); @@ -1839,7 +2015,8 @@ static int h5MemType(hid_t atype) H5Sclose(aspace); H5Aclose(pFile->iCurrentA); - intern_idx=H5Aget_num_attrs(vid); + H5Oget_info(vid, &oinfo); + intern_idx=oinfo.num_attrs; killAttVID(pFile,vid); return NX_OK; @@ -1850,45 +2027,46 @@ static int h5MemType(hid_t atype) void *data, int* datalen, int* iType) { pNexusFile5 pFile; - int iNew, iRet, vid; - hid_t type, atype = -1, glob; + int iNew, vid; + herr_t iRet; + hid_t type, atype = -1; char pBuffer[256]; pFile = NXI5assert (fid); - type = *iType; - glob = 0; - type = nxToHDF5Type(type); + type = nxToHDF5Type(*iType); vid = getAttVID(pFile); - iNew = H5Aopen_name(vid, name); + iNew = H5Aopen_by_name(vid, ".", name, H5P_DEFAULT, H5P_DEFAULT); if (iNew < 0) { - sprintf (pBuffer, "ERROR: attribute %s not found", name); + sprintf (pBuffer, "ERROR: attribute \"%s\" not found", name); killAttVID(pFile,vid); - NXIReportError (NXpData, pBuffer); + NXReportError( pBuffer); return NX_ERROR; } pFile->iCurrentA = iNew; /* finally read the data */ if (type==H5T_C_S1) { + atype = H5Aget_type(pFile->iCurrentA); + H5Tclose(atype); atype=H5Tcopy(type); H5Tset_size(atype,*datalen); iRet = H5Aread(pFile->iCurrentA, atype, data); - *datalen=strlen(data); + *datalen = strlen((char*)data); } else { iRet = H5Aread(pFile->iCurrentA, type, data); *datalen=1; } if (iRet < 0) { - sprintf (pBuffer, "ERROR: HDF could not read attribute data"); - NXIReportError (NXpData, pBuffer); + sprintf (pBuffer, "ERROR: could not read attribute data"); + NXReportError( pBuffer); killAttVID(pFile,vid); return NX_ERROR; } - iRet = H5Aclose(pFile->iCurrentA); + H5Aclose(pFile->iCurrentA); killAttVID(pFile,vid); if (type==H5T_C_S1) @@ -1903,18 +2081,18 @@ static int h5MemType(hid_t atype) NXstatus NX5getattrinfo (NXhandle fid, int *iN) { pNexusFile5 pFile; - char *iname = NULL; - unsigned int idx; + hid_t idx; int vid; - herr_t iRet; - + H5O_info_t oinfo; + pFile = NXI5assert (fid); idx=0; *iN = idx; vid = getAttVID(pFile); - idx=H5Aget_num_attrs(vid); + H5Oget_info(vid, &oinfo); + idx=oinfo.num_attrs; if (idx > 0) { if(pFile->iCurrentG > 0 && pFile->iCurrentD == 0){ *iN = idx -1; @@ -1933,9 +2111,7 @@ static int h5MemType(hid_t atype) NXstatus NX5getgroupID (NXhandle fileid, NXlink* sRes) { pNexusFile5 pFile; - int u, datalen, type = NX_CHAR; - char group_name[64], class_name[64]; - ErrFunc oldErr; + int datalen, type = NX_CHAR; pFile = NXI5assert (fileid); if (pFile->iCurrentG == 0) { @@ -1946,14 +2122,13 @@ static int h5MemType(hid_t atype) this means: if the item is already linked: use the target attribute, else the path to the current node */ - oldErr = NXMGetError(); - NXMSetError(NXpData, ignoreError); + NXMDisableErrorReporting(); datalen = 1024; memset(sRes->targetPath,0,datalen*sizeof(char)); if(NX5getattr(fileid,"target",sRes->targetPath,&datalen,&type) != NX_OK){ buildCurrentPath(pFile,sRes->targetPath,1024); } - NXMSetError(NXpData,oldErr); + NXMEnableErrorReporting(); sRes->linkType = 0; return NX_OK; } @@ -1961,13 +2136,101 @@ static int h5MemType(hid_t atype) return NX_ERROR; } + /* ------------------------------------------------------------------- */ + + NXstatus NX5nativeexternallink(NXhandle fileid, const char* name, const char* externalfile, const char* remotetarget) + { + herr_t iRet; + pNexusFile5 pFile; + hid_t openwhere; + + pFile = NXI5assert(fileid); + + if (pFile->iCurrentG <= 0) { + openwhere = pFile->iFID; + } else { + openwhere = pFile->iCurrentG; + } + + iRet = H5Lcreate_external(externalfile, remotetarget, openwhere, name, H5P_DEFAULT, H5P_DEFAULT); + if (iRet < 0) { + NXReportError("ERROR: making external link failed"); + return NX_ERROR; + } + return NX_OK; + } + /* ------------------------------------------------------------------- */ + + NXstatus NX5nativeinquirefile(NXhandle fileid, char* externalfile, const int filenamelen) + { + pNexusFile5 pFile; + ssize_t name_size; + hid_t openthing; + + pFile = NXI5assert(fileid); + if (pFile->iCurrentD > 0) { + openthing = pFile->iCurrentD; + } else if (pFile->iCurrentG > 0) { + openthing = pFile->iCurrentG; + } else { + openthing = pFile->iFID; + } + + name_size = H5Fget_name(openthing, externalfile, filenamelen); + + // Check for failure again + if( name_size < 0 ) { + NXReportError("ERROR: retrieving file name"); + return NX_ERROR; + } + return NX_OK; + } + /* ------------------------------------------------------------------- */ + + NXstatus NX5nativeisexternallink(NXhandle fileid, const char* name, char* url, const int urllen) + { + pNexusFile5 pFile; + herr_t ret; + H5L_info_t link_buff; + char linkval_buff[1024]; + const char *filepath = NULL, *objpath = NULL; + size_t val_size; + + pFile = NXI5assert(fileid); + memset(url, 0, urllen); + + ret = H5Lget_info(pFile->iFID, name, &link_buff, H5P_DEFAULT); + if (ret < 0 || link_buff.type != H5L_TYPE_EXTERNAL) { + return NX_ERROR; + } + + val_size = link_buff.u.val_size; + if (val_size > sizeof(linkval_buff)) { + NXReportError("ERROR: linkval_buff too small"); + return NX_ERROR; + } + + ret = H5Lget_val(pFile->iFID, name, linkval_buff, val_size, H5P_DEFAULT); + if (ret < 0) { + NXReportError("ERROR: H5Lget_val failed"); + return NX_ERROR; + } + + ret = H5Lunpack_elink_val(linkval_buff, val_size, NULL, &filepath, &objpath); + if (ret < 0) { + NXReportError("ERROR: H5Lunpack_elink_val failed"); + return NX_ERROR; + } + + snprintf(url, urllen-1, "nxfile://%s#%s", filepath, objpath); + return NX_OK; + + } /* ------------------------------------------------------------------- */ NXstatus NX5sameID (NXhandle fileid, NXlink* pFirstID, NXlink* pSecondID) { - pNexusFile5 pFile; - - pFile = NXI5assert (fileid); + NXI5assert(fileid); if ((strcmp(pFirstID->targetPath,pSecondID->targetPath) == 0)){ return NX_OK; } else { @@ -1982,7 +2245,7 @@ static int h5MemType(hid_t atype) pNexusFile5 pFile; pFile = NXI5assert (fid); - NXI5KillAttDir (fid); + NXI5KillAttDir (pFile); return NX_OK; } @@ -1993,33 +2256,34 @@ static int h5MemType(hid_t atype) pNexusFile5 pFile; pFile = NXI5assert (fid); - NXI5KillDir (fid); + NXI5KillDir (pFile); return NX_OK; } /*------------------------------------------------------------------------*/ void NX5assignFunctions(pNexusFunction fHandle) { - + fHandle->nxclose=NX5close; + fHandle->nxreopen=NX5reopen; fHandle->nxflush=NX5flush; fHandle->nxmakegroup=NX5makegroup; fHandle->nxopengroup=NX5opengroup; fHandle->nxclosegroup=NX5closegroup; - fHandle->nxmakedata=NX5makedata; - fHandle->nxcompmakedata=NX5compmakedata; + fHandle->nxmakedata64=NX5makedata64; + fHandle->nxcompmakedata64=NX5compmakedata64; fHandle->nxcompress=NX5compress; fHandle->nxopendata=NX5opendata; fHandle->nxclosedata=NX5closedata; fHandle->nxputdata=NX5putdata; fHandle->nxputattr=NX5putattr; - fHandle->nxputslab=NX5putslab; + fHandle->nxputslab64=NX5putslab64; fHandle->nxgetdataID=NX5getdataID; fHandle->nxmakelink=NX5makelink; fHandle->nxmakenamedlink=NX5makenamedlink; fHandle->nxgetdata=NX5getdata; - fHandle->nxgetinfo=NX5getinfo; + fHandle->nxgetinfo64=NX5getinfo64; fHandle->nxgetnextentry=NX5getnextentry; - fHandle->nxgetslab=NX5getslab; + fHandle->nxgetslab64=NX5getslab64; fHandle->nxgetnextattr=NX5getnextattr; fHandle->nxgetattr=NX5getattr; fHandle->nxgetattrinfo=NX5getattrinfo; @@ -2029,4 +2293,9 @@ void NX5assignFunctions(pNexusFunction fHandle) fHandle->nxinitgroupdir=NX5initgroupdir; fHandle->nxinitattrdir=NX5initattrdir; fHandle->nxprintlink=NX5printlink; + fHandle->nxnativeexternallink=NX5nativeexternallink; + fHandle->nxnativeinquirefile=NX5nativeinquirefile; + fHandle->nxnativeisexternallink=NX5nativeisexternallink; } + +#endif /* HDF5 */ diff --git a/napi5.h b/napi5.h index 61d67315..79490782 100644 --- a/napi5.h +++ b/napi5.h @@ -1,3 +1,6 @@ +#ifndef NAPI5_H +#define NAPI5_H + #define NX5SIGNATURE 959695 #include @@ -5,6 +8,8 @@ /* HDF5 interface */ extern NXstatus NX5open(CONSTCHAR *filename, NXaccess access_method, NXhandle* pHandle); +extern NXstatus NX5reopen(NXhandle pOrigHandle, NXhandle* pNewHandle); + extern NXstatus NX5close(NXhandle* pHandle); extern NXstatus NX5flush(NXhandle* pHandle); @@ -12,25 +17,25 @@ extern NXstatus NX5makegroup (NXhandle handle, CONSTCHAR *name, CONSTCHAR* NXc extern NXstatus NX5opengroup (NXhandle handle, CONSTCHAR *name, CONSTCHAR* NXclass); extern NXstatus NX5closegroup(NXhandle handle); -extern NXstatus NX5makedata (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int dim[]); -extern NXstatus NX5compmakedata (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int dim[], int comp_typ, int bufsize[]); +extern NXstatus NX5makedata64 (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int64_t dim[]); +extern NXstatus NX5compmakedata64 (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int64_t dim[], int comp_typ, int64_t bufsize[]); extern NXstatus NX5compress (NXhandle handle, int compr_type); extern NXstatus NX5opendata (NXhandle handle, CONSTCHAR* label); extern NXstatus NX5closedata(NXhandle handle); -extern NXstatus NX5putdata(NXhandle handle, void* data); +extern NXstatus NX5putdata(NXhandle handle, const void* data); -extern NXstatus NX5putattr(NXhandle handle, CONSTCHAR* name, void* data, int iDataLen, int iType); -extern NXstatus NX5putslab(NXhandle handle, void* data, int start[], int size[]); +extern NXstatus NX5putattr(NXhandle handle, CONSTCHAR* name, const void* data, int iDataLen, int iType); +extern NXstatus NX5putslab64(NXhandle handle, const void* data, const int64_t start[], const int64_t size[]); extern NXstatus NX5getdataID(NXhandle handle, NXlink* pLink); extern NXstatus NX5makelink(NXhandle handle, NXlink* pLink); extern NXstatus NX5printlink(NXhandle handle, NXlink* pLink); extern NXstatus NX5getdata(NXhandle handle, void* data); -extern NXstatus NX5getinfo(NXhandle handle, int* rank, int dimension[], int* datatype); +extern NXstatus NX5getinfo64(NXhandle handle, int* rank, int64_t dimension[], int* datatype); extern NXstatus NX5getnextentry(NXhandle handle, NXname name, NXname nxclass, int* datatype); -extern NXstatus NX5getslab(NXhandle handle, void* data, int start[], int size[]); +extern NXstatus NX5getslab64(NXhandle handle, void* data, const int64_t start[], const int64_t size[]); extern NXstatus NX5getnextattr(NXhandle handle, NXname pName, int *iLength, int *iType); extern NXstatus NX5getattr(NXhandle handle, char* name, void* data, int* iDataLen, int* iType); extern NXstatus NX5getattrinfo(NXhandle handle, int* no_items); @@ -42,7 +47,8 @@ extern NXstatus NX5initattrdir(NXhandle handle); void NX5assignFunctions(pNexusFunction fHandle); -herr_t nxgroup_info(hid_t loc_id, const char *name, void *op_data); -herr_t attr_info(hid_t loc_id, const char *name, void *opdata); -herr_t group_info(hid_t loc_id, const char *name, void *opdata); +herr_t attr_info(hid_t loc_id, const char *name, const H5A_info_t *unused, void *opdata); +herr_t group_info(hid_t loc_id, const char *name, const H5L_info_t *unused, void *opdata); +herr_t nxgroup_info(hid_t loc_id, const char *name, const H5L_info_t *unused, void *op_data); +#endif /* NAPI5_H */ diff --git a/napiconfig.h b/napiconfig.h index 5b238331..4282838a 100755 --- a/napiconfig.h +++ b/napiconfig.h @@ -1,22 +1,28 @@ #ifndef NAPICONFIG_H #define NAPICONFIG_H +#ifdef _WIN32 +#include +#endif /* _WIN32 */ + +#ifdef __VMS +#include +#else #include +#endif /* __VMS */ + /* - * Type definitions + * Integer type definitions + * + * int32_t etc will be defined by configure in nxconfig.h + * if they exist; otherwise include an appropriate header */ -#ifdef HAVE_STDINT_H +#if HAVE_STDINT_H #include -#else -typedef signed char int8_t; -typedef short int int16_t; -typedef int int32_t; -typedef long int64_t; -typedef unsigned char uint8_t; -typedef unsigned short int uint16_t; -typedef unsigned int uint32_t; -typedef unsigned long uint64_t; - +#elif HAVE_INTTYPES_H +#include #endif /* HAVE_STDINT_H */ + + #endif /* NAPICONFIG_H */ diff --git a/napiu.c b/napiu.c index 4cb02093..2a8d9de8 100644 --- a/napiu.c +++ b/napiu.c @@ -103,7 +103,7 @@ static int NXcompress_size = 0; } else { - NXIReportError(NXpData, "Invalid compression option"); + NXReportError( "Invalid compression option"); status = NX_ERROR; } return status; diff --git a/napiu.h b/napiu.h index efc223f8..3f9c3adb 100644 --- a/napiu.h +++ b/napiu.h @@ -24,7 +24,7 @@ $Id$ ----------------------------------------------------------------------------*/ - + #ifndef NEXUSAPIU #define NEXUSAPIU @@ -32,41 +32,59 @@ #ifdef __cplusplus extern "C" { -#endif /* __cplusplus */ +#endif /* __cplusplus */ -extern NXstatus NXUwriteglobals(NXhandle file_id, const char* user, const char* affiliation, const char* address, const char* phone, const char* fax, const char* email); + extern NXstatus NXUwriteglobals(NXhandle file_id, const char *user, + const char *affiliation, + const char *address, const char *phone, + const char *fax, const char *email); -extern NXstatus NXUwritegroup(NXhandle file_id, const char* group_name, const char* group_class); + extern NXstatus NXUwritegroup(NXhandle file_id, const char *group_name, + const char *group_class); -extern NXstatus NXUwritedata(NXhandle file_id, const char* data_name, const void* data, int data_type, int rank, const int dim[], const char* units, const int start[], const int size[]); + extern NXstatus NXUwritedata(NXhandle file_id, const char *data_name, + const void *data, int data_type, int rank, + const int dim[], const char *units, + const int start[], const int size[]); -extern NXstatus NXUreaddata(NXhandle file_id, const char* data_name, void* data, char* units, const int start[], const int size[]); + extern NXstatus NXUreaddata(NXhandle file_id, const char *data_name, + void *data, char *units, const int start[], + const int size[]); -extern NXstatus NXUwritehistogram(NXhandle file_id, const char* data_name, const void* data, const char* units); + extern NXstatus NXUwritehistogram(NXhandle file_id, + const char *data_name, + const void *data, const char *units); -extern NXstatus NXUreadhistogram(NXhandle file_id, const char* data_name, void* data, char* units); + extern NXstatus NXUreadhistogram(NXhandle file_id, const char *data_name, + void *data, char *units); -extern NXstatus NXUsetcompress(NXhandle file_id, int comp_type, int comp_size); + extern NXstatus NXUsetcompress(NXhandle file_id, int comp_type, + int comp_size); -extern NXstatus NXUfindgroup(NXhandle file_id, const char* group_name, char* group_class); + extern NXstatus NXUfindgroup(NXhandle file_id, const char *group_name, + char *group_class); -extern NXstatus NXUfindclass(NXhandle file_id, const char* group_class, char* group_name, int find_index); + extern NXstatus NXUfindclass(NXhandle file_id, const char *group_class, + char *group_name, int find_index); -extern NXstatus NXUfinddata(NXhandle file_id, const char* data_name); + extern NXstatus NXUfinddata(NXhandle file_id, const char *data_name); -extern NXstatus NXUfindattr(NXhandle file_id, const char* attr_name); + extern NXstatus NXUfindattr(NXhandle file_id, const char *attr_name); -extern NXstatus NXUfindsignal(NXhandle file_id, int signal, char* data_name, int* data_rank, int* data_type, int data_dimensions[]); + extern NXstatus NXUfindsignal(NXhandle file_id, int signal, + char *data_name, int *data_rank, + int *data_type, int data_dimensions[]); -extern NXstatus NXUfindaxis(NXhandle file_id, int axis, int primary, char* data_name, int* data_rank, int* data_type, int data_dimensions[]); + extern NXstatus NXUfindaxis(NXhandle file_id, int axis, int primary, + char *data_name, int *data_rank, + int *data_type, int data_dimensions[]); -extern NXstatus NXUfindlink(NXhandle file_id, NXlink* group_id, const char* group_class); + extern NXstatus NXUfindlink(NXhandle file_id, NXlink * group_id, + const char *group_class); -extern NXstatus NXUresumelink(NXhandle file_id, NXlink group_id); + extern NXstatus NXUresumelink(NXhandle file_id, NXlink group_id); #ifdef __cplusplus } -#endif /* __cplusplus */ - +#endif /* __cplusplus */ #endif /*NEXUSAPIU*/ - diff --git a/network.c b/network.c index cd4420e3..be90cf31 100644 --- a/network.c +++ b/network.c @@ -51,606 +51,591 @@ #include #include #include +#include "sics.h" +#include "commandlog.h" +#include "uselect.h" #define PORT 1 #define SOCKET 2 #define UDP 3 /* wait time [ms] between a close and the next open */ -#define WAIT_CLOSE_OPEN 500 +#define WAIT_CLOSE_OPEN 500 + +struct timeval lastclose = { -1, 0 }; -struct timeval lastclose={-1,0}; /*----------------------------------------------------------------------- Redefine this function if another means of error reporting is necessary. */ -#include "Scommon.h" - extern void SICSLogWrite(char *pText, OutCode eCode); /* servlog.c */ - - void WriteToCommandLog(char *p, char *t); - - static void NetError(char *pText) - { +static void NetError(char *pText) +{ /* SICSLogWrite(pText,eError); */ - WriteToCommandLog("NET>", pText); - } + WriteToCommandLog("NET>", pText); +} /* ---------------------------- 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; } + /*-------------------------------------------------------------------------*/ - mkChannel *NETOpenPort(int iPort) - { - mkChannel *pRes = NULL; - int iRet,i; - struct linger lili; - - pRes = (mkChannel *)malloc(sizeof(mkChannel)); - if(!pRes) - return NULL; - - /* open a socket */ - pRes->sockid = socket(AF_INET,SOCK_STREAM,0); - if(pRes->sockid < 0) - { - free(pRes); - return NULL; - } - - /* REUSEADDR, for restarts */ - i = 1; - setsockopt(pRes->sockid,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(int)); - - /* bind */ - memset(&(pRes->adresse),0,sizeof(struct sockaddr_in)); - pRes->adresse.sin_family = AF_INET; - pRes->adresse.sin_addr.s_addr = htonl(INADDR_ANY); - pRes->adresse.sin_port = htons(iPort); - iRet = bind(pRes->sockid,(struct sockaddr *)&(pRes->adresse), - sizeof(struct sockaddr_in)); - if(iRet < 0) - { - free(pRes); - return NULL; - } - - /* listen */ - iRet = listen(pRes->sockid,8); - if(iRet < 0) - { - free(pRes); - return NULL; - } - i = sizeof(struct linger); - lili.l_onoff = 1; - lili.l_linger = 1; - /* - setsockopt(pRes->sockid,SOL_SOCKET,SO_LINGER,&lili,i); - */ - pRes->iType = PORT; - pRes->lMagic = NETMAGIC; - return pRes; - } +mkChannel *NETOpenPort(int iPort) +{ + mkChannel *pRes = NULL; + int iRet, i; + struct linger lili; + + pRes = (mkChannel *) malloc(sizeof(mkChannel)); + if (!pRes) + return NULL; + + /* open a socket */ + pRes->sockid = socket(AF_INET, SOCK_STREAM, 0); + if (pRes->sockid < 0) { + free(pRes); + return NULL; + } + + /* REUSEADDR, for restarts */ + i = 1; + setsockopt(pRes->sockid, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(int)); + + /* bind */ + memset(&(pRes->adresse), 0, sizeof(struct sockaddr_in)); + pRes->adresse.sin_family = AF_INET; + pRes->adresse.sin_addr.s_addr = htonl(INADDR_ANY); + pRes->adresse.sin_port = htons(iPort); + iRet = bind(pRes->sockid, (struct sockaddr *) &(pRes->adresse), + sizeof(struct sockaddr_in)); + if (iRet < 0) { + free(pRes); + return NULL; + } + + /* listen */ + iRet = listen(pRes->sockid, 8); + if (iRet < 0) { + free(pRes); + return NULL; + } + i = sizeof(struct linger); + lili.l_onoff = 1; + lili.l_linger = 1; + /* + setsockopt(pRes->sockid,SOL_SOCKET,SO_LINGER,&lili,i); + */ + pRes->iType = PORT; + pRes->lMagic = NETMAGIC; + return pRes; +} + /*---------------------------------------------------------------------------*/ - mkChannel *NETAccept(mkChannel *self, long timeout) - { - mkChannel *pRes = NULL; - int iRet; - fd_set lMask; - struct timeval tmo = {1,0}; - int i; - socklen_t iLen; - struct linger lili; - - assert(self != NULL); - - if(timeout >= 0) - { - /* select first */ - tmo.tv_usec = (timeout % 1000) * 1000; - tmo.tv_sec = timeout / 1000; - FD_ZERO(&lMask); - FD_SET(self->sockid,&lMask); - if((self->sockid >= FD_SETSIZE) || (self->sockid < 0) ) /* invalid descriptor */ - { - return NULL; /* eof */ - } - iRet = select( (self->sockid + 1),(fd_set *)&lMask, NULL, NULL,&tmo); - if( iRet <= 0) - { - /* failure, or no request */ - return NULL; - } - } - - /* positive: accept */ - iLen = sizeof(struct sockaddr); - pRes = (mkChannel *)malloc(sizeof(mkChannel)); - if(!pRes) return NULL; - - pRes->sockid = accept(self->sockid, - (struct sockaddr *)&(pRes->adresse), - &iLen); - if(pRes->sockid < 0) - { - free(pRes); - return NULL; - } - /* - i = sizeof(struct linger); - lili.l_onoff = 1; - lili.l_linger = 1; - setsockopt(pRes->sockid,SOL_SOCKET,SO_LINGER,&lili,i); - i = 1; - setsockopt(pRes->sockid,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(int)); - */ - pRes->iType = SOCKET; - pRes->lMagic = NETMAGIC; - return pRes; - - } -/*--------------------------------------------------------------------------*/ - mkChannel *NETConnectWithFlags(char *name, int port, int flags) - { - mkChannel *pRes = NULL; - int iRet, i, cnt; - char pBueffel[80]; - struct hostent *pServer = NULL; - struct linger lili; - struct timeval now; - long dif; - int oldopts; - - assert(port > 0); - - /* default name to localhost */ - if(name == NULL) - { - strcpy(pBueffel,"localhost"); - name = pBueffel; - } - - /* new channel */ - pRes = (mkChannel *)malloc(sizeof(mkChannel)); - if(!pRes) - return NULL; +mkChannel *NETAccept(mkChannel * self, long timeout) +{ + mkChannel *pRes = NULL; + int iRet; + fd_set lMask; + struct timeval tmo = { 1, 0 }; + int i; + socklen_t iLen; + struct linger lili; + + assert(self != NULL); + + if (timeout >= 0) { + /* select first */ + tmo.tv_usec = (timeout % 1000) * 1000; + tmo.tv_sec = timeout / 1000; + FD_ZERO(&lMask); + FD_SET(self->sockid, &lMask); + if ((self->sockid >= FD_SETSIZE) || (self->sockid < 0)) { /* invalid descriptor */ + return NULL; /* eof */ + } + iRet = + uselect((self->sockid + 1), (fd_set *) & lMask, NULL, NULL, &tmo); + if (iRet <= 0) { + /* failure, or no request */ + return NULL; + } + } + + /* positive: accept */ + iLen = sizeof(struct sockaddr); + pRes = (mkChannel *) malloc(sizeof(mkChannel)); + if (!pRes) + return NULL; + + pRes->sockid = accept(self->sockid, + (struct sockaddr *) &(pRes->adresse), &iLen); + if (pRes->sockid < 0) { + free(pRes); + return NULL; + } + /* + i = sizeof(struct linger); + lili.l_onoff = 1; + lili.l_linger = 1; + setsockopt(pRes->sockid,SOL_SOCKET,SO_LINGER,&lili,i); + i = 1; + setsockopt(pRes->sockid,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(int)); + */ + pRes->iType = SOCKET; + pRes->lMagic = NETMAGIC; + return pRes; + +} - /* connect */ - iRet = CreateSocketAdress(&(pRes->adresse),name,port); - if(!iRet) - { - free(pRes); - return NULL; - } - pRes->sockid = socket(AF_INET,SOCK_STREAM,0); - if(pRes->sockid < 0) - { - free(pRes); - return NULL; - } - - if (flags & 2) { /* wait if closed recently */ - /* workaround for a bug in Lantronix terminal server: - if a channel is closed and reopened within short time - the connect will be succesful, but a message will be - sent on the channel! */ - - if (lastclose.tv_sec >= 0) { - gettimeofday(&now, NULL); - dif = (now.tv_sec-lastclose.tv_sec)*1000+(now.tv_usec-lastclose.tv_usec)/1000; - if (dif < 0) dif += 24*3600*1000; - } else { - dif = 0; - } - if (dif < WAIT_CLOSE_OPEN) { - usleep((WAIT_CLOSE_OPEN-dif)*1000); - } - } - - if (flags & 1) { /* open in non blocking mode */ - oldopts = fcntl(pRes->sockid, F_GETFL, 0); - fcntl(pRes->sockid, F_SETFL, oldopts | O_NONBLOCK); - } - - iRet = connect(pRes->sockid,(struct sockaddr *)&(pRes->adresse), - sizeof(struct sockaddr_in)); - if(iRet < 0) - { - if (errno != EINPROGRESS) { - free(pRes); - return NULL; - } - } - /* - i = sizeof(struct linger); - lili.l_onoff = 1; - lili.l_linger = 1; - setsockopt(pRes->sockid,SOL_SOCKET,SO_LINGER,&lili,i); - i = 1; - setsockopt(pRes->sockid,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(int)); - */ - pRes->iType = SOCKET; - pRes->lMagic = NETMAGIC; - return pRes; - } /*--------------------------------------------------------------------------*/ - mkChannel *NETConnect(char *name, int port) { - return NETConnectWithFlags(name, port, 0); - } +mkChannel *NETConnectWithFlags(char *name, int port, int flags) +{ + mkChannel *pRes = NULL; + int iRet, i, cnt; + char pBueffel[80]; + struct hostent *pServer = NULL; + struct linger lili; + struct timeval now; + long dif; + int oldopts; + + assert(port > 0); + + /* default name to localhost */ + if (name == NULL) { + strcpy(pBueffel, "localhost"); + name = pBueffel; + } + + /* new channel */ + pRes = (mkChannel *) malloc(sizeof(mkChannel)); + if (!pRes) + return NULL; + + /* connect */ + iRet = CreateSocketAdress(&(pRes->adresse), name, port); + if (!iRet) { + free(pRes); + return NULL; + } + pRes->sockid = socket(AF_INET, SOCK_STREAM, 0); + if (pRes->sockid < 0) { + free(pRes); + return NULL; + } + + if (flags & 2) { /* wait if closed recently */ + /* workaround for a bug in Lantronix terminal server: + if a channel is closed and reopened within short time + the connect will be succesful, but a message will be + sent on the channel! */ + + if (lastclose.tv_sec >= 0) { + gettimeofday(&now, NULL); + dif = + (now.tv_sec - lastclose.tv_sec) * 1000 + (now.tv_usec - + lastclose.tv_usec) / + 1000; + if (dif < 0) + dif += 24 * 3600 * 1000; + } else { + dif = 0; + } + if (dif < WAIT_CLOSE_OPEN) { + usleep((WAIT_CLOSE_OPEN - dif) * 1000); + } + } + + if (flags & 1) { /* open in non blocking mode */ + oldopts = fcntl(pRes->sockid, F_GETFL, 0); + fcntl(pRes->sockid, F_SETFL, oldopts | O_NONBLOCK); + } + + iRet = connect(pRes->sockid, (struct sockaddr *) &(pRes->adresse), + sizeof(struct sockaddr_in)); + if (iRet < 0) { + if (errno != EINPROGRESS) { + free(pRes); + return NULL; + } + } + /* + i = sizeof(struct linger); + lili.l_onoff = 1; + lili.l_linger = 1; + setsockopt(pRes->sockid,SOL_SOCKET,SO_LINGER,&lili,i); + i = 1; + setsockopt(pRes->sockid,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(int)); + */ + pRes->iType = SOCKET; + pRes->lMagic = NETMAGIC; + return pRes; +} + /*--------------------------------------------------------------------------*/ - int NETConnectFinished(mkChannel *self) { - fd_set wmask, rmask; - struct timeval tmo = {0,0}; - int iret; - int oldopts; - - if (self->sockid == 0) { - errno = ENOTCONN; - return -1; - } - oldopts = fcntl(self->sockid, F_GETFL, 0); - if (! (oldopts & O_NONBLOCK)) { /* DCL was | */ - /* assume success when in blocking mode */ - return 1; - } - FD_ZERO(&wmask); - FD_ZERO(&rmask); - FD_SET(self->sockid, &wmask); - FD_SET(self->sockid, &rmask); - iret = select(self->sockid+1, &rmask, &wmask, NULL, &tmo); - if (iret == 0) return 0; /* in progress */ - if (iret > 0) { - /* the connection has either succeded or failed - - the write flag indicates success - - the read flag indicates, if there is already data pending - the read flag should not appear without the write flag - */ - if (FD_ISSET(self->sockid, &wmask)) { /* should always be true */ - if (FD_ISSET(self->sockid, &rmask)) { /* there may already be data for read */ - iret = recv(self->sockid, NULL, 0, 0); /* zero length, check only return value */ - if (iret >= 0) { - iret = 1; /* success */ - } /* else failure */ - } else { - iret = send(self->sockid, NULL, 0, 0); /* zero length, check only return value */ - if (iret >= 0) { - iret = 1; /* success */ - } /* else failure */ - } - } - } - /* reset to blocking mode */ - fcntl(self->sockid, F_SETFL, oldopts & ~ O_NONBLOCK); /* DCL was | */ - return iret; - } -/*------------------------------------------------------------------------*/ - int VerifyChannel(mkChannel *self) - { - if(!self) - { - return 0; - } - if(self->lMagic != NETMAGIC) - { - NetError("CORRUPTED MAGIC: network channel data corrupted"); - return 0; - } - if( (self->sockid < 0) || (self->sockid > 65000) ) - { - NetError("MAGIC DEAD: Invalid socket number, data corrupted"); - return 0; - } +mkChannel *NETConnect(char *name, int port) +{ + return NETConnectWithFlags(name, port, 0); +} + +/*--------------------------------------------------------------------------*/ +int NETConnectFinished(mkChannel * self) +{ + fd_set wmask, rmask; + struct timeval tmo = { 0, 0 }; + int iret; + int oldopts; + int olderrno; + + if (self->sockid == 0) { + errno = ENOTCONN; + return -1; + } + oldopts = fcntl(self->sockid, F_GETFL, 0); + if (!(oldopts | O_NONBLOCK)) { + /* assume success when in blocking mode */ return 1; - } -/*------------------------------------------------------------------------*/ - int NETInfo(mkChannel *self, char *pCompost, int iBufLen) - { + } + FD_ZERO(&wmask); + FD_ZERO(&rmask); + FD_SET(self->sockid, &wmask); + FD_SET(self->sockid, &rmask); + iret = uselect(self->sockid + 1, &rmask, &wmask, NULL, &tmo); + if (iret == 0) + return 0; /* in progress */ + if (iret > 0) { + /* the connection has either succeded or failed + - the write flag indicates success + - the read flag indicates, if there is already data pending + the read flag should not appear without the write flag + */ + if (FD_ISSET(self->sockid, &wmask)) { /* should always be true */ + if (FD_ISSET(self->sockid, &rmask)) { /* there may already be data for read */ + iret = recv(self->sockid, NULL, 0, 0); /* zero length, check only return value */ + if (iret >= 0) { + iret = 1; /* success */ + } /* else failure */ + } else { + iret = send(self->sockid, NULL, 0, 0); /* zero length, check only return value */ + if (iret >= 0) { + iret = 1; /* success */ + } /* else failure */ + } + } + } + /* reset to blocking mode */ + olderrno = errno; + fcntl(self->sockid, F_SETFL, oldopts | ~O_NONBLOCK); + errno = olderrno; + return iret; +} - int t; - socklen_t len; - struct sockaddr_in sin; - struct hostent *host; - - if(!VerifyChannel(self)) - { +/*------------------------------------------------------------------------*/ +int VerifyChannel(mkChannel * self) +{ + if (!self) { + return 0; + } + if (self->lMagic != NETMAGIC) { + NetError("CORRUPTED MAGIC: network channel data corrupted"); + return 0; + } + if ((self->sockid < 0) || (self->sockid > 65000)) { + NetError("MAGIC DEAD: Invalid socket number, data corrupted"); + return 0; + } + return 1; +} + +/*------------------------------------------------------------------------*/ +int NETInfo(mkChannel * self, char *pCompost, int iBufLen) +{ + + int t; + socklen_t len; + struct sockaddr_in sin; + struct hostent *host; + + if (!VerifyChannel(self)) { + return 0; + } + + len = sizeof sin; + if (getpeername(self->sockid, (struct sockaddr *) &sin, &len) < 0) { + return 0; + } else { + if ((host = gethostbyaddr((char *) &sin.sin_addr, + sizeof sin.sin_addr, AF_INET)) == NULL) { + return 0; + } else { + strlcpy(pCompost, host->h_name, iBufLen); + pCompost[iBufLen - 1] = '\0'; + } + } + return 1; +} + +/*--------------------------------------------------------------------------*/ +int NETWrite(mkChannel * self, char *buffer, long lLen) +{ + long iRet; + fd_set lMask; + struct timeval tmo; + char buf[256]; + time_t expire, delta; + char *pos; + long l; + int disconnected; + + if (!VerifyChannel(self)) { + return 0; + } + if (!(self->iType == SOCKET)) { + return 0; + } + + /* + * Check if the we can write to the socket first.... + * Well, this how it should be. However, on linux I observe that + * there is a problem with Java clients not reliably receiving data when + * this is active. + */ + if ((self->sockid >= FD_SETSIZE) || (self->sockid < 0)) { + /* invalid descriptor */ + return 0; + } +#ifdef DO_NOT_SELECT_BEFORE_SEND + iRet = send(self->sockid, buffer, lLen, 0); + if (iRet != lLen) { + self->iType = 0; + if (iRet < 0) { + if (errno == EPIPE) { /* do not write "broken pipe" error */ return 0; } - - len = sizeof sin; - if (getpeername(self->sockid, (struct sockaddr *) &sin, &len) < 0) - { - return 0; - } - else - { - if ((host = gethostbyaddr((char *) &sin.sin_addr, - sizeof sin.sin_addr, - AF_INET)) == NULL) - { - return 0; - } - else - { - strncpy(pCompost,host->h_name,iBufLen); - pCompost[iBufLen-1]='\0'; - } - } - return 1; - } -/*--------------------------------------------------------------------------*/ - int NETWrite(mkChannel *self, char *buffer, long lLen) - { - long iRet; - fd_set lMask; - struct timeval tmo; - char buf[256]; - time_t expire, delta; - char *pos; - long l; - int disconnected; - - if(!VerifyChannel(self)) - { - return 0; - } - if(!(self->iType == SOCKET)) - { - return 0; - } - - /* - * Check if the we can write to the socket first.... - * Well, this how it should be. However, on linux I observe that - * there is a problem with Java clients not reliably receiving data when - * this is active. - */ - if((self->sockid >= FD_SETSIZE) || (self->sockid < 0) ) - { - /* invalid descriptor */ - return 0; - } -#ifdef DO_NOT_SELECT_BEFORE_SEND - iRet = send(self->sockid,buffer,lLen,0); - if (iRet != lLen) { - self->iType = 0; - if (iRet < 0) { - if (errno == EPIPE) { /* do not write "broken pipe" error */ - return 0; - } - snprintf(buf, sizeof buf, "NETWrite: send system error: %s (socket %d)", - strerror(errno), self->sockid); - } else { - snprintf(buf, sizeof buf, "NETWrite: only %ld of %ld bytes sent (socket %d)", - iRet, lLen, self->sockid); - } - NetError(buf); - return 0; - } else { - return 1; - } -#endif - pos = buffer; - l = lLen; - FD_ZERO(&lMask); - disconnected = 0; + snprintf(buf, sizeof buf, + "NETWrite: send system error: %s (socket %d)", + strerror(errno), self->sockid); + } else { + snprintf(buf, sizeof buf, + "NETWrite: only %ld of %ld bytes sent (socket %d)", iRet, + lLen, self->sockid); + } + NetError(buf); + return 0; + } else { + return 1; + } +#endif + pos = buffer; + l = lLen; + FD_ZERO(&lMask); + disconnected = 0; #define TIMEOUT 10 - expire = time(NULL) + TIMEOUT; - while (l > 0) { - delta = expire - time(NULL); - if (delta <= 0) - break; - FD_SET(self->sockid,&lMask); - tmo.tv_usec = 0; - tmo.tv_sec = delta; - iRet = select( (self->sockid + 1),NULL, &lMask, NULL,&tmo); - if (iRet < 0) { - /* failure, or no data */ - self->iType = 0; - snprintf(buf, sizeof buf, - "NETWrite: failure on select before send: %s (socket %d)", - strerror(errno), self->sockid); - NetError(buf); - return 0; - } - if (!FD_ISSET(self->sockid,&lMask)) - break; - - iRet = send(self->sockid,pos,l,0); - disconnected = (iRet == 0); - if (iRet < 0) { - self->iType = 0; - if (errno == EPIPE || errno == ECONNRESET) { /* do not write these errors */ - return 0; - } - snprintf(buf, sizeof buf, "NETWrite: send system error: %s (socket %d)", - strerror(errno), self->sockid); - NetError(buf); - return 0; - } - l -= iRet; - pos += iRet; - } - if (l > 0) { - self->iType = 0; - if (!disconnected) { /* do not write an error message on disconnect */ - snprintf(buf, sizeof buf, "NETWrite: timeout, only %ld of %ld bytes sent (socket %d) %ld.%6.6ld", - lLen - l, lLen, self->sockid, (long)tmo.tv_sec, (long)tmo.tv_usec); - NetError(buf); - } - return 0; - } - return 1; - } + expire = time(NULL) + TIMEOUT; + while (l > 0) { + delta = expire - time(NULL); + if (delta <= 0) + break; + FD_SET(self->sockid, &lMask); + tmo.tv_usec = 0; + tmo.tv_sec = delta; + iRet = uselect((self->sockid + 1), NULL, &lMask, NULL, &tmo); + if (iRet < 0) { + /* failure, or no data */ + self->iType = 0; + snprintf(buf, sizeof buf, + "NETWrite: failure on select before send: %s (socket %d)", + strerror(errno), self->sockid); + NetError(buf); + return 0; + } + if (!FD_ISSET(self->sockid, &lMask)) + break; + + iRet = send(self->sockid, pos, l, 0); + disconnected = (iRet == 0); + if (iRet < 0) { + self->iType = 0; + if (errno == EPIPE || errno == ECONNRESET) { /* do not write these errors */ + return 0; + } + snprintf(buf, sizeof buf, + "NETWrite: send system error: %s (socket %d)", + strerror(errno), self->sockid); + NetError(buf); + return 0; + } + l -= iRet; + pos += iRet; + } + if (l > 0) { + self->iType = 0; + if (!disconnected) { /* do not write an error message on disconnect */ + snprintf(buf, sizeof buf, + "NETWrite: timeout, only %ld of %ld bytes sent (socket %d) %ld.%6.6ld", + lLen - l, lLen, self->sockid, (long) tmo.tv_sec, + (long) tmo.tv_usec); + NetError(buf); + } + return 0; + } + return 1; +} + /* -------------------------------------------------------------------------*/ - long NETRead(mkChannel *self, char *buffer, long lLen, long timeout) - { - fd_set lMask; - struct timeval tmo ={0,1}; - long iRet; - - if(!VerifyChannel(self)) - { - return 0; - } - - if(timeout >= 0) - { - /* setup for select first */ - tmo.tv_usec = (timeout % 1000) *1000; - tmo.tv_sec = timeout / 1000; - FD_ZERO(&lMask); - FD_SET(self->sockid,&lMask); - if((self->sockid >= FD_SETSIZE) || (self->sockid < 0) ) /* invalid descriptor */ - { - return -1; /* eof */ - } - iRet = select( (self->sockid + 1),&lMask, NULL, NULL,&tmo); - if( iRet <= 0) - { - /* failure, or no data - printf(" %d %d\n", iRet, errno); - */ - return 0; - } - } - - /* data or block for read, read */ - memset(buffer,0,lLen); - iRet = recv(self->sockid,buffer,lLen,0); - if(iRet == 0) - {/* eof */ - return -1; - } - if(iRet < 0) - { - return 0; - } - else - { - return iRet; - } - } +long NETRead(mkChannel * self, char *buffer, long lLen, long timeout) +{ + fd_set lMask; + struct timeval tmo = { 0, 1 }; + long iRet; + + if (!VerifyChannel(self)) { + return 0; + } + + if (timeout >= 0) { + /* setup for select first */ + tmo.tv_usec = (timeout % 1000) * 1000; + tmo.tv_sec = timeout / 1000; + FD_ZERO(&lMask); + FD_SET(self->sockid, &lMask); + if ((self->sockid >= FD_SETSIZE) || (self->sockid < 0)) { /* invalid descriptor */ + return -1; /* eof */ + } + iRet = uselect((self->sockid + 1), &lMask, NULL, NULL, &tmo); + if (iRet <= 0) { + /* failure, or no data + printf(" %d %d\n", iRet, errno); + */ + return 0; + } + } + + /* data or block for read, read */ + memset(buffer, 0, lLen); + iRet = recv(self->sockid, buffer, lLen, 0); + if (iRet == 0) { /* eof */ + return -1; + } + if (iRet < 0) { + return 0; + } else { + return iRet; + } +} + /*---------------------------------------------------------------------*/ - int NETAvailable(mkChannel *self, long timeout) - { - fd_set lMask; - struct timeval tmo ={0,1}; - int iRet; - - if(!VerifyChannel(self)) - { - return 0; - } - - /* setup for select */ - tmo.tv_usec = (timeout % 1000) * 1000; - tmo.tv_sec = timeout / 1000; - FD_ZERO(&lMask); - FD_SET(self->sockid,&lMask); - if((self->sockid >= FD_SETSIZE) || (self->sockid < 0) ) - /* invalid descriptor */ - { - return -1; /* eof */ - } - iRet = select( (self->sockid + 1),&lMask, NULL, NULL,&tmo); - if( iRet < 0) - { - return -1; - } - if(FD_ISSET(self->sockid,&lMask)) - { - return 1; - } - else - { - return 0; - } - } +int NETAvailable(mkChannel * self, long timeout) +{ + fd_set lMask; + struct timeval tmo = { 0, 1 }; + int iRet; + + if (!VerifyChannel(self)) { + return 0; + } + + /* setup for select */ + tmo.tv_usec = (timeout % 1000) * 1000; + tmo.tv_sec = timeout / 1000; + FD_ZERO(&lMask); + FD_SET(self->sockid, &lMask); + if ((self->sockid >= FD_SETSIZE) || (self->sockid < 0)) + /* invalid descriptor */ + { + return -1; /* eof */ + } + iRet = uselect((self->sockid + 1), &lMask, NULL, NULL, &tmo); + if (iRet < 0) { + return -1; + } + if (FD_ISSET(self->sockid, &lMask)) { + return 1; + } else { + return 0; + } +} + /*-------------------------------------------------------------------------*/ -int NETReadTillTerm(mkChannel *self, long timeout, +int NETReadTillTerm(mkChannel * self, long timeout, char *pTerm, char *pBuffer, int iBufLen) { struct timeval start, now; - int bufPtr = 0, status, i, length, matchIndex=1; + int bufPtr = 0, status, i, length, matchIndex = 1; char c; long dif; - if(!VerifyChannel(self)) - { + if (!VerifyChannel(self)) { return -1; } - + gettimeofday(&start, NULL); - if (pTerm == NULL) pTerm=""; - + if (pTerm == NULL) + pTerm = ""; + length = strlen(pTerm); - memset(pBuffer,0,iBufLen); - - status = NETAvailable(self,timeout); /* first time: full timeout */ - if(status <= 0) /* return on error or on timeout */ - { + memset(pBuffer, 0, iBufLen); + + status = NETAvailable(self, timeout); /* first time: full timeout */ + if (status <= 0) { /* return on error or on timeout */ return status; } - while (status > 0) - { - status = recv(self->sockid,&c,1,0); - if(status <= 0) - { + while (status > 0) { + status = recv(self->sockid, &c, 1, 0); + if (status <= 0) { return status; } if ('&' != pTerm[0]) { - for(i = 0; i < length; i++) - { - if(c == pTerm[i]) - { - return bufPtr+1; + /* This accepts any terminator */ + for (i = 0; i < length; i++) { + if (c == pTerm[i]) { + return bufPtr + 1; } } } else { + /* this is for accepting a terminator consisting of multiple characters, pTerm[0] is & + * There is evidence that this code is broken. M.K. + */ if (matchIndex == 1 && c == pTerm[1]) { matchIndex++; } else { - if (c== pTerm[matchIndex] && matchIndex < length -1) { + if (c == pTerm[matchIndex] && matchIndex < length - 1) { matchIndex++; } else { if (c == pTerm[matchIndex] && matchIndex == length - 1) { @@ -663,64 +648,100 @@ int NETReadTillTerm(mkChannel *self, long timeout, } } } - if (c == 0 && *pTerm != 0) - { + if (c == 0 && *pTerm != 0) { /* a null character is an error, except when no terminator is defined (binary data) */ return -1; } - if(bufPtr >= iBufLen-1) - { - if (*pTerm != 0) { /* terminator expected */ - return -1; /* overflow */ + if (bufPtr >= iBufLen - 1) { + if (*pTerm != 0) { /* terminator expected */ + return -1; /* overflow */ } pBuffer[bufPtr] = c; - return bufPtr+1; + return bufPtr + 1; } pBuffer[bufPtr] = c; bufPtr++; /* - wait for more data - */ - status = NETAvailable(self,0); /* timeout 0 (just poll) */ - if (status == 0 && timeout > 0) - { + wait for more data + */ + status = NETAvailable(self, 0); /* timeout 0 (just poll) */ + if (status == 0 && timeout > 0) { gettimeofday(&now, NULL); - dif = (now.tv_sec-start.tv_sec)*1000+(now.tv_usec-start.tv_usec)/1000; - if (dif < 0) dif += 24*3600*1000; /* treat midnight correctly */ - if(dif > timeout) - { - return 0; /* timeout */ + dif = + (now.tv_sec - start.tv_sec) * 1000 + (now.tv_usec - + start.tv_usec) / 1000; + if (dif < 0) + dif += 24 * 3600 * 1000; /* treat midnight correctly */ + if (dif > timeout) { + return 0; /* timeout */ } - status = NETAvailable(self,timeout-dif); + status = NETAvailable(self, timeout - dif); }; }; - assert(bufPtr > 0); - return bufPtr; + return status; +} + +/*-------------------------------------------------------------------------*/ +int NETReadRemob(mkChannel * self, long timeout, long timeout2, + char term, char *pBuffer, int iBufLen) +{ + struct timeval start, now; + int bufPtr = 0, status, i, length, matchIndex = 1; + char c; + long dif; + + if (!VerifyChannel(self)) { + return -1; + } + + memset(pBuffer, 0, iBufLen); + + status = NETAvailable(self, timeout); + while (status > 0) { + status = recv(self->sockid, &c, 1, 0); + if (status <= 0) { + return status; + } + if (c == term) { + return bufPtr + 1; + } + if (bufPtr >= iBufLen - 1) { + return -1; /* overflow */ + } + pBuffer[bufPtr] = c; + bufPtr++; + /* + wait for more data + */ + status = NETAvailable(self, timeout2); + }; + return status; } -/*---------------------------------------------------------------------------*/ - int NETClosePort(mkChannel *self) - { - int iRet; - if(!VerifyChannel(self)) - { - return 0; - } - - iRet = close(self->sockid); - gettimeofday(&lastclose, NULL); - self->iType = 0; - self->sockid = 0; - if(iRet < 0) - return 0; - else - return 1; - - } /*---------------------------------------------------------------------------*/ -int NETReconnectWithFlags(mkChannel* self, int flags) +int NETClosePort(mkChannel * self) { int iRet; + + if (!VerifyChannel(self)) { + return 0; + } + + iRet = close(self->sockid); + gettimeofday(&lastclose, NULL); + self->iType = 0; + self->sockid = 0; + if (iRet < 0) + return 0; + else + return 1; + +} + +/*---------------------------------------------------------------------------*/ +int NETReconnectWithFlags(mkChannel * self, int flags) +{ + int iRet = 0; int sock; int oldopts; @@ -728,255 +749,235 @@ int NETReconnectWithFlags(mkChannel* self, int flags) * Get the flags and close the old socket */ oldopts = fcntl(self->sockid, F_GETFL, 0); - close(self->sockid); - /* Reopen and try to get it on the old fd */ - sock = socket(AF_INET,SOCK_STREAM,0); - /* If this isn't the same fd, try to move it over */ + if (self->sockid != 0) { + close(self->sockid); + } + /* Reopen and try to get it on the olf fd */ + sock = socket(AF_INET, SOCK_STREAM, 0); if (self->sockid != sock) { - /* Duplicate the new socket with the old fd if we can */ iRet = fcntl(sock, F_DUPFD, self->sockid); - if (iRet != self->sockid) { - /* If we didn't get the one we want, use original and close new */ + if (iRet != sock) self->sockid = sock; - close(iRet); - } - else { - /* If we did get the one we want, close original and use old */ + else close(sock); - } sock = self->sockid; } /* restore the old flags */ fcntl(self->sockid, F_SETFL, oldopts); /* set socket non-blocking */ oldopts = fcntl(self->sockid, F_GETFL, 0); - if (/*(flags & 1) &&*/ !(oldopts & O_NONBLOCK)) + if ( /*(flags & 1) && */ !(oldopts & O_NONBLOCK)) fcntl(self->sockid, F_SETFL, oldopts | O_NONBLOCK); /* try to reconnect */ iRet = connect(self->sockid, - (struct sockaddr *)&(self->adresse), - sizeof(struct sockaddr_in)); + (struct sockaddr *) &(self->adresse), + sizeof(struct sockaddr_in)); if (iRet < 0) { if (errno == EINPROGRESS) { if ((flags & 1)) { - iRet = 0; /* in progress */ + iRet = 0; /* in progress */ } else { fd_set rmask; fd_set wmask; - struct timeval tmo = {1,0}; + struct timeval tmo = { 1, 0 }; FD_ZERO(&rmask); FD_ZERO(&wmask); FD_SET(self->sockid, &rmask); FD_SET(self->sockid, &wmask); - iRet = select(self->sockid+1, &rmask, &wmask, NULL, &tmo); - if (iRet < 0) /* error */ + iRet = uselect(self->sockid + 1, &rmask, &wmask, NULL, &tmo); + if (iRet < 0) /* error */ iRet = -1; - else if (iRet == 0) /* timeout */ - iRet = 0; /* in progress */ + else if (iRet == 0) /* timeout */ + iRet = 0; /* in progress */ else { char reply[1]; if (FD_ISSET(self->sockid, &rmask)) { iRet = recv(self->sockid, reply, 1, MSG_PEEK); if (iRet <= 0) - iRet = -1; /* failure */ + iRet = -1; /* failure */ } if (FD_ISSET(self->sockid, &wmask)) { iRet = send(self->sockid, NULL, 0, 0); if (iRet < 0) - iRet = -1; /* failure */ + iRet = -1; /* failure */ else - iRet = 1; /* success */ + iRet = 1; /* success */ } } } - } - else /* other error */ - iRet = -1; /* error */ - } - else - iRet = 1; /* success */ - + } else /* other error */ + iRet = -1; /* error */ + } else + iRet = 1; /* success */ + if (iRet != 0 && !(oldopts & O_NONBLOCK)) fcntl(self->sockid, F_SETFL, oldopts); return iRet; } -int NETReconnect(mkChannel* self) +int NETReconnect(mkChannel * self) { return NETReconnectWithFlags(self, 0); } /* ################### UDP -functions ######################################*/ - mkChannel *UDPOpen(int iPort) - { - mkChannel *pRes = NULL; - int iRet, i; - - pRes = (mkChannel *)malloc(sizeof(mkChannel)); - if(!pRes) - return NULL; - - /* open a socket */ - pRes->sockid = socket(AF_INET,SOCK_DGRAM,0); - if(pRes->sockid < 0) - { - free(pRes); - return NULL; - } - - /* REUSEADDR for restarting ability */ - i = 1; - setsockopt(pRes->sockid,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(int)); - - assert(pRes->sockid < (int)(sizeof(long)*8)); - /* if this fails the masks for select will be to - short. - */ - - - /* bind */ - memset(&(pRes->adresse),0,sizeof(struct sockaddr_in)); - pRes->adresse.sin_family = AF_INET; - pRes->adresse.sin_addr.s_addr = htonl(INADDR_ANY); - pRes->adresse.sin_port = htons(iPort); - iRet = bind(pRes->sockid,(struct sockaddr *)&(pRes->adresse), - sizeof(struct sockaddr_in)); - if(iRet < 0) - { - free(pRes); - return NULL; - } +mkChannel *UDPOpen(int iPort) +{ + mkChannel *pRes = NULL; + int iRet, i; - pRes->iType = UDP; - pRes->lMagic = NETMAGIC; - return pRes; - } -/*--------------------------------------------------------------------------*/ - mkChannel *UDPConnect(char *name, int port) - { - mkChannel *pRes = NULL; - int iRet, i; - char pBueffel[80]; - struct hostent *pServer = NULL; - - assert(port > 0); - - /* default name to localhost */ - if(name == NULL) - { - strcpy(pBueffel,"localhost"); - name = pBueffel; - } - - /* new channel */ - pRes = (mkChannel *)malloc(sizeof(mkChannel)); - if(!pRes) - return NULL; + pRes = (mkChannel *) malloc(sizeof(mkChannel)); + if (!pRes) + return NULL; - /* connect */ - iRet = CreateSocketAdress(&(pRes->adresse),name,port); - if(!iRet) - { - free(pRes); - return NULL; - } - pRes->sockid = socket(AF_INET,SOCK_DGRAM,0); - if(pRes->sockid < 0) - { - free(pRes); - return NULL; - } - /* + /* open a socket */ + pRes->sockid = socket(AF_INET, SOCK_DGRAM, 0); + if (pRes->sockid < 0) { + free(pRes); + return NULL; + } + + /* REUSEADDR for restarting ability */ + i = 1; + setsockopt(pRes->sockid, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(int)); + + assert(pRes->sockid < (sizeof(long) * 8)); + /* if this fails the masks for select will be to + short. + */ + + + /* bind */ + memset(&(pRes->adresse), 0, sizeof(struct sockaddr_in)); + pRes->adresse.sin_family = AF_INET; + pRes->adresse.sin_addr.s_addr = htonl(INADDR_ANY); + pRes->adresse.sin_port = htons(iPort); + iRet = bind(pRes->sockid, (struct sockaddr *) &(pRes->adresse), + sizeof(struct sockaddr_in)); + if (iRet < 0) { + free(pRes); + return NULL; + } + + pRes->iType = UDP; + pRes->lMagic = NETMAGIC; + return pRes; +} + +/*--------------------------------------------------------------------------*/ +mkChannel *UDPConnect(char *name, int port) +{ + mkChannel *pRes = NULL; + int iRet, i; + char pBueffel[80]; + struct hostent *pServer = NULL; + + assert(port > 0); + + /* default name to localhost */ + if (name == NULL) { + strcpy(pBueffel, "localhost"); + name = pBueffel; + } + + /* new channel */ + pRes = (mkChannel *) malloc(sizeof(mkChannel)); + if (!pRes) + return NULL; + + /* connect */ + iRet = CreateSocketAdress(&(pRes->adresse), name, port); + if (!iRet) { + free(pRes); + return NULL; + } + pRes->sockid = socket(AF_INET, SOCK_DGRAM, 0); + if (pRes->sockid < 0) { + free(pRes); + return NULL; + } + /* iRet = connect(pRes->sockid,(struct sockaddr *)&(pRes->adresse), - sizeof(struct sockaddr_in)); - */ - iRet = 1; - if(iRet < 0) - { - free(pRes); - return NULL; - } + sizeof(struct sockaddr_in)); + */ + iRet = 1; + if (iRet < 0) { + free(pRes); + return NULL; + } /* i = 1; setsockopt(pRes->sockid,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(int)); */ - pRes->iType = UDP; - pRes->lMagic = NETMAGIC; - return pRes; - } -/*--------------------------------------------------------------------------*/ - long UDPRead(mkChannel *self, char *buffer, long lLen, int timeout) - { - long lMask = 0L; - struct timeval tmo ={0,1}; - long iRet; - socklen_t iLang; - - if(!VerifyChannel(self)) - { - return 0; - } - assert(self->iType == UDP); - - if(timeout >= 0) - { - /* setup for select first */ - tmo.tv_usec = (timeout % 1000) *1000; - tmo.tv_sec = timeout / 1000; - lMask = (1 << self->sockid); - iRet = select( (self->sockid + 1),(fd_set *)&lMask, NULL, NULL,&tmo); - if( iRet <= 0) - { - /* failure, or no data */ - return 0; - } - } - - /* data, read */ - buffer[0] = '\0'; - iLang = sizeof(struct sockaddr_in); - iRet = recvfrom(self->sockid,buffer,lLen,0, - (struct sockaddr *)&(self->adresse), - &iLang); - if(iRet == 0) - {/* eof */ - return -1; - } - if(iRet < 0) - { - return 0; - } - else - { - buffer[iRet] = '\0'; - return iRet; - } - } + pRes->iType = UDP; + pRes->lMagic = NETMAGIC; + return pRes; +} + /*--------------------------------------------------------------------------*/ - int UDPWrite(mkChannel *self, char *buffer, long lLen) - { - int iRet; - - if(!VerifyChannel(self)) - { - return 0; - } - assert(self->iType == UDP); - - iRet = sendto(self->sockid,buffer,lLen,0, - (struct sockaddr *)&(self->adresse),sizeof(struct sockaddr_in)); - fsync(self->sockid); - if(iRet < 0) - { - return 0; - } - else - { - return 1; - } - } - +long UDPRead(mkChannel * self, char *buffer, long lLen, int timeout) +{ + long lMask = 0L; + struct timeval tmo = { 0, 1 }; + long iRet; + socklen_t iLang; + + if (!VerifyChannel(self)) { + return 0; + } + assert(self->iType == UDP); + + if (timeout >= 0) { + /* setup for select first */ + tmo.tv_usec = (timeout % 1000) * 1000; + tmo.tv_sec = timeout / 1000; + lMask = (1 << self->sockid); + iRet = + uselect((self->sockid + 1), (fd_set *) & lMask, NULL, NULL, &tmo); + if (iRet <= 0) { + /* failure, or no data */ + return 0; + } + } + + /* data, read */ + buffer[0] = '\0'; + iLang = sizeof(struct sockaddr_in); + iRet = recvfrom(self->sockid, buffer, lLen, 0, + (struct sockaddr *) &(self->adresse), &iLang); + if (iRet == 0) { /* eof */ + return -1; + } + if (iRet < 0) { + return 0; + } else { + buffer[iRet] = '\0'; + return iRet; + } +} + +/*--------------------------------------------------------------------------*/ +int UDPWrite(mkChannel * self, char *buffer, long lLen) +{ + int iRet; + + if (!VerifyChannel(self)) { + return 0; + } + assert(self->iType == UDP); + + iRet = sendto(self->sockid, buffer, lLen, 0, + (struct sockaddr *) &(self->adresse), + sizeof(struct sockaddr_in)); + fsync(self->sockid); + if (iRet < 0) { + return 0; + } else { + return 1; + } +} + /* ========================================================================== TestCode. Compile with DBCLIENT defined to get a test client, @@ -986,94 +987,81 @@ int NETReconnect(mkChannel* self) #ifdef DBCLIENT - int main(int argc, char *argv[]) - { - char pBueffel[80]; - mkChannel *pChan = NULL; - int iRet; - - pChan = NETConnect("localhost",4711); - if(!pChan) - { - puts("No connection to server"); - exit(2); - } - - for( ; ; ) - { - printf("Client> "); - gets(pBueffel); - if(strcmp(pBueffel,"exit") == 0) - break; - iRet = NETWrite(pChan,pBueffel,strlen(pBueffel)); - if(!iRet) - puts("Write error"); - - iRet = NETRead(pChan,pBueffel,79,2000); - if(iRet < -1) - { - puts("Read error"); - } - else if(iRet > 0) - { - pBueffel[iRet] = '\0'; - puts(pBueffel); - } - } - NETClosePort(pChan); - return 0; +int main(int argc, char *argv[]) +{ + char pBueffel[80]; + mkChannel *pChan = NULL; + int iRet; + + pChan = NETConnect("localhost", 4711); + if (!pChan) { + puts("No connection to server"); + exit(2); } + + for (;;) { + printf("Client> "); + gets(pBueffel); + if (strcmp(pBueffel, "exit") == 0) + break; + iRet = NETWrite(pChan, pBueffel, strlen(pBueffel)); + if (!iRet) + puts("Write error"); + + iRet = NETRead(pChan, pBueffel, 79, 2000); + if (iRet < -1) { + puts("Read error"); + } else if (iRet > 0) { + pBueffel[iRet] = '\0'; + puts(pBueffel); + } + } + NETClosePort(pChan); + return 0; +} #endif #ifdef DBSERVER - int main(int argc, char *argv[]) - { - mkChannel *pPort = NULL; - mkChannel *pCon[20]; - int i,iRet, iPtr = 0; - char pBueffel[132]; - - pPort = NETOpenPort(4711); - if(!pPort) - { - puts("Cannot start server"); - exit(1); - } - - while(1) - { - /* accept new connections */ - pCon[iPtr] = NETAccept(pPort,200); - if(pCon[iPtr]) - { - printf("Connection accepted on socket %d\n",pCon[iPtr]->sockid); - iPtr++; - } - - /* look for messages */ - for(i = 0; i < iPtr; i++) - { - if(pCon[i]) - { - iRet = NETRead(pCon[i],pBueffel,131,200); - if(iRet < 0) - { - printf("closing socket %d\n",pCon[i]->sockid); - NETClosePort(pCon[i]); - free(pCon[i]); - pCon[i] = NULL; - } - else if(iRet > 0) - { - pBueffel[iRet] = '\0'; - printf("Received - %s - from %d\n",pBueffel,pCon[i]->sockid); - NETWrite(pCon[i],"Acknowledge",strlen("Acknowledge")); - } - } - } - - } - +int main(int argc, char *argv[]) +{ + mkChannel *pPort = NULL; + mkChannel *pCon[20]; + int i, iRet, iPtr = 0; + char pBueffel[132]; + pPort = NETOpenPort(4711); + if (!pPort) { + puts("Cannot start server"); + exit(1); + } + + while (1) { + /* accept new connections */ + pCon[iPtr] = NETAccept(pPort, 200); + if (pCon[iPtr]) { + printf("Connection accepted on socket %d\n", pCon[iPtr]->sockid); + iPtr++; } + + /* look for messages */ + for (i = 0; i < iPtr; i++) { + if (pCon[i]) { + iRet = NETRead(pCon[i], pBueffel, 131, 200); + if (iRet < 0) { + printf("closing socket %d\n", pCon[i]->sockid); + NETClosePort(pCon[i]); + free(pCon[i]); + pCon[i] = NULL; + } else if (iRet > 0) { + pBueffel[iRet] = '\0'; + printf("Received - %s - from %d\n", pBueffel, pCon[i]->sockid); + NETWrite(pCon[i], "Acknowledge", strlen("Acknowledge")); + } + } + } + + } + + +} #endif diff --git a/network.h b/network.h index 900d035a..925a9568 100644 --- a/network.h +++ b/network.h @@ -26,13 +26,13 @@ #include #include - typedef struct __MKCHANNEL{ - int sockid; - int iType; - struct sockaddr_in adresse; - long lMagic; - } mkChannel; - +typedef struct __MKCHANNEL { + int sockid; + int iType; + struct sockaddr_in adresse; + long lMagic; +} mkChannel; + #define NETMAGIC 29121993 /*========================= exported functions ============================*/ @@ -41,48 +41,48 @@ /********************** OPENING ************************************** */ - mkChannel *NETOpenPort(int iPort); - /* opens a ServerPort for listening, returns NULL if failure, - else a valid mkChannel structure for the port - */ - - mkChannel *NETAccept(mkChannel *self, long timeout); - /* tries to accept a new connection on the Channel self - until timeout. If a connection can be built a new mkChannel - structure is returned, else NULL. With a negative value or 0 for - timeout this function blocks for an accept. - */ - - mkChannel *NETConnect(char *name, int port); - /* tries to open a client connection to the server specified by name - and port. Returns NULL on failure, a struct else - */ +mkChannel *NETOpenPort(int iPort); + /* opens a ServerPort for listening, returns NULL if failure, + else a valid mkChannel structure for the port + */ - mkChannel *NETConnectWithFlags(char *name, int port, int flags); +mkChannel *NETAccept(mkChannel * self, long timeout); + /* tries to accept a new connection on the Channel self + until timeout. If a connection can be built a new mkChannel + structure is returned, else NULL. With a negative value or 0 for + timeout this function blocks for an accept. + */ + +mkChannel *NETConnect(char *name, int port); + /* tries to open a client connection to the server specified by name + and port. Returns NULL on failure, a struct else + */ + +mkChannel *NETConnectWithFlags(char *name, int port, int flags); /* the same as NETConnect, but with flags: if (flags & 1): do not block on connect (use NETConnectFinished - to check success) + to check success) if (flags & 2): wait 1000 ms after last close (workaround for - a bug in Lantronix terminal server - */ - - int NETConnectFinished(mkChannel *self); + a bug in the Lantronix terminal server) + */ + +int NETConnectFinished(mkChannel * self); /* returns 0 if in progress, 1 on success, a negative value on error - */ - - int NETInfo(mkChannel *self, char *pComposter, int iBufLen); + */ + +int NETInfo(mkChannel * self, char *pComposter, int iBufLen); /* Once a socket is connected it is possible to figure out which host the connection came from. Maximum iBufLen characters of hostname are copied to pComposter - */ + */ - int NETReconnect(mkChannel* self); +int NETReconnect(mkChannel * self); /* If a connection has been lost, try to reconnect using the same * socket id if possible. Blocks for up to one second. * returns 0 if in progress, 1 on success, a negative value on error */ - int NETReconnectWithFlags(mkChannel* self, int flags); +int NETReconnectWithFlags(mkChannel * self, int flags); /* If a connection has been lost, try to reconnect using the same * socket id if possible. If (flags & 1) do not block, use * NETConnectFinished to check success. @@ -90,55 +90,58 @@ */ /* *********************** DATA TRANSFER ******************************** */ - int NETWrite(mkChannel *self, char *buffer, long lLen); - /* writes data to socket self, returns True if success, - false otherwise. - */ - - long NETRead(mkChannel *self, char *buffer, long lLen, long timeout); - /* reads data from socket self into buffer with max length lLen - waits maximum timeout for data. Returns -1 on error, 0 on no - data, and else the length of the data read. With a negative value - or 0 for timeout this function blocks for the read. - */ - int NETAvailable(mkChannel *self, long timeout); +int NETWrite(mkChannel * self, char *buffer, long lLen); + /* writes data to socket self, returns 1 if success, + 0 otherwise. + */ + +long NETRead(mkChannel * self, char *buffer, long lLen, long timeout); + /* reads data from socket self into buffer with max length lLen + waits maximum timeout for data. Returns -1 on error, 0 on no + data, and else the length of the data read. With a negative value + or 0 for timeout this function blocks for the read. + */ +int NETAvailable(mkChannel * self, long timeout); /* returns 1 if data is pending on the port, 0 if none is pending. - */ - int NETReadTillTerm(mkChannel *self, long timeout, + */ +int NETReadTillTerm(mkChannel * self, long timeout, char *pTerm, char *pBuffer, int iBufLen); /* - reads data until one of the terminators defined in pTerm has - been found. The data is copied into the buffer pBuffer. A - maximum length of iBufLen characters is observed. The timeout - parameter defines a maximum time to wait for a terminator to - appear. NETReadTillTerm returns the number of characters read - (including terminator) on success, 0 on a timeout, - and a negative value if a network error occurred. Beware that - this may not work correctly if the wrong terminator is given. - The last one is really needed. - In the new version, timeout is in MILLIseconds (10 -3 sec). - However, the accuracy is machine dependent (for Linux 10 ms, for Tru64 1 ms) - If no terminator is given, the routine waits for iBufLen characters - or timeout. - */ + reads data until one of the terminators defined in pTerm has + been found. The data is copied into the buffer pBuffer. A + maximum length of iBufLen characters is observed. The timeout + parameter defines a maximum time to wait for a terminator to + appear. NETReadTillTerm returns the number of characters read + (including terminator) on success, 0 on a timeout, + and a negative value if a network error occurred. Beware that + this may not work correctly if the wrong terminator is given. + The last one is really needed. + In the new version, timeout is in MILLIseconds (10 -3 sec). + However, the accuracy is machine dependent (for Linux 10 ms, for Tru64 1 ms) + If no terminator is given, the routine waits for iBufLen characters + or timeout. + */ +int NETReadRemob(mkChannel *self, long timeout, long timeout2, + char term, char *pBuffer, int iBufLen); + /* special version for remob */ /* ********************* KILLING FIELD ******************************** */ - int NETClosePort(mkChannel *self); - /* closes a port, do not forget to free the channel data- - structure afterwards, returns True on success, False else - */ - +int NETClosePort(mkChannel * self); + /* closes a port, do not forget to free the channel data- + structure afterwards, returns True on success, False else + */ + /*################## ConnectionLess functions ##########################*/ - mkChannel *UDPOpen(int iPort); +mkChannel *UDPOpen(int iPort); /* opens a port connectionless communications. - */ - mkChannel *UDPConnect(char *name, int iPort); + */ +mkChannel *UDPConnect(char *name, int iPort); /* connects a client for connectionless communication - */ - + */ + /* can use NETClosePort */ - - long UDPRead(mkChannel *self, char *buffer, long lLen, int timeout); - int UDPWrite(mkChannel *self, char *buffer, long lLen); + +long UDPRead(mkChannel * self, char *buffer, long lLen, int timeout); +int UDPWrite(mkChannel * self, char *buffer, long lLen); #endif diff --git a/nigpib.c b/nigpib.c index 32384f13..ceae9d40 100644 --- a/nigpib.c +++ b/nigpib.c @@ -15,90 +15,102 @@ #include #include "fortify.h" #include "sics.h" -#include +#include #include "gpibcontroller.i" typedef struct __GPIB *pGPIB; /*--------------------------------------------------------------------------*/ static int NIattach(int boardNo, int address, int secondaryAddress, - int tmo, int eot, int eos){ + int tmo, int eot, int eos) +{ int devID; devID = ibdev(boardNo, address, secondaryAddress, tmo, eot, eos); - if(devID < 0){ + if (devID < 0) { return -iberr; } else { return devID; } } + /*---------------------------------------------------------------------*/ -static int NIdetach(int devID){ +static int NIdetach(int devID) +{ int status; status = ibonl(devID, 0); - if(status & ERR){ + if (status & ERR) { return -iberr; } else { return 1; } } + /*-------------------------------------------------------------------*/ -static int NIwrite(int devID, void *buffer, int bytesToWrite){ +static int NIwrite(int devID, void *buffer, int bytesToWrite) +{ int status; - - status = ibwrt(devID,buffer,bytesToWrite); - if(status & ERR){ - return - iberr; - } else { + + status = ibwrt(devID, buffer, bytesToWrite); + if (status & ERR) { + return -iberr; + } else { return 1; } } + /*-------------------------------------------------------------------*/ -static int NIread(int devID, void *buffer, int bytesToRead){ +static int NIread(int devID, void *buffer, int bytesToRead) +{ int status; - - status = ibrd(devID,buffer,bytesToRead); - if(status & ERR){ - return - iberr; - } else { + + status = ibrd(devID, buffer, bytesToRead); + if (status & ERR) { + return -iberr; + } else { return 1; } } + /*--------------------------------------------------------------------*/ -static int NIclear(int devID){ +static int NIclear(int devID) +{ ibclr(devID); return 1; } -/*-----------------------------------------------------------------*/ -static void NIerror(int code, char *buffer, int maxBuffer){ - int flag = - code; - switch(flag){ +/*-----------------------------------------------------------------*/ +static void NIerror(int code, char *buffer, int maxBuffer) +{ + int flag = -code; + + switch (flag) { case EDVR: case ENEB: case ECIC: - strncpy(buffer,"NI-GPIB not correctly installed or bad address", - maxBuffer); + strlcpy(buffer, "NI-GPIB not correctly installed or bad address", + maxBuffer); return; case EABO: - strncpy(buffer,"Timeout on data transfer",maxBuffer); + strlcpy(buffer, "Timeout on data transfer", maxBuffer); return; case EBUS: - strncpy(buffer,"No device connected to GPIB or address errror", - maxBuffer); + strlcpy(buffer, "No device connected to GPIB or address errror", + maxBuffer); return; case ENOL: - strncpy(buffer,"No listeners on bus. Perhaps address error?", - maxBuffer); + strlcpy(buffer, "No listeners on bus. Perhaps address error?", + maxBuffer); return; default: - strncpy(buffer,"Unrecognised error code, fix nigpib.c", - maxBuffer); + strlcpy(buffer, "Unrecognised error code, fix nigpib.c", maxBuffer); break; } } + /*------------------------------------------------------------------*/ -void NIassign(pGPIB self){ +void NIassign(pGPIB self) +{ self->attach = NIattach; self->detach = NIdetach; self->send = NIwrite; diff --git a/nintf.c b/nintf.c index 42e554e0..1c8a326e 100644 --- a/nintf.c +++ b/nintf.c @@ -3,24 +3,46 @@ is an implementation. Mark Koennecke, February 2000 + + Added double version, Mark Koennecke, August 2008 ---------------------------------------------------------------------------*/ #include - float nintf(float f) - { - double ip, rm, dVal; - float fRes; +float nintf(float f) +{ + double ip, rm, dVal; + float fRes; - dVal = (double)f; - rm = modf(dVal,&ip); - if(rm < .0)rm = -rm; - if(rm > .5) - { - if(ip < .0) - ip -= 1.; - else - ip += 1.; + dVal = (double) f; + rm = modf(dVal, &ip); + if (rm < .0) + rm = -rm; + if (rm > .5) { + if (ip < .0) + ip -= 1.; + else + ip += 1.; - } - return (float) ip; } + return (float) ip; +} + +/*-------------------------------------------------------------------*/ +double nintd(double f) +{ + double ip, rm, dVal; + double fRes; + + dVal = (double) f; + rm = modf(dVal, &ip); + if (rm < .0) + rm = -rm; + if (rm > .5) { + if (ip < .0) + ip -= 1.; + else + ip += 1.; + + } + return (double) ip; +} diff --git a/nread.c b/nread.c index 4c337baf..a7948974 100644 --- a/nread.c +++ b/nread.c @@ -10,7 +10,7 @@ Telnet Functionality added: Mark Koennecke, January 1998 Revamped login to non telnet connection. - Mark Koennecke, October 20000 + Mark Koennecke, October 2000 -----------------------------------------------------------------------------*/ #include @@ -21,6 +21,8 @@ #include #endif #include +#include + #include "fortify.h" #include "lld.h" #include "network.h" @@ -38,383 +40,342 @@ #include "telnet.h" #include "nread.h" #include "commandlog.h" +#include "uselect.h" +#include "trace.h" extern pServer pServ; -extern int VerifyChannel(mkChannel *self); /* defined in network.c */ +extern int VerifyChannel(mkChannel * self); /* defined in network.c */ #define NRMAGIC 1061996 /* #define TELNETDEBUG 1 */ - typedef enum { - tData, - tIAC, - tWill, - tWont, - tDo, - tDont, - tCR, - tSB, - tSBIN, - tSE } TelnetStatus; +typedef enum { + tData, + tIAC, + tWill, + tWont, + tDo, + tDont, + tCR, + tSB, + tSBIN, + tSE +} TelnetStatus; +extern char *ConID(SConnection *pCon); /* from conman.c */ /*--------------------------------------------------------------------------*/ - typedef struct __netreader { - pServer pMain; /* The server ds */ - int iList; /* the list of sockets to check */ - int iPasswdTimeout; - int iReadTimeout; - int iEnd; - long lMagic; - } NetReader; +typedef struct __netreader { + pServer pMain; /* The server ds */ + int iList; /* the list of sockets to check */ + int iPasswdTimeout; + int iReadTimeout; + int iEnd; + long lMagic; + pDynString conList; +} NetReader; /*--------------------------------------------------------------------------- The structure used for an item in the Net Reader list of connections */ - typedef struct { - mkChannel *pSock; - SConnection *pCon; - eNRType eType; - char pHold[512]; - int iEOD; - TelnetStatus tStatus; - int iReadable; - } NetItem, *pNetItem; +typedef struct { + mkChannel *pSock; + SConnection *pCon; + eNRType eType; + char pHold[512]; + int iEOD; + TelnetStatus tStatus; + int iReadable; +} NetItem, *pNetItem; /*----------------------------------------------------------------------------*/ - pNetRead CreateNetReader(pServer pTask, int iPasswdTimeout, int iReadTimeout) - { - pNetRead pNew = NULL; - - assert(pTask); - assert(iPasswdTimeout > 0); - assert(iReadTimeout >= 0); - - pNew = (pNetRead)malloc(sizeof(NetReader)); - if(!pNew) - { - return NULL; - } - memset(pNew,0,sizeof(NetReader)); - - pNew->iList = LLDcreate(sizeof(NetItem)); - if(pNew->iList < 0) - { - free(pNew); - return NULL; - } - pNew->pMain = pTask; - pNew->iPasswdTimeout = iPasswdTimeout; - pNew->iReadTimeout = iReadTimeout; - pNew->lMagic = NRMAGIC; - return pNew; - } -/*--------------------------------------------------------------------------*/ - void DeleteNetReader(void *pData) - { - pNetRead self = NULL; - - self = (pNetRead)pData; - assert(self); - if(self->lMagic != NRMAGIC) - { - return; - } - - LLDdelete(self->iList); - free(self); - } -/*--------------------------------------------------------------------------*/ - int NetReadRegister(pNetRead self, mkChannel *pSock, eNRType eType, - SConnection *pCon) - { - NetItem sItem, sEntry; - char buffer[80]; - int iRet; - - assert(self); - if(!VerifyChannel(pSock)) - { - return 0; - } - - sItem.pSock = pSock; - sItem.eType = eType; - sItem.pCon = pCon; - sItem.iEOD = 0; - sItem.tStatus = tData; - sItem.iReadable = 0; - memset(sItem.pHold,0,511); - - /* check if the entry is already there */ - iRet = LLDnodePtr2First(self->iList); - while(iRet != 0) - { - LLDnodeDataTo(self->iList,&sEntry); - if(sEntry.pSock->sockid == pSock->sockid) - { - snprintf(buffer, sizeof buffer, "NetReadRegister twice %d type %d", pSock->sockid, eType); - WriteToCommandLog("SYS>",buffer); - return 1; - } - iRet = LLDnodePtr2Next(self->iList); - } +pNetRead CreateNetReader(pServer pTask, int iPasswdTimeout, + int iReadTimeout) +{ + pNetRead pNew = NULL; - LLDnodeAppendFrom(self->iList, &sItem); - return 1; + assert(pTask); + assert(iPasswdTimeout > 0); + assert(iReadTimeout >= 0); + + pNew = (pNetRead) malloc(sizeof(NetReader)); + if (!pNew) { + return NULL; } + memset(pNew, 0, sizeof(NetReader)); + + pNew->iList = LLDcreate(sizeof(NetItem)); + pNew->conList = CreateDynString(1024, 1024); + if (pNew->iList < 0 || pNew->conList == NULL) { + free(pNew); + return NULL; + } + pNew->pMain = pTask; + pNew->iPasswdTimeout = iPasswdTimeout; + pNew->iReadTimeout = iReadTimeout; + pNew->lMagic = NRMAGIC; + return pNew; +} + /*--------------------------------------------------------------------------*/ - int NetReadRemove(pNetRead self, mkChannel *pSock) - { - NetItem sItem; - int iRet; - - assert(self); - if(self->lMagic != NRMAGIC) - { - return 0; - } - - /* find the entry to remove */ - iRet = LLDnodePtr2First(self->iList); - while(iRet != 0) - { - LLDnodeDataTo(self->iList,&sItem); - if(sItem.pSock == pSock) - { - LLDnodeDelete(self->iList); - return 1; - } - iRet = LLDnodePtr2Next(self->iList); - } +void DeleteNetReader(void *pData) +{ + pNetRead self = NULL; + + self = (pNetRead) pData; + assert(self); + if (self->lMagic != NRMAGIC) { + return; + } + + LLDdelete(self->iList); + if (self->conList != NULL) { + DeleteDynString(self->conList); + } + free(self); +} + +/*--------------------------------------------------------------------------*/ +int NetReadRegister(pNetRead self, mkChannel * pSock, eNRType eType, + SConnection * pCon) +{ + NetItem sItem, sEntry; + char buffer[80]; + int iRet; + + assert(self); + if (!VerifyChannel(pSock)) { return 0; } -/*-------------------------------------------------------------------------*/ - static int NetReadAccept(pNetRead self, mkChannel *pSock) - { - mkChannel *pNew = NULL; - char pBuffer[1064]; - int iRet; - SConnection *pRes = NULL; - char *pUser = NULL, *pPasswd = NULL; - time_t target; - - if(!VerifyChannel(pSock)) - { - return 0; - } - - /* check for new connection */ - pNew = NETAccept(pSock,0); - if(pNew) - { - /* create connection object */ - pRes = SCreateConnection(self->pMain->pSics,pNew,3); - if(!pRes) - { - SICSLogWrite("Failure to allocate new Connection",eInternal); - NETClosePort(pNew); - free(pNew); - return 0; - } - else - { - /* register the connection and create a task for it here */ - NetReadRegister(self,pNew,command, pRes); - TaskRegister(self->pMain->pTasker, - SCTaskFunction, - SCSignalFunction, - SCDeleteConnection, - pRes, - 1); - SCSendOK(pRes); - return 1; - } - } - else - { - return 0; - } + + sItem.pSock = pSock; + sItem.eType = eType; + sItem.pCon = pCon; + sItem.iEOD = 0; + sItem.tStatus = tData; + sItem.iReadable = 0; + memset(sItem.pHold, 0, 511); + + /* check if the entry is already there */ + iRet = LLDnodePtr2First(self->iList); + while (iRet != 0) { + LLDnodeDataTo(self->iList, &sEntry); + if (sEntry.pSock->sockid == pSock->sockid) { + snprintf(buffer, sizeof buffer, "NetReadRegister twice %d type %d", + pSock->sockid, eType); + WriteToCommandLog("SYS>", buffer); + return 1; + } + iRet = LLDnodePtr2Next(self->iList); } + + LLDnodeAppendFrom(self->iList, &sItem); + return 1; +} + +/*--------------------------------------------------------------------------*/ +int NetReadRemove(pNetRead self, mkChannel * pSock) +{ + NetItem sItem; + int iRet; + + assert(self); + if (self->lMagic != NRMAGIC) { + return 0; + } + + /* find the entry to remove */ + iRet = LLDnodePtr2First(self->iList); + while (iRet != 0) { + LLDnodeDataTo(self->iList, &sItem); + if (sItem.pSock == pSock) { + LLDnodeDelete(self->iList); + return 1; + } + iRet = LLDnodePtr2Next(self->iList); + } + return 0; +} + +/*-------------------------------------------------------------------------*/ +static int NetReadAccept(pNetRead self, mkChannel * pSock) +{ + mkChannel *pNew = NULL; + char pBuffer[1064]; + int iRet; + SConnection *pRes = NULL; + char *pUser = NULL, *pPasswd = NULL; + time_t target; + + if (!VerifyChannel(pSock)) { + return 0; + } + + /* check for new connection */ + pNew = NETAccept(pSock, 0); + if (pNew) { + /* create connection object */ + /* TODO + pRes = SCreateConnection(self->pMain->pSics,pNew,3); + */ + if (!pRes) { + SICSLogWrite("Failure to allocate new Connection", eInternal); + NETClosePort(pNew); + free(pNew); + return 0; + } else { + /* register the connection and create a task for it here */ + NetReadRegister(self, pNew, command, pRes); + TaskRegister(self->pMain->pTasker, + SCTaskFunction, + SCSignalFunction, SCDeleteConnection, pRes, 1); + SCSendOK(pRes); + return 1; + } + } else { + return 0; + } +} + /*--------------------------------------------------------------------------*/ #define COLLECT 0 #define SKIPTERM 1 /*------------------------------------------------------------------------*/ - static int NetReadRead(pNetRead self, pNetItem pItem) - { - char *pPtr, *pEnd, *pBufEnd; - char pBuffer[1024], pMuell[20]; - char pBueffel[80]; - int i, iInt, iRet, iStat, state; +static int NetReadRead(pNetRead self, pNetItem pItem) +{ + char *pPtr, *pEnd, *pBufEnd; + char pBuffer[1024], pMuell[20]; + char pBueffel[80]; + int i, iInt, iRet, iStat, state; - /* read first */ - memset(pBuffer,0,1024); - iRet = NETRead(pItem->pCon->pSock,pBuffer, 1022,0); - if(iRet < 0) /* EOF */ - { - pItem->pCon->iEnd = 1; - NetReadRemove(self,pItem->pCon->pSock); - return 0; - } - else if(iRet == 0) /* should not happen */ - { - return 1; - } - /* iRet is now the number of bytes read. Now we check for command - interrupts */ - pPtr = strstr(pBuffer,"INT1712"); - if(pPtr) - { - sscanf(pPtr, "%s %d",pMuell, &iInt); - if(SCMatchRights(pItem->pCon,usUser)) - { - TaskSignal(self->pMain->pTasker, SICSINT, &iInt); - sprintf(pBueffel,"INTERRUPT %d issued on sock %d", - iInt,pItem->pCon->pSock->sockid); - WriteToCommandLog("SYS>",pBueffel); - if(iInt == eEndServer) - { - TaskStop(self->pMain->pTasker); - } - } - else - { - SCWrite(pItem->pCon, - "ERROR: insufficient privilege to invoke Interrupt", - eError); - } - return 0; - } - - /* split into command lines - and put into fifo - */ - pBufEnd = pBuffer + iRet; - pPtr = pBuffer; - pEnd = pBuffer; - state = COLLECT; - while(pEnd < pBufEnd) - { - switch(state) - { - case COLLECT: - if( (*pEnd != '\r') && (*pEnd != '\n')) - { - pEnd++; - } - else - { - /* there is a string between pPtr and pEnd */ - *pEnd = '\0'; - /* do we have something in hold ? */ - if(strlen(pItem->pHold) > 0) - { - strcat(pItem->pHold,pPtr); - /* DFC locking for protocol zero only */ - if (pItem->pCon->iProtocolID == 0 && - CostaLocked(pItem->pCon->pStack)) - iStat = 0; - else - iStat = CostaTop(pItem->pCon->pStack,pItem->pHold); - if(!iStat) - { - SCWrite(pItem->pCon,"ERROR: Busy",eError); - } - pItem->pHold[0] = '\0'; - } - else - { - /* no, normal command */ - /* DFC locking for protocol zero only */ - if (pItem->pCon->iProtocolID == 0 && - CostaLocked(pItem->pCon->pStack)) - iStat = 0; - else - iStat = CostaTop(pItem->pCon->pStack,pPtr); - if(!iStat) - { - SCWrite(pItem->pCon,"ERROR: Busy",eError); - } - } - pPtr = pEnd +1; - pEnd = pPtr; - state = SKIPTERM; - } - break; - case SKIPTERM: - if( (*pEnd != '\r') && (*pEnd != '\n')) - { - state = COLLECT; - pPtr = pEnd; - } - else - { - pEnd++; - pPtr = pEnd; - } - break; - } - } - /* when we are here we may still have an incomplete command pending */ - if(pEnd != pPtr && strlen(pPtr) > 0) - { - strcpy(pItem->pHold,pPtr); - } - return 1; - } -/*-------------------------- telnet protocoll code -------------------------*/ - static int TelnetAccept(pNetRead self, mkChannel *pSock) - { - mkChannel *pNew = NULL; - char pBuffer[1064]; - int iRet; - SConnection *pRes = NULL; - pTelTask pTel = NULL; - - if(!VerifyChannel(pSock)) - { - return 0; - } - - /* check for new connection */ - pNew = NETAccept(pSock,0); - if(pNew) - { - /* create connection object */ - pRes = SCreateConnection(self->pMain->pSics,pNew,usSpy); - if(!pRes) - { - SICSLogWrite("Failure to allocate new Connection",eInternal); - NETClosePort(pNew); - free(pNew); - return 0; - } - else - { - /* Create a task object for the telnet connection */ - pTel = CreateTelnet(pRes); - if(!pTel) - { - SICSLogWrite("Failure to allocate new Telnet Task Object", - eInternal); - SCDeleteConnection(pRes); - return 0; - } - /* register connection and task */ - pRes->iTelnet = 1; - NetReadRegister(self,pNew,tcommand, pRes); - TaskRegister(self->pMain->pTasker, - TelnetTask, - TelnetSignal, - DeleteTelnet, - pTel, - 1); - return 1; - } - } - else - { - return 0; - } + /* read first */ + memset(pBuffer, 0, 1024); + iRet = NETRead(pItem->pCon->pSock, pBuffer, 1022, 0); + if (iRet < 0) { /* EOF */ + pItem->pCon->iEnd = 1; + NetReadRemove(self, pItem->pCon->pSock); + return 0; + } else if (iRet == 0) { /* should not happen */ + return 1; } + /* iRet is now the number of bytes read. Now we check for command + interrupts */ + pPtr = strstr(pBuffer, "INT1712"); + if (pPtr) { + sscanf(pPtr, "%s %d", pMuell, &iInt); + if (SCMatchRights(pItem->pCon, usUser)) { + traceCommand(ConID(pItem->pCon),"interrupt: %d",iInt); + TaskSignal(self->pMain->pTasker, SICSINT, &iInt); + snprintf(pBueffel,sizeof(pBueffel)-1, "INTERRUPT %d issued on sock %d", + iInt, pItem->pCon->pSock->sockid); + WriteToCommandLog("SYS>", pBueffel); + if (iInt == eEndServer) { + TaskStop(self->pMain->pTasker); + } + } else { + SCWrite(pItem->pCon, + "ERROR: insufficient privilege to invoke Interrupt", eError); + } + return 0; + } + + /* split into command lines + and put into fifo + */ + pBufEnd = pBuffer + iRet; + pPtr = pBuffer; + pEnd = pBuffer; + state = COLLECT; + while (pEnd < pBufEnd) { + switch (state) { + case COLLECT: + if ((*pEnd != '\r') && (*pEnd != '\n')) { + pEnd++; + } else { + /* there is a string between pPtr and pEnd */ + *pEnd = '\0'; + /* do we have something in hold ? */ + if (strlen(pItem->pHold) > 0) { + strlcat(pItem->pHold, pPtr,511); + iStat = CostaTop(pItem->pCon->pStack, pItem->pHold); + if (!iStat) { + SCWrite(pItem->pCon, "ERROR: Busy", eError); + } + pItem->pHold[0] = '\0'; + } else { + /* no, normal command */ + iStat = CostaTop(pItem->pCon->pStack, pPtr); + if (!iStat) { + SCWrite(pItem->pCon, "ERROR: Busy", eError); + } + } + pPtr = pEnd + 1; + pEnd = pPtr; + state = SKIPTERM; + } + break; + case SKIPTERM: + if ((*pEnd != '\r') && (*pEnd != '\n')) { + state = COLLECT; + pPtr = pEnd; + } else { + pEnd++; + pPtr = pEnd; + } + break; + } + } + /* when we are here we may still have an incomplete command pending */ + if (pEnd != pPtr && strlen(pPtr) > 0) { + strlcpy(pItem->pHold, pPtr, 511); + } + return 1; +} + +/*-------------------------- telnet protocoll code -------------------------*/ +static int TelnetAccept(pNetRead self, mkChannel * pSock) +{ + mkChannel *pNew = NULL; + char pBuffer[1064]; + int iRet; + SConnection *pRes = NULL; + pTelTask pTel = NULL; + + if (!VerifyChannel(pSock)) { + return 0; + } + + /* check for new connection */ + pNew = NETAccept(pSock, 0); + if (pNew) { + /* create connection object */ + /* TODO + pRes = SCreateConnection(self->pMain->pSics,pNew,usSpy); + */ + if (!pRes) { + SICSLogWrite("Failure to allocate new Connection", eInternal); + NETClosePort(pNew); + free(pNew); + return 0; + } else { + /* Create a task object for the telnet connection */ + pTel = CreateTelnet(pRes); + if (!pTel) { + SICSLogWrite("Failure to allocate new Telnet Task Object", + eInternal); + SCDeleteConnection(pRes); + return 0; + } + /* register connection and task */ + pRes->iTelnet = 1; + NetReadRegister(self, pNew, tcommand, pRes); + TaskRegister(self->pMain->pTasker, + TelnetTask, TelnetSignal, DeleteTelnet, pTel, 1); + return 1; + } + } else { + return 0; + } +} + /*------------------------------------------------------------------------ Telnet is fully described in RFC-854. This implementation is very simple. It just supports the NVT and no options. Implementation is via a state @@ -424,7 +385,7 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */ /* Telnet codes */ #define SE 240 #define NOP 241 -#define DM 242 /* data mark */ +#define DM 242 /* data mark */ #define BRK 243 #define IP 244 #define AO 245 @@ -440,651 +401,947 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */ #define IAC 255 #define EOR 239 /*-----------------------------------------------------------------------*/ - static int TelnetReply(pNetItem pItem, char code, char cChar) - { - char pReply[3]; - - pReply[0] = IAC; - pReply[1] = code; - pReply[2] = cChar; - - NETWrite(pItem->pCon->pSock,pReply,3); - return 1; - } +static int TelnetReply(pNetItem pItem, char code, char cChar) +{ + char pReply[3]; + + pReply[0] = IAC; + pReply[1] = code; + pReply[2] = cChar; + + NETWrite(pItem->pCon->pSock, pReply, 3); + return 1; +} + /*------------------------------------------------------------------------*/ - static int TelnetRead(pNetRead self, pNetItem pItem) - { - char pBuffer[1024], pMuell[20], pError[256]; - int i, iStat, iInt, iRet; - int cChar; - char *pPtr = NULL; - SConnection *pOwner = NULL; - - /* read first */ - memset(pBuffer,0,1023); - iRet = NETRead(pItem->pCon->pSock,pBuffer, 1022,0); - if(iRet < 0) /* EOF */ - { - pItem->pCon->iEnd = 1; - NetReadRemove(self,pItem->pCon->pSock); - return 0; - } - else if(iRet == 0) /* should not happen */ - { - return 1; - } - - /* iRet is now the number of bytes read. Now we check for command - interrupts */ - pPtr = strstr(pBuffer,"INT1712"); - if(pPtr) - { - sscanf(pPtr, "%s %d",pMuell, &iInt); - if(SCMatchRights(pItem->pCon,usUser)) - { - /* owners may kill own tasks, otherwise manager - privilege is required. - */ - pOwner = GetExeOwner(pServ->pExecutor); - if(pOwner) - { - if(pOwner != pItem->pCon) - { - if(!SCMatchRights(pItem->pCon,usMugger)) - { - SCWrite(pItem->pCon, - "ERROR: Insufficient privilege to stop other people's experiments", - eError); - return 1; - } - } - } - TaskSignal(self->pMain->pTasker, SICSINT, &iInt); - sprintf(pError,"INTERRUPT %d issued on sock %d",iInt, - pItem->pCon->pSock->sockid); - WriteToCommandLog("SYS>",pError); - if(iInt == eEndServer) - { - TaskStop(self->pMain->pTasker); - } - } - else - { - SCWrite(pItem->pCon,"ERROR: insufficient privilege to invoke Interrupt", - eError); - } - return 1; - } - - /* do telnet analysis of the data buffer */ - for(i = 0; i < iRet; i++) - { - cChar = (int)pBuffer[i]; -#ifdef TELNETDEBUG - if( (cChar > 48) && (cChar < 128) ) - { - printf("char: %c\n",cChar); - } - else - { - printf("Control: %d\n",cChar); - } -#endif - /* Telnet status switching */ - switch(pItem->tStatus) - { - case tData: - switch(cChar) - { - case IAC: - pItem->tStatus = tIAC; - break; - case '\r': - case '\n': - /* DFC locking for protocol zero only */ - if (pItem->pCon->iProtocolID == 0 && - CostaLocked(pItem->pCon->pStack)) - iStat = 0; - else - iStat = CostaTop(pItem->pCon->pStack,pItem->pHold); - /* printf("%s\n",pItem->pHold); */ - if(!iStat) - { - SCWrite(pItem->pCon,"ERROR: Busy",eError); - } - memset(pItem->pHold,0,511); - pItem->iEOD = 0; - pItem->tStatus = tCR; - break; - case (char)8: /* backspace */ - pItem->iEOD--; - if(pItem->iEOD < 0) - { - pItem->iEOD = 0; - } - break; - case (char)0:/* ignore 0 character sent as end of text */ - break; - default: - pItem->pHold[pItem->iEOD] = cChar; - pItem->iEOD++; - break; - - } /* end of tData case */ - break; - case tCR: /* ignore the second character after a newline. - Telnet gives you two characters for newline - */ - pItem->tStatus = tData; - break; - case tIAC: - switch(cChar) - { - case IAC: - pItem->tStatus = tData; - break; - case WILL: - pItem->tStatus = tWill; - break; - case WONT: - pItem->tStatus = tWont; - break; - case DONT: - pItem->tStatus = tDont; - break; - case DO: - pItem->tStatus = tDo; - break; - case EOR: - pItem->tStatus = tData; - break; - case SB: - pItem->tStatus = tSB; - break; - case EC: - pItem->iEOD--; - if(pItem->iEOD < 0) - { - pItem->iEOD = 0; - } - pItem->tStatus = tData; - break; - case EL: - memset(pItem->pHold,0,511); - pItem->iEOD = 0; - pItem->tStatus = tData; - break; - case IP: - SCSetInterrupt(pItem->pCon,eAbortBatch); - pItem->tStatus = tData; - break; - default: - pItem->tStatus = tData; - break; - } /* end of tIAC */ - break; - case tWill: /* we do not do options! */ - TelnetReply(pItem,DONT,cChar); - pItem->tStatus = tData; - break; - case tWont: /* we do not do options! A Wont is sent by the client - if it cannot do a option we requested it to have. As - we do not try to force options, this should not happen - */ - pItem->tStatus = tData; - break; - case tDo: /* we do not do options! */ - TelnetReply(pItem,WONT,cChar); - pItem->tStatus = tData; - break; - case tDont: /* we do not do options! A Dont is sent by the client - if it cannot do a option we requested it to have. As - we do not try to force options, this should not happen - */ - pItem->tStatus = tData; - break; - case tSB: /* as we do not have options, we cannot have suboption - negotaitions. Something is seriously wrong when - we are here. It is a protocoll error. However, we - ignore it silently. tSB marks the start of the - subnegotiation. The current character must be the - option code we are dealing with. - */ - pItem->tStatus = tSE; - break; - case tSE: - /* now we are in the suboption parameter. Normally data - should be copied to a suboption string buffer here - until SE. - */ - switch(cChar) - { - case IAC: - break; - case SE: - pItem->tStatus = tData; - /* suboption interpretation would go here */ - break; - default: - /* copy data to suboption buffer */ - break; - } - break; - - default: - /* There is something wrong here! */ - sprintf(pError,"ERROR: bad telnet code %d", cChar); - SICSLogWrite(pError,eInternal); - pItem->tStatus = tData; - break; - - } - } - return 1; - } - -/*---------------------------------------------------------------------------*/ - static int NetReadUDP(pNetRead self, pNetItem pItem) - { - char pBueffel[512], pMuell[20]; - int iRet, iInt; - char *pPtr = NULL; - - /* read */ - iRet = UDPRead(pItem->pSock,pBueffel,510,0); - if(iRet > 10) /* something has beeen sent, verfify */ - { - pPtr = strstr(pBueffel,"SICSINT"); - if(pPtr) - { - sscanf(pPtr,"%s %d", pMuell, &iInt); - TaskSignal(self->pMain->pTasker, SICSINT, &iInt); - if(iInt == eEndServer) - { - TaskStop(self->pMain->pTasker); - } - return 1; - } - } - return 0; +static int TelnetRead(pNetRead self, pNetItem pItem) +{ + char pBuffer[1024], pMuell[20], pError[256]; + int i, iStat, iInt, iRet; + int cChar; + char *pPtr = NULL; + SConnection *pOwner = NULL; + + /* read first */ + memset(pBuffer, 0, 1023); + iRet = NETRead(pItem->pCon->pSock, pBuffer, 1022, 0); + if (iRet < 0) { /* EOF */ + pItem->pCon->iEnd = 1; + NetReadRemove(self, pItem->pCon->pSock); + return 0; + } else if (iRet == 0) { /* should not happen */ + return 1; } -/*-------------------------------------------------------------------------*/ - int NetReaderTask(void *pData) - { - pNetRead self = NULL; - fd_set lMask; - struct timeval tmo = {0,1}; - int iRet, iStatus; - int iCount; - NetItem NItem; - int conCount = 0; - char num[50]; - IPair *options = NULL; - char buffer[1024]; - int bufferLen; - static int bufferFull=0; - - self = (pNetRead)pData; - assert(self); - if(self->lMagic != NRMAGIC) - { - return 0; - } - - /* check for end */ - if(self->iEnd) - { - return 0; - } - - /* build the select mask */ - FD_ZERO(&lMask); - iRet = LLDnodePtr2First(self->iList); - iCount = 0; - buffer[0] = '\0'; - bufferLen = 0; - while(iRet != 0) - { - LLDnodeDataTo(self->iList,&NItem); - if(!VerifyChannel(NItem.pSock)) - { - break; - } - snprintf(num,sizeof num, "%d, type %d:", NItem.pSock->sockid, NItem.eType); - if (bufferLen + strlen(num) < sizeof buffer) { - strcpy(buffer + bufferLen, num); - bufferLen += strlen(num); - } else { - if (bufferFull == 0) { - bufferFull = 1; + + /* iRet is now the number of bytes read. Now we check for command + interrupts */ + pPtr = strstr(pBuffer, "INT1712"); + if (pPtr) { + sscanf(pPtr, "%s %d", pMuell, &iInt); + if (SCMatchRights(pItem->pCon, usUser)) { + /* owners may kill own tasks, otherwise manager + privilege is required. + */ + pOwner = GetExeOwner(pServ->pExecutor); + if (pOwner) { + if (pOwner != pItem->pCon) { + if (!SCMatchRights(pItem->pCon, usMugger)) { + SCWrite(pItem->pCon, + "ERROR: Insufficient privilege to stop other people's experiments", + eError); + return 1; + } } } - FD_SET(NItem.pSock->sockid,&lMask); - if(NItem.pSock->sockid > iCount) - { - iCount = NItem.pSock->sockid; + TaskSignal(self->pMain->pTasker, SICSINT, &iInt); + traceCommand(ConID(pItem->pCon),"interrupt: %d",iInt); + snprintf(pError,sizeof(pError)-1, "INTERRUPT %d issued on sock %d", iInt, + pItem->pCon->pSock->sockid); + WriteToCommandLog("SYS>", pError); + if (iInt == eEndServer) { + TaskStop(self->pMain->pTasker); } - conCount++; - iRet = LLDnodePtr2Next(self->iList); + } else { + SCWrite(pItem->pCon, + "ERROR: insufficient privilege to invoke Interrupt", eError); } - - snprintf(num,sizeof num,"%d", conCount); - IFSetOption(pSICSOptions,"ConnectionCount",num); - IFSetOption(pSICSOptions,"ConMask",buffer); - - if (bufferFull == 1) { - bufferFull = 2; - WriteToCommandLog("BUFFERFULL>",buffer); + return 1; + } + + /* do telnet analysis of the data buffer */ + for (i = 0; i < iRet; i++) { + cChar = (int) pBuffer[i]; +#ifdef TELNETDEBUG + if ((cChar > 48) && (cChar < 128)) { + printf("char: %c\n", cChar); + } else { + printf("Control: %d\n", cChar); } - - /* the select itself */ - tmo.tv_usec = self->iReadTimeout; - iCount++; - iRet = select(iCount, &lMask,NULL,NULL,&tmo); - if(iRet <= 0) /* no pending request */ - { +#endif + /* Telnet status switching */ + switch (pItem->tStatus) { + case tData: + switch (cChar) { + case IAC: + pItem->tStatus = tIAC; + break; + case '\r': + case '\n': + iStat = CostaTop(pItem->pCon->pStack, pItem->pHold); + /* printf("%s\n",pItem->pHold); */ + if (!iStat) { + SCWrite(pItem->pCon, "ERROR: Busy", eError); + } + memset(pItem->pHold, 0, 511); + pItem->iEOD = 0; + pItem->tStatus = tCR; + break; + case (char) 8: /* backspace */ + pItem->iEOD--; + if (pItem->iEOD < 0) { + pItem->iEOD = 0; + } + break; + case (char) 0: /* ignore 0 character sent as end of text */ + break; + default: + pItem->pHold[pItem->iEOD] = cChar; + pItem->iEOD++; + break; + + } /* end of tData case */ + break; + case tCR: /* ignore the second character after a newline. + Telnet gives you two characters for newline + */ + pItem->tStatus = tData; + break; + case tIAC: + switch (cChar) { + case IAC: + pItem->tStatus = tData; + break; + case WILL: + pItem->tStatus = tWill; + break; + case WONT: + pItem->tStatus = tWont; + break; + case DONT: + pItem->tStatus = tDont; + break; + case DO: + pItem->tStatus = tDo; + break; + case EOR: + pItem->tStatus = tData; + break; + case SB: + pItem->tStatus = tSB; + break; + case EC: + pItem->iEOD--; + if (pItem->iEOD < 0) { + pItem->iEOD = 0; + } + pItem->tStatus = tData; + break; + case EL: + memset(pItem->pHold, 0, 511); + pItem->iEOD = 0; + pItem->tStatus = tData; + break; + case IP: + SCSetInterrupt(pItem->pCon, eAbortBatch); + pItem->tStatus = tData; + break; + default: + pItem->tStatus = tData; + break; + } /* end of tIAC */ + break; + case tWill: /* we do not do options! */ + TelnetReply(pItem, DONT, cChar); + pItem->tStatus = tData; + break; + case tWont: /* we do not do options! A Wont is sent by the client + if it cannot do a option we requested it to have. As + we do not try to force options, this should not happen + */ + pItem->tStatus = tData; + break; + case tDo: /* we do not do options! */ + TelnetReply(pItem, WONT, cChar); + pItem->tStatus = tData; + break; + case tDont: /* we do not do options! A Dont is sent by the client + if it cannot do a option we requested it to have. As + we do not try to force options, this should not happen + */ + pItem->tStatus = tData; + break; + case tSB: /* as we do not have options, we cannot have suboption + negotaitions. Something is seriously wrong when + we are here. It is a protocoll error. However, we + ignore it silently. tSB marks the start of the + subnegotiation. The current character must be the + option code we are dealing with. + */ + pItem->tStatus = tSE; + break; + case tSE: + /* now we are in the suboption parameter. Normally data + should be copied to a suboption string buffer here + until SE. + */ + switch (cChar) { + case IAC: + break; + case SE: + pItem->tStatus = tData; + /* suboption interpretation would go here */ + break; + default: + /* copy data to suboption buffer */ + break; + } + break; + + default: + /* There is something wrong here! */ + snprintf(pError,sizeof(pError)-1, "ERROR: bad telnet code %d", cChar); + SICSLogWrite(pError, eInternal); + pItem->tStatus = tData; + break; + + } + } + return 1; +} + +/*---------------------------------------------------------------------------*/ +static int NetReadUDP(pNetRead self, pNetItem pItem) +{ + char pBueffel[512], pMuell[20]; + int iRet, iInt; + char *pPtr = NULL; + + /* read */ + iRet = UDPRead(pItem->pSock, pBueffel, 510, 0); + if (iRet > 10) { /* something has beeen sent, verfify */ + pPtr = strstr(pBueffel, "SICSINT"); + if (pPtr) { + sscanf(pPtr, "%s %d", pMuell, &iInt); + TaskSignal(self->pMain->pTasker, SICSINT, &iInt); + if (iInt == eEndServer) { + TaskStop(self->pMain->pTasker); + } return 1; } - - - /* now go through all registered things and handle the message */ - iRet = LLDnodePtr2First(self->iList); - while(iRet != 0) - { - LLDnodeDataTo(self->iList,&NItem); - if(FD_ISSET(NItem.pSock->sockid,&lMask)) /* data */ - { - switch(NItem.eType) - { - /* lists have been changed after accept, return */ - case naccept: - NetReadAccept(self,NItem.pSock); - return 1; - break; - case taccept: - TelnetAccept(self,NItem.pSock); - return 1; - break; - case command: - iStatus = NetReadRead(self,&NItem); - if(iStatus == 0) /* there was an eof */ - { - /* do not continue, list is messy */ - return 1; - } - break; - case tcommand: - iStatus = TelnetRead(self,&NItem); - if(iStatus == 0) /* there was an eof */ - { - /* do not continue, list is messy */ - return 1; - } - break; - case udp: - NetReadUDP(self,&NItem); - break; - case user: - NItem.iReadable = 1; - LLDnodeDataFrom(self->iList, &NItem); - break; - } - LLDnodeDataFrom(self->iList,&NItem); - } - iRet = LLDnodePtr2Next(self->iList); - } - - /* done, finally */ - return 1; - } -/*--------------------------------------------------------------------------*/ - void NetReaderSignal(void *pUser, int iSignal, void *pEventData) - { - pNetRead self = NULL; - int *iInt; - - self = (pNetRead)pUser; - assert(self); - iInt = (int *)pEventData; - - if(iSignal == SICSINT) - { - iInt = (int *)pEventData; - if(*iInt == eEndServer) - { - self->iEnd = 1; - } - } } -/*--------------------------------------------------------------------------*/ - typedef struct { - pNetRead pRead; - mkChannel *pChan; - int iEnd; - } ReadWait, *pReadWait; -/*--------------------------------------------------------------------------*/ - static void ReadWaitFree(void *pData) - { - pReadWait pWait = NULL; - - pWait = (pReadWait)pData; - if(!pWait) - { - return; - } - - if(pWait->pChan) - { - free(pWait->pChan); - } - free(pWait); - } -/*--------------------------------------------------------------------------*/ - static void ReadWaitSignal(void *pUser, int iSignal, void *pSigData) - { - pReadWait pWait = NULL; - int *iInt; - - pWait = (pReadWait)pUser; - assert(pWait); - - if(iSignal == SICSINT) - { - iInt = (int *)pSigData; - if(*iInt != eContinue) - { - pWait->iEnd = 1; - } - } - } -/*---------------------------------------------------------------------------*/ - static int Wait4ReadTask(void *pData) - { - pReadWait pWait = NULL; - NetItem sItem; - int iRet; - - pWait = (pReadWait)pData; - assert(pWait); - - if(pWait->iEnd) - { - return 0; /* an interrupt occurred */ - } - - iRet = LLDnodePtr2First(pWait->pRead->iList); - while(iRet != 0) - { - LLDnodeDataTo(pWait->pRead->iList, &sItem); - if(sItem.pSock == pWait->pChan) - { - if(sItem.iReadable) - { - NetReadRemove(pWait->pRead,pWait->pChan); - return 0; - } - } - iRet = LLDnodePtr2Next(pWait->pRead->iList); - } - return 1; - } -/*---------------------------------------------------------------------------*/ - int NetReadWait4Data(pNetRead self, int iSocket) - { - pReadWait pNew = NULL; - mkChannel *pChan = NULL; - long lID; - int iRet; - - /* make a new ReadWait */ - pNew = (pReadWait)malloc(sizeof(ReadWait)); - if(!pNew) - { - return 0; - } - - /* make a new channel */ - pChan = (mkChannel *)malloc(sizeof(mkChannel)); - if(!pChan) - { - free(pNew); - return 0; - } - pChan->sockid = iSocket; - pChan->lMagic = NETMAGIC; - - /* put it into the NetReader */ - iRet = NetReadRegister(self,pChan,user,NULL); - if(!iRet) - { - return 0; - } - - /* start the wait task */ - pNew->pChan = pChan; - pNew->iEnd = 0; - pNew->pRead = self; - lID = TaskRegister(self->pMain->pTasker, - Wait4ReadTask, - ReadWaitSignal, - ReadWaitFree, - pNew,0); - - /* wait for finish */ - TaskWait(self->pMain->pTasker,lID); - - return 1; - } -/*--------------------------------------------------------------------------*/ - int NetReadRegisterUserSocket(pNetRead self, int iSocket) - { - mkChannel *pChan = NULL; - int iRet; - - - /* make a new channel */ - pChan = (mkChannel *)malloc(sizeof(mkChannel)); - if(!pChan) - { - return 0; - } - pChan->sockid = iSocket; - pChan->lMagic = NETMAGIC; - - /* put it into the NetReader */ - iRet = NetReadRegister(self,pChan,user,NULL); - if(!iRet) - { - return 0; - } - return 1; - } -/*--------------------------------------------------------------------------*/ - int NetReadRemoveUserSocket(pNetRead self, int iSocket) - { - NetItem sItem; - int iRet; - - assert(self); - if(self->lMagic != NRMAGIC) - { - return 0; - } - - /* find the entry to remove */ - iRet = LLDnodePtr2First(self->iList); - while(iRet != 0) - { - LLDnodeDataTo(self->iList,&sItem); - if(sItem.eType == user) - { - if(sItem.pSock->sockid == iSocket) - { - free(sItem.pSock); - LLDnodeDelete(self->iList); - return 1; - } - } - iRet = LLDnodePtr2Next(self->iList); - } - return 0; - } -/*--------------------------------------------------------------------------*/ - int NetReadReadable(pNetRead self, int iSocket) - { - NetItem sItem; - int iRet; - - assert(self); - - /* find the entry to read */ - iRet = LLDnodePtr2First(self->iList); - while(iRet != 0) - { - LLDnodeDataTo(self->iList,&sItem); - if(sItem.eType == user) - { - if(sItem.pSock->sockid == iSocket) - { - if(sItem.iReadable) - { - return 1; - } - else - { - return 0; - } - } - } - iRet = LLDnodePtr2Next(self->iList); - } - return 0; - } -/*--------------------------------------------------------------------------*/ - int NetReadResetUser(pNetRead self, int iSocket) - { - NetItem sItem; - int iRet; - - assert(self); - - /* find the entry to remove */ - iRet = LLDnodePtr2First(self->iList); - while(iRet != 0) - { - LLDnodeDataTo(self->iList,&sItem); - if(sItem.eType == user) - { - if(sItem.pSock->sockid == iSocket) - { - sItem.iReadable = 0; - LLDnodeDataFrom(self->iList,&sItem); - return 1; - } - } - iRet = LLDnodePtr2Next(self->iList); - } + return 0; +} + +/*-------------------------------------------------------------------------*/ +int NetReaderTask(void *pData) +{ + pNetRead self = NULL; + fd_set lMask; + struct timeval tmo = { 0, 1 }; + int iRet, iStatus; + int iCount; + NetItem NItem; + int conCount = 0; + char num[50]; + IPair *options = NULL; + + self = (pNetRead) pData; + assert(self); + if (self->lMagic != NRMAGIC) { return 0; } + /* check for end */ + if (self->iEnd) { + return 0; + } + ANETprocess(); + + /* build the select mask */ + FD_ZERO(&lMask); + iRet = LLDnodePtr2First(self->iList); + iCount = 0; + DynStringClear(self->conList); + while (iRet != 0) { + LLDnodeDataTo(self->iList, &NItem); + if (!VerifyChannel(NItem.pSock)) { + break; + } + + snprintf(num,sizeof(num)-1, "%d, type %d:", NItem.pSock->sockid, NItem.eType); + if (conCount < 100) { + DynStringConcat(self->conList, num); + } + FD_SET(NItem.pSock->sockid, &lMask); + if (NItem.pSock->sockid > iCount) { + iCount = NItem.pSock->sockid; + } + conCount++; + if (conCount > 100) { + WriteToCommandLog("WAYTOMANYCONNECTIONS> ", + GetCharArray(self->conList)); + } + iRet = LLDnodePtr2Next(self->iList); + } + + if (conCount > 100) { + WriteToCommandLog("WAYTOMANYCONNECTIONS> ", + GetCharArray(self->conList)); + } + + /* + * This costs a surprising amount of CPU-time, in a test 10%! + * This is why it has been commented away + snprintf(num, sizeof num, "%d", conCount); + IFSetOption(pSICSOptions, "ConnectionCount", num); + IFSetOption(pSICSOptions, "ConMask", GetCharArray(self->conList)); +*/ + + /* the select itself */ + tmo.tv_usec = self->iReadTimeout; + iCount++; + iRet = uselect(iCount, &lMask, NULL, NULL, &tmo); + if (iRet <= 0) { /* no pending request */ + return 1; + } + + + /* now go through all registered things and handle the message */ + iRet = LLDnodePtr2First(self->iList); + while (iRet != 0) { + LLDnodeDataTo(self->iList, &NItem); + if (FD_ISSET(NItem.pSock->sockid, &lMask)) { /* data */ + switch (NItem.eType) { + /* lists have been changed after accept, return */ + case naccept: + NetReadAccept(self, NItem.pSock); + return 1; + break; + case taccept: + TelnetAccept(self, NItem.pSock); + return 1; + break; + case command: + iStatus = NetReadRead(self, &NItem); + if (iStatus == 0) { /* there was an eof */ + /* do not continue, list is messy */ + return 1; + } + break; + case tcommand: + iStatus = TelnetRead(self, &NItem); + if (iStatus == 0) { /* there was an eof */ + /* do not continue, list is messy */ + return 1; + } + break; + case udp: + NetReadUDP(self, &NItem); + break; + case user: + NItem.iReadable = 1; + LLDnodeDataFrom(self->iList, &NItem); + break; + } + LLDnodeDataFrom(self->iList, &NItem); + } + iRet = LLDnodePtr2Next(self->iList); + } + + /* done, finally */ + return 1; +} + +/*--------------------------------------------------------------------------*/ +void NetReaderSignal(void *pUser, int iSignal, void *pEventData) +{ + pNetRead self = NULL; + int *iInt; + + self = (pNetRead) pUser; + assert(self); + iInt = (int *) pEventData; + + if (iSignal == SICSINT) { + iInt = (int *) pEventData; + if (*iInt == eEndServer) { + self->iEnd = 1; + } + } +} + +/*--------------------------------------------------------------------------*/ +typedef struct { + pNetRead pRead; + mkChannel *pChan; + int iEnd; +} ReadWait, *pReadWait; +/*--------------------------------------------------------------------------*/ +static void ReadWaitFree(void *pData) +{ + pReadWait pWait = NULL; + + pWait = (pReadWait) pData; + if (!pWait) { + return; + } + + if (pWait->pChan) { + free(pWait->pChan); + } + free(pWait); +} + +/*--------------------------------------------------------------------------*/ +static void ReadWaitSignal(void *pUser, int iSignal, void *pSigData) +{ + pReadWait pWait = NULL; + int *iInt; + + pWait = (pReadWait) pUser; + assert(pWait); + + if (iSignal == SICSINT) { + iInt = (int *) pSigData; + if (*iInt != eContinue) { + pWait->iEnd = 1; + } + } +} + +/*---------------------------------------------------------------------------*/ +static int Wait4ReadTask(void *pData) +{ + pReadWait pWait = NULL; + NetItem sItem; + int iRet; + + pWait = (pReadWait) pData; + assert(pWait); + + if (pWait->iEnd) { + return 0; /* an interrupt occurred */ + } + + iRet = LLDnodePtr2First(pWait->pRead->iList); + while (iRet != 0) { + LLDnodeDataTo(pWait->pRead->iList, &sItem); + if (sItem.pSock == pWait->pChan) { + if (sItem.iReadable) { + NetReadRemove(pWait->pRead, pWait->pChan); + return 0; + } + } + iRet = LLDnodePtr2Next(pWait->pRead->iList); + } + return 1; +} + +/*---------------------------------------------------------------------------*/ +int NetReadWait4Data(pNetRead self, int iSocket) +{ + pReadWait pNew = NULL; + mkChannel *pChan = NULL; + long lID; + int iRet; + + /* make a new ReadWait */ + pNew = (pReadWait) malloc(sizeof(ReadWait)); + if (!pNew) { + return 0; + } + + /* make a new channel */ + pChan = (mkChannel *) malloc(sizeof(mkChannel)); + if (!pChan) { + free(pNew); + return 0; + } + pChan->sockid = iSocket; + pChan->lMagic = NETMAGIC; + + /* put it into the NetReader */ + iRet = NetReadRegister(self, pChan, user, NULL); + if (!iRet) { + return 0; + } + + /* start the wait task */ + pNew->pChan = pChan; + pNew->iEnd = 0; + pNew->pRead = self; + lID = TaskRegister(self->pMain->pTasker, + Wait4ReadTask, ReadWaitSignal, ReadWaitFree, pNew, 0); + + /* wait for finish */ + TaskWait(self->pMain->pTasker, lID); + + return 1; +} + +/*--------------------------------------------------------------------------*/ +int NetReadRegisterUserSocket(pNetRead self, int iSocket) +{ + mkChannel *pChan = NULL; + int iRet; + + + /* make a new channel */ + pChan = (mkChannel *) malloc(sizeof(mkChannel)); + if (!pChan) { + return 0; + } + pChan->sockid = iSocket; + pChan->lMagic = NETMAGIC; + + /* put it into the NetReader */ + iRet = NetReadRegister(self, pChan, user, NULL); + if (!iRet) { + return 0; + } + return 1; +} + +/*--------------------------------------------------------------------------*/ +int NetReadRemoveUserSocket(pNetRead self, int iSocket) +{ + NetItem sItem; + int iRet; + + assert(self); + if (self->lMagic != NRMAGIC) { + return 0; + } + + /* find the entry to remove */ + iRet = LLDnodePtr2First(self->iList); + while (iRet != 0) { + LLDnodeDataTo(self->iList, &sItem); + if (sItem.eType == user) { + if (sItem.pSock->sockid == iSocket) { + free(sItem.pSock); + LLDnodeDelete(self->iList); + return 1; + } + } + iRet = LLDnodePtr2Next(self->iList); + } + return 0; +} + +/*--------------------------------------------------------------------------*/ +int NetReadReadable(pNetRead self, int iSocket) +{ + NetItem sItem; + int iRet; + + assert(self); + + /* find the entry to read */ + iRet = LLDnodePtr2First(self->iList); + while (iRet != 0) { + LLDnodeDataTo(self->iList, &sItem); + if (sItem.eType == user) { + if (sItem.pSock->sockid == iSocket) { + if (sItem.iReadable) { + return 1; + } else { + return 0; + } + } + } + iRet = LLDnodePtr2Next(self->iList); + } + return 0; +} + +/*--------------------------------------------------------------------------*/ +int NetReadResetUser(pNetRead self, int iSocket) +{ + NetItem sItem; + int iRet; + + assert(self); + + /* find the entry to remove */ + iRet = LLDnodePtr2First(self->iList); + while (iRet != 0) { + LLDnodeDataTo(self->iList, &sItem); + if (sItem.eType == user) { + if (sItem.pSock->sockid == iSocket) { + sItem.iReadable = 0; + LLDnodeDataFrom(self->iList, &sItem); + return 1; + } + } + iRet = LLDnodePtr2Next(self->iList); + } + return 0; +} + +/*=================================================================================== + * new code to support the ANET network stuff + * =================================================================================*/ +typedef struct { + pDynString command; + int state; + SConnection *pCon; +} CommandCBData, *pCommandCBData; +/*----------------------------------------------------------------------------------*/ +static void killCommandCBData(void *data) +{ + pCommandCBData self = (pCommandCBData) data; + if (self == NULL) { + return; + } + if (self->command != NULL) { + DeleteDynString(self->command); + } + free(self); +} + +/*----------------------------------------------------------------------------------*/ +static int testAndInvokeInterrupt(pCommandCBData self, int handle) +{ + char *pPtr, *pInt; + char buffer[512]; + int iInt; + + pPtr = GetCharArray(self->command); + if ((pInt = strstr(pPtr, "INT1712")) != NULL) { + sscanf(pInt, "%s %d", buffer, &iInt); + if (SCMatchRights(self->pCon, usUser)) { + traceCommand(ConID(self->pCon),"interrupt:%d",iInt); + TaskSignal(pServ->pTasker, SICSINT, &iInt); + snprintf(buffer, 512, "INTERRUPT %d issued on sock %d", + iInt, handle); + WriteToCommandLog("SYS>", buffer); + if (iInt == eEndServer) { + TaskStop(pServ->pTasker); + } + } else { + SCWrite(self->pCon, + "ERROR: insufficient privilege to invoke Interrupt", eError); + } + return 1; + } else if(strstr(pPtr,"Poch") != NULL){ + SCPureSockWrite(self->pCon,"Poch\r\n", eLog); + return 1; + } + return 0; +} + +/*----------------------------------------------------------------------------------*/ +static int CommandDataCB(int handle, void *userData) +{ + pCommandCBData self = (pCommandCBData) userData; + int i, length, status; + char *pPtr = NULL; + + assert(self != NULL); + pPtr = ANETreadPtr(handle, &length); + if (pPtr == NULL) { + return 1; + } + for (i = 0; i < length; i++) { + switch (self->state) { + case COLLECT: + if (pPtr[i] == '\r' || pPtr[i] == '\n') { + self->state = SKIPTERM; + if (!testAndInvokeInterrupt(self, handle)) { + status = + CostaTop(self->pCon->pStack, GetCharArray(self->command)); + if (!status) { + SCWrite(self->pCon, "ERROR: Busy", eError); + } + } + DynStringClear(self->command); + } else { + if (pPtr[i] != '\0') { + DynStringConcatChar(self->command, pPtr[i]); + } + } + break; + case SKIPTERM: + if (pPtr[i] != '\r' && pPtr[i] != '\n' && pPtr[i] != '\0') { + DynStringConcatChar(self->command, pPtr[i]); + self->state = COLLECT; + } + break; + } + } + ANETreadConsume(handle, length); + return 1; +} + +/*----------------------------------------------------------------------------------*/ +static int CommandAcceptCB(int handle, void *userData) +{ + SConnection *pCon = NULL; + pCommandCBData usData = NULL; + + pCon = SCreateConnection(pServ->pSics, handle, 3); + usData = malloc(sizeof(CommandCBData)); + if (pCon == NULL || usData == NULL) { + SICSLogWrite("Failure to allocate new Connection", eInternal); + return 0; + } + usData->command = CreateDynString(256, 256); + if (usData->command == NULL) { + SICSLogWrite("Failure to allocate new Connection", eInternal); + return 0; + } + usData->pCon = pCon; + usData->state = COLLECT; + TaskRegister(pServ->pTasker, + SCTaskFunction, + SCSignalFunction, SCDeleteConnection, pCon, 1); + ANETsetReadCallback(handle, CommandDataCB, usData, killCommandCBData); + SCSendOK(pCon); + return 1; +} + +/*-----------------------------------------------------------------------*/ +static int ANETTelnetReply(int sockHandle, char code, char cChar) +{ + char pReply[3]; + + pReply[0] = IAC; + pReply[1] = code; + pReply[2] = cChar; + + ANETwrite(sockHandle, pReply, 3); + return 1; +} + +/*-----------------------------------------------------------------------*/ +static int ANETTelnetProcess(int handle, void *usData) +{ + pCommandCBData self = NULL; + int length, status, i; + int cChar; + char *pPtr = NULL; + char pError[256]; + + self = (pCommandCBData) usData; + assert(self != NULL); + + pPtr = ANETreadPtr(handle, &length); + + /* do telnet analysis of the data buffer */ + for (i = 0; i < length; i++) { + cChar = (int) pPtr[i]; +#ifdef TELNETDEBUG + if ((cChar > 48) && (cChar < 128)) { + printf("char: %c\n", cChar); + } else { + printf("Control: %d\n", cChar); + } +#endif + /* Telnet status switching */ + switch (self->state) { + case tData: + switch (cChar) { + case IAC: + self->state = tIAC; + break; + case '\r': + case '\n': + if (!testAndInvokeInterrupt(self, handle)) { + status = + CostaTop(self->pCon->pStack, GetCharArray(self->command)); + if (!status) { + SCWrite(self->pCon, "ERROR: Busy", eError); + } + } + self->state = tCR; + DynStringClear(self->command); + break; + case (char) 8: /* backspace */ + DynStringBackspace(self->command); + break; + case (char) 0: /* ignore 0 character sent as end of text */ + break; + default: + DynStringConcatChar(self->command, (char) cChar); + break; + + } /* end of tData case */ + break; + case tCR: + if (cChar == '\r' || cChar == '\n' || cChar == '\0') { + continue; + } else { + self->state = tData; + DynStringConcatChar(self->command, (char) cChar); + } + break; + case tIAC: + switch (cChar) { + case IAC: + self->state = tData; + break; + case WILL: + self->state = tWill; + break; + case WONT: + self->state = tWont; + break; + case DONT: + self->state = tDont; + break; + case DO: + self->state = tDo; + break; + case EOR: + self->state = tData; + break; + case SB: + self->state = tSB; + break; + case EC: + DynStringBackspace(self->command); + self->state = tData; + break; + case EL: + DynStringClear(self->command); + self->state = tData; + break; + case IP: + SCSetInterrupt(self->pCon, eAbortBatch); + self->state = tData; + break; + default: + self->state = tData; + break; + } /* end of tIAC */ + break; + case tWill: /* we do not do options! */ + ANETTelnetReply(handle, DONT, cChar); + self->state = tData; + break; + case tWont: /* we do not do options! A Wont is sent by the client + if it cannot do a option we requested it to have. As + we do not try to force options, this should not happen + */ + self->state = tData; + break; + case tDo: /* we do not do options! */ + ANETTelnetReply(handle, WONT, cChar); + self->state = tData; + break; + case tDont: /* we do not do options! A Dont is sent by the client + if it cannot do a option we requested it to have. As + we do not try to force options, this should not happen + */ + self->state = tData; + break; + case tSB: /* as we do not have options, we cannot have suboption + negotaitions. Something is seriously wrong when + we are here. It is a protocoll error. However, we + ignore it silently. tSB marks the start of the + subnegotiation. The current character must be the + option code we are dealing with. + */ + self->state = tSE; + break; + case tSE: + /* now we are in the suboption parameter. Normally data + should be copied to a suboption string buffer here + until SE. + */ + switch (cChar) { + case IAC: + break; + case SE: + self->state = tData; + /* suboption interpretation would go here */ + break; + default: + /* copy data to suboption buffer */ + break; + } + break; + + default: + /* There is something wrong here! */ + snprintf(pError,sizeof(pError)-1, "ERROR: bad telnet code %d", cChar); + SICSLogWrite(pError, eInternal); + self->state = tData; + break; + + } /* end master swicth */ + } /* end for loop */ + ANETreadConsume(handle, length); + return 1; +} + +/*----------------------------------------------------------------------------------*/ +static int TelnetAcceptCB(int handle, void *userData) +{ + SConnection *pCon = NULL; + pCommandCBData usData = NULL; + pTelTask pTel = NULL; + + pCon = SCreateConnection(pServ->pSics, handle, 3); + usData = malloc(sizeof(CommandCBData)); + if (pCon == NULL || usData == NULL) { + SICSLogWrite("Failure to allocate new Connection", eInternal); + return 0; + } + usData->command = CreateDynString(256, 256); + if (usData->command == NULL) { + SICSLogWrite("Failure to allocate new Connection", eInternal); + return 0; + } + usData->pCon = pCon; + usData->state = tData; + /* Create a task object for the telnet connection */ + pTel = CreateTelnet(pCon); + if (!pTel) { + SICSLogWrite("Failure to allocate new Telnet Task Object", eInternal); + SCDeleteConnection(pCon); + return 0; + } + /* register connection and task */ + pCon->iTelnet = 1; + TaskRegister(pServ->pTasker, + TelnetTask, TelnetSignal, DeleteTelnet, pTel, 1); + ANETsetReadCallback(handle, ANETTelnetProcess, + usData, killCommandCBData); + SCSendOK(pCon); + return 1; +} + +/*------------------------------------------------------------------------------------*/ +static void NREADlog(int level, char *txt, void *userData) +{ + traceSys("anet",txt); + puts(txt); +} + +/*------------------------------------------------------------------------------------*/ +int NetReadInstallANETPort(pNetRead self, eNRType eType, int iPort) +{ + ANETsetLog(NREADlog, NULL); + switch (eType) { + case naccept: + return ANETopenServerPort(iPort, CommandAcceptCB, NULL); + break; + case taccept: + return ANETopenServerPort(iPort, TelnetAcceptCB, NULL); + break; + } + return 0; +} diff --git a/nread.h b/nread.h index ea4cebda..15436177 100644 --- a/nread.h +++ b/nread.h @@ -14,23 +14,25 @@ #define SICSNETREADER /*--------------------------------------------------------------------------*/ - typedef struct __netreader *pNetRead; - typedef enum {naccept, command, udp, user, taccept, tcommand} eNRType; +typedef struct __netreader *pNetRead; +typedef enum { naccept, command, udp, user, taccept, tcommand } eNRType; /*--------------------------------------------------------------------------*/ - pNetRead CreateNetReader(pServer pServ, int iPasswdTimeout, - int iReadTimeout); - void DeleteNetReader(void *pData); +pNetRead CreateNetReader(pServer pServ, int iPasswdTimeout, + int iReadTimeout); +void DeleteNetReader(void *pData); /*--------------------------------------------------------------------------*/ - int NetReadRegister(pNetRead self, mkChannel *pSock, eNRType eType, - SConnection *pCon); - int NetReadRegisterUserSocket(pNetRead self, int iSocket); - int NetReadRemove(pNetRead self, mkChannel *pSock); - int NetReadRemoveUserSocket(pNetRead self, int iSocket); +int NetReadRegister(pNetRead self, mkChannel * pSock, eNRType eType, + SConnection * pCon); +int NetReadRegisterUserSocket(pNetRead self, int iSocket); +int NetReadRemove(pNetRead self, mkChannel * pSock); +int NetReadRemoveUserSocket(pNetRead self, int iSocket); /*-------------------------------------------------------------------------*/ - int NetReaderTask(void *pReader); - void NetReaderSignal(void *pUser, int iSignal, void *pSigData); - int NetReadWait4Data(pNetRead self, int iSocket); - int NetReadReadable(pNetRead self, int iSocket); - int NetReadResetUser(pNetRead self, int iSocket); +int NetReaderTask(void *pReader); +void NetReaderSignal(void *pUser, int iSignal, void *pSigData); +int NetReadWait4Data(pNetRead self, int iSocket); +int NetReadReadable(pNetRead self, int iSocket); +int NetReadResetUser(pNetRead self, int iSocket); +/*--------------------------------------------------------------------------*/ +int NetReadInstallANETPort(pNetRead self, eNRType eType, int iPort); #endif diff --git a/nread.tex b/nread.tex index 63df11cc..fd81c227 100644 --- a/nread.tex +++ b/nread.tex @@ -11,11 +11,11 @@ through a command channel A prior version of SICS had a select system call for each of these cases. It was found, that the code spent most of its time in the select system call -thus intrdoducing a major performance problem. +thus introducing a major performance problem. The select system call can handle more then one file descriptor in one call. This is exactly what this module handles. It does a global select on -all open sockets and forwards any pending data to approriate handlers. +all open sockets and forwards any pending data to appropriate handlers. This scheme brought a drastic performance improvement. @@ -25,13 +25,13 @@ differently: A connection request will be validated, a new connection object will be created and a new task for this connection object will be started. -A command will be placed in the apropriate command stack for the task +A command will be placed in the appropriate command stack for the task belonging to this connection to work on in a later stage. The netreader will also take care that all commands are complete, this is the terminator \verb+\n+ or \verb+\r+ has been sent. Both forms of interrupt will be interpreted and a suitable signal -will be sent to all runing tasks if the interrupt request is valid. +will be sent to all running tasks if the interrupt request is valid. In order to perform his tasks the network reader needs to maintain a list of all open sockets and their types. Additionally it needs to know about the @@ -61,6 +61,11 @@ come in on a user socket. This function is problematic with dynamically creates and deleted objects such as environment device objects. Its use is therefore no longer recommended. +In January 2009 a new asynchronous I/O structure was devised. This makes most of +NetReader obsolete. However, it was decided to keep the old structure for the +time being. A new function, NetReadInstallANETPort was added to install server +ports for the new system. + Thus the interface looks like this: \begin{flushleft} \small @@ -88,7 +93,9 @@ $\langle$nrint {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ int NetReadWait4Data(pNetRead self, int iSocket);@\\ \mbox{}\verb@ int NetReadReadable(pNetRead self, int iSocket);@\\ \mbox{}\verb@ int NetReadResetUser(pNetRead self, int iSocket);@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@/*--------------------------------------------------------------------------*/@\\ +\mbox{}\verb@ int NetReadInstallANETPort(pNetRead self, eNRType eType, int iPort); @\\ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} @@ -153,7 +160,7 @@ if not. \mbox{}\verb@#define SICSNETREADER@\\ \mbox{}\verb@@$\langle$nrint {\footnotesize ?}$\rangle$\verb@@\\ \mbox{}\verb@#endif@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-2ex} \end{minipage}\\[4ex] diff --git a/nread.w b/nread.w index 6279c8c3..f9c1fba2 100644 --- a/nread.w +++ b/nread.w @@ -11,11 +11,11 @@ through a command channel A prior version of SICS had a select system call for each of these cases. It was found, that the code spent most of its time in the select system call -thus intrdoducing a major performance problem. +thus introducing a major performance problem. The select system call can handle more then one file descriptor in one call. This is exactly what this module handles. It does a global select on -all open sockets and forwards any pending data to approriate handlers. +all open sockets and forwards any pending data to appropriate handlers. This scheme brought a drastic performance improvement. @@ -25,13 +25,13 @@ differently: A connection request will be validated, a new connection object will be created and a new task for this connection object will be started. -A command will be placed in the apropriate command stack for the task +A command will be placed in the appropriate command stack for the task belonging to this connection to work on in a later stage. The netreader will also take care that all commands are complete, this is the terminator \verb+\n+ or \verb+\r+ has been sent. Both forms of interrupt will be interpreted and a suitable signal -will be sent to all runing tasks if the interrupt request is valid. +will be sent to all running tasks if the interrupt request is valid. In order to perform his tasks the network reader needs to maintain a list of all open sockets and their types. Additionally it needs to know about the @@ -61,6 +61,11 @@ come in on a user socket. This function is problematic with dynamically creates and deleted objects such as environment device objects. Its use is therefore no longer recommended. +In January 2009 a new asynchronous I/O structure was devised. This makes most of +NetReader obsolete. However, it was decided to keep the old structure for the +time being. A new function, NetReadInstallANETPort was added to install server +ports for the new system. + Thus the interface looks like this: @d nrint @{ @@ -83,6 +88,8 @@ Thus the interface looks like this: int NetReadWait4Data(pNetRead self, int iSocket); int NetReadReadable(pNetRead self, int iSocket); int NetReadResetUser(pNetRead self, int iSocket); +/*--------------------------------------------------------------------------*/ + int NetReadInstallANETPort(pNetRead self, eNRType eType, int iPort); @} This starts off with the definition of a data type for the net reader and an diff --git a/nserver.c b/nserver.c index de27ba07..99b76c3f 100644 --- a/nserver.c +++ b/nserver.c @@ -28,7 +28,7 @@ #include "devexec.h" #include "passwd.h" #include "lld.h" -#include "macro.h" +#include "macro.h" #include "perfmon.h" #include "nread.h" #include "ofac.h" @@ -37,536 +37,476 @@ #include "tcldrivable.h" #include "nserver.h" #include "sicshipadaba.h" +#include "commandlog.h" - int ServerSetupInterrupt(int iPort, pNetRead pNet, pTaskMan pTasker); +int ServerSetupInterrupt(int iPort, pNetRead pNet, pTaskMan pTasker); /* configures a port for listening for interrupts - */ + */ - extern void StopExit(void); /* in SICSmain.c */ - - extern int openDevexecLog(); /* in devexec.c */ - - extern void NetWatchInit(void); /* in nwatch.c */ +extern void StopExit(void); /* in SICSmain.c */ + +extern int openDevexecLog(); /* in devexec.c */ + +extern void NetWatchInit(void); /* in nwatch.c */ /* ========================= Less dreadful file statics =================== */ #define DEFAULTINIFILE "servo.tcl" #define DEFAULTSTATUSFILE "sicsstat.tcl" - - static int iFortifyScope; - +#define INIT(F) { void F(void); F(); } + +static int iFortifyScope; + #include "obdes.h" -#include "interface.h" +#include "interface.h" #include "sicsvar.h" #include "emon.h" /*----------------------------------------------------------------------*/ - pEnvMon GetEnvMon(SicsInterp *pSics) - { - CommandList *pCom; - - assert(pSics); - - pCom = FindCommand(pSics,"emon"); - assert(pCom); - assert(pCom->pData); - return (pEnvMon)pCom->pData; - } +pEnvMon GetEnvMon(SicsInterp * pSics) +{ + CommandList *pCom; + + assert(pSics); + + pCom = FindCommand(pSics, "emon"); + assert(pCom); + assert(pCom->pData); + return (pEnvMon) pCom->pData; +} + /*-------------------------------------------------------------------------*/ - int InitServer(char *file, pServer *pServ) - { - char *pText = NULL; - int iPort, iRet; - FILE *fp; - pSicsVariable pVar; - char pBueffel[512]; - SConnection *pCon = NULL; - pServer self = NULL; - char *pPtr; - int iCommandTimeOut, iPasswordTimeOut, i; - pNetRead pReader = NULL; - pPerfMon pMon = NULL; - CommandList *pCom; - pid_t myPid; +int InitServer(char *file, pServer * pServ) +{ + char *pText = NULL; + int iPort, iRet; + FILE *fp; + pSicsVariable pVar; + char pBueffel[512]; + SConnection *pCon = NULL; + pServer self = NULL; + char *pPtr; + int iCommandTimeOut, iPasswordTimeOut, i; + pNetRead pReader = NULL; + pPerfMon pMon = NULL; + CommandList *pCom; + pid_t myPid; - /* allocate a new server structure */ - self = (pServer)malloc(sizeof(SicsServer)); - if(!self) - { - puts("DEADLY ERROR: Cannot allocate server data structure!"); - return 0; - } - memset(self,0,sizeof(SicsServer)); - *pServ = self; + /* allocate a new server structure */ + self = (pServer) malloc(sizeof(SicsServer)); + if (!self) { + puts("DEADLY ERROR: Cannot allocate server data structure!"); + return 0; + } + memset(self, 0, sizeof(SicsServer)); + *pServ = self; - /* define any signal handlers */ - signal(SIGPIPE,SIG_IGN); + /* define any signal handlers */ + signal(SIGPIPE, SIG_IGN); - /* configure fortify */ - iFortifyScope = Fortify_EnterScope(); - Fortify_CheckAllMemory(); - - /* interpreter */ - self->pSics = InitInterp(); - assert(self->pSics); + /* configure fortify */ + iFortifyScope = Fortify_EnterScope(); + (void)Fortify_CheckAllMemory(); - /* initialise tasker */ - assert(TaskerInit(&self->pTasker)); - - pSICSOptions = IFAddOption(pSICSOptions, "ConnectionCount","0"); - pSICSOptions = IFAddOption(pSICSOptions, "ConMask","0"); - - /* initialize the network watcher */ - NetWatchInit(); - - /* initialise the server from script */ - if(file == NULL) - { - iRet = InitObjectCommands(self,DEFAULTINIFILE); - } - else - { - iRet = InitObjectCommands(self,file); - } - if(!iRet) - { - if(file) - { - printf("Error on initialization file --> %s <-- \n",file); - } - else - { - printf("Error on initialization file --> %s <-- \n",DEFAULTINIFILE); - } - return 0; - } - self->dummyCon = SCCreateDummyConnection(self->pSics); - - /* - check for option RedirectFile and redirect stout/sterr to it - if present. - */ - pPtr = NULL; - pPtr = IFindOption(pSICSOptions,"RedirectFile"); - if(pPtr != NULL) - { - myPid = getpid(); - sprintf(pBueffel,"%s%5.5d.log",pPtr,(int)myPid); - fp = freopen(pBueffel,"w",stdout); - if(!fp) - { - printf("Failed to redirect stdout/stderr to %s\n",pBueffel); - } - fp = freopen(pBueffel,"w",stderr); - if(!fp) - { - printf("Failed to redirect stdout/stderr to %s\n",pBueffel); - } - } + /* interpreter */ + self->pSics = InitInterp(); + self->dummyCon = SCCreateDummyConnection(self->pSics); + assert(self->dummyCon != NULL); + assert(self->pSics); - - /* initialise net reader */ - pPtr = NULL; - pPtr = IFindOption(pSICSOptions,"ReadTimeOut"); - if(pPtr != NULL) - { - i = atoi(pPtr); - iCommandTimeOut = i; + /* initialise tasker */ + assert(TaskerInit(&self->pTasker)); + + pSICSOptions = IFAddOption(pSICSOptions, "ConnectionCount", "0"); + pSICSOptions = IFAddOption(pSICSOptions, "ConMask", "0"); + + /* initialize the network watcher */ + NetWatchInit(); + + /* initialise the server from script */ + SetWriteHistory(0); + if (file == NULL) { + iRet = InitObjectCommands(self, DEFAULTINIFILE); + } else { + iRet = InitObjectCommands(self, file); + } + if (!iRet) { + if (file) { + printf("Error on initialization file --> %s <-- \n", file); + } else { + printf("Error on initialization file --> %s <-- \n", DEFAULTINIFILE); } - else - { - iCommandTimeOut = 100; /* this is in microseconds and anyway o.k. */ + return 0; + } + self->dummyCon = SCCreateDummyConnection(self->pSics); + + /* + check for option RedirectFile and redirect stout/sterr to it + if present. + */ + pPtr = NULL; + pPtr = IFindOption(pSICSOptions, "RedirectFile"); + if (pPtr != NULL) { + myPid = getpid(); + snprintf(pBueffel,sizeof(pBueffel)-1, "%s%5.5d.log", pPtr, (int) myPid); + fp = freopen(pBueffel, "w", stdout); + if (!fp) { + printf("Failed to redirect stdout/stderr to %s\n", pBueffel); } - pPtr = NULL; - pPtr = IFindOption(pSICSOptions,"ReadUserPasswdTimeout"); - if(pPtr != NULL) - { - i = atoi(pPtr); - iPasswordTimeOut = i; + fp = freopen(pBueffel, "w", stderr); + if (!fp) { + printf("Failed to redirect stdout/stderr to %s\n", pBueffel); } - else - { - iPasswordTimeOut = 1; /* never used, but checked ! */ - } - assert((pReader = CreateNetReader(self,iPasswordTimeOut,iCommandTimeOut)) != NULL); - TaskRegister(self->pTasker, - NetReaderTask, - NetReaderSignal, - NULL, /* call DeleteNetReader later than TaskerDelete */ - pReader,1); - self->pReader = pReader; - - /* the socket */ - pText = IFindOption(pSICSOptions,"ServerPort"); - if(!pText) - { - printf("Cannot find ServerPort number in options file %s\n", - "This value is required!"); - DeleteInterp(self->pSics); - IFDeleteOptions(pSICSOptions); - return 0; - } - iRet = sscanf(pText,"%d",&iPort); - if( (iRet != 1) || (iPort < 1024) ) - { - printf("Invalid port number specified in Server initialisation file\n"); - DeleteInterp(self->pSics); - IFDeleteOptions(pSICSOptions); - return 0; - } + } + + + /* initialise net reader */ + pPtr = NULL; + pPtr = IFindOption(pSICSOptions, "ReadTimeOut"); + if (pPtr != NULL) { + i = atoi(pPtr); + iCommandTimeOut = i; + } else { + iCommandTimeOut = 100; /* this is in microseconds and anyway o.k. */ + } + pPtr = NULL; + pPtr = IFindOption(pSICSOptions, "ReadUserPasswdTimeout"); + if (pPtr != NULL) { + i = atoi(pPtr); + iPasswordTimeOut = i; + } else { + iPasswordTimeOut = 1; /* never used, but checked ! */ + } + assert((pReader = + CreateNetReader(self, iPasswordTimeOut, + iCommandTimeOut)) != NULL); + TaskRegister(self->pTasker, NetReaderTask, NetReaderSignal, NULL, /* call DeleteNetReader later than TaskerDelete */ + pReader, 1); + self->pReader = pReader; + + /* the socket */ + pText = IFindOption(pSICSOptions, "ServerPort"); + if (!pText) { + printf("Cannot find ServerPort number in options file %s\n", + "This value is required!"); + DeleteInterp(self->pSics); + IFDeleteOptions(pSICSOptions); + return 0; + } + iRet = sscanf(pText, "%d", &iPort); + if ((iRet != 1) || (iPort < 1024)) { + printf + ("Invalid port number specified in Server initialisation file\n"); + DeleteInterp(self->pSics); + IFDeleteOptions(pSICSOptions); + return 0; + } + /* self->pServerPort = NETOpenPort(iPort); if(!self->pServerPort) { - printf("Cannot open Server Socket\n"); - DeleteInterp(self->pSics); - IFDeleteOptions(pSICSOptions); - return 0; + printf("Cannot open Server Socket\n"); + DeleteInterp(self->pSics); + IFDeleteOptions(pSICSOptions); + return 0; } NetReadRegister(pReader, self->pServerPort, naccept, NULL); - - /* the device executor */ - openDevexecLog(); - DevexecLog("START","SICS"); + */ + NetReadInstallANETPort(pReader, naccept, iPort); - - /* initialize Interrupt Port */ - pText = IFindOption(pSICSOptions,"InterruptPort"); - if(!pText) - { - printf("Cannot find InterruptPort number in options file %s\n", - "This value is required!"); - DeleteInterp(self->pSics); - IFDeleteOptions(pSICSOptions); - return 0; - } - iRet = sscanf(pText,"%d",&iPort); - if( (iRet != 1) || (iPort < 1024) ) - { - printf("Invalid port number specified in Server initialisation file\n"); - DeleteInterp(self->pSics); - IFDeleteOptions(pSICSOptions); - return 0; - } - iRet = ServerSetupInterrupt(iPort,pReader,self->pTasker); - if(!iRet) - { - SCWrite(pCon,"WARNING: UDP interrupt port not initialized",eWarning); - } - /* install a secret fully priviledged entry point for ME */ - AddUser("Achterbahn","Kiel",usInternal); + /* the device executor */ + openDevexecLog(); + DevexecLog("START", "SICS"); - /* install environment monitor */ - self->pMonitor = GetEnvMon(self->pSics); - TaskRegister(self->pTasker, - EnvMonTask, - EnvMonSignal, - NULL, - self->pMonitor,1); - - /* install performance monitor */ - pMon = CreatePerfMon(20); - AddCommand(self->pSics,"Performance",PerfMonWrapper,DeletePerfMon,pMon); - TaskRegister(self->pTasker, - PerfMonTask, - PerfMonSignal, - NULL, - pMon,1); - /* install telnet port */ - InstallTelnet(); - - /* If the restore file has not been loaded, do so now */ - if(!hasRestored()) - { - strcpy(pBueffel,"restore"); - SCInvoke(self->dummyCon,self->pSics,pBueffel); - } - - /* exit handlers need to be installed here */ - atexit(StopExit); - Fortify_CheckAllMemory(); - return 1; - + /* initialize Interrupt Port */ + pText = IFindOption(pSICSOptions, "InterruptPort"); + if (!pText) { + printf("Cannot find InterruptPort number in options file %s\n", + "This value is required!"); + DeleteInterp(self->pSics); + IFDeleteOptions(pSICSOptions); + return 0; } + iRet = sscanf(pText, "%d", &iPort); + if ((iRet != 1) || (iPort < 1024)) { + printf + ("Invalid port number specified in Server initialisation file\n"); + DeleteInterp(self->pSics); + IFDeleteOptions(pSICSOptions); + return 0; + } + iRet = ServerSetupInterrupt(iPort, pReader, self->pTasker); + if (!iRet) { + SCWrite(pCon, "WARNING: UDP interrupt port not initialized", eWarning); + } + /* install a secret fully priviledged entry point for ME */ + AddUser("Achterbahn", "Kiel", usInternal); + + /* install environment monitor */ + self->pMonitor = GetEnvMon(self->pSics); + TaskRegister(self->pTasker, + EnvMonTask, EnvMonSignal, NULL, self->pMonitor, 1); + + /* install performance monitor */ + pMon = CreatePerfMon(20); + AddCommand(self->pSics, "Performance", PerfMonWrapper, DeletePerfMon, + pMon); + TaskRegister(self->pTasker, PerfMonTask, PerfMonSignal, NULL, pMon, 1); + /* Install a second one for higher granularity measurement */ + pMon = CreatePerfMon(2); + TaskRegister(self->pTasker, PerfMonTask, PerfMonSignal, DeletePerfMon, pMon, 1); + + + /* install telnet port */ + InstallTelnet(); + + /* If the restore file has not been loaded, do so now */ + if (!hasRestored()) { + strcpy(pBueffel, "restore"); + SCInvoke(self->dummyCon, self->pSics, pBueffel); + } + SetWriteHistory(1); + + INIT(StatusFileInit); + + /* exit handlers need to be installed here */ + atexit(StopExit); + (void)Fortify_CheckAllMemory(); + return 1; + +} + /*---------------------------------------------------------------------------*/ - void StopServer(pServer self) - { - SConnection *pCurrent, *pTemp; - char pBueffel[512]; - char *pText = NULL; - SConnection *pCon = NULL; - pSite site = NULL; +void StopServer(pServer self) +{ + SConnection *pCurrent, *pTemp; + char pBueffel[512]; + char *pText = NULL; + SConnection *pCon = NULL; + pSite site = NULL; - /* clear all pending bullshit */ - ClearExecutor(self->pExecutor); - DevexecLog("STOP","SICS"); + /* clear all pending bullshit */ + ClearExecutor(self->pExecutor); + DevexecLog("STOP", "SICS"); - /* shut telnet down */ - KillTelnet(); + /* shut telnet down */ + KillTelnet(); - /* shut tasker down */ - TaskerDelete(&self->pTasker); - self->pTasker = NULL; + /* shut tasker down */ + TaskerDelete(&self->pTasker); + self->pTasker = NULL; - /* save status */ - if(!self->simMode) - { - strcpy(pBueffel,"Backup "); - pText = IFindOption(pSICSOptions,"statusfile"); - if(pText) - { - strcat(pBueffel,pText); - } - else - { - strcat(pBueffel,DEFAULTSTATUSFILE); - } - if(self->dummyCon) - { - InterpExecute(self->pSics,self->dummyCon,pBueffel); - SCDeleteConnection(self->dummyCon); - } - else - { - printf("ERROR: Cannot allocate dummy connection, status NOT saved"); - } + /* save status */ + if (!self->simMode) { + strcpy(pBueffel, "Backup "); + pText = IFindOption(pSICSOptions, "statusfile"); + if (pText) { + strlcat(pBueffel, pText,511); + } else { + strcat(pBueffel, DEFAULTSTATUSFILE); } - - /* close redirection file if present */ - pText = NULL; - pText = IFindOption(pSICSOptions,"RedirectFile"); - if(pText) - { - fclose(stderr); + if (self->dummyCon) { + InterpExecute(self->pSics, self->dummyCon, pBueffel); + SCDeleteConnection(self->dummyCon); + } else { + printf("ERROR: Cannot allocate dummy connection, status NOT saved"); } - - /* clean out */ - if(self->pSics) - { - DeleteInterp(self->pSics); - self->pSics = NULL; - } - /* remove options after interpreter as some object kill functions - may use options */ - if(pSICSOptions) - IFDeleteOptions(pSICSOptions); - - /* delete net reader */ - DeleteNetReader(self->pReader); - self->pReader = NULL; - - /* close the server port */ - if(self->pServerPort) - { - NETClosePort(self->pServerPort); - free(self->pServerPort); - } - - - /* remove the in memory password database */ - KillPasswd(); - - - /* close Interrupt system */ - ServerStopInterrupt(); - - /* Remove Status Callback */ - KillStatus(NULL); - - /* - kill the site data structure - */ - site = getSite(); - if(site != NULL) - { - site->KillSite(site); - } - - /* - kill overloaded interfaces data - */ - killTclDrivable(); - - KillFreeConnections(); - - killSICSHipadaba(); - - /* close the List system */ - LLDsystemClose(); - - /* make fortify print his findings */ - Fortify_DumpAllMemory(iFortifyScope); - Fortify_LeaveScope(); - - free(self); - } -/*------------------------------------------------------------------------*/ - void RunServer(pServer self) - { - TaskSchedule(self->pTasker); + + /* close redirection file if present */ + pText = NULL; + pText = IFindOption(pSICSOptions, "RedirectFile"); + if (pText) { + fclose(stderr); } + + /* clean out */ + if (self->pSics) { + DeleteInterp(self->pSics); + self->pSics = NULL; + } + /* remove options after interpreter as some object kill functions + may use options */ + if (pSICSOptions) + IFDeleteOptions(pSICSOptions); + + /* delete net reader */ + DeleteNetReader(self->pReader); + self->pReader = NULL; + + /* close the server port */ + if (self->pServerPort) { + NETClosePort(self->pServerPort); + free(self->pServerPort); + } + + + /* remove the in memory password database */ + KillPasswd(); + + + /* close Interrupt system */ + ServerStopInterrupt(); + + /* Remove Status Callback */ + KillStatus(NULL); + + /* + kill the site data structure + */ + site = getSite(); + if (site != NULL) { + site->KillSite(site); + } + + /* + kill overloaded interfaces data + */ + killTclDrivable(); + + KillFreeConnections(); + + killSICSHipadaba(); + + /* close the List system */ + LLDsystemClose(); + + /* make fortify print his findings */ + (void)Fortify_DumpAllMemory(iFortifyScope); + (void)Fortify_LeaveScope(); + + free(self); + +} + /*------------------------------------------------------------------------*/ - typedef struct { - time_t tFinish; - int iEnd; - } WaitStruct, *pWaitStruct; +void RunServer(pServer self) +{ + TaskSchedule(self->pTasker); +} + +/*------------------------------------------------------------------------*/ +typedef struct { + double dFinish; + int iEnd; +} WaitStruct, *pWaitStruct; /*-------------------------------------------------------------------------*/ - static int WaitTask(void *pData) - { - time_t tNow; - pWaitStruct self = NULL; - - self = (pWaitStruct)pData; - if(self->iEnd) - { - return 0; - } - - tNow = time(NULL); - if(tNow >= self->tFinish) - { - return 0; /* done */ - } - else - { - return 1; - } +static int WaitTask(void *pData) +{ + pWaitStruct self = NULL; + + self = (pWaitStruct) pData; + if (self->iEnd) { + return 0; } + + if (DoubleTime() >= self->dFinish) { + return 0; /* done */ + } else { + return 1; + } +} + /*-----------------------------------------------------------------------*/ - static void WaitSignal(void *pUser, int iSignal, void *pEventData) - { - pWaitStruct self = NULL; - int *iInt; - - self = (pWaitStruct)pUser; - assert(self); - iInt = (int *)pEventData; - - if(iSignal == SICSINT) - { - iInt = (int *)pEventData; - if(*iInt > eContinue) - { - self->iEnd = 1; - } - } +static void WaitSignal(void *pUser, int iSignal, void *pEventData) +{ + pWaitStruct self = NULL; + int *iInt; + + self = (pWaitStruct) pUser; + assert(self); + iInt = (int *) pEventData; + + if (iSignal == SICSINT) { + iInt = (int *) pEventData; + if (*iInt > eContinue) { + self->iEnd = 1; + } } - +} + /*-------------------------------------------------------------------------- UserWait: the user command for waiting, expects one arg: time to wait in seconds ---------------------------------------------------------------------------*/ - int UserWait(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - int i; - char pBueffel[80]; - float fVal; - Status eOld; - time_t tNow; - WaitStruct sWait; - pTaskMan pTask; - long lID; - - assert(pCon); - assert(pSics); - assert(pData); - - pTask = GetTasker(); - - if(argc < 2) - { - sprintf(pBueffel,"Insufficient number of args to %s",argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* try convert to a number */ - i = sscanf(argv[1],"%f",&fVal); - if(i < 1) - { - sprintf(pBueffel,"Expected numeric argument to %s, got %s", - argv[0], argv[1]); - SCWrite(pCon,pBueffel,eInError); - return 0; - } - - if(pServ->simMode) - { - return 1; - } +int UserWait(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + int i; + char pBueffel[80]; + float fVal; + Status eOld; + WaitStruct sWait; + pTaskMan pTask; + long lID; - eOld = GetStatus(); - SetStatus(eUserWait); - tNow = time(NULL); - sWait.tFinish = tNow + (time_t)fVal; - sWait.iEnd = 0; - lID = TaskRegister(pTask,WaitTask,WaitSignal,NULL,&sWait,1); - TaskWait(pTask,lID); - SetStatus(eOld); - if(SCGetInterrupt(pCon) != eContinue) - { - return 0; - } - else - { - return 1; - } - } -/*------------------------------------------------------------------------*/ - int SicsWaitOld(long lTime) - { - WaitStruct sWait; - pTaskMan pTasker = NULL; - time_t tNow; - long lID; + assert(pCon); + assert(pSics); + assert(pData); - if(pServ->simMode) - { - return 1; - } + pTask = GetTasker(); - pTasker = GetTasker(); - tNow = time(NULL); - sWait.tFinish = tNow + lTime; - sWait.iEnd = 0; - lID = TaskRegister(pTasker,WaitTask,WaitSignal,NULL,&sWait,1); - TaskWait(pTasker,lID); + if (argc < 2) { + snprintf(pBueffel,sizeof(pBueffel)-1, "Insufficient number of args to %s", argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* try convert to a number */ + i = sscanf(argv[1], "%f", &fVal); + if (i < 1) { + snprintf(pBueffel,sizeof(pBueffel)-1, "Expected numeric argument to %s, got %s", + argv[0], argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + if (pServ->simMode) { return 1; } -/*------------------------------------------------------------------------ - The new SicsWait is still on probation. It prevents commands to be - executed on the same task on which the Sicswait is acting. - M.K. December 2005 - -------------------------------------------------------------------------*/ - int SicsWait(long lTime) - { - pTaskMan pTasker = NULL; - time_t endTime; - if(pServ->simMode) - { - return 1; - } - pTasker = GetTasker(); - endTime = time(NULL) + lTime; - while(time(NULL) < endTime) - { - TaskYield(pTasker); - } - return 1; + eOld = GetStatus(); + SetStatus(eUserWait); + sWait.dFinish = DoubleTime() + (double)fVal; + sWait.iEnd = 0; + lID = TaskRegister(pTask, WaitTask, WaitSignal, NULL, &sWait, 1); + TaskWait(pTask, lID); + SetStatus(eOld); + if (SCGetInterrupt(pCon) != eContinue) { + return 0; + } else { + return 1; } +} +/*--------------------------------------------------------------------------*/ +int SicsWait(long lTime) +{ + pTaskMan pTasker = NULL; + time_t endTime; + + if (pServ->simMode) { + return 1; + } + pTasker = GetTasker(); + endTime = time(NULL) + lTime; + while (time(NULL) < endTime) { + TaskYield(pTasker); + } + return 1; +} + /*-------------------------------------------------------------------------*/ - void ServerWriteGlobal(char *pMessage,int iOut) - { - pTaskMan pTasker = NULL; - - pTasker = GetTasker(); - - TaskSignal(pTasker,SICSBROADCAST,pMessage); - } +void ServerWriteGlobal(char *pMessage, int iOut) +{ + pTaskMan pTasker = NULL; + + pTasker = GetTasker(); + + TaskSignal(pTasker, SICSBROADCAST, pMessage); +} + /*-------------------------------------------------------------------------*/ - int ServerIsStarting(pServer self) - { - return self->pReader == NULL; - } +int ServerIsStarting(pServer self) +{ + return self->pReader == NULL; +} diff --git a/nserver.h b/nserver.h index 3c644041..c4396347 100644 --- a/nserver.h +++ b/nserver.h @@ -19,36 +19,37 @@ #include "task.h" #include "network.h" - typedef struct __SicsServer *pServer; +typedef struct __SicsServer *pServer; #include "nread.h" - typedef struct __SicsServer { - SicsInterp *pSics; - pTaskMan pTasker; - pExeList pExecutor; - pEnvMon pMonitor; - mkChannel *pServerPort; - pNetRead pReader; - int simMode; - SConnection *dummyCon; - } SicsServer; +typedef struct __SicsServer { + SicsInterp *pSics; + pTaskMan pTasker; + pExeList pExecutor; + pEnvMon pMonitor; + mkChannel *pServerPort; + pNetRead pReader; + int simMode; + SConnection *dummyCon; +} SicsServer; /*----------------------------------------------------------------------*/ - int InitServer(char *file, pServer *pServ); - void RunServer(pServer self); - void StopServer(pServer self); +int InitServer(char *file, pServer * pServ); +void RunServer(pServer self); +void StopServer(pServer self); /*----------------------------------------------------------------------*/ - SicsInterp *GetInterpreter(void); - pExeList GetExecutor(void); - pTaskMan GetTasker(void); - void ServerWriteGlobal(char *pMessage, int iCode); +SicsInterp *GetInterpreter(void); +pExeList GetExecutor(void); +pTaskMan GetTasker(void); +void ServerWriteGlobal(char *pMessage, int iCode); - int UserWait(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); +int UserWait(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); + +int SicsWait(long lTime); +int ServerIsStarting(pServer self); - int SicsWait(long lTime); - int ServerIsStarting(pServer self); #endif diff --git a/nwatch.c b/nwatch.c index b7ded80f..32f8d674 100644 --- a/nwatch.c +++ b/nwatch.c @@ -19,30 +19,32 @@ #include "fortify.h" #include "nwatch.h" #include "sics.h" +#include "uselect.h" #define NWMAGIC 51966 /* Net Watcher control structure */ typedef struct __netwatcher_s { - pNWContext cq_head; /* head of socket context queue */ - pNWContext cq_tail; /* tail of socket context queue */ - int nInvalid; /* number of invalidated entries */ - pNWTimer tq_head; /* head of timer context queue */ - pNWTimer tq_tail; /* tail of timer context queue */ - long lMagic; /* integrity check */ + pNWContext cq_head; /* head of socket context queue */ + pNWContext cq_tail; /* tail of socket context queue */ + int nInvalid; /* number of invalidated entries */ + pNWTimer tq_head; /* head of timer context queue */ + pNWTimer tq_tail; /* tail of timer context queue */ + long lMagic; /* integrity check */ } NetWatch, *pNetWatch; /* Singleton pattern */ static pNetWatch instance = NULL; -static int NetWatchTask(void* pData); +static int NetWatchTask(void *pData); /** * \brief Initialises the Net Watcher singleton and starts the task * * \return 1=success, 0=failure */ -int NetWatchInit(void) { +int NetWatchInit(void) +{ /* * If the singleton has not yet been created, do so now */ @@ -61,17 +63,14 @@ int NetWatchInit(void) { * The timer context object private definition */ typedef struct __netwatchtimer { - pNWTimer next; /* chain to next event */ - struct timeval tv; /* time when event is due */ - pNWCallback func; /* function to call */ - void* cntx; /* abstract context to pass to callback */ - int msec; /* millisecond delay time */ - int tick; /* millisecond repeat rate */ - long int vrfy; /* integrity check */ + pNWTimer next; /* chain to next event */ + struct timeval tv; /* time when event is due */ + pNWCallback func; /* function to call */ + void *cntx; /* abstract context to pass to callback */ + long int tick; /* millisecond repeat rate */ + long int vrfy; /* integrity check */ } NWTimer; -static pNWTimer activeTimer = NULL; - /* * \brief private function to insert an entry into the sorted timer queue. * @@ -84,7 +83,6 @@ static int NetWatchTimerInsQue(pNetWatch self, pNWTimer handle) if (self->tq_head == NULL) { self->tq_head = self->tq_tail = handle; handle->next = NULL; - handle->vrfy = NWMAGIC; return 1; } /* if new one is not earlier than latest one, insert after latest */ @@ -94,7 +92,6 @@ static int NetWatchTimerInsQue(pNetWatch self, pNWTimer handle) self->tq_tail->next = handle; self->tq_tail = handle; handle->next = NULL; - handle->vrfy = NWMAGIC; return 1; } /* if new one is not later than earliest one, insert before earliest */ @@ -103,26 +100,21 @@ static int NetWatchTimerInsQue(pNetWatch self, pNWTimer handle) handle->tv.tv_usec <= self->tq_head->tv.tv_usec)) { handle->next = self->tq_head; self->tq_head = handle; - handle->vrfy = NWMAGIC; return 1; - } - else - { + } else { /* must be in between two so start at the first entry */ pNWTimer pNxt = self->tq_head; /* follow chain until the one after this one is greater than new one */ while (pNxt->next && - (handle->tv.tv_sec > pNxt->next->tv.tv_sec || - (handle->tv.tv_sec == pNxt->next->tv.tv_sec && - handle->tv.tv_usec > pNxt->next->tv.tv_usec))) + (handle->tv.tv_sec > pNxt->next->tv.tv_sec || + (handle->tv.tv_sec == pNxt->next->tv.tv_sec && + handle->tv.tv_usec > pNxt->next->tv.tv_usec))) pNxt = pNxt->next; /* slip new one in between this one and the next one */ handle->next = pNxt->next; - pNxt->next = handle ; - handle->vrfy = NWMAGIC; - return 1; + pNxt->next = handle; } - return 0; + return 1; } /* @@ -133,10 +125,9 @@ static int NetWatchTimerInsQue(pNetWatch self, pNWTimer handle) */ static int NetWatchTimerRemQue(pNetWatch self, pNWTimer handle) { - assert(handle->vrfy == NWMAGIC); /* handle the case of first and possibly only */ if (handle == self->tq_head) { - self->tq_head = self->tq_head->next; /* may be NULL */ + self->tq_head = self->tq_head->next; /* may be NULL */ if (handle == self->tq_tail) self->tq_tail = NULL; } @@ -154,16 +145,14 @@ static int NetWatchTimerRemQue(pNetWatch self, pNWTimer handle) if (handle == self->tq_tail) self->tq_tail = pNxt; } - handle->vrfy = 0; return 1; } -int NetWatchRegisterTimer(pNWTimer* handle, int mSec, - pNWCallback callback, void* context) +int NetWatchRegisterTimer(pNWTimer * handle, int mSec, + pNWCallback callback, void *context) { - assert(callback); pNetWatch self = instance; - if(!self || self->lMagic != NWMAGIC) + if (!self || self->lMagic != NWMAGIC) return 0; pNWTimer pNew = (pNWTimer) malloc(sizeof(NWTimer)); if (pNew == NULL) @@ -173,22 +162,22 @@ int NetWatchRegisterTimer(pNWTimer* handle, int mSec, pNew->tv.tv_sec += mSec / 1000; pNew->tv.tv_usec += 1000 * (mSec % 1000); if (pNew->tv.tv_usec > 1000000) { - pNew->tv.tv_sec ++; + pNew->tv.tv_sec++; pNew->tv.tv_usec -= 1000000; } - pNew->msec = mSec; pNew->tick = 0; pNew->func = callback; pNew->cntx = context; + pNew->vrfy = NWMAGIC; NetWatchTimerInsQue(self, pNew); *handle = pNew; return 1; } -int NetWatchRegisterTimerPeriodic(pNWTimer* handle, int mSecInitial, int mSecPeriod, - pNWCallback callback, void* context) +int NetWatchRegisterTimerPeriodic(pNWTimer * handle, int mSecInitial, + int mSecPeriod, pNWCallback callback, + void *context) { - assert(callback); if (NetWatchRegisterTimer(handle, mSecInitial, callback, context)) { pNWTimer pNew = *handle; if (pNew == NULL) @@ -200,33 +189,16 @@ int NetWatchRegisterTimerPeriodic(pNWTimer* handle, int mSecInitial, int mSecPer return 0; } -pNWTimer NetWatchGetActiveTimer(void) -{ - return activeTimer; -} - -int NetWatchGetTimerInitial(pNWTimer handle) -{ - if (handle == NULL || (handle->vrfy != NWMAGIC && handle->vrfy != ~NWMAGIC)) - return 0; - return handle->msec; -} - -int NetWatchGetTimerDelay(pNWTimer handle) -{ - return NetWatchGetTimerInitial(handle); -} - int NetWatchGetTimerPeriod(pNWTimer handle) { - if (handle == NULL || (handle->vrfy != NWMAGIC && handle->vrfy != ~NWMAGIC)) + if (handle == NULL || handle->vrfy != NWMAGIC) return 0; return handle->tick; } int NetWatchSetTimerPeriod(pNWTimer handle, int mSecPeriod) { - if (handle == NULL || (handle->vrfy != NWMAGIC && handle->vrfy != ~NWMAGIC)) + if (handle == NULL || handle->vrfy != NWMAGIC) return 0; handle->tick = mSecPeriod; return 1; @@ -237,21 +209,20 @@ int NetWatchRemoveTimer(pNWTimer handle) pNetWatch self = instance; if (!self || self->lMagic != NWMAGIC) return 0; - if (handle == NULL || handle->vrfy != NWMAGIC) - return 0; NetWatchTimerRemQue(self, handle); + handle->vrfy = 0; free(handle); return 1; } /* private data */ typedef struct __netwatchcontext { - pNWContext next; /* chain pointer */ - int sock; /* socket to watch */ - int mode; /* read or write */ - pNWCallback func; /* user supplied callback function */ - void* cntx; /* user supplied callback context */ - long vrfy; /* integrity check */ + pNWContext next; /* chain pointer */ + int sock; /* socket to watch */ + int mode; /* read or write */ + pNWCallback func; /* user supplied callback function */ + void *cntx; /* user supplied callback context */ + long vrfy; /* integrity check */ } NWContext; /** @@ -262,17 +233,15 @@ typedef struct __netwatchcontext { */ static int NetWatchContextInsQue(pNetWatch self, pNWContext handle) { - if (self->cq_head == NULL) /* empty */ + if (self->cq_head == NULL) /* empty */ self->cq_head = self->cq_tail = handle; else { self->cq_tail->next = handle; self->cq_tail = handle; } - handle->vrfy = NWMAGIC; return 1; } -#if 0 /* no longer used */ /** * \brief private function to remove entry from unsorted queue * @@ -281,12 +250,11 @@ static int NetWatchContextInsQue(pNetWatch self, pNWContext handle) */ static void NetWatchContextRemQue(pNetWatch self, pNWContext handle) { - if (handle == self->cq_head) { /* if first */ + if (handle == self->cq_head) { /* if first */ self->cq_head = self->cq_head->next; - if (handle == self->cq_tail) /* if also last */ + if (handle == self->cq_tail) /* if also last */ self->cq_tail = NULL; - } - else { + } else { pNWContext pNxt = self->cq_head; while (pNxt) { if (handle == pNxt->next) { @@ -295,13 +263,11 @@ static void NetWatchContextRemQue(pNetWatch self, pNWContext handle) } pNxt = pNxt->next; } - if (handle == self->cq_tail) /* if last */ + if (handle == self->cq_tail) /* if last */ self->cq_tail = pNxt; } - handle->vrfy = 0; return; } -#endif /** * \brief private function to purge invalid entries @@ -320,30 +286,29 @@ static void NetWatchContextPrgQue(pNetWatch self) free(tmp); } pNxt = self->cq_head; - while (pNxt && pNxt->next) { - if (pNxt->next->sock < 0) { + while (pNxt) { + if (pNxt->next && pNxt->next->sock < 0) { pNWContext tmp = NULL; tmp = pNxt->next; pNxt->next = pNxt->next->next; tmp->vrfy = 0; free(tmp); - continue; } pNxt = pNxt->next; } - /* if the queue is empty then pNxt is NULL else pNxt points to the tail */ - self->cq_tail = pNxt; + /* if the queue is empty clear the tail */ + if (self->cq_head == NULL) + self->cq_tail = pNxt; self->nInvalid = 0; return; } -int NetWatchRegisterCallback(pNWContext* handle, int iSocket, - pNWCallback callback, void* context) +int NetWatchRegisterCallback(pNWContext * handle, int iSocket, + pNWCallback callback, void *context) { - assert(callback); pNWContext pNew = NULL; pNetWatch self = instance; - if(!self || self->lMagic != NWMAGIC) + if (!self || self->lMagic != NWMAGIC) return 0; if (iSocket < 0 || iSocket > 65535) return 0; @@ -355,6 +320,7 @@ int NetWatchRegisterCallback(pNWContext* handle, int iSocket, pNew->mode = nwatch_read; pNew->func = callback; pNew->cntx = context; + pNew->vrfy = NWMAGIC; *handle = pNew; NetWatchContextInsQue(self, pNew); return 1; @@ -365,13 +331,10 @@ int NetWatchRemoveCallback(pNWContext handle) pNetWatch self = instance; if (handle == NULL || handle->vrfy != NWMAGIC) return 0; - if(!self || self->lMagic != NWMAGIC) + if (!self || self->lMagic != NWMAGIC) return 0; - /* mark as invalid */ handle->sock = -1; - /* increment count of invalid */ self->nInvalid++; - /* leave for garbage collection */ return 1; } @@ -393,37 +356,37 @@ int NetWatchSetMode(pNWContext handle, int mode) /** * \brief the registered SICS Task to drive all this */ -int NetWatchTask (void* pData) +int NetWatchTask(void *pData) { pNetWatch self = NULL; pNWContext pNWC = NULL; fd_set rMask; fd_set wMask; - struct timeval tmo = {0,0}; + struct timeval tmo = { 0, 0 }; int iRet; int iCount; /* Check the singleton */ self = (pNetWatch) instance; - if(!self || self->lMagic != NWMAGIC) + if (!self || self->lMagic != NWMAGIC) return 0; /* Purge the invalidated */ if (self->nInvalid > 0) NetWatchContextPrgQue(self); - /* build the select mask */ + /* build the select mask */ FD_ZERO(&rMask); FD_ZERO(&wMask); pNWC = self->cq_head; iCount = -1; - while(pNWC) { + while (pNWC) { if (pNWC->sock >= 0 && pNWC->sock <= 65535) { if (pNWC->mode & nwatch_read) - FD_SET(pNWC->sock,&rMask); + FD_SET(pNWC->sock, &rMask); if (pNWC->mode & nwatch_write) - FD_SET(pNWC->sock,&wMask); - if(pNWC->sock > iCount) { + FD_SET(pNWC->sock, &wMask); + if (pNWC->sock > iCount) { iCount = pNWC->sock; } } @@ -432,14 +395,13 @@ int NetWatchTask (void* pData) iRet = 0; if (iCount >= 0) - iRet = select(iCount+1, &rMask, &wMask, NULL, &tmo); + iRet = uselect(iCount + 1, &rMask, &wMask, NULL, &tmo); - if(iRet > 0) { + if (iRet > 0) { /* invoke the active callbacks */ iCount = 0; pNWC = self->cq_head; - while(pNWC) - { + while (pNWC) { if (pNWC->sock >= 0 && pNWC->sock <= 65535) { int action_mode = 0; if ((pNWC->mode & nwatch_read) && FD_ISSET(pNWC->sock, &rMask)) @@ -448,7 +410,7 @@ int NetWatchTask (void* pData) action_mode |= nwatch_write; if (action_mode != 0) { int iStatus; - iStatus = (*pNWC->func)(pNWC->cntx, action_mode); + iStatus = (*pNWC->func) (pNWC->cntx, action_mode); } } pNWC = pNWC->next; @@ -463,16 +425,12 @@ int NetWatchTask (void* pData) while (self->tq_head) { pNWTimer pNew = self->tq_head; if (tv.tv_sec < pNew->tv.tv_sec || - (tv.tv_sec == pNew->tv.tv_sec && + (tv.tv_sec == pNew->tv.tv_sec && tv.tv_usec < pNew->tv.tv_usec)) { break; } NetWatchTimerRemQue(self, pNew); - activeTimer = pNew; - activeTimer->vrfy = ~NWMAGIC; iStatus = pNew->func(pNew->cntx, 0); - activeTimer->vrfy = 0; - activeTimer = NULL; /* * If this is a recurrent timer and the function * indicates to keep it going, put it back in @@ -483,8 +441,8 @@ int NetWatchTask (void* pData) */ gettimeofday(&tv, NULL); while (tv.tv_sec > pNew->tv.tv_sec || - (tv.tv_sec == pNew->tv.tv_sec && - tv.tv_usec > pNew->tv.tv_usec)) { + (tv.tv_sec == pNew->tv.tv_sec && + tv.tv_usec > pNew->tv.tv_usec)) { pNew->tv.tv_usec += 1000 * pNew->tick; if (pNew->tv.tv_usec > 1000000) { pNew->tv.tv_sec += pNew->tv.tv_usec / 1000000; @@ -492,8 +450,8 @@ int NetWatchTask (void* pData) } } NetWatchTimerInsQue(self, pNew); - } - else { + } else { + pNew->vrfy = 0; free(pNew); } } diff --git a/nwatch.h b/nwatch.h index 4d5a0de4..03f41fb4 100644 --- a/nwatch.h +++ b/nwatch.h @@ -22,7 +22,7 @@ * * \return normally zero, for future use */ -typedef int (*pNWCallback)(void* context, int mode); +typedef int (*pNWCallback) (void *context, int mode); /* the abstract timer object handle */ typedef struct __netwatchtimer *pNWTimer; @@ -36,8 +36,8 @@ typedef struct __netwatchtimer *pNWTimer; * \param context abstract context passed to callback function * \return success=1, failure=0 */ -int NetWatchRegisterTimer(pNWTimer* handle, int mSec, - pNWCallback callback, void* context); +int NetWatchRegisterTimer(pNWTimer * handle, int mSec, + pNWCallback callback, void *context); /** * \brief register a periodic timer @@ -49,13 +49,10 @@ int NetWatchRegisterTimer(pNWTimer* handle, int mSec, * \param context abstract context passed to callback function * \return success=1, failure=0 */ -int NetWatchRegisterTimerPeriodic(pNWTimer* handle, int mSecInitial, int mSecPeriod, - pNWCallback callback, void* context); +int NetWatchRegisterTimerPeriodic(pNWTimer * handle, int mSecInitial, + int mSecPeriod, pNWCallback callback, + void *context); -pNWTimer NetWatchGetActiveTimer(void); - -int NetWatchGetTimerDelay(pNWTimer handle); -int NetWatchGetTimerInitial(pNWTimer handle); int NetWatchGetTimerPeriod(pNWTimer handle); int NetWatchSetTimerPeriod(pNWTimer handle, int mSecPeriod); /** @@ -78,8 +75,8 @@ typedef struct __netwatchcontext *pNWContext; * \param context abstract context passed to callback function * \return success=1, failure=0 */ -int NetWatchRegisterCallback(pNWContext* handle, int iSocket, - pNWCallback callback, void* context); +int NetWatchRegisterCallback(pNWContext * handle, int iSocket, + pNWCallback callback, void *context); /** * \brief remove a socket callback registration @@ -106,4 +103,4 @@ int NetWatchGetMode(pNWContext handle); */ int NetWatchSetMode(pNWContext handle, int mode); -#endif /* SICSNETWATCHER */ +#endif /* SICSNETWATCHER */ diff --git a/nx_stptok.h b/nx_stptok.h new file mode 100644 index 00000000..2f75e1ef --- /dev/null +++ b/nx_stptok.h @@ -0,0 +1,6 @@ +#ifndef NX_STPTOK +#define NX_STPTOK + +extern char *stptok(const char *s, char *tok, size_t toklen, char *brk); + +#endif /* NX_STPTOK */ diff --git a/nxcopy.c b/nxcopy.c index 116b00b1..89f0f899 100644 --- a/nxcopy.c +++ b/nxcopy.c @@ -13,11 +13,13 @@ #include "sicsdata.h" #include "nxcopy.h" #include "HistMem.h" +#include "macro.h" /*------------------------------------------------------------------------------- * decode a SWIG style pointer into the real pointer value. * Stolen from SWIG generated code. --------------------------------------------------------------------------------*/ -static const char *SWIG_UnpackData(const char *c, void *ptr, size_t sz) { +static const char *SWIG_UnpackData(const char *c, void *ptr, size_t sz) +{ register unsigned char *u = (unsigned char *) ptr; register const unsigned char *eu = u + sz; for (; u != eu; ++u) { @@ -26,269 +28,463 @@ static const char *SWIG_UnpackData(const char *c, void *ptr, size_t sz) { if ((d >= '0') && (d <= '9')) uu = ((d - '0') << 4); else if ((d >= 'a') && (d <= 'f')) - uu = ((d - ('a'-10)) << 4); - else + uu = ((d - ('a' - 10)) << 4); + else return (char *) 0; d = *(c++); if ((d >= '0') && (d <= '9')) uu |= (d - '0'); else if ((d >= 'a') && (d <= 'f')) - uu |= (d - ('a'-10)); - else + uu |= (d - ('a' - 10)); + else return (char *) 0; *u = uu; } return c; } + /*-------------------------------------------------------------------------------*/ -int isTypeAllowed(int type){ - switch(type){ - case NX_INT32: - case NX_UINT32: - case NX_FLOAT32: - return 1; - break; - default: - return 0; - break; - } -} +int isTypeAllowed(int type) +{ + switch (type) { + case NX_INT32: + case NX_UINT32: + case NX_FLOAT32: + return 1; + break; + default: + return 0; + break; + } +} + /*-------------------------------------------------------------------------------- * copy an nxdataset to a sicsdata object --------------------------------------------------------------------------------*/ -static int NXDataToSicsdata(ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *CONST objv[]){ - Tcl_Obj *resultPtr; - const char *text; - pNXDS data = NULL; - pSICSData sicsData; - int length, i; - - if(objc < 3) { - Tcl_WrongNumArgs(interp,objc,objv,"Usage: nxdatatosicsdata nxdata sicsdata"); - return TCL_ERROR; - } - resultPtr = Tcl_GetObjResult(interp); - - /* - * get nxdataset pointer - */ - text = Tcl_GetStringFromObj(objv[1],NULL); - if(strstr(text,"NULL") != NULL){ - Tcl_SetStringObj(resultPtr,"nxdata argument is NULL pointer",38); - return TCL_ERROR; - } - text++; - SWIG_UnpackData(text,&data,sizeof(void *)); +static int NXDataToSicsdata(ClientData clientData, Tcl_Interp * interp, + int objc, Tcl_Obj * CONST objv[]) +{ + Tcl_Obj *resultPtr; + const char *text; + pNXDS data = NULL; + pSICSData sicsData; + int length, i; - if(data->magic != MAGIC){ - Tcl_SetStringObj(resultPtr,"nxdata argument is no valid nxdataset", - strlen("nxdata argument is no valid nxdataset")); - return TCL_ERROR; - } - length = getNXDatasetLength(data); - if(!isTypeAllowed(data->type)){ - Tcl_SetStringObj(resultPtr,"can only copy int and float types", - strlen("can only copy int and float types")); - return TCL_ERROR; - } + if (objc < 3) { + Tcl_WrongNumArgs(interp, objc, objv, + "Usage: nxdatatosicsdata nxdata sicsdata"); + return TCL_ERROR; + } + resultPtr = Tcl_GetObjResult(interp); - /* - * locate sicsdata - */ - text = Tcl_GetStringFromObj(objv[2],NULL); - sicsData = (pSICSData)FindCommandData(pServ->pSics,(char *)text,"SICSData"); - if(sicsData == NULL){ - Tcl_SetStringObj(resultPtr,"sicsdata argument is no valid SICSData", - strlen("sicsdata argument is no valid SICSData")); - return TCL_ERROR; - } - - /* - * copy the data - */ - if(data->type == NX_FLOAT32){ - for(i = 0; i < length; i++){ - setSICSDataFloat(sicsData,i,data->u.fPtr[i]); - } - } else { - for(i = 0; i < length; i++){ - setSICSDataInt(sicsData,i,data->u.iPtr[i]); - } - } - - return TCL_OK; -} -/*--------------------------------------------------------------------------*/ -static hdbValue NXDatasetToHdbValue(pNXDS data){ - hdbValue val; - int length, i; - - length = getNXDatasetLength(data); - switch(getNXDatasetType(data)){ - case NX_INT32: - case NX_UINT32: - if(length == 1){ - val = MakeHdbInt(data->u.iPtr[0]); - } else { - val = MakeHdbIntArray(length,data->u.iPtr); - val.dataType = HIPINTVARAR; - } - break; - case NX_FLOAT32: - if(length == 1){ - val = MakeHdbFloat((double)data->u.fPtr[0]); - } else { - val = makeHdbValue(HIPFLOATAR,length); - for(i = 0; i < length; i++){ - val.v.floatArray[i] = (double)data->u.fPtr[i]; - } - val.dataType = HIPFLOATVARAR; - } - break; - case NX_FLOAT64: - if(length == 1){ - val = MakeHdbFloat(data->u.dPtr[0]); - } else { - val = MakeHdbFloatArray(length,data->u.dPtr); - } - break; - case NX_CHAR: - case NX_INT8: - case NX_UINT8: - val = MakeHdbText(data->u.cPtr); - break; - case NX_INT16: - case NX_UINT16: - if(length == 1){ - val = MakeHdbInt((int)data->u.sPtr[0]); - } else { - val = makeHdbValue(HIPINTAR,length); - for(i = 0; i < length; i++){ - val.v.intArray[i] = (int)data->u.sPtr[i]; - } - } - break; + /* + * get nxdataset pointer + */ + text = Tcl_GetStringFromObj(objv[1], NULL); + if (strstr(text, "NULL") != NULL) { + Tcl_SetStringObj(resultPtr, "nxdata argument is NULL pointer", 38); + return TCL_ERROR; + } + text++; + SWIG_UnpackData(text, &data, sizeof(void *)); + + if (data->magic != MAGIC) { + Tcl_SetStringObj(resultPtr, "nxdata argument is no valid nxdataset", + strlen("nxdata argument is no valid nxdataset")); + return TCL_ERROR; + } + length = getNXDatasetLength(data); + if (!isTypeAllowed(data->type)) { + Tcl_SetStringObj(resultPtr, "can only copy int and float types", + strlen("can only copy int and float types")); + return TCL_ERROR; + } + + /* + * locate sicsdata + */ + text = Tcl_GetStringFromObj(objv[2], NULL); + sicsData = + (pSICSData) FindCommandData(pServ->pSics, (char *) text, "SICSData"); + if (sicsData == NULL) { + Tcl_SetStringObj(resultPtr, "sicsdata argument is no valid SICSData", + strlen("sicsdata argument is no valid SICSData")); + return TCL_ERROR; + } + + /* + * copy the data + */ + if (data->type == NX_FLOAT32) { + for (i = 0; i < length; i++) { + setSICSDataFloat(sicsData, i, data->u.fPtr[i]); } - return val; + } else { + for (i = 0; i < length; i++) { + setSICSDataInt(sicsData, i, data->u.iPtr[i]); + } + } + + return TCL_OK; } + +/*--------------------------------------------------------------------------*/ +static hdbValue NXDatasetToHdbValue(pNXDS data) +{ + hdbValue val; + int length, i; + + length = getNXDatasetLength(data); + switch (getNXDatasetType(data)) { + case NX_INT32: + case NX_UINT32: + if (length == 1) { + val = MakeHdbInt(data->u.iPtr[0]); + } else { + val = MakeHdbIntArray(length, data->u.iPtr); + val.dataType = HIPINTVARAR; + } + break; + case NX_FLOAT32: + if (length == 1) { + val = MakeHdbFloat((double) data->u.fPtr[0]); + } else { + val = makeHdbValue(HIPFLOATAR, length); + for (i = 0; i < length; i++) { + val.v.floatArray[i] = (double) data->u.fPtr[i]; + } + val.dataType = HIPFLOATVARAR; + } + break; + case NX_FLOAT64: + if (length == 1) { + val = MakeHdbFloat(data->u.dPtr[0]); + } else { + val = MakeHdbFloatArray(length, data->u.dPtr); + } + break; + case NX_CHAR: + case NX_INT8: + case NX_UINT8: + val = MakeHdbText(data->u.cPtr); + break; + case NX_INT16: + case NX_UINT16: + if (length == 1) { + val = MakeHdbInt((int) data->u.sPtr[0]); + } else { + val = makeHdbValue(HIPINTAR, length); + for (i = 0; i < length; i++) { + val.v.intArray[i] = (int) data->u.sPtr[i]; + } + } + break; + } + return val; +} + /*--------------------------------------------------------------------------- * copy the content of an nxdataset onto a Hipadaba node *---------------------------------------------------------------------------*/ -static int NXDataToHdbNode(ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *CONST objv[]){ - pNXDS data = NULL; - Tcl_Obj *resultPtr; - int length, status; - const char *text; - pHdb node = NULL; - hdbValue val; +static int NXDataToHdbNode(ClientData clientData, Tcl_Interp * interp, + int objc, Tcl_Obj * CONST objv[]) +{ + pNXDS data = NULL; + Tcl_Obj *resultPtr; + int length, status; + const char *text; + pHdb node = NULL; + hdbValue val; - if(objc < 3) { - Tcl_WrongNumArgs(interp,objc,objv,"Usage: nxdatatohdb nxdata path"); - return TCL_ERROR; - } - resultPtr = Tcl_GetObjResult(interp); - - /* - * get nxdataset pointer - */ - text = Tcl_GetStringFromObj(objv[1],NULL); - if(strstr(text,"NULL") != NULL){ - Tcl_SetStringObj(resultPtr,"nxdata argument is NULL pointer",38); - return TCL_ERROR; - } - text++; - SWIG_UnpackData(text,&data,sizeof(void *)); + if (objc < 3) { + Tcl_WrongNumArgs(interp, objc, objv, "Usage: nxdatatohdb nxdata path"); + return TCL_ERROR; + } + resultPtr = Tcl_GetObjResult(interp); - if(data->magic != MAGIC){ - Tcl_SetStringObj(resultPtr,"nxdata argument is no valid nxdataset", - strlen("nxdata argument is no valid nxdataset")); - return TCL_ERROR; - } - length = getNXDatasetLength(data); + /* + * get nxdataset pointer + */ + text = Tcl_GetStringFromObj(objv[1], NULL); + if (strstr(text, "NULL") != NULL) { + Tcl_SetStringObj(resultPtr, "nxdata argument is NULL pointer", 38); + return TCL_ERROR; + } + text++; + SWIG_UnpackData(text, &data, sizeof(void *)); - /* - * locate node - */ - text = Tcl_GetStringFromObj(objv[2],NULL); - node = GetHipadabaNode(GetHipadabaRoot(),(char *)text); - if(node == NULL){ - Tcl_SetStringObj(resultPtr,"path does not point to a valid node", - strlen("path does not point to a valid node")); - return TCL_ERROR; - } - - val = NXDatasetToHdbValue(data); - status = UpdateHipadabaPar(node,val,NULL); - if(status != 1){ - Tcl_SetStringObj(resultPtr,"data type mismatch", - strlen("data type mismatch")); - return TCL_ERROR; - } - return TCL_OK; + if (data->magic != MAGIC) { + Tcl_SetStringObj(resultPtr, "nxdata argument is no valid nxdataset", + strlen("nxdata argument is no valid nxdataset")); + return TCL_ERROR; + } + length = getNXDatasetLength(data); + + /* + * locate node + */ + text = Tcl_GetStringFromObj(objv[2], NULL); + node = GetHipadabaNode(GetHipadabaRoot(), (char *) text); + if (node == NULL) { + Tcl_SetStringObj(resultPtr, "path does not point to a valid node", + strlen("path does not point to a valid node")); + return TCL_ERROR; + } + + val = NXDatasetToHdbValue(data); + status = UpdateHipadabaPar(node, val, NULL); + if (status != 1) { + Tcl_SetStringObj(resultPtr, "data type mismatch", + strlen("data type mismatch")); + return TCL_ERROR; + } + return TCL_OK; } /*---------------------------------------------------------------------------*/ -static int NXDataToHM(ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *CONST objv[]){ - pNXDS data = NULL; - Tcl_Obj *resultPtr; - int length, status; - const char *text; - pHistMem pHM = NULL; - SConnection *pCon = NULL; +static int NXDataSend(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]) +{ + Tcl_Obj *resultPtr; + pNXDS data = NULL; + SConnection *pCon = NULL; + char *sendName = NULL; + int *dataToSend = NULL; + int length, i; + const char *text; + char buffer[256]; - if(objc < 3) { - Tcl_WrongNumArgs(interp,objc,objv,"Usage: nxdatatohdb nxdata path"); - return TCL_ERROR; - } - resultPtr = Tcl_GetObjResult(interp); - - /* - * get nxdataset pointer - */ - text = Tcl_GetStringFromObj(objv[1],NULL); - if(strstr(text,"NULL") != NULL){ - Tcl_SetStringObj(resultPtr,"nxdata argument is NULL pointer",38); - return TCL_ERROR; - } - text++; - SWIG_UnpackData(text,&data,sizeof(void *)); + if (objc < 3) { + Tcl_WrongNumArgs(interp, objc, objv, "Usage: nxdatasend nxdata sendname"); + return TCL_ERROR; + } + resultPtr = Tcl_GetObjResult(interp); - if(data->magic != MAGIC){ - Tcl_SetStringObj(resultPtr,"nxdata argument is no valid nxdataset", - strlen("nxdata argument is no valid nxdataset")); - return TCL_ERROR; - } - length = getNXDatasetLength(data); - - /* - * get HM - */ - text = Tcl_GetStringFromObj(objv[2],NULL); - pHM = (pHistMem)FindCommandData(pServ->pSics,(char *)text,"HistMem"); - if(pHM == NULL){ - Tcl_SetStringObj(resultPtr,"hm argument is not histogram memory", - strlen("hm argument is not histogram memory")); - return TCL_ERROR; - } - - if(getNXDatasetType(data) != NX_INT32 || GetHistLength(pHM) < length){ - Tcl_SetStringObj(resultPtr,"data to hm type or length mismatch", - strlen("data to hm type or length mismatch")); - return TCL_ERROR; - } - - pCon = SCCreateDummyConnection(pServ->pSics); - SetHistogram(pHM, pCon, 0,0,length, data->u.iPtr); - SCDeleteConnection(pCon); - - return TCL_OK; + /* + * get nxdataset pointer + */ + text = Tcl_GetStringFromObj(objv[1], NULL); + if (strstr(text, "NULL") != NULL) { + strncpy(buffer, "nxdata argument is NULL pointer", sizeof(buffer)); + Tcl_SetStringObj(resultPtr,buffer,strlen(buffer)); + return TCL_ERROR; + } + text++; + SWIG_UnpackData(text, &data, sizeof(void *)); + + if (data->magic != MAGIC) { + strncpy(buffer, "nxdata argument is no valid nxdataset" , sizeof(buffer)); + Tcl_SetStringObj(resultPtr,buffer,strlen(buffer)); + return TCL_ERROR; + } + length = getNXDatasetLength(data); + + /* + * get connection + */ + pCon = MacroPeek(); + if(pCon == NULL){ + strncpy(buffer, "connection not FOUND!", sizeof(buffer)); + Tcl_SetStringObj(resultPtr,buffer,strlen(buffer)); + return TCL_ERROR; + } + + /* + * get send name + */ + sendName = Tcl_GetStringFromObj(objv[2], NULL); + if (strstr(text, "NULL") != NULL) { + strncpy(buffer, "sendname argument is NULL pointer", sizeof(buffer)); + Tcl_SetStringObj(resultPtr,buffer,strlen(buffer)); + return TCL_ERROR; + } + + dataToSend = malloc(length*sizeof(int)); + if(dataToSend == NULL){ + strncpy(buffer, "Out-of-memory in NXDataSend", sizeof(buffer)); + Tcl_SetStringObj(resultPtr,buffer,strlen(buffer)); + return TCL_ERROR; + } + switch(getNXDatasetType(data)){ + case NX_INT32: + case NX_UINT32: + for(i = 0; i < length; i++){ + dataToSend[i] = htonl(data->u.iPtr[i]); + } + break; + case NX_INT16: + case NX_UINT16: + for(i = 0; i < length; i++){ + dataToSend[i] = htonl((int)data->u.sPtr[i]); + } + break; + default: + strncpy(buffer, "Datatype not supported", sizeof(buffer)); + Tcl_SetStringObj(resultPtr,buffer,strlen(buffer)); + return TCL_ERROR; + } + SCWriteZipped(pCon, sendName, dataToSend, length * sizeof(int)); + free(dataToSend); + strncpy(buffer, "OK", sizeof(buffer)); + Tcl_SetStringObj(resultPtr,buffer,strlen(buffer)); + + return TCL_OK; } /*---------------------------------------------------------------------------*/ -int NXcopy_Init(Tcl_Interp *pInter){ - Tcl_CreateObjCommand(pInter,"nxToSicsData",NXDataToSicsdata,NULL,NULL); - Tcl_CreateObjCommand(pInter,"nxToHdb",NXDataToHdbNode,NULL,NULL); - Tcl_CreateObjCommand(pInter,"nxToHM",NXDataToHM,NULL,NULL); - return 1; +static int NXDataSendBin(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]) +{ + Tcl_Obj *resultPtr; + pNXDS data = NULL; + SConnection *pCon = NULL; + char *sendName = NULL; + int *dataToSend = NULL; + int length, i; + const char *text; + char buffer[256]; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, objc, objv, "Usage: nxdatasend nxdata sendname"); + return TCL_ERROR; + } + resultPtr = Tcl_GetObjResult(interp); + + /* + * get nxdataset pointer + */ + text = Tcl_GetStringFromObj(objv[1], NULL); + if (strstr(text, "NULL") != NULL) { + strncpy(buffer, "nxdata argument is NULL pointer", sizeof(buffer)); + Tcl_SetStringObj(resultPtr,buffer,strlen(buffer)); + return TCL_ERROR; + } + text++; + SWIG_UnpackData(text, &data, sizeof(void *)); + + if (data->magic != MAGIC) { + strncpy(buffer, "nxdata argument is no valid nxdataset" , sizeof(buffer)); + Tcl_SetStringObj(resultPtr,buffer,strlen(buffer)); + return TCL_ERROR; + } + length = getNXDatasetLength(data); + + /* + * get connection + */ + pCon = MacroPeek(); + if(pCon == NULL){ + strncpy(buffer, "connection not FOUND!", sizeof(buffer)); + Tcl_SetStringObj(resultPtr,buffer,strlen(buffer)); + return TCL_ERROR; + } + + /* + * get send name + */ + sendName = Tcl_GetStringFromObj(objv[2], NULL); + if (strstr(text, "NULL") != NULL) { + strncpy(buffer, "sendname argument is NULL pointer", sizeof(buffer)); + Tcl_SetStringObj(resultPtr,buffer,strlen(buffer)); + return TCL_ERROR; + } + + dataToSend = malloc(length*sizeof(int)); + if(dataToSend == NULL){ + strncpy(buffer, "Out-of-memory in NXDataSend", sizeof(buffer)); + Tcl_SetStringObj(resultPtr,buffer,strlen(buffer)); + return TCL_ERROR; + } + switch(getNXDatasetType(data)){ + case NX_INT32: + case NX_UINT32: + for(i = 0; i < length; i++){ + dataToSend[i] = htonl(data->u.iPtr[i]); + } + break; + case NX_INT16: + case NX_UINT16: + for(i = 0; i < length; i++){ + dataToSend[i] = htonl((int)data->u.sPtr[i]); + } + break; + default: + strncpy(buffer, "Datatype not supported", sizeof(buffer)); + Tcl_SetStringObj(resultPtr,buffer,strlen(buffer)); + return TCL_ERROR; + } + SCWriteBinary(pCon, sendName, dataToSend, length * sizeof(int)); + free(dataToSend); + strncpy(buffer, "OK", sizeof(buffer)); + Tcl_SetStringObj(resultPtr,buffer,strlen(buffer)); + + return TCL_OK; +} +/*---------------------------------------------------------------------------*/ +static int NXDataToHM(ClientData clientData, Tcl_Interp * interp, + int objc, Tcl_Obj * CONST objv[]) +{ + pNXDS data = NULL; + Tcl_Obj *resultPtr; + int length, status; + const char *text; + pHistMem pHM = NULL; + SConnection *pCon = NULL; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, objc, objv, "Usage: nxdatatohdb nxdata path"); + return TCL_ERROR; + } + resultPtr = Tcl_GetObjResult(interp); + + /* + * get nxdataset pointer + */ + text = Tcl_GetStringFromObj(objv[1], NULL); + if (strstr(text, "NULL") != NULL) { + Tcl_SetStringObj(resultPtr, "nxdata argument is NULL pointer", 38); + return TCL_ERROR; + } + text++; + SWIG_UnpackData(text, &data, sizeof(void *)); + + if (data->magic != MAGIC) { + Tcl_SetStringObj(resultPtr, "nxdata argument is no valid nxdataset", + strlen("nxdata argument is no valid nxdataset")); + return TCL_ERROR; + } + length = getNXDatasetLength(data); + + /* + * get HM + */ + text = Tcl_GetStringFromObj(objv[2], NULL); + pHM = (pHistMem) FindCommandData(pServ->pSics, (char *) text, "HistMem"); + if (pHM == NULL) { + Tcl_SetStringObj(resultPtr, "hm argument is not histogram memory", + strlen("hm argument is not histogram memory")); + return TCL_ERROR; + } + + if (getNXDatasetType(data) != NX_INT32 || GetHistLength(pHM) < length) { + Tcl_SetStringObj(resultPtr, "data to hm type or length mismatch", + strlen("data to hm type or length mismatch")); + return TCL_ERROR; + } + + pCon = SCCreateDummyConnection(pServ->pSics); + SetHistogram(pHM, pCon, 0, 0, length, data->u.iPtr); + SCDeleteConnection(pCon); + + return TCL_OK; +} + +/*---------------------------------------------------------------------------*/ +int NXcopy_Init(Tcl_Interp * pInter) +{ + Tcl_CreateObjCommand(pInter, "nxToSicsData", NXDataToSicsdata, NULL, + NULL); + Tcl_CreateObjCommand(pInter, "nxToHdb", NXDataToHdbNode, NULL, NULL); + Tcl_CreateObjCommand(pInter, "nxToHM", NXDataToHM, NULL, NULL); + Tcl_CreateObjCommand(pInter, "nxSend", NXDataSend, NULL, NULL); + Tcl_CreateObjCommand(pInter, "nxSendBin", NXDataSendBin, NULL, NULL); + return 1; } diff --git a/nxcopy.h b/nxcopy.h index 539fae36..cc49852d 100644 --- a/nxcopy.h +++ b/nxcopy.h @@ -11,6 +11,6 @@ #define NXCOPY_H_ #include -int NXcopy_Init(Tcl_Interp *pTcl); +int NXcopy_Init(Tcl_Interp * pTcl); -#endif /*NXCOPY_H_*/ +#endif /*NXCOPY_H_ */ diff --git a/nxdata.c b/nxdata.c deleted file mode 100644 index ff060a11..00000000 --- a/nxdata.c +++ /dev/null @@ -1,900 +0,0 @@ -/*-------------------------------------------------------------------------- - N X D A T A - - This implements the data file writing for the Powder diffractometers - HRPT and DMC. - - Mark Koennecke, March-April 1997 - - Updated and expanded: Mark Koennecke, November 1999 - - Copyright: - - Labor fuer Neutronenstreuung - Paul Scherrer Institut - CH-5423 Villigen-PSI - - - The authors hereby grant permission to use, copy, modify, distribute, - and license this software and its documentation for any purpose, provided - that existing copyright notices are retained in all copies and that this - notice is included verbatim in any distributions. No written agreement, - license, or royalty fee is required for any of the authorized uses. - Modifications to this software may be copyrighted by their authors - and need not follow the licensing terms described here, provided that - the new terms are clearly indicated on the first page of each file where - they apply. - - IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY - FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY - DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - - THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, - INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE - IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE - NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR - MODIFICATIONS. -----------------------------------------------------------------------------*/ -#include -#include -#include -#include -#include -#include "fortify.h" -#include "sics.h" -#include "sicsvar.h" -#include "nxdict.h" -#include "modriv.h" -#include "motor.h" -#include "nxdata.h" -#include "nxutil.h" -#include "selector.h" -#include "selvar.h" -#include "countdriv.h" -#include "counter.h" -#include "danu.h" -#include "HistMem.h" -#include "udpquieck.h" -#include "evcontroller.h" -#include "nxscript.h" - - -#define DMCDETNAM "DMC-BF3-Detector" -#define DMCDETOB "detector" -#define HRPTDETNAM "Cerca-Detector" - -/*-----------------------------------------------------------------------*/ - static void SNError(void *pData, char *text) - { - SConnection *pCon; - - assert(pData); - pCon = (SConnection *)pData; - SCWrite(pCon,text,eError); - } -/*-----------------------------------------------------------------------*/ -char *SNXMakeFileName(SicsInterp *pSics, SConnection *pCon) -{ - char *pPtr = NULL; - pPtr = makeFilename(pSics,pCon); - if(pPtr == NULL) - { - pPtr = strdup("emergency.hdf"); - } - return pPtr; -} -/*------------------------------------------------------------------------*/ - char *SNXMakeFileNameOld(SicsInterp *pSics, SConnection *pCon) - { - pSicsVariable pPath = NULL, pPref = NULL, pEnd = NULL; - char *pRes = NULL; - int iLen, iNum, iYear; - char pNumText[10]; - CommandList *pCom = NULL; - - /* Try, get all the Variables */ - pPath = FindVariable(pSics,"sicsdatapath"); - pPref = FindVariable(pSics,"sicsdataprefix"); - pCom = FindCommand(pSics,"sicsdatanumber"); - pEnd = FindVariable(pSics,"sicsdatapostfix"); - - if( (!pPath) || (!pPref) || (!pCom) || (!pEnd) ) - { - SCWrite(pCon, - "ERROR: cannot read variables for automatic data file name creation", - eError); - SCWrite(pCon,"ERROR: This is a VERY, VERY, VERY serious installation problem", - eError); - SCWrite(pCon,"ERROR: your data will be dumped into emergency.hdf",eError); - return strdup("emergency.hdf"); - } - - /* find length */ - iLen = strlen(pPath->text); - iLen += strlen(pPref->text); - iLen += 8; /* for number + year */ - iLen += strlen(pEnd->text); - iLen += 10; /* safety margin */ - - /* allocate memory */ - pRes = (char *)malloc(iLen*sizeof(char)); - if(!pRes) - { - SCWrite(pCon,"ERROR: no memory in SNXMakeFileName",eError); - return NULL; - } - memset(pRes,0,iLen); - - /* build the filename */ - strcpy(pRes,pPath->text); - strcat(pRes,pPref->text); - iNum = IncrementDataNumber(pCom->pData,&iYear); - if(iNum < 0) - { - SCWrite(pCon,"ERROR: cannot increment data number!",eError); - SCWrite(pCon,"ERROR: your data will be dumped to emergency.hdf",eError); - free(pRes); - return strdup("emergency.hdf"); - } - sprintf(pNumText,"%5.5d",iNum); - strcat(pRes,pNumText); - sprintf(pNumText,"%4.4d",iYear); - strcat(pRes,pNumText); - strcat(pRes,pEnd->text); - - - /* install an error handler */ - NXMSetError((void *)pCon,SNError); - - return pRes; - } -/*-------------------------------------------------------------------------*/ - NXhandle SNXStartFile(SConnection *pCon, SicsInterp *pSics) - { - NXhandle pFile = NULL; - char *filename = NULL; - pSicsVariable pVar = NULL; - int iStat; - char pBueffel[512], pTime[132]; - - /* get a filename */ - filename = SNXMakeFileName(pSics,pCon); - if(!filename) - { - return NULL; - } - - /* create a Nexus file */ - NXopen(filename,NXACC_CREATE,&pFile); - if(!pFile) - { - SCWrite(pCon,"ERROR: cannot create data file ",eError); - free(filename); - return NULL; - } - - /* tell Uwe User what we are doing */ - sprintf(pBueffel,"Writing %s ......",filename); - SCWrite(pCon,pBueffel,eWarning); - - /* store global attributes */ - iStat = NXputattr(pFile,"file_name",filename, - strlen(filename)+1,NX_CHAR); - if(iStat == NX_ERROR) - { - SCWrite(pCon,"ERROR: writing file_name attribute to Nexus file",eError); - } - - /* filename no longer needed*/ - free(filename); - - /* write creation time */ - SNXFormatTime(pTime,132); - iStat = NXputattr(pFile,"file_time",pTime, - strlen(pTime)+1,NX_CHAR); - if(iStat == NX_ERROR) - { - SCWrite(pCon,"ERROR: writing date attribute to Nexus file",eError); - } - sprintf(pBueffel,"File created at StarDate: %s",pTime); - SCWrite(pCon,pBueffel,eWarning); - - pVar = FindVariable(pSics,"instrument"); - if(pVar) - { - iStat = NXputattr(pFile,"instrument",pVar->text, - strlen(pVar->text)+1,NX_CHAR); - if(iStat == NX_ERROR) - { - SCWrite(pCon,"ERROR: writing instrument attribute to Nexus file",eError); - } - } - pVar = NULL; - pVar = FindVariable(pSics,"user"); - if(pVar) - { - iStat = NXputattr(pFile,"owner",pVar->text, - strlen(pVar->text)+1,NX_CHAR); - if(iStat == NX_ERROR) - { - SCWrite(pCon,"ERROR: writing owner attribute to Nexus file",eError); - } - } - - pVar = NULL; - pVar = FindVariable(pSics,"address"); - if(pVar) - { - iStat = NXputattr(pFile,"owner_adress",pVar->text, - strlen(pVar->text)+1,NX_CHAR); - if(iStat == NX_ERROR) - { - SCWrite(pCon,"ERROR: writing owner_adress attribute to Nexus file",eError); - } - } - pVar = NULL; - pVar = FindVariable(pSics,"phone"); - if(pVar) - { - iStat = NXputattr(pFile,"owner_telephone_number",pVar->text, - strlen(pVar->text)+1,NX_CHAR); - if(iStat == NX_ERROR) - { - SCWrite(pCon,"ERROR: writing owner_telephone_number attribute to Nexus file",eError); - } - } - pVar = NULL; - pVar = FindVariable(pSics,"fax"); - if(pVar) - { - iStat = NXputattr(pFile,"owner_fax_number",pVar->text, - strlen(pVar->text)+1,NX_CHAR); - if(iStat == NX_ERROR) - { - SCWrite(pCon,"ERROR: writing owner_fax_number attribute to Nexus file",eError); - } - } - pVar = NULL; - pVar = FindVariable(pSics,"email"); - if(pVar) - { - iStat = NXputattr(pFile,"owner_email",pVar->text, - strlen(pVar->text)+1,NX_CHAR); - if(iStat == NX_ERROR) - { - SCWrite(pCon,"ERROR: writing owner_email attribute to Nexus file",eError); - } - } - pVar = NULL; - return pFile; - } -/*--------------------------------------------------------------------------*/ - int SNXStartEntry(NXhandle Nfil, int iNew, SicsInterp *pSics) - { - int iStat; - char pName[80]; - pSicsVariable pVar = NULL; - int iDim[2]; - - /* format an entry name */ - if(iNew < 10) - { - sprintf(pName,"entry%1.1d", iNew); - } - else if( (iNew > 9) && (iNew < 100) ) - { - sprintf(pName,"entry%2.2d",iNew); - } - else if( (iNew > 99) && (iNew < 1000) ) - { - sprintf(pName,"entry%3.3d",iNew); - } - else if( (iNew > 9999) && (iNew < 10000) ) - { - sprintf(pName,"entry%4.4d",iNew); - } - else - { - return 0; - } - - /* create entry and step into it */ - iStat = NXmakegroup(Nfil,pName,"NXentry"); - if(iStat == NX_ERROR) - { - return 0; - } - iStat = NXopengroup(Nfil,pName,"NXentry"); - if(iStat == NX_ERROR) - { - return 0; - } - - /* write entry level attributes here */ - pVar = FindVariable(pSics,"title"); - if(pVar) - { - iDim[0] = strlen(pVar->text) + 1; - NXmakedata(Nfil,"title",NX_CHAR,1,iDim); - NXopendata(Nfil,"title"); - NXputdata(Nfil,pVar->text); - NXclosedata(Nfil); - } - /* write time */ - SNXFormatTime(pName,79); - iDim[0] = strlen(pName) + 1; - NXmakedata(Nfil,"start_time",NX_CHAR,1,iDim); - NXopendata(Nfil,"start_time"); - NXputdata(Nfil,pName); - NXclosedata(Nfil); - - return 1; - } -/*-------------------------------------------------------------------------*/ - int SNenter(NXhandle Nfil, char *name, char *class) - { - int iStat; - - iStat = NXmakegroup(Nfil,name,class); - if(iStat == NX_ERROR) - { - NXclose(&Nfil); - return 0; - } - iStat = NXopengroup(Nfil,name,class); - if(iStat == NX_ERROR) - { - NXclose(&Nfil); - return 0; - } - - return 1; - } -/*-------------------------------------------------------------------------*/ - int SNputdata1(NXhandle Nfil, char *name, int datatype, int iLong, - void *pData) - { - int iStat; - int iDim[2]; - - iDim[0] = iLong; - iStat = NXmakedata (Nfil, name, datatype, 1, (int *) iDim); - if(iStat == NX_ERROR) - { - NXclose(&Nfil); - return 0; - } - iStat = NXopendata(Nfil,name); - if(iStat == NX_ERROR) - { - NXclose(&Nfil); - return 0; - } - iStat = NXputdata(Nfil,pData); - if(iStat == NX_ERROR) - { - NXclose(&Nfil); - return 0; - } - iStat = NXclosedata(Nfil); - if(iStat == NX_ERROR) - { - NXclose(&Nfil); - return 0; - } - return 1; - - } - -/*-------------------------------------------------------------------------*/ - int SNputdata1att(NXhandle Nfil, char *name, int datatype, int iLong, - void *pData, char *attname, char *val) - { - int iStat; - int iDim[2]; - - iDim[0] = iLong; - iStat = NXmakedata (Nfil, name, datatype, 1, (int *) iDim); - if(iStat == NX_ERROR) - { - NXclose(&Nfil); - return 0; - } - iStat = NXopendata(Nfil,name); - if(iStat == NX_ERROR) - { - NXclose(&Nfil); - return 0; - } - iStat = NXputdata(Nfil,pData); - if(iStat == NX_ERROR) - { - NXclose(&Nfil); - return 0; - } - iStat = NXputattr(Nfil,attname,val, - strlen(val) + 1,NX_CHAR); - if(iStat == NX_ERROR) - { - NXclose(&Nfil); - return 0; - } - iStat = NXclosedata(Nfil); - if(iStat == NX_ERROR) - { - NXclose(&Nfil); - return 0; - } - return 1; - - } -/*-----------------------------------------------------------------------*/ - static int SNPutMotor(NXhandle hfil, SicsInterp *pSics, - SConnection *pCon,char *sicsname, - char *dataname, char *units) - { - float fVal; - char pBueffel[512]; - int iRet; - pMotor pMot; - - pMot = FindMotor(pSics,sicsname); - if(!pMot) - { - sprintf(pBueffel,"ERROR: motor %s not found ", sicsname); - SCWrite(pCon,pBueffel,eError); - return 0; - } - iRet = MotorGetSoftPosition(pMot,pCon,&fVal); - if(iRet != 1) - { - sprintf(pBueffel,"ERROR: cannot read motor %s", sicsname); - SCWrite(pCon,pBueffel,eError); - return 0; - } - return SNputdata1att(hfil,dataname, NX_FLOAT32,1,&fVal,"Units",units); - } -#ifdef NONINTF - extern float nintf(float f); -#endif -/*--------------------------------------------------------------------------*/ - int SNMakeDMC(SConnection *pCon, SicsInterp *pSics) - { - NXhandle Nfil; - NXlink lWave, lDetData, lStart, lTemp, lMoni, lStep, lNumber, - lTheta, lSetData; - int iDim[2]; - float fEnd,fStart, fStep; - int iStat; - pSicsVariable pVar; - pSicsSelector pSel = NULL; - pICountable pCountInt; - pIDrivable pDrive = NULL; - pSelVar pPell; - char *pP; - float fVal; - float *fTheta; - float fTh, f2Th, fB1, fB2; - pMotor pMot = NULL; - CommandList *pCom = NULL; - int iVal, i; - char pBuffer[132]; - pHistMem pHist = NULL; - HistInt *lData = NULL; - CounterMode eCount; - int *iTVal = NULL; - pDummy pDum; - int bHRPT = 0; - float fMean, fStdDev; - pVarLog pLog = NULL; - - /* open the file & entry */ - Nfil = SNXStartFile(pCon,pSics); - if(!Nfil) - { - return 0; - } - - iStat = SNXStartEntry(Nfil,1,pSics); - if(!iStat) - { - NXclose(&Nfil); - return 0; - } - - /* create the instrument Vgroup */ - pVar = FindVariable(pSics,"instrument"); - if(strcmp(pVar->text,"HRPT") == 0) - { - bHRPT = 1; - } - assert(pVar); - iStat = SNenter(Nfil,pVar->text,"NXpsdpowder"); - if(!iStat) - { - return 0; - } - /* write the Kollimator for HRPT */ - if(bHRPT) - { - iStat = SNenter(Nfil,"kollimator","NXkollimator"); - if(!iStat) - { - return 0; - } - pMot = FindMotor(pSics,"CEX1"); - if(pMot) - { - iStat = MotorGetSoftPosition(pMot,pCon,&fStart); - iStat = SNputdata1att(Nfil,"kollimator1",NX_FLOAT32,1, - &fStart,"Units","degrees"); - } - pMot = FindMotor(pSics,"CEX2"); - if(pMot) - { - iStat = MotorGetSoftPosition(pMot,pCon,&fStart); - iStat = SNputdata1att(Nfil,"kollimator2",NX_FLOAT32,1, - &fStart,"Units","degrees"); - } - NXclosegroup(Nfil); /* leave kollimator */ - } - - /* write the Monochromator data */ - iStat = SNenter(Nfil,"Monochromator","NXcrystal"); - if(!iStat) - { - return 0; - } - if(bHRPT) - { - pVar = FindVariable(pSics,"lambda"); - if(pVar) - { - VarGetFloat(pVar,&fVal); - SNputdata1att(Nfil,"lambda",NX_FLOAT32,1,&fVal, - "Units","Angstroem"); - NXopendata(Nfil,"lambda"); - NXgetdataID(Nfil,&lWave); - NXclosedata(Nfil); - } - pVar = FindVariable(pSics,"monotype"); - if(pVar) - { - iStat = SNputdata1(Nfil,"type",NX_CHAR,strlen(pVar->text), - pVar->text); - } - /* write tons of motors for the monochromator */ - SNPutMotor(Nfil,pSics,pCon,"momu", - "omega_upper","degree"); - SNPutMotor(Nfil,pSics,pCon,"mtvu", - "vertical_translation_upper","mm"); - SNPutMotor(Nfil,pSics,pCon,"mtpu", - "paralell_translation_upper","mm"); - SNPutMotor(Nfil,pSics,pCon,"mgvu", - "vertical_tilt_upper","degree"); - SNPutMotor(Nfil,pSics,pCon,"mgpu", - "parallel_tilt_upper","degree"); - SNPutMotor(Nfil,pSics,pCon,"mcvu", - "curvature_upper",""); - SNPutMotor(Nfil,pSics,pCon,"moml", - "omega_lower","degree"); - SNPutMotor(Nfil,pSics,pCon,"mtvl", - "vertical_translation_lower","mm"); - SNPutMotor(Nfil,pSics,pCon,"mtpl", - "parallel_translation_lower","degree"); - SNPutMotor(Nfil,pSics,pCon,"mgvl", - "vertical_tilt_lower","degree"); - SNPutMotor(Nfil,pSics,pCon,"mgpl", - "parallel_tilt_lower","degree"); - SNPutMotor(Nfil,pSics,pCon,"mcvl", - "curvature_lower","degree"); - SNPutMotor(Nfil,pSics,pCon,"mexz", - "lift","mm"); - } - else - { - pCom = FindCommand(pSics,"mono"); - assert(pCom); - pSel = (pSicsSelector)pCom->pData; - pP = MonoGetType(pSel); - iStat = SNputdata1(Nfil,"type",NX_CHAR,strlen(pP), pP); - if(!iStat) - { - return 0; - } - pCom = NULL; - pCom = FindCommand(pSics,"lambda"); - assert(pCom); - pPell = (pSelVar)pCom->pData; - assert(iHasType(pPell,"SicsSelVar")); - fVal = GetSelValue(pPell,pCon); - iStat = SNputdata1(Nfil,"lambda",NX_FLOAT32,1,&fVal); - if(!iStat) - { - return 0; - } - NXopendata(Nfil,"lambda"); - NXputattr(Nfil,"Units","Angstroem",10,NX_CHAR); - NXgetdataID(Nfil,&lWave); - NXclosedata(Nfil); - iStat = GetMonoPositions(pSel,pCon,&fTh,&f2Th, &fB1, &fB2); - if(iStat) - /* skip if not readable, error has been reported lower down */ - { - SNputdata1att(Nfil,"theta",NX_FLOAT32,1,&fTh, - "Units","degrees"); - SNputdata1att(Nfil,"two_theta",NX_FLOAT32, 1,&f2Th, - "Units","degrees"); - SNputdata1att(Nfil,"curvature",NX_FLOAT32, 1,&fB1, - "Units","mm"); - } - /* more monochromatic motors */ - SNPutMotor(Nfil,pSics,pCon,"monox", - "x_translation","mm"); - SNPutMotor(Nfil,pSics,pCon,"monoy", - "y_translation","mm"); - SNPutMotor(Nfil,pSics,pCon,"monophi", - "phi","degree"); - SNPutMotor(Nfil,pSics,pCon,"monochi", - "chi","degree"); - } - NXclosegroup(Nfil); /* leave monochromator */ - - /* start Detector vGroup */ - if(bHRPT) - { - iStat = SNenter(Nfil,HRPTDETNAM,"NXpsd"); - } - else - { - iStat = SNenter(Nfil,DMCDETNAM,"NXpsd"); - } - /* get the histogram memory object */ - pCom = FindCommand(pSics,"banana"); - assert(pCom); - pHist = pCom->pData; - assert(pHist); - - /* counter mode */ - eCount = GetHistCountMode(pHist); - if(eCount == eTimer) - { - strcpy(pBuffer,"Timer"); - } - else - { - strcpy(pBuffer,"Monitor"); - } - iStat = SNputdata1(Nfil,"CounterMode",NX_CHAR,strlen(pBuffer), pBuffer); - if(!iStat) - { - return 0; - } - - /* count preset */ - fVal = GetHistPreset(pHist); - if(eCount == eTimer) - { - iStat = SNputdata1(Nfil,"Preset",NX_FLOAT32,1, &fVal); - } - else - { - fVal = nintf(fVal); - iStat = SNputdata1(Nfil,"Preset",NX_FLOAT32,1, &fVal); - } - if(!iStat) - { - return 0; - } - - /* monitor value */ - pDum = (pDummy)pHist; - pCountInt = pDum->pDescriptor->GetInterface(pDum,COUNTID); - { - pCountInt->TransferData(pHist,pCon); - } - iVal = GetHistMonitor(pHist, 1, pCon); - if(iVal < 0) - { - return 0; - } - iStat = SNputdata1(Nfil,"Monitor",NX_INT32,1, &iVal); - /* - count time - */ - fVal = GetHistCountTime(pHist,pCon); - SNputdata1att(Nfil,"time",NX_FLOAT32,1,&fVal,"Units","seconds"); - - /* - more monitors - */ - iVal = GetHistMonitor(pHist, 0, pCon); - SNputdata1(Nfil,"beam_monitor",NX_INT32,1, &iVal); - iVal = GetHistMonitor(pHist, 4, pCon); - SNputdata1(Nfil,"proton_monitor",NX_INT32,1, &iVal); - NXopendata(Nfil,"Monitor"); - NXgetdataID(Nfil,&lMoni); - NXclosedata(Nfil); - - - /* stepwidth */ - pVar = FindVariable(pSics,"detstepwidth"); - if(!pVar) - { - return 0; - } - fVal = pVar->fVal; - iStat = SNputdata1(Nfil,"Step",NX_FLOAT32,1, &fVal); - if(!iStat) - { - return 0; - } - NXopendata(Nfil,"Step"); - NXgetdataID(Nfil,&lStep); - NXclosedata(Nfil); - - /* histogram Length */ - GetHistDim(pHist,iDim,&iVal); - iVal = iDim[0]; - if(iVal < 1) - { - return 0; - } - iStat = SNputdata1(Nfil,"no_of_steps",NX_INT32,1, &iVal); - if(iStat < 1) - { - return 0; - } - NXopendata(Nfil,"no_of_steps"); - NXgetdataID(Nfil,&lNumber); - NXclosedata(Nfil); - - /* actual data */ - lData = (HistInt *)malloc(iVal*sizeof(HistInt)); - if(!lData) - { - return 0; - } - iStat = GetHistogram(pHist,pCon,0,0,iVal,lData,iVal*sizeof(HistInt)); - if(!iStat) - { - return 0; - } - iStat = SNputdata1(Nfil,"Counts",NX_INT32,iVal, lData); - if(!iStat) - { - return 0; - } - free(lData); - NXopendata(Nfil,"Counts"); - NXgetdataID(Nfil,&lSetData); - strcpy(pBuffer,"1"); - NXputattr(Nfil,"signal",pBuffer,strlen(pBuffer)+1,NX_CHAR); - NXclosedata(Nfil); - - /* motor position */ - pMot = FindMotor(pSics,"a4"); - assert(pMot); - iStat = MotorGetSoftPosition(pMot,pCon,&fStart); - iStat = SNputdata1att(Nfil,"two_theta_start",NX_FLOAT32,1, - &fStart,"Units","degrees"); - if(!iStat) - { - return 0; - } - - /* create 2Theta array and store it */ - fTheta = NULL; - fTheta = (float *)malloc(iVal*sizeof(NX_FLOAT32)); - if(!fTheta) - { - return 0; - } - for(i = 0; i < iVal; i++) - { - fTheta[i] = fStart + i*fVal; - } - iStat = SNputdata1att(Nfil,"two_theta",NX_FLOAT32,iVal, - fTheta,"Units","degrees"); - if(!iStat) - { - return 0; - } - /* get link, put axis attribute */ - NXopendata(Nfil,"two_theta"); - NXputattr(Nfil,"axis","1",strlen("1")+1,NX_CHAR); - NXgetdataID(Nfil,&lTheta); - NXclosedata(Nfil); - free(fTheta); - - - NXopendata(Nfil,"two_theta_start"); - NXgetdataID(Nfil,&lStart); - NXclosedata(Nfil); - NXclosegroup(Nfil); /* detector Vgroup */ - NXclosegroup(Nfil); /* instrument Vgroup */ - - /* do the sample Vgroup */ - iStat = SNenter(Nfil,"Sample","NXpowder"); - if(!iStat) - { - return 0; - } - pVar = FindVariable(pSics,"sample"); - if(pVar) - { - iDim[0] = strlen(pVar->text) + 1; - NXmakedata(Nfil,"sample_name",NX_CHAR,1,iDim); - NXopendata(Nfil,"sample_name"); - NXputdata(Nfil,pVar->text); - NXclosedata(Nfil); - } - pVar = FindVariable(pSics,"sample_mur"); - if(pVar) - { - SNputdata1att(Nfil,"sample_mur",NX_FLOAT32, 1,&pVar->fVal, - "Units","???"); - } - /* do a3 */ - SNPutMotor(Nfil,pSics,pCon,"a3", - "sample_table_rotation","degree"); - - /* write sample environment here */ - pCom = FindCommand(pSics,"temperature"); - if(pCom) - { - pDum = (pDummy)pCom->pData; - pDrive = pDum->pDescriptor->GetInterface(pDum,DRIVEID); - if(pDrive) /* a proper environment device */ - { - pLog = EVCGetVarLog( (pEVControl)pCom->pData); - if(pLog) - { - VarlogGetMean(pLog,&fMean,&fStdDev); - SNputdata1att(Nfil,"temperature_mean",NX_FLOAT32, 1,&fMean, - "Units","K"); - SNputdata1att(Nfil,"temperature_stddev",NX_FLOAT32, 1, - &fStdDev,"Units","K"); - } - fVal = pDrive->GetValue(pCom->pData,pCon); - } - else /* a simple variable */ - { - VarGetFloat((pSicsVariable)pDum,&fVal); - } - SNputdata1att(Nfil,"sample_temperature",NX_FLOAT32, 1,&fVal, - "Units","K"); - } - NXclosegroup(Nfil); /* sample Vgroup */ - - /* write the data Vgroup */ - SNenter(Nfil,"data1","NXdata"); - NXmakelink(Nfil,&lWave); - NXmakelink(Nfil,&lTheta); - NXmakelink(Nfil,&lStart); - NXmakelink(Nfil,&lSetData); - NXmakelink(Nfil,&lMoni); - NXmakelink(Nfil,&lStep); - NXmakelink(Nfil,&lNumber); - - /* send quieck message */ - i = 131; - iVal = NX_CHAR; - NXgetattr(Nfil,"file_name",pBuffer,&i,&iVal); - SendQuieck(QUIECK,pBuffer); - - /* done */ - NXclose(&Nfil); - return 1; - } - -/*--------------------------------------------------------------------------*/ - int SNStoreDMC(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, - char *argv[]) - - { - return SNMakeDMC(pCon,pSics); - } diff --git a/nxdata.h b/nxdata.h deleted file mode 100644 index c3ecae95..00000000 --- a/nxdata.h +++ /dev/null @@ -1,30 +0,0 @@ - -/*------------------------------------------------------------------------- - N X D A T A - - Some routines for handling Nexus data file writing. - - Mark Koennecke, April 1997 - - copyright: see implementation file. ---------------------------------------------------------------------------*/ -#ifndef SICSNXDATA -#define SICSNXDATA - - char *SNXMakeFileName(SicsInterp *pSics, SConnection *pCon); - - NXhandle SNXStartFile(SConnection *pCon, SicsInterp *pSics); - - int SNXStartEntry(NXhandle Nfil, int iNew, SicsInterp *pSics); - - void SNXFormatTime(char *pBuffer, int iBufLen); - - int SNFinishFile(NXhandle Nfil); - - int SNMakeDMC(SConnection *pCon, SicsInterp *pSics); - -int SNStoreDMC(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, - char *argv[]); - -#endif - diff --git a/nxdata.tex b/nxdata.tex deleted file mode 100644 index efc5abc6..00000000 --- a/nxdata.tex +++ /dev/null @@ -1,192 +0,0 @@ -\subsection{NXdata} -NXdata is a module for writing Powder Diffraction Data files. The -routines here are somewhat obsolete as they refer to NeXus writing -using the standard Napi routines which is quite involved. Usually, -NeXus files are written from SICS through the NXDICT aware utility -routines in NXUTIL. - -If not stated -otherwise, all routines return 1 on successful completion and 0 when an -error is detected. Please note, that many of these routines expect to find -certain data items in the Sics Interpreter. This implies, that any naming -changes in the initialisation file might force changes in here as well. - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap1} -$\langle$Protos {\footnotesize ?}$\rangle\equiv$ -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ char *SNXMakeFileName(SicsInterp *pSics, SConnection *pCon);@\\ -\mbox{}\verb@@$\diamond$ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}} -\item Macro defined by scraps ?, ?, ?, ?, ?, ?, ?. -\item Macro referenced in scrap ?. -\end{list} -\end{minipage}\\[4ex] -\end{flushleft} -SNXMakeFileName creates a new filename from the SICS variables SicsDataPath, -SicsDataPresript, SicsDataNumber and SicsDataEnding. SicsDataNumber will be -incremented as well. The function returns a newly allocate buffer with the -assembled filename or NULL on error. Note, that the caller is responsible -for freeing the memory associated with the filename afterwards. - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap2} -$\langle$Protos {\footnotesize ?}$\rangle\equiv$ -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ NXhandle SNXStartFile(SConnection *pCon, SicsInterp *pSics); @\\ -\mbox{}\verb@@$\diamond$ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}} -\item Macro defined by scraps ?, ?, ?, ?, ?, ?, ?. -\item Macro referenced in scrap ?. -\end{list} -\end{minipage}\\[4ex] -\end{flushleft} -First calls SNXMakeFileName in order to get a new Filename. -Then a new Nexus file is -created and all the standard headings are filled in: Filename, User, -instrument, date etc. This routine also installs an error handler which -prints errors to pCon. -If successful, the SicsDataNumber is incremented and -an NXhandle into the new file is returned. If there is a problem, NULL -will be returned. The file returned will be positioned at root level. - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap3} -$\langle$Protos {\footnotesize ?}$\rangle\equiv$ -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ int SNXStartEntry(NXhandle Nfil, int iNew, SicsInterp *pSics);@\\ -\mbox{}\verb@@$\diamond$ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}} -\item Macro defined by scraps ?, ?, ?, ?, ?, ?, ?. -\item Macro referenced in scrap ?. -\end{list} -\end{minipage}\\[4ex] -\end{flushleft} -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap4} -$\langle$Protos {\footnotesize ?}$\rangle\equiv$ -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ void SNXFormatTime(char *pBuffer, int iBufLen);@\\ -\mbox{}\verb@@$\diamond$ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}} -\item Macro defined by scraps ?, ?, ?, ?, ?, ?, ?. -\item Macro referenced in scrap ?. -\end{list} -\end{minipage}\\[4ex] -\end{flushleft} -SNXFormatTime formats the current system time in a form compatible to the -NeXus standard. Input parameters is a Buffer to hold the string and a -length of the buffer. Maximum iBufLen characters will be copied to that -buffer. - -SNXStartEntry creates a new entry corresponding to iNew in the Nexus file -Nfil. SNXStartEntry will position Nfil in this new entry. Any data items -labeled as Comment or intent will be written to the file as well. - - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap5} -$\langle$Protos {\footnotesize ?}$\rangle\equiv$ -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ int SNFinishFile(NXhandle Nfil);@\\ -\mbox{}\verb@@$\diamond$ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}} -\item Macro defined by scraps ?, ?, ?, ?, ?, ?, ?. -\item Macro referenced in scrap ?. -\end{list} -\end{minipage}\\[4ex] -\end{flushleft} -SNFinishFile will end a Nexus file properly. - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap6} -$\langle$Protos {\footnotesize ?}$\rangle\equiv$ -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ int SNMakeDMC(SConnection *pCon, SicsInterp *pSics);@\\ -\mbox{}\verb@@$\diamond$ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}} -\item Macro defined by scraps ?, ?, ?, ?, ?, ?, ?. -\item Macro referenced in scrap ?. -\end{list} -\end{minipage}\\[4ex] -\end{flushleft} -SNMakeDMC produces a Nexus DMC data file from the currently valid -information. It orchestrates all of the above. - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap7} -$\langle$Protos {\footnotesize ?}$\rangle\equiv$ -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@int SNStoreDMC(SConnection *pCon, SicsInterp *pSics, void *pData, int argc,@\\ -\mbox{}\verb@ char *argv[]);@\\ -\mbox{}\verb@@$\diamond$ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}} -\item Macro defined by scraps ?, ?, ?, ?, ?, ?, ?. -\item Macro referenced in scrap ?. -\end{list} -\end{minipage}\\[4ex] -\end{flushleft} -SNStoreData is the wrapper function used to install a DMC data storage -command in the Sics interpreter. - - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap8} -\verb@"nxdata.h"@ {\footnotesize ? }$\equiv$ -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@/*-------------------------------------------------------------------------@\\ -\mbox{}\verb@ N X D A T A@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ Some routines for handling Nexus data file writing.@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ Mark Koennecke, April 1997@\\ -\mbox{}\verb@ @\\ -\mbox{}\verb@ copyright: see implementation file.@\\ -\mbox{}\verb@--------------------------------------------------------------------------*/@\\ -\mbox{}\verb@#ifndef SICSNXDATA@\\ -\mbox{}\verb@#define SICSNXDATA@\\ -\mbox{}\verb@@$\langle$Protos {\footnotesize ?, \ldots\ }$\rangle$\verb@ @\\ -\mbox{}\verb@#endif @\\ -\mbox{}\verb@@\\ -\mbox{}\verb@@$\diamond$ -\end{list} -\vspace{-2ex} -\end{minipage}\\[4ex] -\end{flushleft} diff --git a/nxdata.w b/nxdata.w deleted file mode 100644 index 572324b8..00000000 --- a/nxdata.w +++ /dev/null @@ -1,89 +0,0 @@ -\subsection{NXdata} -NXdata is a module for writing Powder Diffraction Data files. The -routines here are somewhat obsolete as they refer to NeXus writing -using the standard Napi routines which is quite involved. Usually, -NeXus files are written from SICS through the NXDICT aware utility -routines in NXUTIL. - -If not stated -otherwise, all routines return 1 on successful completion and 0 when an -error is detected. Please note, that many of these routines expect to find -certain data items in the Sics Interpreter. This implies, that any naming -changes in the initialisation file might force changes in here as well. - -@d Protos @{ - char *SNXMakeFileName(SicsInterp *pSics, SConnection *pCon); -@} -SNXMakeFileName creates a new filename from the SICS variables SicsDataPath, -SicsDataPresript, SicsDataNumber and SicsDataEnding. SicsDataNumber will be -incremented as well. The function returns a newly allocate buffer with the -assembled filename or NULL on error. Note, that the caller is responsible -for freeing the memory associated with the filename afterwards. - -@d Protos @{ - NXhandle SNXStartFile(SConnection *pCon, SicsInterp *pSics); -@} -First calls SNXMakeFileName in order to get a new Filename. -Then a new Nexus file is -created and all the standard headings are filled in: Filename, User, -instrument, date etc. This routine also installs an error handler which -prints errors to pCon. -If successful, the SicsDataNumber is incremented and -an NXhandle into the new file is returned. If there is a problem, NULL -will be returned. The file returned will be positioned at root level. - -@d Protos @{ - int SNXStartEntry(NXhandle Nfil, int iNew, SicsInterp *pSics); -@} - -@d Protos @{ - void SNXFormatTime(char *pBuffer, int iBufLen); -@} - -SNXFormatTime formats the current system time in a form compatible to the -NeXus standard. Input parameters is a Buffer to hold the string and a -length of the buffer. Maximum iBufLen characters will be copied to that -buffer. - -SNXStartEntry creates a new entry corresponding to iNew in the Nexus file -Nfil. SNXStartEntry will position Nfil in this new entry. Any data items -labeled as Comment or intent will be written to the file as well. - - -@d Protos @{ - int SNFinishFile(NXhandle Nfil); -@} - -SNFinishFile will end a Nexus file properly. - -@d Protos @{ - int SNMakeDMC(SConnection *pCon, SicsInterp *pSics); -@} - -SNMakeDMC produces a Nexus DMC data file from the currently valid -information. It orchestrates all of the above. - -@d Protos @{ -int SNStoreDMC(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, - char *argv[]); -@} -SNStoreData is the wrapper function used to install a DMC data storage -command in the Sics interpreter. - - -@o nxdata.h @{ -/*------------------------------------------------------------------------- - N X D A T A - - Some routines for handling Nexus data file writing. - - Mark Koennecke, April 1997 - - copyright: see implementation file. ---------------------------------------------------------------------------*/ -#ifndef SICSNXDATA -#define SICSNXDATA -@< Protos@> -#endif - -@} diff --git a/nxdataset.c b/nxdataset.c index 6d419196..327ad4f4 100644 --- a/nxdataset.c +++ b/nxdataset.c @@ -34,20 +34,22 @@ static int getTypeSize(int typecode){ } } /*-----------------------------------------------------------------------*/ -pNXDS createNXDataset(int rank, int typecode, int dim[]){ +pNXDS createNXDataset(int rank, int typecode, int64_t dim[]){ pNXDS pNew = NULL; - int i, length; + int64_t length; + int i; pNew = (pNXDS)malloc(sizeof(NXDS)); if(pNew == NULL){ return NULL; } - pNew->dim = (int *)malloc(rank*sizeof(int)); + pNew->dim = (int64_t *)malloc(rank*sizeof(int64_t)); for(i = 0, length = 1; i < rank; i++){ length *= dim[i]; } - pNew->u.ptr = malloc(length*getTypeSize(typecode)); + /* add +1 in case of string NULL termination */ + pNew->u.ptr = malloc(length*getTypeSize(typecode)+1); if(pNew->dim == NULL || pNew->u.ptr == NULL){ free(pNew); @@ -60,7 +62,8 @@ pNXDS createNXDataset(int rank, int typecode, int dim[]){ pNew->dim[i] = dim[i]; } pNew->magic = MAGIC; - memset(pNew->u.ptr,0,length*getTypeSize(typecode)); + /* add +1 in case of string NULL termination - see above */ + memset(pNew->u.ptr,0,length*getTypeSize(typecode)+1); return pNew; } /*---------------------------------------------------------------------*/ @@ -71,7 +74,7 @@ pNXDS createTextNXDataset(char *name){ if(pNew == NULL){ return NULL; } - pNew->dim = (int *)malloc(sizeof(int)); + pNew->dim = (int64_t *)malloc(sizeof(int64_t)); pNew->u.cPtr = strdup(name); if(pNew->dim == NULL || pNew->u.ptr == NULL){ free(pNew); @@ -158,8 +161,8 @@ int getNXDatasetByteLength(pNXDS dataset){ /*---------------------------------------------------------------------- This calculates an arbitray address in C storage order -----------------------------------------------------------------------*/ -static int calculateAddress(pNXDS dataset, int pos[]){ - int result, mult; +static int64_t calculateAddress(pNXDS dataset, int64_t pos[]){ + int64_t result, mult; int i, j; result = pos[dataset->rank - 1]; @@ -175,10 +178,9 @@ static int calculateAddress(pNXDS dataset, int pos[]){ return result; } /*-----------------------------------------------------------------------*/ -double getNXDatasetValue(pNXDS dataset, int pos[]){ - int address; - double value; - +double getNXDatasetValue(pNXDS dataset, int64_t pos[]){ + int64_t address; + if(dataset == NULL){ return 0; } @@ -190,7 +192,7 @@ double getNXDatasetValue(pNXDS dataset, int pos[]){ return getNXDatasetValueAt(dataset, address); } /*----------------------------------------------------------------------*/ -double getNXDatasetValueAt(pNXDS dataset, int address){ +double getNXDatasetValueAt(pNXDS dataset, int64_t address){ double value; if(dataset == NULL){ @@ -228,7 +230,7 @@ double getNXDatasetValueAt(pNXDS dataset, int address){ /*-----------------------------------------------------------------------*/ char *getNXDatasetText(pNXDS dataset){ char *resultBuffer = NULL; - int length, status = 1; + int status = 1; if(dataset == NULL){ return strdup("NULL"); @@ -263,8 +265,8 @@ char *getNXDatasetText(pNXDS dataset){ return resultBuffer; } /*----------------------------------------------------------------------*/ -int putNXDatasetValue(pNXDS dataset, int pos[], double value){ - int address; +int putNXDatasetValue(pNXDS dataset, int64_t pos[], double value){ + int64_t address; if(dataset == NULL){ return 0; @@ -277,7 +279,7 @@ int putNXDatasetValue(pNXDS dataset, int pos[], double value){ return putNXDatasetValueAt(dataset,address,value); } /*---------------------------------------------------------------------*/ -int putNXDatasetValueAt(pNXDS dataset, int address, double value){ +int putNXDatasetValueAt(pNXDS dataset, int64_t address, double value){ /* this code is dangerous, it casts without checking the data range. This may cause trouble in some cases @@ -307,140 +309,150 @@ int putNXDatasetValueAt(pNXDS dataset, int address, double value){ } return 1; } + /*---------------------------------------------------------------------- This is working recursively through the dimensions. When at the last: actual copying takes place. -----------------------------------------------------------------------*/ -static void copyCutData(pNXDS source, pNXDS target, int sourceDim[], - int targetDim[], int start[], int end[], - int dim){ +static void copyCutData(pNXDS source, pNXDS target, int64_t sourceDim[], + int64_t targetDim[], int64_t start[], int64_t end[], int dim) +{ int i, length; double val; targetDim[dim] = 0; length = end[dim] - start[dim]; - if(dim == source->rank -1){ - for(i = 0; i < length; i++){ + if (dim == source->rank - 1) { + for (i = 0; i < length; i++) { sourceDim[dim] = start[dim] + i; - val = getNXDatasetValue(source,sourceDim); + val = getNXDatasetValue(source, sourceDim); targetDim[dim] = i; putNXDatasetValue(target, targetDim, val); } } else { - for(i = 0; i < length; i++){ + for (i = 0; i < length; i++) { sourceDim[dim] = start[dim] + i; targetDim[dim] = i; - copyCutData(source,target, sourceDim, targetDim, start, end, dim+1); + copyCutData(source, target, sourceDim, targetDim, start, end, + dim + 1); } } } -/*-----------------------------------------------------------------------*/ -pNXDS cutNXDataset(pNXDS source, int start[], int end[]){ - pNXDS result = NULL; - int newDim[NX_MAXRANK], i; - int sourceDim[NX_MAXRANK], targetDim[NX_MAXRANK]; - for(i = 0; i < source->rank; i++){ - if(start[i] < 0 || end[i] > source->dim[i]){ - fprintf(stderr,"ERROR: invalid boundaries specified for cutting"); +/*-----------------------------------------------------------------------*/ +pNXDS cutNXDataset(pNXDS source, int64_t start[], int64_t end[]) +{ + pNXDS result = NULL; + int64_t newDim[NX_MAXRANK], i; + int64_t sourceDim[NX_MAXRANK], targetDim[NX_MAXRANK]; + + for (i = 0; i < source->rank; i++) { + if (start[i] < 0 || end[i] > source->dim[i]) { + fprintf(stderr, "ERROR: invalid boundaries specified for cutting"); return NULL; } newDim[i] = end[i] - start[i]; - if(newDim[i] <= 0){ - fprintf(stderr,"ERROR: invalid cut limits specified for cutting dataset"); + if (newDim[i] <= 0) { + fprintf(stderr, + "ERROR: invalid cut limits specified for cutting dataset"); return NULL; } } result = createNXDataset(source->rank, source->type, newDim); - if(result == NULL){ - fprintf(stderr,"ERROR: out of memory creating result dataset"); + if (result == NULL) { + fprintf(stderr, "ERROR: out of memory creating result dataset"); return NULL; } - + copyCutData(source, result, sourceDim, targetDim, start, end, 0); return result; } + /*---------------------------------------------------------------------- - This recurses through all dimesnions, thereby skipping the summed one. - At the end of the rescusion the actual summing is performed. + This recurses through all dimensions, thereby skipping the summed one. + At the end of the recursion the actual summing is performed. ----------------------------------------------------------------------*/ -static void sumData(pNXDS source, pNXDS target, int sourceDim[], - int targetDim[], int targetDimCount, int dimNo, - int start, int end, int currentDim){ +static void sumData(pNXDS source, pNXDS target, int64_t sourceDim[], + int64_t targetDim[], int targetDimCount, int dimNo, + int start, int end, int currentDim) +{ int i, length; double val, sumVal; /* - when we have recursed through all dimensions - we actually do the sums... - */ - if(currentDim == source->rank){ + when we have recursed through all dimensions + we actually do the sums... + */ + if (currentDim == source->rank) { length = end - start; sumVal = getNXDatasetValue(target, targetDim); - for(i = 0; i < length; i++){ + for (i = 0; i < length; i++) { sourceDim[dimNo] = start + i; - val = getNXDatasetValue(source,sourceDim); + val = getNXDatasetValue(source, sourceDim); sumVal += val; } putNXDatasetValue(target, targetDim, sumVal); } else { /* - jump over the summed dimension while recursing - through the dimensions - */ - if(currentDim == dimNo){ - sumData(source,target,sourceDim, - targetDim,targetDimCount, - dimNo,start,end,currentDim+1); + jump over the summed dimension while recursing + through the dimensions + */ + if (currentDim == dimNo) { + sumData(source, target, sourceDim, + targetDim, targetDimCount, + dimNo, start, end, currentDim + 1); } else { /* - loop over all values of the non summed dimension - */ - for(i = 0; i < source->dim[currentDim]; i++){ - /* - the problem here is that we have to jump over the summed - dimension here. This why we have to maintain a separate - dimension count for the target array. Jumping is done - above. - */ - targetDim[targetDimCount] = i; - targetDimCount++; + loop over all values of the non summed dimension + */ + for (i = 0; i < source->dim[currentDim]; i++) { + /* + the problem here is that we have to jump over the summed + dimension here. This why we have to maintain a separate + dimension count for the target array. Jumping is done + above. + */ + targetDim[targetDimCount] = i; + targetDimCount++; - sourceDim[currentDim] = i; - sumData(source,target,sourceDim,targetDim,targetDimCount, - dimNo,start,end,currentDim+1); - targetDimCount--; + sourceDim[currentDim] = i; + sumData(source, target, sourceDim, targetDim, targetDimCount, + dimNo, start, end, currentDim + 1); + targetDimCount--; } } } } + /*-----------------------------------------------------------------------*/ -pNXDS sumNXDataset(pNXDS source, int dimNo, int start, int end){ - int newDim[NX_MAXRANK], targetDim[NX_MAXRANK], sourceDim[NX_MAXRANK]; +pNXDS sumNXDataset(pNXDS source, int dimNo, int start, int end) +{ + int64_t newDim[NX_MAXRANK], targetDim[NX_MAXRANK], sourceDim[NX_MAXRANK]; pNXDS result = NULL; int i, count; - if(dimNo < 0 || dimNo > source->rank-1) { - fprintf(stderr,"ERROR: invalid dimension for summing requested"); + if (dimNo < 0 || dimNo > source->rank - 1) { + fprintf(stderr, "ERROR: invalid dimension for summing requested"); return NULL; } /* - make result dataset with missing summed dimension - */ - for(i = 0, count = 0; i < source->rank; i++){ - if(i != dimNo){ + make result dataset with missing summed dimension + */ + for (i = 0, count = 0; i < source->rank; i++) { + if (i != dimNo) { newDim[count] = source->dim[i]; count++; } } - result = createNXDataset(source->rank-1, source->type, newDim); - if(result == NULL){ - fprintf(stderr,"ERROR: out of memory creating result dataset"); + result = createNXDataset(source->rank - 1, source->type, newDim); + if (result == NULL) { + fprintf(stderr, "ERROR: out of memory creating result dataset"); return NULL; } - sumData(source,result,sourceDim,targetDim,0, - dimNo, start, end, 0); + sumData(source, result, sourceDim, targetDim, 0, dimNo, start, end, 0); return result; } + + diff --git a/nxdataset.h b/nxdataset.h index ab5d33a9..98eff2e8 100644 --- a/nxdataset.h +++ b/nxdataset.h @@ -18,7 +18,7 @@ typedef struct { int magic; int rank; int type; - int *dim; + int64_t *dim; char *format; union { void *ptr; @@ -53,7 +53,7 @@ typedef struct { #endif -pNXDS createNXDataset(int rank, int typecode, int dim[]); +pNXDS createNXDataset(int rank, int typecode, int64_t dim[]); pNXDS createTextNXDataset(char *name); void dropNXDataset(pNXDS dataset); @@ -64,14 +64,14 @@ int getNXDatasetType(pNXDS dataset); int getNXDatasetLength(pNXDS dataset); int getNXDatasetByteLength(pNXDS dataset); -double getNXDatasetValue(pNXDS dataset, int pos[]); -double getNXDatasetValueAt(pNXDS dataset, int address); +double getNXDatasetValue(pNXDS dataset, int64_t pos[]); +double getNXDatasetValueAt(pNXDS dataset, int64_t address); char *getNXDatasetText(pNXDS dataset); -int putNXDatasetValue(pNXDS dataset, int pos[], double value); -int putNXDatasetValueAt(pNXDS dataset, int address, double value); +int putNXDatasetValue(pNXDS dataset, int64_t pos[], double value); +int putNXDatasetValueAt(pNXDS dataset, int64_t address, double value); -pNXDS cutNXDataset(pNXDS source, int start[], int end[]); +pNXDS cutNXDataset(pNXDS source, int64_t start[], int64_t end[]); pNXDS sumNXDataset(pNXDS source, int dimNo, int start, int end); #endif diff --git a/nxdict.c b/nxdict.c index 263257a2..05f62d44 100644 --- a/nxdict.c +++ b/nxdict.c @@ -47,8 +47,7 @@ /*-------------------------------------------------------------------------- Things defined in napi.c for error reporting ---------------------------------------------------------------------------*/ - extern void *NXpData; - extern void (*NXIReportError)(void *pData, char *pBuffer); +static void *NXpData = NULL; /*--------------------------------------------------------------------------*/ /* #define DEFDEBUG 1 */ /* define DEFDEBUG when you wish to print your definition strings before @@ -58,53 +57,50 @@ /*-------------------------------------------------------------------------*/ - typedef struct __NXdict - { - int iID; - pStringDict pDictionary; - } sNXdict; +typedef struct __NXdict { + int iID; + pStringDict pDictionary; +} sNXdict; /*------------------ verbosity level -------------------------------------*/ - static int iVerbosity = 0 ; +static int iVerbosity = 0; /*-------------------------------------------------------------------------*/ - static char *NXDIReadFile(FILE *fd) - { - char *pNew = NULL; - long lLength = 0; - - assert(fd); +static char *NXDIReadFile(FILE * fd) +{ + char *pNew = NULL; + long lLength = 0; - /* determine length of file */ - fseek(fd,0L,SEEK_END); - lLength = ftell(fd); - if(lLength <= 0) - { - return NULL; - } - fseek(fd,0L,SEEK_SET); + assert(fd); - /* allocate buffer */ - lLength += 3; - pNew = (char *)malloc(lLength*sizeof(char)); - if(!pNew) - { - return NULL; - } - memset(pNew,0,lLength); /* this ensures a 0 at the end */ - - /* read file */ - fread(pNew,sizeof(char),lLength-3,fd); - - /* check for existence of the NXDICT string in the file */ - if(strncmp(pNew,"##NXDICT-1.0",12) != 0 ) - { - NXIReportError(NXpData,"ERROR: This is NO NXdict file"); - free(pNew); - return NULL; - } - return pNew; + /* determine length of file */ + fseek(fd, 0L, SEEK_END); + lLength = ftell(fd); + if (lLength <= 0) { + return NULL; } + fseek(fd, 0L, SEEK_SET); + + /* allocate buffer */ + lLength += 3; + pNew = (char *) malloc(lLength * sizeof(char)); + if (!pNew) { + return NULL; + } + memset(pNew, 0, lLength); /* this ensures a 0 at the end */ + + /* read file */ + fread(pNew, sizeof(char), lLength - 3, fd); + + /* check for existence of the NXDICT string in the file */ + if (strncmp(pNew, "##NXDICT-1.0", 12) != 0) { + NXReportError("ERROR: This is NO NXdict file"); + free(pNew); + return NULL; + } + return pNew; +} + /*--------------------------------------------------------------------------*/ @@ -115,69 +111,56 @@ #define FEQUAL 5 #define FSLASH 6 - static char *NXDIfNextToken(char *pPtr, char *pToken, int *iToken) - { - pToken[0] = '\0'; - /* skip whitespace */ - while( (*pPtr == ' ') || (*pPtr == '\t') ) - { - pPtr++; - } +static char *NXDIfNextToken(char *pPtr, char *pToken, int *iToken) +{ + pToken[0] = '\0'; + /* skip whitespace */ + while ((*pPtr == ' ') || (*pPtr == '\t')) { + pPtr++; + } + + /* check for special characters */ + if (*pPtr == '#') { + *iToken = FHASH; + pToken[0] = *pPtr; + pPtr++; + return pPtr; + } else if (*pPtr == '\n') { + *iToken = FEOL; + pToken[0] = *pPtr; + pPtr++; + return pPtr; + } else if (*pPtr == '\0') { + *iToken = FEOB; + pToken[0] = *pPtr; + pPtr++; + return pPtr; + } else if (*pPtr == '=') { + *iToken = FEQUAL; + pToken[0] = *pPtr; + pPtr++; + return pPtr; + } else if (*pPtr == '\\') { + *iToken = FSLASH; + pToken[0] = *pPtr; + pPtr++; + return pPtr; + } else { + *iToken = FWORD; + /* copy word to pToken */ + while ((*pPtr != ' ') && (*pPtr != '\t') && + (*pPtr != '\n') && (*pPtr != '\0') && (*pPtr != '=')) { + *pToken = *pPtr; + pPtr++; + pToken++; + } + *pToken = '\0'; + return pPtr; + } + /* not reached */ + return pPtr; +} - /* check for special characters */ - if(*pPtr == '#') - { - *iToken = FHASH; - pToken[0] = *pPtr; - pPtr++; - return pPtr; - } - else if(*pPtr == '\n') - { - *iToken = FEOL; - pToken[0] = *pPtr; - pPtr++; - return pPtr; - } - else if(*pPtr == '\0') - { - *iToken = FEOB; - pToken[0] = *pPtr; - pPtr++; - return pPtr; - } - else if(*pPtr == '=') - { - *iToken = FEQUAL; - pToken[0] = *pPtr; - pPtr++; - return pPtr; - } - else if(*pPtr == '\\') - { - *iToken = FSLASH; - pToken[0] = *pPtr; - pPtr++; - return pPtr; - } - else - { - *iToken = FWORD; - /* copy word to pToken */ - while( (*pPtr != ' ') && (*pPtr != '\t') && - (*pPtr != '\n') && (*pPtr != '\0') && (*pPtr != '=') ) - { - *pToken = *pPtr; - pPtr++; - pToken++; - } - *pToken = '\0'; - return pPtr; - } - /* not reached */ - return pPtr; - } - /*------------------------------------------------------------------------*/ @@ -186,438 +169,398 @@ #define AMODE 0 #define DMODE 1 - static void NXDIParse(char *pBuffer, pStringDict pDict) - { - char *pPtr; - int iToken; - int iMode; - char pAlias[1024]; - char pDefinition[8192]; /* this is > 10 lines of definition */ - char pWord[1024]; +static void NXDIParse(char *pBuffer, pStringDict pDict) +{ + char *pPtr; + int iToken; + int iMode; + char pAlias[132]; + char pDefinition[1024]; /* this is > 10 lines of definition */ + char pWord[132]; - assert(pBuffer); - assert(pDict); + assert(pBuffer); + assert(pDict); - iMode = AMODE; - pPtr = pBuffer; - iToken = -1; - pDefinition[0] = '\0'; - pAlias[0] = '\0'; - pWord[0] = '\0'; + iMode = AMODE; + pPtr = pBuffer; + iToken = -1; + pDefinition[0] = '\0'; + pAlias[0] = '\0'; + pWord[0] = '\0'; - while(iToken != FEOB) - { - pPtr = NXDIfNextToken(pPtr,pWord,&iToken); - switch(iToken) - { - case FHASH: - case FSLASH: /* skip over \n to next non blank */ - while(*pPtr != '\n') - { - pPtr++; - /* check for end of file */ - if(*pPtr == '\0') - { - return; - } - } - pPtr++; - break; - case FEQUAL: /* do a mode change */ - iMode = DMODE; - pDefinition[0] = '\0'; - break; + while (iToken != FEOB) { + pPtr = NXDIfNextToken(pPtr, pWord, &iToken); + switch (iToken) { + case FHASH: + case FSLASH: /* skip over \n to next non blank */ + while (*pPtr != '\n') { + pPtr++; + /* check for end of file */ + if (*pPtr == '\0') { + return; + } + } + pPtr++; + break; + case FEQUAL: /* do a mode change */ + iMode = DMODE; + pDefinition[0] = '\0'; + break; - case FWORD: - if(iMode == AMODE) - { - strcpy(pAlias,pWord); - } - else - { - strcat(pDefinition,pWord); - strcat(pDefinition," "); - } - break; - case FEOL: - if(iMode == DMODE) - { - /* enter in dictionary */ - StringDictAddPair(pDict,pAlias,pDefinition); - iMode = AMODE; - pAlias[0] = '\0'; - } - break; - case FEOB: - if(iMode == AMODE) - { - /* empty line or a problem */ - } - else - { - /* enter in dictionary */ - StringDictAddPair(pDict,pAlias,pDefinition); - iMode = AMODE; - pAlias[0] = '\0'; - } - return; - default: - assert(0); /* unrecognized token is a programming - error - */ - break; - } - } + case FWORD: + if (iMode == AMODE) { + strcpy(pAlias, pWord); + } else { + strcat(pDefinition, pWord); + strcat(pDefinition, " "); + } + break; + case FEOL: + if (iMode == DMODE) { + /* enter in dictionary */ + StringDictAddPair(pDict, pAlias, pDefinition); + iMode = AMODE; + pAlias[0] = '\0'; + } + break; + case FEOB: + if (iMode == AMODE) { + /* empty line or a problem */ + } else { + /* enter in dictionary */ + StringDictAddPair(pDict, pAlias, pDefinition); + iMode = AMODE; + pAlias[0] = '\0'; + } + return; + default: + assert(0); /* unrecognized token is a programming + error + */ + break; + } + } +} + + +/*--------------------------------------------------------------------------*/ +NXstatus NXDinitfromfile(char *filename, NXdict * pData) +{ + NXdict pNew = NULL; + FILE *fd = NULL; + char *pBuffer = NULL; + char pError[512]; + + + + /* allocate a new NXdict structure */ + if (iVerbosity == NXalot) { + NXReportError("Allocating new NXdict structure "); + } + pNew = (NXdict) malloc(sizeof(sNXdict)); + if (!pNew) { + NXReportError("Insufficient memory for creation of NXdict"); + return NX_ERROR; + } + + /* initialise it */ + pNew->iID = NXDMAGIC; + pNew->pDictionary = CreateStringDict(); + if (!pNew->pDictionary) { + NXReportError("Insufficient memory for creation of NXdict"); + free(pNew); + return NX_ERROR; } -/*--------------------------------------------------------------------------*/ - NXstatus NXDinitfromfile(char *filename, NXdict *pData) - { - NXdict pNew = NULL; - FILE *fd = NULL; - char *pBuffer = NULL; - char pError[512]; + + /* is there a file name argument */ + if (filename == NULL) { + if (iVerbosity == NXalot) { + NXReportError("NXDinitfrom file finished without data"); + } + *pData = pNew; + return NX_OK; + } - - /* allocate a new NXdict structure */ - if(iVerbosity == NXalot) - { - NXIReportError(NXpData, "Allocating new NXdict structure "); - } - pNew = (NXdict)malloc(sizeof(sNXdict)); - if(!pNew) - { - NXIReportError(NXpData, "Insufficient memory for creation of NXdict"); - return NX_ERROR; - } - - /* initialise it */ - pNew->iID = NXDMAGIC; - pNew->pDictionary = CreateStringDict(); - if(!pNew->pDictionary) - { - NXIReportError(NXpData, "Insufficient memory for creation of NXdict"); - free(pNew); - return NX_ERROR; - } + fd = fopen(filename, "rb"); + if (!fd) { + sprintf(pError, "ERROR: file %s NOT found ", filename); + NXReportError(pError); + NXReportError("NXDinitfrom file finished without data"); + *pData = pNew; + return NX_ERROR; + } + /* read the file contents */ + if (iVerbosity == NXalot) { + NXReportError("NXDinitfrom: reading file"); + } + pBuffer = NXDIReadFile(fd); + fclose(fd); /* we are done with it then */ + if (!pBuffer) { + sprintf(pError, "ERROR: reading file %s or no memory", filename); + NXReportError(pError); + NXReportError("NXDinitfrom file finished without data"); + *pData = pNew; + return NX_ERROR; + } - /* is there a file name argument */ - if(filename == NULL) - { - if(iVerbosity == NXalot) - { - NXIReportError(NXpData, "NXDinitfrom file finished without data"); - } - *pData = pNew; - return NX_OK; - } + /* parse it */ + if (iVerbosity == NXalot) { + NXReportError("NXDinitfrom: parsing dictionary definitions"); + } + NXDIParse(pBuffer, pNew->pDictionary); - fd = fopen(filename,"rb"); - if(!fd) - { - sprintf(pError,"ERROR: file %s NOT found ",filename); - NXIReportError(NXpData, pError); - NXIReportError(NXpData, "NXDinitfrom file finished without data"); - *pData = pNew; - return NX_ERROR; - } + if (iVerbosity == NXalot) { + NXReportError("NXDinitfrom: performed successfully"); + } + free(pBuffer); + *pData = pNew; + return NX_OK; +} - - /* read the file contents */ - if(iVerbosity == NXalot) - { - NXIReportError(NXpData, "NXDinitfrom: reading file"); - } - pBuffer = NXDIReadFile(fd); - fclose(fd); /* we are done with it then */ - if(!pBuffer) - { - sprintf(pError,"ERROR: reading file %s or no memory",filename); - NXIReportError(NXpData, pError); - NXIReportError(NXpData, "NXDinitfrom file finished without data"); - *pData = pNew; - return NX_ERROR; - } - - /* parse it */ - if(iVerbosity == NXalot) - { - NXIReportError(NXpData, "NXDinitfrom: parsing dictionary definitions"); - } - NXDIParse(pBuffer, pNew->pDictionary); - - - if(iVerbosity == NXalot) - { - NXIReportError(NXpData, "NXDinitfrom: performed successfully"); - } - free(pBuffer); - *pData = pNew; - return NX_OK; - } /*--------------------------------------------------------------------------*/ - NXdict NXDIAssert(NXdict handle) - { - NXdict self = NULL; - assert(handle); - self = (NXdict)handle; - assert(self->iID == NXDMAGIC); - return self; - } +NXdict NXDIAssert(NXdict handle) +{ + NXdict self = NULL; + assert(handle); + self = (NXdict) handle; + assert(self->iID == NXDMAGIC); + return self; +} /*-------------------------------------------------------------------------*/ - NXstatus NXDclose(NXdict handle, char *filename) - { - NXdict self; - const char *pKey = NULL; - char pValue[1024]; - FILE *fd = NULL; +NXstatus NXDclose(NXdict handle, char *filename) +{ + NXdict self; + const char *pKey = NULL; + char pValue[1024]; + FILE *fd = NULL; - self = NXDIAssert(handle); + self = NXDIAssert(handle); - if(filename) /* we must write a file */ - { - if(iVerbosity == NXalot) - { - sprintf(pValue,"Writing file %s",filename); - NXIReportError(NXpData, pValue); - } - fd = fopen(filename,"w"); - if(!fd) - { - sprintf(pValue,"ERROR: opening file %s for write",filename); - NXIReportError(NXpData, pValue); - return NX_ERROR; - } - - /* write our magic recognition header */ - fprintf(fd,"##NXDICT-1.0\n"); + if (filename) { /* we must write a file */ + if (iVerbosity == NXalot) { + sprintf(pValue, "Writing file %s", filename); + NXReportError(pValue); + } + fd = fopen(filename, "w"); + if (!fd) { + sprintf(pValue, "ERROR: opening file %s for write", filename); + NXReportError(pValue); + return NX_ERROR; + } - /* write all our keys */ - pKey = StringDictGetNext(self->pDictionary, pValue,1023); - while(pKey != NULL) - { - fprintf(fd,"%s = %s\n",pKey,pValue); - pKey = StringDictGetNext(self->pDictionary,pValue,1023); - } - fclose(fd); - if(iVerbosity == NXalot) - { - sprintf(pValue,"File %s written",filename); - NXIReportError(NXpData, pValue); - } - } + /* write our magic recognition header */ + fprintf(fd, "##NXDICT-1.0\n"); - /* now we send the cleaners in */ - DeleteStringDict(self->pDictionary); - free(self); - return NX_OK; - } + /* write all our keys */ + pKey = StringDictGetNext(self->pDictionary, pValue, 1023); + while (pKey != NULL) { + fprintf(fd, "%s = %s\n", pKey, pValue); + pKey = StringDictGetNext(self->pDictionary, pValue, 1023); + } + fclose(fd); + if (iVerbosity == NXalot) { + sprintf(pValue, "File %s written", filename); + NXReportError(pValue); + } + } + + /* now we send the cleaners in */ + DeleteStringDict(self->pDictionary); + free(self); + return NX_OK; +} /*------------------------------------------------------------------------*/ - NXstatus NXDadd(NXdict handle, char *alias, char *pDef) - { - NXdict self; - int iRet; +NXstatus NXDadd(NXdict handle, char *alias, char *pDef) +{ + NXdict self; + int iRet; + + self = NXDIAssert(handle); + iRet = StringDictAddPair(self->pDictionary, alias, pDef); + if (!iRet) { + return NX_ERROR; + } + return NX_OK; +} - self = NXDIAssert(handle); - iRet = StringDictAddPair(self->pDictionary,alias,pDef); - if(!iRet) - { - return NX_ERROR; - } - return NX_OK; - } /*---------------------------------------------------------------------------*/ - NXstatus NXDget(NXdict handle, char *pKey, char *pBuffer, int iBufLen) - { - NXdict self; - int iRet; +NXstatus NXDget(NXdict handle, char *pKey, char *pBuffer, int iBufLen) +{ + NXdict self; + int iRet; - self = NXDIAssert(handle); - iRet = StringDictGet(self->pDictionary,pKey,pBuffer,iBufLen); - if(!iRet) - { - return NX_ERROR; - } + self = NXDIAssert(handle); + iRet = StringDictGet(self->pDictionary, pKey, pBuffer, iBufLen); + if (!iRet) { + return NX_ERROR; + } #ifdef DEFDEBUG - printf("Resolved: %s to %s\n",pKey,pBuffer); + printf("Resolved: %s to %s\n", pKey, pBuffer); #endif - return NX_OK; - } -/*-------------------------------------------------------------------------*/ - NXstatus NXDupdate(NXdict handle, char *pKey, char *pNewVal) - { - NXdict self; - int iRet; + return NX_OK; +} + +/*-------------------------------------------------------------------------*/ +NXstatus NXDupdate(NXdict handle, char *pKey, char *pNewVal) +{ + NXdict self; + int iRet; + + self = NXDIAssert(handle); + iRet = StringDictUpdate(self->pDictionary, pKey, pNewVal); + if (!iRet) { + return NX_ERROR; + } + return NX_OK; +} - self = NXDIAssert(handle); - iRet = StringDictUpdate(self->pDictionary,pKey,pNewVal); - if(!iRet) - { - return NX_ERROR; - } - return NX_OK; - } /*-----------------------------------------------------------------------*/ #define NORMAL 1 #define ALIAS 2 - pDynString NXDItextreplace(NXdict handle, char *pDefString) - { - NXdict self; - int iRet, iPos, i; - pDynString pReplaced = NULL; - char pBueffel[1024]; - char pBuffer2[1024]; - char *pPtr; - int iState; +pDynString NXDItextreplace(NXdict handle, char *pDefString) +{ + NXdict self; + int iRet, iPos, i; + pDynString pReplaced = NULL; + char pBueffel[1024]; + char pBuffer2[1024]; + char *pPtr; + int iState; - self = NXDIAssert(handle); - - /* create a dynamic string */ - pReplaced = CreateDynString(strlen(pDefString),512); - if(!pReplaced) - { - NXIReportError(NXpData,"ERROR: out of memory in NXDtextreplace"); - return NULL; - } + self = NXDIAssert(handle); - /* the loop */ - iState = NORMAL; - for(i = 0, pPtr = pDefString; i < strlen(pDefString); i++,pPtr++) - { - if(iState == NORMAL) - { - if(*pPtr == '$') - { - iState = ALIAS; - memset(pBueffel,0,1024); - iPos = 0; - } - else - { - DynStringConcatChar(pReplaced,*pPtr); - } + /* create a dynamic string */ + pReplaced = CreateDynString(strlen(pDefString), 512); + if (!pReplaced) { + NXReportError("ERROR: out of memory in NXDtextreplace"); + return NULL; + } + + /* the loop */ + iState = NORMAL; + for (i = 0, pPtr = pDefString; i < strlen(pDefString); i++, pPtr++) { + if (iState == NORMAL) { + if (*pPtr == '$') { + iState = ALIAS; + memset(pBueffel, 0, 1024); + iPos = 0; + } else { + DynStringConcatChar(pReplaced, *pPtr); + } + } else if (iState == ALIAS) { + switch (*pPtr) { + case '(': /* ignore */ + break; + case ')': + /* do the replacement */ + memset(pBuffer2, 0, 1023); + iRet = NXDget(handle, pBueffel, pBuffer2, 1023); + if (iRet != NX_OK) { + DeleteDynString(pReplaced); + return NULL; } - else if(iState == ALIAS) - { - switch(*pPtr) - { - case '(': /* ignore */ - break; - case ')': - /* do the replacement */ - memset(pBuffer2,0,1023); - iRet = NXDget(handle, pBueffel,pBuffer2,1023); - if(iRet != NX_OK) - { - DeleteDynString(pReplaced); - return NULL; - } - DynStringConcat(pReplaced,pBuffer2); - iState = NORMAL; - break; - default: - pBueffel[iPos] = *pPtr; - iPos++; - if(iPos >= 1024) - { - NXIReportError(NXpData, - "ERROR: buffer overrun in NXDItextreplace"); - DeleteDynString(pReplaced); - return NULL; - } - break; - } + DynStringConcat(pReplaced, pBuffer2); + iState = NORMAL; + break; + default: + pBueffel[iPos] = *pPtr; + iPos++; + if (iPos >= 1024) { + NXReportError("ERROR: buffer overrun in NXDItextreplace"); + DeleteDynString(pReplaced); + return NULL; } - } + break; + } + } + } #ifdef DEFDEBUG - printf("Replacement result: %s\n",GetCharArray(pReplaced)); + printf("Replacement result: %s\n", GetCharArray(pReplaced)); #endif - return pReplaced; - } + return pReplaced; +} + /*------------------------------------------------------------------------*/ - NXstatus NXDdefget(NXdict handle, char *pKey, char *pBuffer, int iBufLen) - { - int status; - pDynString pRep = NULL; +NXstatus NXDdefget(NXdict handle, char *pKey, char *pBuffer, int iBufLen) +{ + int status; + pDynString pRep = NULL; + + status = NXDget(handle, pKey, pBuffer, iBufLen); + if (status != NX_OK) { + return status; + } + + pRep = NXDItextreplace(handle, pBuffer); + if (pRep) { + strncpy(pBuffer, GetCharArray(pRep), iBufLen); + status = NX_OK; + DeleteDynString(pRep); + } else { + status = NX_ERROR; + } + return status; +} - status = NXDget(handle,pKey,pBuffer,iBufLen); - if(status != NX_OK) - { - return status; - } - - pRep = NXDItextreplace(handle,pBuffer); - if(pRep) - { - strncpy(pBuffer,GetCharArray(pRep),iBufLen); - status = NX_OK; - DeleteDynString(pRep); - } - else - { - status = NX_ERROR; - } - return status; - } /*--------------------------------------------------------------------------*/ - NXstatus NXDtextreplace(NXdict handle, char *pDefString, - char *pBuffer, int iBufLen) - { - pDynString pResult = NULL; - char *pPtr = NULL; +NXstatus NXDtextreplace(NXdict handle, char *pDefString, + char *pBuffer, int iBufLen) +{ + pDynString pResult = NULL; + char *pPtr = NULL; - pResult = NXDItextreplace(handle,pDefString); - if(!pResult) - { - return NX_ERROR; - } + pResult = NXDItextreplace(handle, pDefString); + if (!pResult) { + return NX_ERROR; + } - /* copy results home */ - pPtr = GetCharArray(pResult); - strncpy(pBuffer,pPtr,iBufLen); - DeleteDynString(pResult); - return NX_OK; - } + /* copy results home */ + pPtr = GetCharArray(pResult); + strncpy(pBuffer, pPtr, iBufLen); + DeleteDynString(pResult); + return NX_OK; +} /*------------------- The Defintion String Parser -----------------------*/ /*------- Data structures */ - typedef struct { - char *pText; - int iCode; - } TokDat; +typedef struct { + char *pText; + int iCode; +} TokDat; #define TERMSDS 100 #define TERMVG 200 #define TERMLINK 300 - typedef struct { - char *pPtr; - char pToken[256]; - int iToken; - int iDepth; - int iMayCreate; - int iTerminal; - } ParDat; +typedef struct { + char *pPtr; + char pToken[256]; + int iToken; + int iDepth; + int iMayCreate; + int iTerminal; +} ParDat; - static void DummyError(void *pData, char *pError) - { - return; - } - typedef struct { - char name[256]; - char value[256]; - }AttItem; +static void DummyError(void *p, char *pError) +{ + return; +} +typedef struct { + char name[256]; + char value[256]; +} AttItem; /*---------------- Token name defines ---------------------------*/ #define DSLASH 0 @@ -640,1367 +583,1234 @@ /*----------------- Keywords ----------------------------------------*/ - static TokDat TokenList[12] = { - {"SDS",DSDS}, - {"NXLINK",DLINK}, - {"NXVGROUP",DGROUP}, - {"-dim",DDIM}, - {"-type",DTYPE}, - {"-rank",DRANK}, - {"-attr",DATTR}, - {"-chunk",CHUNK}, - {"-LZW",DLZW}, - {"-HUF",DHUF}, - {"-RLE",DRLE}, - {NULL,0} }; +static TokDat TokenList[12] = { + {"SDS", DSDS}, + {"NXLINK", DLINK}, + {"NXVGROUP", DGROUP}, + {"-dim", DDIM}, + {"-type", DTYPE}, + {"-rank", DRANK}, + {"-attr", DATTR}, + {"-chunk", CHUNK}, + {"-LZW", DLZW}, + {"-HUF", DHUF}, + {"-RLE", DRLE}, + {NULL, 0} +}; /*-----------------------------------------------------------------------*/ - static void NXDIDefToken(ParDat *sStat) - { - int i; - +static void NXDIDefToken(ParDat * sStat) +{ + int i; - sStat->pToken[0] = '\0'; - /* skip whitespace */ - while( (*(sStat->pPtr) == ' ') || (*(sStat->pPtr) == '\t') ) - { - sStat->pPtr++; - } + sStat->pToken[0] = '\0'; - /* check for special characters */ - if(*(sStat->pPtr) == '/') - { - sStat->iToken = DSLASH; - sStat->pToken[0] = *(sStat->pPtr); - sStat->pPtr++; - return; - } - else if(*(sStat->pPtr) == ',') - { - sStat->iToken = DKOMMA; - sStat->pToken[0] = *(sStat->pPtr); - sStat->pPtr++; - return; - } - else if(*(sStat->pPtr) == '\0') - { - sStat->iToken = DEND; - sStat->pToken[0] = *(sStat->pPtr); - sStat->pPtr++; - return; - } - else if(*(sStat->pPtr) == '{') - { - sStat->iToken = DOPEN; - sStat->pToken[0] = *(sStat->pPtr); - sStat->pPtr++; - return; - } - else if(*(sStat->pPtr) == '}') - { - sStat->iToken = DCLOSE; - sStat->pToken[0] = *(sStat->pPtr); - sStat->pPtr++; - return; - } - else - { - sStat->iToken = DWORD; - /* copy word to pToken */ - i = 0; - while( (*(sStat->pPtr) != ' ') && (*(sStat->pPtr) != '\t') && - (*(sStat->pPtr) != '/') && (*(sStat->pPtr) != '\0') && - (*(sStat->pPtr) != ',') && (*(sStat->pPtr) != '}') ) - { - sStat->pToken[i] = *(sStat->pPtr); - sStat->pPtr++; - i++; - } - sStat->pToken[i] = '\0'; + /* skip whitespace */ + while ((*(sStat->pPtr) == ' ') || (*(sStat->pPtr) == '\t')) { + sStat->pPtr++; + } + + /* check for special characters */ + if (*(sStat->pPtr) == '/') { + sStat->iToken = DSLASH; + sStat->pToken[0] = *(sStat->pPtr); + sStat->pPtr++; + return; + } else if (*(sStat->pPtr) == ',') { + sStat->iToken = DKOMMA; + sStat->pToken[0] = *(sStat->pPtr); + sStat->pPtr++; + return; + } else if (*(sStat->pPtr) == '\0') { + sStat->iToken = DEND; + sStat->pToken[0] = *(sStat->pPtr); + sStat->pPtr++; + return; + } else if (*(sStat->pPtr) == '{') { + sStat->iToken = DOPEN; + sStat->pToken[0] = *(sStat->pPtr); + sStat->pPtr++; + return; + } else if (*(sStat->pPtr) == '}') { + sStat->iToken = DCLOSE; + sStat->pToken[0] = *(sStat->pPtr); + sStat->pPtr++; + return; + } else { + sStat->iToken = DWORD; + /* copy word to pToken */ + i = 0; + while ((*(sStat->pPtr) != ' ') && (*(sStat->pPtr) != '\t') && + (*(sStat->pPtr) != '/') && (*(sStat->pPtr) != '\0') && + (*(sStat->pPtr) != ',') && (*(sStat->pPtr) != '}')) { + sStat->pToken[i] = *(sStat->pPtr); + sStat->pPtr++; + i++; + } + sStat->pToken[i] = '\0'; /*--------- try to find word in Tokenlist */ - for(i = 0; i < 11; i++) - { - if(strcmp(sStat->pToken,TokenList[i].pText) == 0) - { - sStat->iToken = TokenList[i].iCode; - break; - } - } - return; - } - /* not reached */ - return; - } -/*-----------------------------------------------------------------------*/ - static void NXDIAttValue(ParDat *sStat) - { - int i; - - - sStat->pToken[0] = '\0'; - - /* skip whitespace */ - while( (*(sStat->pPtr) == ' ') || (*(sStat->pPtr) == '\t') ) - { - sStat->pPtr++; - } - - if(*(sStat->pPtr) == ',') - { - sStat->iToken = DKOMMA; - sStat->pToken[0] = *(sStat->pPtr); - sStat->pPtr++; - return; - } - else if(*(sStat->pPtr) == '\0') - { - sStat->iToken = DEND; - sStat->pToken[0] = *(sStat->pPtr); - sStat->pPtr++; - return; - } - else if(*(sStat->pPtr) == '{') - { - sStat->iToken = DOPEN; - sStat->pToken[0] = *(sStat->pPtr); - sStat->pPtr++; - return; - } - else if(*(sStat->pPtr) == '}') - { - sStat->iToken = DCLOSE; - sStat->pToken[0] = *(sStat->pPtr); - sStat->pPtr++; - return; - } - else - { - sStat->iToken = DWORD; - /* copy word to pToken */ - i = 0; - while( (*(sStat->pPtr) != ' ') && (*(sStat->pPtr) != '\t') && - (*(sStat->pPtr) != '\0') && - (*(sStat->pPtr) != ',') && (*(sStat->pPtr) != '}') ) - { - sStat->pToken[i] = *(sStat->pPtr); - sStat->pPtr++; - i++; - } - sStat->pToken[i] = '\0'; - return; - } - /* not reached */ - return; - } - - -/*------------------------------------------------------------------------*/ - - int NXDIParsePath(NXhandle hfil, ParDat *pParse) - { - int iRet, iToken; - void (*ErrFunc)(void *pData, char *pErr); - char pName[132], pClass[132]; - char pError[256]; - - /* get the name */ - NXDIDefToken(pParse); /* next token */ - if( (pParse->iToken == DSDS) || (pParse->iToken == DGROUP) - || (pParse->iToken == DLINK) ) - { - /* put back & OK */ - pParse->pPtr -= strlen(pParse->pToken); - return NX_OK; - } - if(pParse->iToken != DWORD) - { - sprintf(pError,"ERROR: parse error at %s, expected vGroup name", - pParse->pToken); - NXIReportError(NXpData, pError); - return NX_ERROR; - } - strcpy(pName,pParse->pToken); - - /* now we expect a komma */ - NXDIDefToken(pParse); /* next token */ - if(pParse->iToken != DKOMMA) - { - sprintf(pError,"ERROR: parse error at %s, expected komma", - pParse->pToken); - NXIReportError(NXpData, pError); - return NX_ERROR; - } - - /* next must be the class */ - NXDIDefToken(pParse); /* next token */ - if(pParse->iToken != DWORD) - { - sprintf(pError,"ERROR: parse error at %s, expected vGroup class", - pParse->pToken); - NXIReportError(NXpData, pError); - return NX_ERROR; - } - strcpy(pClass,pParse->pToken); - - /* done reading, ACTION, first install dummy error handler */ - ErrFunc = NXIReportError; - NXMSetError(NXpData, DummyError); - - /* try opening vGroup */ - iRet = NXopengroup(hfil, pName, pClass); - NXMSetError(NXpData,ErrFunc); - if(iRet == NX_OK) - { - pParse->iDepth++; - return NX_OK; - } - else - { - /* we need to create it, if we may */ - if(pParse->iMayCreate) - { - iRet = NXmakegroup(hfil,pName,pClass); - if(iRet != NX_OK) - { - /* a comment on this one has already been written! */ - return iRet; - } - iRet = NXopengroup(hfil,pName,pClass); - if(iRet != NX_OK) - { - /* a comment on this one has already been written! */ - return iRet; - } - pParse->iDepth++; - return NX_OK; - } - else - { - /* this is an error */ - sprintf(pError,"ERROR: vGroup %s, %s NOT found",pName, pClass); - NXIReportError(NXpData,pError); - return NX_ERROR; - } - } - /* not reached */ - return NX_ERROR; - } - -/*------------------------------------------------------------------------*/ - - static int NXDIParseAttr(ParDat *pParse, int iList) - { - char pError[256]; - int iRet; - AttItem sAtt; - - /* a { is expected */ - NXDIDefToken(pParse); - if(pParse->iToken != DOPEN) - { - sprintf(pError,"ERROR: expected {, got %s",pParse->pToken); - NXIReportError(NXpData,pError); - return NX_ERROR; - } - - /* a word is expected */ - NXDIDefToken(pParse); - if(pParse->iToken != DWORD) - { - sprintf(pError,"ERROR: expected attribute name, got %s",pParse->pToken); - NXIReportError(NXpData,pError); - return NX_ERROR; - } - strcpy(sAtt.name,pParse->pToken); - - /* a , is expected */ - NXDIDefToken(pParse); - if(pParse->iToken != DKOMMA) - { - sprintf(pError,"ERROR: expected , , got %s",pParse->pToken); - NXIReportError(NXpData,pError); - return NX_ERROR; - } - - /* a word is expected */ - NXDIAttValue(pParse); - if(pParse->iToken != DWORD) - { - sprintf(pError,"ERROR: expected attribute value, got %s",pParse->pToken); - NXIReportError(NXpData,pError); - return NX_ERROR; - } - strcpy(sAtt.value,pParse->pToken); - - /* a } is expected */ - NXDIDefToken(pParse); - if(pParse->iToken != DCLOSE) - { - sprintf(pError,"ERROR: expected }, got %s",pParse->pToken); - NXIReportError(NXpData,pError); - return NX_ERROR; - } - - /* enter into list */ - LLDnodeAppendFrom(iList,&sAtt); - return NX_OK; - } - -/*------------------------------------------------------------------------*/ - static int NXDIParseDim(ParDat *pParse, int *iDim) - { - char pError[256]; - int iRet, i; - - /* initialise dimensions to 0 */ - for(i = 0; i < NX_MAXRANK; i++) - { - iDim[i] = 0; - } - - NXDIDefToken(pParse); - if(pParse->iToken != DOPEN) - { - sprintf(pError,"ERROR: expected {, got %s",pParse->pToken); - NXIReportError(NXpData,pError); - return NX_ERROR; - } - - i = 0; - while(pParse->iToken != DCLOSE) - { - /* get a number */ - NXDIDefToken(pParse); - if(pParse->iToken != DWORD) - { - sprintf(pError,"ERROR: expected number, got %s",pParse->pToken); - NXIReportError(NXpData,pError); - return NX_ERROR; - } - iDim[i] = atoi(pParse->pToken); - i++; - /* next must be close of komma */ - NXDIDefToken(pParse); - if( (pParse->iToken != DKOMMA) && (pParse->iToken != DCLOSE) ) - { - sprintf(pError,"ERROR: expected , or }, got %s",pParse->pToken); - NXIReportError(NXpData,pError); - return NX_ERROR; - } - if(pParse->iToken == DCLOSE) - { - break; - } - } - return NX_OK; - } -/*------------------------------------------------------------------------*/ - static TokDat tDatType[] = { - {"DFNT_FLOAT32",NX_FLOAT32}, - {"DFNT_FLOAT64",NX_FLOAT64}, - {"DFNT_INT8",NX_INT8}, - {"DFNT_UINT8",NX_UINT8}, - {"DFNT_INT16",NX_INT16}, - {"DFNT_UINT16",NX_UINT16}, - {"DFNT_INT32",NX_INT32}, - {"DFNT_UINT32",NX_UINT32}, - {"DFNT_CHAR",NX_CHAR}, - {"NX_FLOAT32",NX_FLOAT32}, - {"NX_FLOAT64",NX_FLOAT64}, - {"NX_INT8",NX_INT8}, - {"NX_UINT8",NX_UINT8}, - {"NX_INT16",NX_INT16}, - {"NX_UINT16",NX_UINT16}, - {"NX_INT32",NX_INT32}, - {"NX_UINT32",NX_UINT32}, - {"NX_CHAR",NX_CHAR}, - {NULL,-122} }; - - - - static int NXDIParseType(ParDat *pParse, int *iType) - { - char pError[256]; - int i = 0; - - NXDIDefToken(pParse); - if(pParse->iToken != DWORD) - { - sprintf(pError,"ERROR: expected data type, got %s", pParse->pToken); - NXIReportError(NXpData,pError); - return NX_ERROR; + for (i = 0; i < 11; i++) { + if (strcmp(sStat->pToken, TokenList[i].pText) == 0) { + sStat->iToken = TokenList[i].iCode; + break; } - - /* try to interpret data type */ - while(tDatType[i].iCode > 0) { - if(strcmp(tDatType[i].pText,pParse->pToken) == 0) - { - *iType = tDatType[i].iCode; - return NX_OK; - } - i++; - } - /* if we are here, the data type has not been recognized. Reason for - some boring error reporting code - */ - sprintf(pError,"ERROR: %s not recognized as valid data type", - pParse->pToken); - NXIReportError(NXpData,pError); - return NX_ERROR; - } - -/*-------------------------------------------------------------------------*/ - static int NXDIParseSDS(NXhandle hfil, ParDat *pParse) - { - int iType = NX_FLOAT32; - int iRank = 1; - int iCompress = NX_COMP_NONE; - int iDim[NX_MAXRANK], iChunk[NX_MAXRANK]; - int iList, iChunkDefined = 0 ; - int iRet, iStat, i; - char pError[256]; - char pName[NX_MAXNAMELEN]; - void (*ErrFunc)(void *pData, char *pErr); - AttItem sAtt; - - - iDim[0] = 1; - /* first find the name */ - NXDIDefToken(pParse); - if(pParse->iToken != DWORD) - { - sprintf(pError,"ERROR: parsing, expected name, got %s", - pParse->pToken); - NXIReportError(NXpData,pError); - return NX_ERROR; - } - strcpy(pName,pParse->pToken); - - /* create the attribute list */ - iList = LLDcreate(sizeof(AttItem)); - if(iList < 0) - { - NXIReportError(NXpData, "ERROR: cannot create list in NXDIParseSDS"); - return NX_ERROR; - } - - NXDIDefToken(pParse); - while(pParse->iToken != DEND) - { - switch(pParse->iToken) - { - case DRANK: /* rank */ - NXDIDefToken(pParse); /* advance */ - if(pParse->iToken != DWORD) - { - sprintf(pError, - "ERROR: expected int, got %s", pParse->pToken); - NXIReportError(NXpData,pError); - LLDdelete(iList); - return NX_ERROR; - } - iRank = atoi(pParse->pToken); - break; - case CHUNK: /* chunk size for compression */ - iRet = NXDIParseDim(pParse, iChunk); - if(iRet == NX_ERROR) - { - LLDdelete(iList); - return iRet; - } - iChunkDefined = 1; - break; - case DDIM: - iRet = NXDIParseDim(pParse, iDim); - if(iRet == NX_ERROR) - { - LLDdelete(iList); - return iRet; - } - break; - case DTYPE: - iRet = NXDIParseType(pParse, &iType); - if(iRet == NX_ERROR) - { - LLDdelete(iList); - return iRet; - } - break; - case DATTR: - iRet = NXDIParseAttr(pParse, iList); - if(iRet == NX_ERROR) - { - LLDdelete(iList); - return iRet; - } - break; - case DLZW: - iCompress = NX_COMP_LZW; - break; - case DRLE: - iCompress = NX_COMP_RLE; - break; - case DHUF: - iCompress = NX_COMP_HUF; - break; - case DEND: - break; - default: - sprintf(pError,"ERROR: cannot identify token %s", - pParse->pToken); - NXIReportError(NXpData, pError); - LLDdelete(iList); - return NX_ERROR; - - } - NXDIDefToken(pParse); - } - - /* whew! got all information for doing the SDS - However, if the chunk sizes for compression have not - been set, default them to the dimensions of the data set - */ - if(iChunkDefined == 0) - { - for(i = 0; i < iRank; i++) - { - iChunk[i] = iDim[i]; - } - } - if(iChunk[0] < 0) { - iChunk[0] = 1; - } - - /* first install dummy error handler, try open it, then - deinstall again and create if allowed - */ - ErrFunc = NXIReportError; - NXMSetError(NXpData, DummyError); - - /* try opening SDS */ - iRet = NXopendata(hfil, pName); - NXMSetError(NXpData,ErrFunc); - if(iRet == NX_OK) - { - LLDdelete(iList); - return NX_OK; - } - else - { - /* we need to create it, if we may */ - if(pParse->iMayCreate) - { - iRet = NXcompmakedata(hfil,pName,iType, iRank,iDim, - iCompress,iChunk); - if(iRet != NX_OK) - { - /* a comment on this one has already been written! */ - LLDdelete(iList); - return iRet; - } - iRet = NXopendata(hfil,pName); - if(iRet != NX_OK) - { - /* a comment on this one has already been written! */ - LLDdelete(iList); - return iRet; - } - - /* put attributes in */ - iRet = LLDnodePtr2First(iList); - while(iRet != 0) - { - LLDnodeDataTo(iList,&sAtt); - iStat = NXputattr(hfil,sAtt.name, - sAtt.value,strlen(sAtt.value),NX_CHAR); - if(iStat != NX_OK) - { - /* NeXus already complained bitterly */ - LLDdelete(iList); - return iStat; - } - iRet = LLDnodePtr2Next(iList); - } - LLDdelete(iList); - return NX_OK; - } - else - { - /* this is an error */ - sprintf(pError,"ERROR: SDS %s NOT found",pName); - NXIReportError(NXpData,pError); - LLDdelete(iList); - return NX_ERROR; - } - } - return NX_OK; - } -/*------------------------------------------------------------------------*/ - static int NXDIParseLink(NXhandle hfil, NXdict pDict,ParDat *pParse) - { - char pError[256]; - int i, iRet; - - /* need one word of alias */ - NXDIDefToken(pParse); - if(pParse->iToken != DCLOSE) - { - sprintf(pError,"ERROR: expected alias , got %s",pParse->pToken); - NXIReportError(NXpData,pError); - return NX_ERROR; - } - - /* move back in hierarchy */ - for(i = 0; i < pParse->iDepth; i++) - { - iRet = NXclosegroup(hfil); - if(iRet == NX_ERROR) - { - return NX_ERROR; - } - } - - /* open the link instead */ - return NXDopenalias(hfil, pDict, pParse->pToken); - - } -/*------------------------------------------------------------------------*/ - int NXDIDefParse(NXhandle hFil, NXdict pDict, ParDat *pParse) - { - int iRet; - char pError[256]; - - pParse->iToken = -1; - while(pParse->iToken != DEND) - { - NXDIDefToken(pParse); /* next token */ - switch(pParse->iToken) - { - case DEND: - break; - case DSLASH: - iRet = NXDIParsePath(hFil, pParse); - if(iRet == NX_ERROR) - { - return NX_ERROR; - } - break; - case DSDS: - iRet = NXDIParseSDS(hFil, pParse); - if(iRet == NX_ERROR) - { - return NX_ERROR; - } - pParse->iTerminal = TERMSDS; - break; - case DLINK: - iRet = NXDIParseLink(hFil,pDict, pParse); - if(iRet == NX_ERROR) - { - return NX_ERROR; - } - pParse->iTerminal = TERMLINK; - break; - case DGROUP: - pParse->iTerminal = TERMVG; - return NX_OK; - default: - sprintf(pError, - "ERROR: Definition String parse error: %s not permitted here", - pParse->pToken); - NXIReportError(NXpData,pError); - return NX_ERROR; - break; - } - } - return NX_OK; } -/*----------------------------------------------------------------------*/ - NXstatus NXDIUnwind(NXhandle hFil, int iDepth) - { - int i, iRet; - - for(i = 0; i < iDepth; i++) - { - iRet = NXclosegroup(hFil); - if(iRet != NX_OK) - { - return NX_ERROR; - } - } - return NX_OK; + return; } -/*-------------------- The Data Transfer Functions ----------------------*/ - NXstatus NXDopendef(NXhandle hfil, NXdict dict, char *pDef) - { - NXdict pDict; - ParDat pParse; - int iRet, i, iStat; + /* not reached */ + return; +} - pDict = NXDIAssert(dict); - - /* parse and act on definition string */ - pParse.iMayCreate = 1; - pParse.pPtr = pDef; - pParse.iDepth = 0; - iRet = NXDIDefParse(hfil,pDict,&pParse); - if(iRet == NX_ERROR) - { - /* unwind and throw up */ - iRet = NXDIUnwind(hfil,pParse.iDepth); - return NX_ERROR; - } - - return iRet; - } -/*------------------------------------------------------------------------*/ - NXstatus NXDopenalias(NXhandle hfil, NXdict dict, char *pAlias) - { - NXdict pDict; - int iRet; - char pDefinition[2048]; - pDynString pReplaced = NULL; - - pDict = NXDIAssert(dict); - - /* get Definition String */ - iRet = NXDget(pDict,pAlias,pDefinition,2047); - if(iRet != NX_OK) - { - sprintf(pDefinition,"ERROR: alias %s not recognized",pAlias); - NXIReportError(NXpData,pDefinition); - return NX_ERROR; - } - - /* do the text replacement */ - pReplaced = NXDItextreplace(dict,pDefinition); - if(!pReplaced) - { - return NX_ERROR; - } - - /* call NXDopendef */ - iRet = NXDopendef(hfil,dict,GetCharArray(pReplaced)); - DeleteDynString(pReplaced); - return iRet; - } -/*------------------------------------------------------------------------*/ - NXstatus NXDputdef(NXhandle hFil, NXdict dict, char *pDef, void *pData) - { - NXdict pDict; - ParDat pParse; - int iRet, i, iStat; - - pDict = NXDIAssert(dict); - - /* parse and act on definition string */ - pParse.iMayCreate = 1; - pParse.pPtr = pDef; - pParse.iDepth = 0; -#ifdef DEFDEBUG - printf("Putting: %s\n",pDef); -#endif - iRet = NXDIDefParse(hFil,pDict,&pParse); - if(iRet == NX_ERROR) - { - NXDIUnwind(hFil,pParse.iDepth); - return NX_ERROR; - } - - - /* only SDS can be written */ - if(pParse.iTerminal != TERMSDS) - { - NXIReportError(NXpData, - "ERROR: can only write to an SDS!"); - iStat = NX_ERROR; - } - else - { - /* the SDS should be open by now, write it */ - iStat = NXputdata(hFil, pData); - iRet = NXclosedata(hFil); - } +/*-----------------------------------------------------------------------*/ +static void NXDIAttValue(ParDat * sStat) +{ + int i; - /* rewind the hierarchy */ - iRet = NXDIUnwind(hFil,pParse.iDepth); - if(iRet != NX_OK) - { - return NX_ERROR; - } - return iStat; - } -/*------------------------------------------------------------------------*/ - NXstatus NXDputalias(NXhandle hFil, NXdict dict, char *pAlias, void *pData) - { - NXdict pDict; - int iRet; - char pDefinition[2048]; - pDynString pReplaced = NULL; + sStat->pToken[0] = '\0'; - pDict = NXDIAssert(dict); - - /* get Definition String */ - iRet = NXDget(pDict,pAlias,pDefinition,2047); - if(iRet != NX_OK) - { - sprintf(pDefinition,"ERROR: alias %s not recognized",pAlias); - NXIReportError(NXpData,pDefinition); - return NX_ERROR; - } - - /* do text replacement */ - pReplaced = NXDItextreplace(dict,pDefinition); - if(!pReplaced) - { - return NX_ERROR; - } - - /* call NXDputdef */ - iRet = NXDputdef(hFil,dict,GetCharArray(pReplaced),pData); - DeleteDynString(pReplaced); - return iRet; - } -/*------------------------------------------------------------------------*/ - NXstatus NXDgetdef(NXhandle hFil, NXdict dict, char *pDef, void *pData) - { - NXdict pDict; - ParDat pParse; - int iRet, i, iStat; - - pDict = NXDIAssert(dict); - - /* parse and act on definition string */ - pParse.iMayCreate = 0; - pParse.pPtr = pDef; - pParse.iDepth = 0; -#ifdef DEFDEBUG - printf("Getting: %s\n",pDef); -#endif - iRet = NXDIDefParse(hFil,pDict,&pParse); - if(iRet == NX_ERROR) - { - /* unwind and throw up */ - NXDIUnwind(hFil,pParse.iDepth); - return NX_ERROR; - } - - - /* only SDS can be written */ - if(pParse.iTerminal != TERMSDS) - { - NXIReportError(NXpData, - "ERROR: can only write to an SDS!"); - iStat = NX_ERROR; - } - else - { - /* the SDS should be open by now, read it */ - iStat = NXgetdata(hFil, pData); - iRet = NXclosedata(hFil); - } - - - /* rewind the hierarchy */ - iRet = NXDIUnwind(hFil,pParse.iDepth); - if(iRet != NX_OK) - { - return NX_ERROR; - } - return iStat; - } - -/*------------------------------------------------------------------------*/ - NXstatus NXDgetalias(NXhandle hFil, NXdict dict, char *pAlias, void *pData) - { - NXdict pDict; - int iRet; - char pDefinition[2048]; - pDynString pReplaced = NULL; - - pDict = NXDIAssert(dict); - - /* get Definition String */ - iRet = NXDget(pDict,pAlias,pDefinition,2047); - if(iRet != NX_OK) - { - sprintf(pDefinition,"ERROR: alias %s not recognized",pAlias); - NXIReportError(NXpData,pDefinition); - return NX_ERROR; - } - - /* do text replacement */ - pReplaced = NXDItextreplace(dict,pDefinition); - if(!pReplaced) - { - return NX_ERROR; - } - - /* call NXDgetdef */ - iRet = NXDgetdef(hFil,dict,GetCharArray(pReplaced),pData); - DeleteDynString(pReplaced); - return iRet; - } -/*------------------------------------------------------------------------*/ - - NXstatus NXDinfodef(NXhandle hFil, NXdict dict, char *pDef, int *rank, - int dimension[], int *iType) - { - NXdict pDict; - ParDat pParse; - int iRet, i, iStat; - - pDict = NXDIAssert(dict); - - /* parse and act on definition string */ - pParse.iMayCreate = 0; - pParse.pPtr = pDef; - pParse.iDepth = 0; -#ifdef DEFDEBUG - printf("Getting: %s\n",pDef); -#endif - iRet = NXDIDefParse(hFil,pDict,&pParse); - if(iRet == NX_ERROR) - { - /* unwind and throw up */ - NXDIUnwind(hFil,pParse.iDepth); - return NX_ERROR; - } - - - /* only SDS can be written */ - if(pParse.iTerminal != TERMSDS) - { - NXIReportError(NXpData, - "ERROR: can only write to an SDS!"); - iStat = NX_ERROR; - } - else - { - /* the SDS should be open by now, read it */ - iStat = NXgetinfo(hFil, rank,dimension, iType); - iRet = NXclosedata(hFil); - } - - - /* rewind the hierarchy */ - iRet = NXDIUnwind(hFil,pParse.iDepth); - if(iRet != NX_OK) - { - return NX_ERROR; - } - return iStat; - } - -/*------------------------------------------------------------------------*/ - - NXstatus NXDinfoalias(NXhandle hFil, NXdict dict, char *pAlias, int *rank, - int dimension[], int *iType) - { - NXdict pDict; - int iRet; - char pDefinition[2048]; - pDynString pReplaced = NULL; - - pDict = NXDIAssert(dict); - - /* get Definition String */ - iRet = NXDget(pDict,pAlias,pDefinition,2047); - if(iRet != NX_OK) - { - sprintf(pDefinition,"ERROR: alias %s not recognized",pAlias); - NXIReportError(NXpData,pDefinition); - return NX_ERROR; - } - - /* do text replacement */ - pReplaced = NXDItextreplace(dict,pDefinition); - if(!pReplaced) - { - return NX_ERROR; - } - - /* call NXDgetdef */ - iRet = NXDinfodef(hFil,dict,GetCharArray(pReplaced),rank,dimension,iType); - DeleteDynString(pReplaced); - return iRet; + /* skip whitespace */ + while ((*(sStat->pPtr) == ' ') || (*(sStat->pPtr) == '\t')) { + sStat->pPtr++; } + if (*(sStat->pPtr) == ',') { + sStat->iToken = DKOMMA; + sStat->pToken[0] = *(sStat->pPtr); + sStat->pPtr++; + return; + } else if (*(sStat->pPtr) == '\0') { + sStat->iToken = DEND; + sStat->pToken[0] = *(sStat->pPtr); + sStat->pPtr++; + return; + } else if (*(sStat->pPtr) == '{') { + sStat->iToken = DOPEN; + sStat->pToken[0] = *(sStat->pPtr); + sStat->pPtr++; + return; + } else if (*(sStat->pPtr) == '}') { + sStat->iToken = DCLOSE; + sStat->pToken[0] = *(sStat->pPtr); + sStat->pPtr++; + return; + } else { + sStat->iToken = DWORD; + /* copy word to pToken */ + i = 0; + while ((*(sStat->pPtr) != ' ') && (*(sStat->pPtr) != '\t') && + (*(sStat->pPtr) != '\0') && + (*(sStat->pPtr) != ',') && (*(sStat->pPtr) != '}')) { + sStat->pToken[i] = *(sStat->pPtr); + sStat->pPtr++; + i++; + } + sStat->pToken[i] = '\0'; + return; + } + /* not reached */ + return; +} + + /*------------------------------------------------------------------------*/ - NXstatus NXDdeflink(NXhandle hFil, NXdict dict, - char *pTarget, char *pVictim) - { - NXdict pDict; - ParDat pParseT, pParseV; - int iRet, i, iStat; - NXlink sLink; - pDict = NXDIAssert(dict); +int NXDIParsePath(NXhandle hfil, ParDat * pParse) +{ + int iRet, iToken; + char pName[132], pClass[132]; + char pError[256]; + void *pData = NULL; - -#ifdef DEFDEBUG - printf("Linking: %s\n",pVictim); - printf("To: %s\n", pTarget); -#endif - - - /* parse Victim */ - pParseV.iMayCreate = 0; - pParseV.pPtr = pVictim; - pParseV.iDepth = 0; - iRet = NXDIDefParse(hFil,pDict,&pParseV); - if(iRet == NX_ERROR) - { - /* unwind and throw up */ - NXDIUnwind(hFil,pParseV.iDepth); - return NX_ERROR; - } - /* get link data */ - if(pParseV.iTerminal == TERMSDS) - { - NXgetdataID(hFil,&sLink); - iRet = NXclosedata(hFil); - if(iRet != NX_OK) - { - /* unwind and throw up */ - NXDIUnwind(hFil,pParseV.iDepth); - return NX_ERROR; - } - } - else if(pParseV.iTerminal == TERMVG) - { - NXgetgroupID(hFil,&sLink); - } - else - { - assert(0); /* serious programming error */ - } - /* Unwind */ - iRet = NXDIUnwind(hFil,pParseV.iDepth); - if(iRet != NX_OK) - { - return NX_ERROR; - } - - /* parse Target */ - pParseT.iMayCreate = 1; - pParseT.pPtr = pTarget; - pParseT.iDepth = 0; - iRet = NXDIDefParse(hFil,pDict,&pParseT); - if(iRet == NX_ERROR) - { - /* unwind and throw up */ - NXDIUnwind(hFil,pParseT.iDepth); - return NX_ERROR; - } - /* check it being a vGroup! */ - if(pParseT.iTerminal != TERMVG) - { - NXIReportError(NXpData,"ERROR: can link only into a vGroup"); - NXDIUnwind(hFil,pParseT.iDepth); - return NX_ERROR; - } - - /* link, finally */ - iRet = NXmakelink(hFil,&sLink); - /* Unwind anyway */ - iStat = NXDIUnwind(hFil,pParseT.iDepth); - if(iStat != NX_OK) - { - return NX_ERROR; - } - return iStat; + /* get the name */ + NXDIDefToken(pParse); /* next token */ + if ((pParse->iToken == DSDS) || (pParse->iToken == DGROUP) + || (pParse->iToken == DLINK)) { + /* put back & OK */ + pParse->pPtr -= strlen(pParse->pToken); + return NX_OK; } -/*--------------------------------------------------------------------------*/ - NXstatus NXDaliaslink(NXhandle hFil, NXdict dict, - char *pTarget, char *pVictim) - { - char pTargetDef[2048], pVictimDef[2048]; - int iRet; - NXdict pDict; - pDynString pRep1 = NULL, pRep2 = NULL; - - pDict = NXDIAssert(dict); - - /* get Target Definition String */ - iRet = NXDget(pDict,pTarget,pTargetDef,2047); - if(iRet != NX_OK) - { - sprintf(pTargetDef,"ERROR: alias %s not recognized",pTarget); - NXIReportError(NXpData,pTargetDef); - return NX_ERROR; - } - - /* get Victim definition string */ - iRet = NXDget(pDict,pVictim,pVictimDef,2047); - if(iRet != NX_OK) - { - sprintf(pTargetDef,"ERROR: alias %s not recognized",pTarget); - NXIReportError(NXpData,pTargetDef); - return NX_ERROR; - } - - /* do replacements */ - pRep1 = NXDItextreplace(dict,pTargetDef); - pRep2 = NXDItextreplace(dict,pVictimDef); - if( (!pRep1) || (!pRep2) ) - { - if(pRep1) - DeleteDynString(pRep1); - if(pRep2) - DeleteDynString(pRep2); - return NX_ERROR; - } - - /* call NXdeflin */ - iRet = NXDdeflink(hFil,pDict,GetCharArray(pRep1),GetCharArray(pRep2)); - DeleteDynString(pRep1); - DeleteDynString(pRep2); - return iRet; + if (pParse->iToken != DWORD) { + sprintf(pError, "ERROR: parse error at %s, expected vGroup name", + pParse->pToken); + NXReportError(pError); + return NX_ERROR; } + strcpy(pName, pParse->pToken); + + /* now we expect a komma */ + NXDIDefToken(pParse); /* next token */ + if (pParse->iToken != DKOMMA) { + sprintf(pError, "ERROR: parse error at %s, expected komma", + pParse->pToken); + NXReportError(pError); + return NX_ERROR; + } + + /* next must be the class */ + NXDIDefToken(pParse); /* next token */ + if (pParse->iToken != DWORD) { + sprintf(pError, "ERROR: parse error at %s, expected vGroup class", + pParse->pToken); + NXReportError(pError); + return NX_ERROR; + } + strcpy(pClass, pParse->pToken); + + /* done reading, ACTION, first install dummy error handler */ + NXMDisableErrorReporting(); + + /* try opening vGroup */ + iRet = NXopengroup(hfil, pName, pClass); + NXMEnableErrorReporting(); + if (iRet == NX_OK) { + pParse->iDepth++; + return NX_OK; + } else { + /* we need to create it, if we may */ + if (pParse->iMayCreate) { + iRet = NXmakegroup(hfil, pName, pClass); + if (iRet != NX_OK) { + /* a comment on this one has already been written! */ + return iRet; + } + iRet = NXopengroup(hfil, pName, pClass); + if (iRet != NX_OK) { + /* a comment on this one has already been written! */ + return iRet; + } + pParse->iDepth++; + return NX_OK; + } else { + /* this is an error */ + sprintf(pError, "ERROR: vGroup %s, %s NOT found", pName, pClass); + NXReportError(pError); + return NX_ERROR; + } + } + /* not reached */ + return NX_ERROR; +} + +/*------------------------------------------------------------------------*/ + +static int NXDIParseAttr(ParDat * pParse, int iList) +{ + char pError[256]; + int iRet; + AttItem sAtt; + + /* a { is expected */ + NXDIDefToken(pParse); + if (pParse->iToken != DOPEN) { + sprintf(pError, "ERROR: expected {, got %s", pParse->pToken); + NXReportError(pError); + return NX_ERROR; + } + + /* a word is expected */ + NXDIDefToken(pParse); + if (pParse->iToken != DWORD) { + sprintf(pError, "ERROR: expected attribute name, got %s", + pParse->pToken); + NXReportError(pError); + return NX_ERROR; + } + strcpy(sAtt.name, pParse->pToken); + + /* a , is expected */ + NXDIDefToken(pParse); + if (pParse->iToken != DKOMMA) { + sprintf(pError, "ERROR: expected , , got %s", pParse->pToken); + NXReportError(pError); + return NX_ERROR; + } + + /* a word is expected */ + NXDIAttValue(pParse); + if (pParse->iToken != DWORD) { + sprintf(pError, "ERROR: expected attribute value, got %s", + pParse->pToken); + NXReportError(pError); + return NX_ERROR; + } + strcpy(sAtt.value, pParse->pToken); + + /* a } is expected */ + NXDIDefToken(pParse); + if (pParse->iToken != DCLOSE) { + sprintf(pError, "ERROR: expected }, got %s", pParse->pToken); + NXReportError(pError); + return NX_ERROR; + } + + /* enter into list */ + LLDnodeAppendFrom(iList, &sAtt); + return NX_OK; +} + +/*------------------------------------------------------------------------*/ +static int NXDIParseDim(ParDat * pParse, int *iDim) +{ + char pError[256]; + int iRet, i; + + /* initialise dimensions to 0 */ + for (i = 0; i < NX_MAXRANK; i++) { + iDim[i] = 0; + } + + NXDIDefToken(pParse); + if (pParse->iToken != DOPEN) { + sprintf(pError, "ERROR: expected {, got %s", pParse->pToken); + NXReportError(pError); + return NX_ERROR; + } + + i = 0; + while (pParse->iToken != DCLOSE) { + /* get a number */ + NXDIDefToken(pParse); + if (pParse->iToken != DWORD) { + sprintf(pError, "ERROR: expected number, got %s", pParse->pToken); + NXReportError(pError); + return NX_ERROR; + } + iDim[i] = atoi(pParse->pToken); + i++; + /* next must be close of komma */ + NXDIDefToken(pParse); + if ((pParse->iToken != DKOMMA) && (pParse->iToken != DCLOSE)) { + sprintf(pError, "ERROR: expected , or }, got %s", pParse->pToken); + NXReportError( pError); + return NX_ERROR; + } + if (pParse->iToken == DCLOSE) { + break; + } + } + return NX_OK; +} + +/*------------------------------------------------------------------------*/ +static TokDat tDatType[] = { + {"DFNT_FLOAT32", NX_FLOAT32}, + {"DFNT_FLOAT64", NX_FLOAT64}, + {"DFNT_INT8", NX_INT8}, + {"DFNT_UINT8", NX_UINT8}, + {"DFNT_INT16", NX_INT16}, + {"DFNT_UINT16", NX_UINT16}, + {"DFNT_INT32", NX_INT32}, + {"DFNT_UINT32", NX_UINT32}, + {"DFNT_CHAR", NX_CHAR}, + {"NX_FLOAT32", NX_FLOAT32}, + {"NX_FLOAT64", NX_FLOAT64}, + {"NX_INT8", NX_INT8}, + {"NX_UINT8", NX_UINT8}, + {"NX_INT16", NX_INT16}, + {"NX_UINT16", NX_UINT16}, + {"NX_INT32", NX_INT32}, + {"NX_UINT32", NX_UINT32}, + {"NX_CHAR", NX_CHAR}, + {NULL, -122} +}; + + + +static int NXDIParseType(ParDat * pParse, int *iType) +{ + char pError[256]; + int i = 0; + + NXDIDefToken(pParse); + if (pParse->iToken != DWORD) { + sprintf(pError, "ERROR: expected data type, got %s", pParse->pToken); + NXReportError(pError); + return NX_ERROR; + } + + /* try to interpret data type */ + while (tDatType[i].iCode > 0) { + if (strcmp(tDatType[i].pText, pParse->pToken) == 0) { + *iType = tDatType[i].iCode; + return NX_OK; + } + i++; + } + /* if we are here, the data type has not been recognized. Reason for + some boring error reporting code + */ + sprintf(pError, "ERROR: %s not recognized as valid data type", + pParse->pToken); + NXReportError(pError); + return NX_ERROR; +} + /*-------------------------------------------------------------------------*/ - static void SNXFormatTime(char *pBuffer, int iBufLen) - { - time_t iDate; - struct tm *psTime; +static int NXDIParseSDS(NXhandle hfil, ParDat * pParse) +{ + int iType = NX_FLOAT32; + int iRank = 1; + int iCompress = NX_COMP_NONE; + int iDim[NX_MAXRANK], iChunk[NX_MAXRANK]; + int iList, iChunkDefined = 0; + int iRet, iStat, i; + char pError[256]; + char pName[NX_MAXNAMELEN]; + AttItem sAtt; + + + iDim[0] = 1; + /* first find the name */ + NXDIDefToken(pParse); + if (pParse->iToken != DWORD) { + sprintf(pError, "ERROR: parsing, expected name, got %s", + pParse->pToken); + NXReportError(pError); + return NX_ERROR; + } + strcpy(pName, pParse->pToken); + + /* create the attribute list */ + iList = LLDcreate(sizeof(AttItem)); + if (iList < 0) { + NXReportError("ERROR: cannot create list in NXDIParseSDS"); + return NX_ERROR; + } + + NXDIDefToken(pParse); + while (pParse->iToken != DEND) { + switch (pParse->iToken) { + case DRANK: /* rank */ + NXDIDefToken(pParse); /* advance */ + if (pParse->iToken != DWORD) { + sprintf(pError, "ERROR: expected int, got %s", pParse->pToken); + NXReportError(pError); + LLDdelete(iList); + return NX_ERROR; + } + iRank = atoi(pParse->pToken); + break; + case CHUNK: /* chunk size for compression */ + iRet = NXDIParseDim(pParse, iChunk); + if (iRet == NX_ERROR) { + LLDdelete(iList); + return iRet; + } + iChunkDefined = 1; + break; + case DDIM: + iRet = NXDIParseDim(pParse, iDim); + if (iRet == NX_ERROR) { + LLDdelete(iList); + return iRet; + } + break; + case DTYPE: + iRet = NXDIParseType(pParse, &iType); + if (iRet == NX_ERROR) { + LLDdelete(iList); + return iRet; + } + break; + case DATTR: + iRet = NXDIParseAttr(pParse, iList); + if (iRet == NX_ERROR) { + LLDdelete(iList); + return iRet; + } + break; + case DLZW: + iCompress = NX_COMP_LZW; + break; + case DRLE: + iCompress = NX_COMP_RLE; + break; + case DHUF: + iCompress = NX_COMP_HUF; + break; + case DEND: + break; + default: + sprintf(pError, "ERROR: cannot identify token %s", pParse->pToken); + NXReportError(pError); + LLDdelete(iList); + return NX_ERROR; + + } + NXDIDefToken(pParse); + } + + /* whew! got all information for doing the SDS + However, if the chunk sizes for compression have not + been set, default them to the dimensions of the data set + */ + if (iChunkDefined == 0) { + for (i = 0; i < iRank; i++) { + iChunk[i] = iDim[i]; + } + } + if (iChunk[0] < 0) { + iChunk[0] = 1; + } + + /* first install dummy error handler, try open it, then + deinstall again and create if allowed + */ + NXMDisableErrorReporting(); + + /* try opening SDS */ + iRet = NXopendata(hfil, pName); + NXMEnableErrorReporting(); + if (iRet == NX_OK) { + LLDdelete(iList); + return NX_OK; + } else { + /* we need to create it, if we may */ + if (pParse->iMayCreate) { + iRet = NXcompmakedata(hfil, pName, iType, iRank, iDim, + iCompress, iChunk); + if (iRet != NX_OK) { + /* a comment on this one has already been written! */ + LLDdelete(iList); + return iRet; + } + iRet = NXopendata(hfil, pName); + if (iRet != NX_OK) { + /* a comment on this one has already been written! */ + LLDdelete(iList); + return iRet; + } + + /* put attributes in */ + iRet = LLDnodePtr2First(iList); + while (iRet != 0) { + LLDnodeDataTo(iList, &sAtt); + iStat = NXputattr(hfil, sAtt.name, + sAtt.value, strlen(sAtt.value), NX_CHAR); + if (iStat != NX_OK) { + /* NeXus already complained bitterly */ + LLDdelete(iList); + return iStat; + } + iRet = LLDnodePtr2Next(iList); + } + LLDdelete(iList); + return NX_OK; + } else { + /* this is an error */ + sprintf(pError, "ERROR: SDS %s NOT found", pName); + NXReportError(pError); + LLDdelete(iList); + return NX_ERROR; + } + } + return NX_OK; +} + +/*------------------------------------------------------------------------*/ +static int NXDIParseLink(NXhandle hfil, NXdict pDict, ParDat * pParse) +{ + char pError[256]; + int i, iRet; + + /* need one word of alias */ + NXDIDefToken(pParse); + if (pParse->iToken != DCLOSE) { + sprintf(pError, "ERROR: expected alias , got %s", pParse->pToken); + NXReportError(pError); + return NX_ERROR; + } + + /* move back in hierarchy */ + for (i = 0; i < pParse->iDepth; i++) { + iRet = NXclosegroup(hfil); + if (iRet == NX_ERROR) { + return NX_ERROR; + } + } + + /* open the link instead */ + return NXDopenalias(hfil, pDict, pParse->pToken); + +} + +/*------------------------------------------------------------------------*/ +int NXDIDefParse(NXhandle hFil, NXdict pDict, ParDat * pParse) +{ + int iRet; + char pError[256]; + + pParse->iToken = -1; + while (pParse->iToken != DEND) { + NXDIDefToken(pParse); /* next token */ + switch (pParse->iToken) { + case DEND: + break; + case DSLASH: + iRet = NXDIParsePath(hFil, pParse); + if (iRet == NX_ERROR) { + return NX_ERROR; + } + break; + case DSDS: + iRet = NXDIParseSDS(hFil, pParse); + if (iRet == NX_ERROR) { + return NX_ERROR; + } + pParse->iTerminal = TERMSDS; + break; + case DLINK: + iRet = NXDIParseLink(hFil, pDict, pParse); + if (iRet == NX_ERROR) { + return NX_ERROR; + } + pParse->iTerminal = TERMLINK; + break; + case DGROUP: + pParse->iTerminal = TERMVG; + return NX_OK; + default: + sprintf(pError, + "ERROR: Definition String parse error: %s not permitted here", + pParse->pToken); + NXReportError(pError); + return NX_ERROR; + break; + } + } + return NX_OK; +} + +/*----------------------------------------------------------------------*/ +NXstatus NXDIUnwind(NXhandle hFil, int iDepth) +{ + int i, iRet; + + for (i = 0; i < iDepth; i++) { + iRet = NXclosegroup(hFil); + if (iRet != NX_OK) { + return NX_ERROR; + } + } + return NX_OK; +} + +/*-------------------- The Data Transfer Functions ----------------------*/ +NXstatus NXDopendef(NXhandle hfil, NXdict dict, char *pDef) +{ + NXdict pDict; + ParDat pParse; + int iRet, i, iStat; + + pDict = NXDIAssert(dict); + + /* parse and act on definition string */ + pParse.iMayCreate = 1; + pParse.pPtr = pDef; + pParse.iDepth = 0; + iRet = NXDIDefParse(hfil, pDict, &pParse); + if (iRet == NX_ERROR) { + /* unwind and throw up */ + iRet = NXDIUnwind(hfil, pParse.iDepth); + return NX_ERROR; + } + + return iRet; +} + +/*------------------------------------------------------------------------*/ +NXstatus NXDopenalias(NXhandle hfil, NXdict dict, char *pAlias) +{ + NXdict pDict; + int iRet; + char pDefinition[2048]; + pDynString pReplaced = NULL; + + pDict = NXDIAssert(dict); + + /* get Definition String */ + iRet = NXDget(pDict, pAlias, pDefinition, 2047); + if (iRet != NX_OK) { + sprintf(pDefinition, "ERROR: alias %s not recognized", pAlias); + NXReportError(pDefinition); + return NX_ERROR; + } + + /* do the text replacement */ + pReplaced = NXDItextreplace(dict, pDefinition); + if (!pReplaced) { + return NX_ERROR; + } + + /* call NXDopendef */ + iRet = NXDopendef(hfil, dict, GetCharArray(pReplaced)); + DeleteDynString(pReplaced); + return iRet; +} + +/*------------------------------------------------------------------------*/ +NXstatus NXDputdef(NXhandle hFil, NXdict dict, char *pDef, void *pData) +{ + NXdict pDict; + ParDat pParse; + int iRet, i, iStat; + + pDict = NXDIAssert(dict); + + /* parse and act on definition string */ + pParse.iMayCreate = 1; + pParse.pPtr = pDef; + pParse.iDepth = 0; +#ifdef DEFDEBUG + printf("Putting: %s\n", pDef); +#endif + iRet = NXDIDefParse(hFil, pDict, &pParse); + if (iRet == NX_ERROR) { + NXDIUnwind(hFil, pParse.iDepth); + return NX_ERROR; + } + + + /* only SDS can be written */ + if (pParse.iTerminal != TERMSDS) { + NXReportError("ERROR: can only write to an SDS!"); + iStat = NX_ERROR; + } else { + /* the SDS should be open by now, write it */ + iStat = NXputdata(hFil, pData); + iRet = NXclosedata(hFil); + } + + + /* rewind the hierarchy */ + iRet = NXDIUnwind(hFil, pParse.iDepth); + if (iRet != NX_OK) { + return NX_ERROR; + } + return iStat; +} + +/*------------------------------------------------------------------------*/ +NXstatus NXDputalias(NXhandle hFil, NXdict dict, char *pAlias, void *pData) +{ + NXdict pDict; + int iRet; + char pDefinition[2048]; + pDynString pReplaced = NULL; + + pDict = NXDIAssert(dict); + + /* get Definition String */ + iRet = NXDget(pDict, pAlias, pDefinition, 2047); + if (iRet != NX_OK) { + sprintf(pDefinition, "ERROR: alias %s not recognized", pAlias); + NXReportError( pDefinition); + return NX_ERROR; + } + + /* do text replacement */ + pReplaced = NXDItextreplace(dict, pDefinition); + if (!pReplaced) { + return NX_ERROR; + } + + /* call NXDputdef */ + iRet = NXDputdef(hFil, dict, GetCharArray(pReplaced), pData); + DeleteDynString(pReplaced); + return iRet; +} + +/*------------------------------------------------------------------------*/ +NXstatus NXDgetdef(NXhandle hFil, NXdict dict, char *pDef, void *pData) +{ + NXdict pDict; + ParDat pParse; + int iRet, i, iStat; + + pDict = NXDIAssert(dict); + + /* parse and act on definition string */ + pParse.iMayCreate = 0; + pParse.pPtr = pDef; + pParse.iDepth = 0; +#ifdef DEFDEBUG + printf("Getting: %s\n", pDef); +#endif + iRet = NXDIDefParse(hFil, pDict, &pParse); + if (iRet == NX_ERROR) { + /* unwind and throw up */ + NXDIUnwind(hFil, pParse.iDepth); + return NX_ERROR; + } + + + /* only SDS can be written */ + if (pParse.iTerminal != TERMSDS) { + NXReportError("ERROR: can only write to an SDS!"); + iStat = NX_ERROR; + } else { + /* the SDS should be open by now, read it */ + iStat = NXgetdata(hFil, pData); + iRet = NXclosedata(hFil); + } + + + /* rewind the hierarchy */ + iRet = NXDIUnwind(hFil, pParse.iDepth); + if (iRet != NX_OK) { + return NX_ERROR; + } + return iStat; +} + +/*------------------------------------------------------------------------*/ +NXstatus NXDgetalias(NXhandle hFil, NXdict dict, char *pAlias, void *pData) +{ + NXdict pDict; + int iRet; + char pDefinition[2048]; + pDynString pReplaced = NULL; + + pDict = NXDIAssert(dict); + + /* get Definition String */ + iRet = NXDget(pDict, pAlias, pDefinition, 2047); + if (iRet != NX_OK) { + sprintf(pDefinition, "ERROR: alias %s not recognized", pAlias); + NXReportError(pDefinition); + return NX_ERROR; + } + + /* do text replacement */ + pReplaced = NXDItextreplace(dict, pDefinition); + if (!pReplaced) { + return NX_ERROR; + } + + /* call NXDgetdef */ + iRet = NXDgetdef(hFil, dict, GetCharArray(pReplaced), pData); + DeleteDynString(pReplaced); + return iRet; +} + +/*------------------------------------------------------------------------*/ + +NXstatus NXDinfodef(NXhandle hFil, NXdict dict, char *pDef, int *rank, + int dimension[], int *iType) +{ + NXdict pDict; + ParDat pParse; + int iRet, i, iStat; + + pDict = NXDIAssert(dict); + + /* parse and act on definition string */ + pParse.iMayCreate = 0; + pParse.pPtr = pDef; + pParse.iDepth = 0; +#ifdef DEFDEBUG + printf("Getting: %s\n", pDef); +#endif + iRet = NXDIDefParse(hFil, pDict, &pParse); + if (iRet == NX_ERROR) { + /* unwind and throw up */ + NXDIUnwind(hFil, pParse.iDepth); + return NX_ERROR; + } + + + /* only SDS can be written */ + if (pParse.iTerminal != TERMSDS) { + NXReportError("ERROR: can only write to an SDS!"); + iStat = NX_ERROR; + } else { + /* the SDS should be open by now, read it */ + iStat = NXgetinfo(hFil, rank, dimension, iType); + iRet = NXclosedata(hFil); + } + + + /* rewind the hierarchy */ + iRet = NXDIUnwind(hFil, pParse.iDepth); + if (iRet != NX_OK) { + return NX_ERROR; + } + return iStat; +} + +/*------------------------------------------------------------------------*/ + +NXstatus NXDinfoalias(NXhandle hFil, NXdict dict, char *pAlias, int *rank, + int dimension[], int *iType) +{ + NXdict pDict; + int iRet; + char pDefinition[2048]; + pDynString pReplaced = NULL; + + pDict = NXDIAssert(dict); + + /* get Definition String */ + iRet = NXDget(pDict, pAlias, pDefinition, 2047); + if (iRet != NX_OK) { + sprintf(pDefinition, "ERROR: alias %s not recognized", pAlias); + NXReportError(pDefinition); + return NX_ERROR; + } + + /* do text replacement */ + pReplaced = NXDItextreplace(dict, pDefinition); + if (!pReplaced) { + return NX_ERROR; + } + + /* call NXDgetdef */ + iRet = + NXDinfodef(hFil, dict, GetCharArray(pReplaced), rank, dimension, + iType); + DeleteDynString(pReplaced); + return iRet; +} + +/*------------------------------------------------------------------------*/ +NXstatus NXDdeflink(NXhandle hFil, NXdict dict, + char *pTarget, char *pVictim) +{ + NXdict pDict; + ParDat pParseT, pParseV; + int iRet, i, iStat; + NXlink sLink; + + pDict = NXDIAssert(dict); + + +#ifdef DEFDEBUG + printf("Linking: %s\n", pVictim); + printf("To: %s\n", pTarget); +#endif + + + /* parse Victim */ + pParseV.iMayCreate = 0; + pParseV.pPtr = pVictim; + pParseV.iDepth = 0; + iRet = NXDIDefParse(hFil, pDict, &pParseV); + if (iRet == NX_ERROR) { + /* unwind and throw up */ + NXDIUnwind(hFil, pParseV.iDepth); + return NX_ERROR; + } + /* get link data */ + if (pParseV.iTerminal == TERMSDS) { + NXgetdataID(hFil, &sLink); + iRet = NXclosedata(hFil); + if (iRet != NX_OK) { + /* unwind and throw up */ + NXDIUnwind(hFil, pParseV.iDepth); + return NX_ERROR; + } + } else if (pParseV.iTerminal == TERMVG) { + NXgetgroupID(hFil, &sLink); + } else { + assert(0); /* serious programming error */ + } + /* Unwind */ + iRet = NXDIUnwind(hFil, pParseV.iDepth); + if (iRet != NX_OK) { + return NX_ERROR; + } + + /* parse Target */ + pParseT.iMayCreate = 1; + pParseT.pPtr = pTarget; + pParseT.iDepth = 0; + iRet = NXDIDefParse(hFil, pDict, &pParseT); + if (iRet == NX_ERROR) { + /* unwind and throw up */ + NXDIUnwind(hFil, pParseT.iDepth); + return NX_ERROR; + } + /* check it being a vGroup! */ + if (pParseT.iTerminal != TERMVG) { + NXReportError("ERROR: can link only into a vGroup"); + NXDIUnwind(hFil, pParseT.iDepth); + return NX_ERROR; + } + + /* link, finally */ + iRet = NXmakelink(hFil, &sLink); + /* Unwind anyway */ + iStat = NXDIUnwind(hFil, pParseT.iDepth); + if (iStat != NX_OK) { + return NX_ERROR; + } + return iStat; +} - /* make time string */ - iDate = time(NULL); - psTime = localtime(&iDate); - memset(pBuffer,0,iBufLen); - strftime(pBuffer,iBufLen,"%Y-%m-%d %H:%M:%S",psTime); - } /*--------------------------------------------------------------------------*/ - NXstatus NXUwriteglobals(NXhandle pFile, - char *filename, - char *owner, - char *adress, - char *phone, - char *email, - char *fax, - char *instrument) - { - char pBueffel[512]; - int iStat; - - /* store global attributes, now done by NXopen +NXstatus NXDaliaslink(NXhandle hFil, NXdict dict, + char *pTarget, char *pVictim) +{ + char pTargetDef[2048], pVictimDef[2048]; + int iRet; + NXdict pDict; + pDynString pRep1 = NULL, pRep2 = NULL; + + pDict = NXDIAssert(dict); + + /* get Target Definition String */ + iRet = NXDget(pDict, pTarget, pTargetDef, 2047); + if (iRet != NX_OK) { + sprintf(pTargetDef, "ERROR: alias %s not recognized", pTarget); + NXReportError(pTargetDef); + return NX_ERROR; + } + + /* get Victim definition string */ + iRet = NXDget(pDict, pVictim, pVictimDef, 2047); + if (iRet != NX_OK) { + sprintf(pTargetDef, "ERROR: alias %s not recognized", pTarget); + NXReportError(pTargetDef); + return NX_ERROR; + } + + /* do replacements */ + pRep1 = NXDItextreplace(dict, pTargetDef); + pRep2 = NXDItextreplace(dict, pVictimDef); + if ((!pRep1) || (!pRep2)) { + if (pRep1) + DeleteDynString(pRep1); + if (pRep2) + DeleteDynString(pRep2); + return NX_ERROR; + } + + /* call NXdeflin */ + iRet = NXDdeflink(hFil, pDict, GetCharArray(pRep1), GetCharArray(pRep2)); + DeleteDynString(pRep1); + DeleteDynString(pRep2); + return iRet; +} + +/*-------------------------------------------------------------------------*/ +static void SNXFormatTime(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); +} + +/*--------------------------------------------------------------------------*/ +NXstatus NXUwriteglobals(NXhandle pFile, + char *filename, + char *owner, + char *adress, + char *phone, + char *email, char *fax, char *instrument) +{ + char pBueffel[512]; + int iStat; + + /* store global attributes, now done by NXopen iStat = NXputattr(pFile,"file_name",filename, - strlen(filename)+1,NX_CHAR); + strlen(filename)+1,NX_CHAR); if(iStat == NX_ERROR) { - return NX_ERROR; + return NX_ERROR; } - */ - - /* write creation time, now done by NXopen + */ + + /* write creation time, now done by NXopen SNXFormatTime(pBueffel,512); iStat = NXputattr(pFile,"file_time",pBueffel, - strlen(pBueffel)+1,NX_CHAR); + strlen(pBueffel)+1,NX_CHAR); if(iStat == NX_ERROR) { - return NX_ERROR; + return NX_ERROR; } - */ + */ - /* instrument name */ - iStat = NXputattr(pFile,"instrument",instrument, - strlen(instrument)+1,NX_CHAR); - if(iStat == NX_ERROR) - { - return iStat; - } + /* instrument name */ + iStat = NXputattr(pFile, "instrument", instrument, + strlen(instrument) + 1, NX_CHAR); + if (iStat == NX_ERROR) { + return iStat; + } - /* owner */ - iStat = NXputattr(pFile,"owner",owner, - strlen(owner)+1,NX_CHAR); - if(iStat == NX_ERROR) - { - return iStat; - } + /* owner */ + iStat = NXputattr(pFile, "owner", owner, strlen(owner) + 1, NX_CHAR); + if (iStat == NX_ERROR) { + return iStat; + } - /* Adress */ - iStat = NXputattr(pFile,"owner_adress",adress, - strlen(adress)+1,NX_CHAR); - if(iStat == NX_ERROR) - { - return iStat; - } + /* Adress */ + iStat = NXputattr(pFile, "owner_adress", adress, + strlen(adress) + 1, NX_CHAR); + if (iStat == NX_ERROR) { + return iStat; + } - /* phone */ - iStat = NXputattr(pFile,"owner_telephone_number",phone, - strlen(phone)+1,NX_CHAR); - if(iStat == NX_ERROR) - { - return iStat; - } + /* phone */ + iStat = NXputattr(pFile, "owner_telephone_number", phone, + strlen(phone) + 1, NX_CHAR); + if (iStat == NX_ERROR) { + return iStat; + } - /* fax */ - iStat = NXputattr(pFile,"owner_fax_number",fax, - strlen(fax)+1,NX_CHAR); - if(iStat == NX_ERROR) - { - return iStat; - } + /* fax */ + iStat = NXputattr(pFile, "owner_fax_number", fax, + strlen(fax) + 1, NX_CHAR); + if (iStat == NX_ERROR) { + return iStat; + } + + /* email */ + iStat = NXputattr(pFile, "owner_email", email, + strlen(email) + 1, NX_CHAR); + if (iStat == NX_ERROR) { + return iStat; + } + return NX_OK; +} - /* email */ - iStat = NXputattr(pFile,"owner_email",email, - strlen(email)+1,NX_CHAR); - if(iStat == NX_ERROR) - { - return iStat; - } - return NX_OK; - } /*-----------------------------------------------------------------------*/ - NXstatus NXUentergroup(NXhandle hFil, char *name, char *class) - { - void (*ErrFunc)(void *pData, char *pErr); - int iRet; +NXstatus NXUentergroup(NXhandle hFil, char *name, char *class) +{ + int iRet; + + /* ACTION, first install dummy error handler */ + NXMDisableErrorReporting(); + + + /* try opening vGroup */ + iRet = NXopengroup(hFil, name, class); + NXMEnableErrorReporting(); + if (iRet == NX_OK) { + return NX_OK; + } else { + /* we need to create it */ + iRet = NXmakegroup(hFil, name, class); + if (iRet != NX_OK) { + /* a comment on this one has already been written! */ + return iRet; + } + iRet = NXopengroup(hFil, name, class); + if (iRet != NX_OK) { + /* a comment on this one has already been written! */ + return iRet; + } + } + return NX_OK; +} - /* ACTION, first install dummy error handler */ - ErrFunc = NXIReportError; - NXMSetError(NXpData, DummyError); - - /* try opening vGroup */ - iRet = NXopengroup(hFil, name, class); - NXMSetError(NXpData,ErrFunc); - if(iRet == NX_OK) - { - return NX_OK; - } - else - { - /* we need to create it */ - iRet = NXmakegroup(hFil,name,class); - if(iRet != NX_OK) - { - /* a comment on this one has already been written! */ - return iRet; - } - iRet = NXopengroup(hFil,name,class); - if(iRet != NX_OK) - { - /* a comment on this one has already been written! */ - return iRet; - } - } - return NX_OK; - } /*-----------------------------------------------------------------------*/ - NXstatus NXUenterdata(NXhandle hFil, char *label, int datatype, - int rank, int dim[], char *pUnits) - { - void (*ErrFunc)(void *pData, char *pErr); - int iRet; +NXstatus NXUenterdata(NXhandle hFil, char *label, int datatype, + int rank, int dim[], char *pUnits) +{ + int iRet; + + /* ACTION, first install dummy error handler */ + NXMDisableErrorReporting(); + + /* try opening SDS */ + iRet = NXopendata(hFil, label); + NXMEnableErrorReporting(); + if (iRet == NX_OK) { + return NX_OK; + } else { + /* we need to create it */ + iRet = NXmakedata(hFil, label, datatype, rank, dim); + if (iRet != NX_OK) { + /* a comment on this one has already been written! */ + return iRet; + } + iRet = NXopendata(hFil, label); + if (iRet != NX_OK) { + /* a comment on this one has already been written! */ + return iRet; + } + iRet = NXputattr(hFil, "Units", pUnits, strlen(pUnits) + 1, NX_INT8); + if (iRet != NX_OK) { + /* a comment on this one has already been written! */ + return iRet; + } + } + return NX_OK; +} - /* ACTION, first install dummy error handler */ - ErrFunc = NXIReportError; - NXMSetError(NXpData, DummyError); - - /* try opening SDS */ - iRet = NXopendata(hFil, label); - NXMSetError(NXpData,ErrFunc); - if(iRet == NX_OK) - { - return NX_OK; - } - else - { - /* we need to create it */ - iRet = NXmakedata(hFil,label, datatype, rank,dim); - if(iRet != NX_OK) - { - /* a comment on this one has already been written! */ - return iRet; - } - iRet = NXopendata(hFil,label); - if(iRet != NX_OK) - { - /* a comment on this one has already been written! */ - return iRet; - } - iRet = NXputattr(hFil, "Units",pUnits, - strlen(pUnits) + 1,NX_INT8); - if(iRet != NX_OK) - { - /* a comment on this one has already been written! */ - return iRet; - } - } - return NX_OK; - } /*-----------------------------------------------------------------------*/ - NXstatus NXUallocSDS(NXhandle hFil, void **pData) - { - int iDIM[NX_MAXRANK]; - int iRank,iType; - int iRet, i; - long lLength; +NXstatus NXUallocSDS(NXhandle hFil, void **pData) +{ + int iDIM[NX_MAXRANK]; + int iRank, iType; + int iRet, i; + long lLength; - /* get info */ - iRet = NXgetinfo(hFil,&iRank, iDIM, &iType); - if(iRet != NX_OK) - { - return iRet; - } + /* get info */ + iRet = NXgetinfo(hFil, &iRank, iDIM, &iType); + if (iRet != NX_OK) { + return iRet; + } - /* calculate Size */ - lLength = iDIM[0]; - for(i = 1; i < iRank; i++) - { - lLength *= iDIM[i]; - } - switch(iType) - { - case NX_FLOAT32: - lLength *= sizeof(float); - break; - case NX_FLOAT64: - lLength *= sizeof(double); - break; - case NX_INT8: - case NX_CHAR: - lLength *= sizeof(char); - break; - case NX_UINT8: - lLength *= sizeof(unsigned char); - break; - case NX_INT16: - lLength *= sizeof(short); - break; - case NX_UINT16: - lLength *= sizeof(unsigned short); - break; - case NX_INT32: - lLength *= sizeof(int); - break; - case NX_UINT32: - lLength *= sizeof(int); - break; - default: - NXIReportError(NXpData,"ERROR: Internal: number type not recoginized"); - return NX_ERROR; - } + /* calculate Size */ + lLength = iDIM[0]; + for (i = 1; i < iRank; i++) { + lLength *= iDIM[i]; + } + switch (iType) { + case NX_FLOAT32: + lLength *= sizeof(float); + break; + case NX_FLOAT64: + lLength *= sizeof(double); + break; + case NX_INT8: + case NX_CHAR: + lLength *= sizeof(char); + break; + case NX_UINT8: + lLength *= sizeof(unsigned char); + break; + case NX_INT16: + lLength *= sizeof(short); + break; + case NX_UINT16: + lLength *= sizeof(unsigned short); + break; + case NX_INT32: + lLength *= sizeof(int); + break; + case NX_UINT32: + lLength *= sizeof(int); + break; + default: + NXReportError("ERROR: Internal: number type not recoginized"); + return NX_ERROR; + } + + /* time to malloc */ + *pData = NULL; + *pData = malloc(lLength); + if (*pData == NULL) { + NXReportError("ERROR: memory exhausted in NXUallocSDS"); + return NX_ERROR; + } + memset(*pData, 0, lLength); + return NX_OK; +} - /* time to malloc */ - *pData = NULL; - *pData = malloc(lLength); - if(*pData == NULL) - { - NXIReportError(NXpData,"ERROR: memory exhausted in NXUallocSDS"); - return NX_ERROR; - } - memset(*pData,0,lLength); - return NX_OK; - } /*----------------------------------------------------------------------*/ - NXstatus NXUfreeSDS(void **pData) - { - free(*pData); - *pData = NULL; - return NX_OK; - } - +NXstatus NXUfreeSDS(void **pData) +{ + free(*pData); + *pData = NULL; + return NX_OK; +} diff --git a/nxdict.h b/nxdict.h index 197a26a7..a7ee0623 100644 --- a/nxdict.h +++ b/nxdict.h @@ -10,13 +10,13 @@ ----------------------------------------------------------------------------*/ #ifndef NXDICTAPI #define NXDICTAPI -#include "napi.h" /* make sure, napi is included */ +#include "napi.h" /* make sure, napi is included */ /*-------------------- NXDict data types & defines ----------------------*/ #line 195 "nxdict.w" - typedef struct __NXdict *NXdict; +typedef struct __NXdict *NXdict; #line 2252 "nxdict.w" @@ -26,38 +26,36 @@ #line 201 "nxdict.w" - NXstatus NXDinitfromfile(char *filename, NXdict *pDict); - NXstatus NXDclose(NXdict handle, char *filename); +NXstatus NXDinitfromfile(char *filename, NXdict * pDict); +NXstatus NXDclose(NXdict handle, char *filename); - NXstatus NXDadd(NXdict handle, char *alias, char *DefString); - NXstatus NXDget(NXdict handle, char *alias, char *pBuffer, int iBufLen); - NXstatus NXDupdate(NXdict handle, char *alias, char *pNewVal); - NXstatus NXDtextreplace(NXdict handle, char *pDefString, char *pBuffer, - int iBuflen); +NXstatus NXDadd(NXdict handle, char *alias, char *DefString); +NXstatus NXDget(NXdict handle, char *alias, char *pBuffer, int iBufLen); +NXstatus NXDupdate(NXdict handle, char *alias, char *pNewVal); +NXstatus NXDtextreplace(NXdict handle, char *pDefString, char *pBuffer, + int iBuflen); #line 2256 "nxdict.w" -/*----------------- Dictionary added data transfer -----------------------*/ +/*----------------- Dictionary added data transfer -----------------------*/ #line 240 "nxdict.w" - NXstatus NXDputalias(NXhandle file, NXdict dict, - char *alias, void *pData); - NXstatus NXDputdef(NXhandle file, NXdict dict, char *pDefString, void *pData); +NXstatus NXDputalias(NXhandle file, NXdict dict, char *alias, void *pData); +NXstatus NXDputdef(NXhandle file, NXdict dict, char *pDefString, + void *pData); - NXstatus NXDgetalias(NXhandle file, NXdict dict, - char *alias, void *pData); - NXstatus NXDgetdef(NXhandle file, NXdict dict, char *pDefString, void *pData); - NXstatus NXDdefget(NXdict handle, char *pKey, char *pBuffer, int iBufLen); +NXstatus NXDgetalias(NXhandle file, NXdict dict, char *alias, void *pData); +NXstatus NXDgetdef(NXhandle file, NXdict dict, char *pDefString, + void *pData); +NXstatus NXDdefget(NXdict handle, char *pKey, char *pBuffer, int iBufLen); - NXstatus NXDaliaslink(NXhandle file, NXdict dict, - char *pAlias1, char *pAlias2); - NXstatus NXDdeflink(NXhandle file, NXdict dict, - char *pDef1, char *pDef2); +NXstatus NXDaliaslink(NXhandle file, NXdict dict, + char *pAlias1, char *pAlias2); +NXstatus NXDdeflink(NXhandle file, NXdict dict, char *pDef1, char *pDef2); - NXstatus NXDopenalias(NXhandle file, NXdict dict, - char *alias); - NXstatus NXDopendef(NXhandle file, NXdict dict, char *pDefString); +NXstatus NXDopenalias(NXhandle file, NXdict dict, char *alias); +NXstatus NXDopendef(NXhandle file, NXdict dict, char *pDefString); #line 2258 "nxdict.w" @@ -66,22 +64,19 @@ #line 310 "nxdict.w" - NXstatus NXUwriteglobals(NXhandle file, - char *filename, - char *owner, - char *adress, - char *phone, - char *email, - char *fax, - char *thing); +NXstatus NXUwriteglobals(NXhandle file, + char *filename, + char *owner, + char *adress, + char *phone, char *email, char *fax, char *thing); - NXstatus NXUentergroup(NXhandle hFil, char *name, char *class); - NXstatus NXUenterdata (NXhandle fileid, char* label, int datatype, - int rank, int dim[], char *pUnits); - - NXstatus NXUallocSDS(NXhandle hFil, void **pData); - NXstatus NXUfreeSDS(void **pData); +NXstatus NXUentergroup(NXhandle hFil, char *name, char *class); +NXstatus NXUenterdata(NXhandle fileid, char *label, int datatype, + int rank, int dim[], char *pUnits); + +NXstatus NXUallocSDS(NXhandle hFil, void **pData); +NXstatus NXUfreeSDS(void **pData); #line 2260 "nxdict.w" diff --git a/nxdump.c b/nxdump.c index afcfd30c..224847e7 100644 --- a/nxdump.c +++ b/nxdump.c @@ -16,95 +16,113 @@ #define INDENT_AMOUNT " " -char * -type2s(uint type){ +char *type2s(uint type) +{ static char unknownType[40]; - switch (type){ - case DFNT_NONE: return "DFNT_NONE"; - case DFNT_FLOAT32: return "DFNT_FLOAT32"; - case DFNT_FLOAT64: return "DFNT_FLOAT64"; - case DFNT_INT8: return "DFNT_INT8"; - case DFNT_UINT8: return "DFNT_UINT8"; - case DFNT_INT16: return "DFNT_INT16"; - case DFNT_UINT16: return "DFNT_UINT16"; - case DFNT_INT32: return "DFNT_INT32"; - case DFNT_UINT32: return "DFNT_UINT32"; + switch (type) { + case DFNT_NONE: + return "DFNT_NONE"; + case DFNT_FLOAT32: + return "DFNT_FLOAT32"; + case DFNT_FLOAT64: + return "DFNT_FLOAT64"; + case DFNT_INT8: + return "DFNT_INT8"; + case DFNT_UINT8: + return "DFNT_UINT8"; + case DFNT_INT16: + return "DFNT_INT16"; + case DFNT_UINT16: + return "DFNT_UINT16"; + case DFNT_INT32: + return "DFNT_INT32"; + case DFNT_UINT32: + return "DFNT_UINT32"; } return "Unsupported!"; } -int dumpAttr(NXhandle NXdat, char * parent, char * indent) { +int dumpAttr(NXhandle NXdat, char *parent, char *indent) +{ int length, itype; char name[VGNAMELENMAX], *data; NXstatus NXstat; - while((NXstat = NXgetnextattr(NXdat, name, &length, &itype)) != NX_EOD) { + while ((NXstat = NXgetnextattr(NXdat, name, &length, &itype)) != NX_EOD) { data = (char *) malloc(length + 1); NXstat = NXgetattr(NXdat, name, data, length); data[length] = 0; - printf("%s%s:%s=%s\n",indent,parent,name,data); + printf("%s%s:%s=%s\n", indent, parent, name, data); } return 0; } -int dumpSDS(NXhandle NXdat, char * name, char * indent) { +int dumpSDS(NXhandle NXdat, char *name, char *indent) +{ char new_indent[80]; - int rank, dims[MAX_VAR_DIMS], datatype,i; + int rank, dims[MAX_VAR_DIMS], datatype, i; NXstatus NXstat; - strcpy(new_indent,indent); strcat(new_indent,INDENT_AMOUNT); + strcpy(new_indent, indent); + strcat(new_indent, INDENT_AMOUNT); NXstat = NXopendata(NXdat, name); NXstat = NXgetinfo(NXdat, &rank, dims, &datatype); - printf("%sSD %s (datatype=%s, rank=%d, dimensions=%d",new_indent, + printf("%sSD %s (datatype=%s, rank=%d, dimensions=%d", new_indent, name, type2s(datatype), rank, dims[0]); if (rank > 1) { - for (i=1;i%s\n",indent,class,name); - if ((NXstat = NXopengroup(NXdat,name,class)) == NX_ERROR) { - fprintf(stderr,"Error opening V group %s!",name); - return -1; - } - dumpVG(NXdat,new_indent); - NXstat = NXclosegroup(NXdat); - printf("%sv %s->%s\n",indent,class,name); + if (! + ((strcmp(class, "Dim0.0") == 0) + || (strcmp(class, "CDF0.0") == 0))) { + printf("%sV %s->%s\n", indent, class, name); + if ((NXstat = NXopengroup(NXdat, name, class)) == NX_ERROR) { + fprintf(stderr, "Error opening V group %s!", name); + return -1; + } + dumpVG(NXdat, new_indent); + NXstat = NXclosegroup(NXdat); + printf("%sv %s->%s\n", indent, class, name); } - break; + break; default: - dumpSDS(NXdat,name,new_indent); + dumpSDS(NXdat, name, new_indent); } } return 0; } -void -main(int argc, char ** argv) { +void main(int argc, char **argv) +{ char name[VGNAMELENMAX], class[VGNAMELENMAX], indent[80] = ""; int datatype; char filename[80]; @@ -112,13 +130,13 @@ main(int argc, char ** argv) { NXstatus NXstat; if (argc < 2) { - fprintf(stderr,"Usage: nxdump \n"); + fprintf(stderr, "Usage: nxdump \n"); exit(1); } - strcpy(filename,argv[1]); + strcpy(filename, argv[1]); - if ((NXdat = NXopen(filename,DFACC_RDWR)) == NULL) { - fprintf(stderr,"Unable to access file %s! Exiting...\n",filename); + if ((NXdat = NXopen(filename, DFACC_RDWR)) == NULL) { + fprintf(stderr, "Unable to access file %s! Exiting...\n", filename); exit(1); } @@ -130,4 +148,3 @@ main(int argc, char ** argv) { NXclose(NXdat); } - diff --git a/nxinter_wrap.c b/nxinter_wrap.c index a2dda998..a2aaf7d7 100644 --- a/nxinter_wrap.c +++ b/nxinter_wrap.c @@ -19,10 +19,10 @@ # if (__SUNPRO_CC <= 0x560) # define SWIGTEMPLATEDISAMBIGUATOR template # else -# define SWIGTEMPLATEDISAMBIGUATOR +# define SWIGTEMPLATEDISAMBIGUATOR # endif # else -# define SWIGTEMPLATEDISAMBIGUATOR +# define SWIGTEMPLATEDISAMBIGUATOR # endif #endif @@ -39,14 +39,14 @@ #ifndef SWIGUNUSED # if defined(__GNUC__) # if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) -# define SWIGUNUSED __attribute__ ((__unused__)) +# define SWIGUNUSED __attribute__ ((__unused__)) # else # define SWIGUNUSED # endif # elif defined(__ICC) -# define SWIGUNUSED __attribute__ ((__unused__)) +# define SWIGUNUSED __attribute__ ((__unused__)) # else -# define SWIGUNUSED +# define SWIGUNUSED # endif #endif @@ -54,7 +54,7 @@ # ifdef __cplusplus # define SWIGUNUSEDPARM(p) # else -# define SWIGUNUSEDPARM(p) p SWIGUNUSED +# define SWIGUNUSEDPARM(p) p SWIGUNUSED # endif #endif @@ -97,7 +97,7 @@ # define SWIGSTDCALL __stdcall # else # define SWIGSTDCALL -# endif +# endif #endif /* Deal with Microsoft's attempt at deprecating C standard runtime functions */ @@ -242,10 +242,10 @@ */ -#define SWIG_OK (0) +#define SWIG_OK (0) #define SWIG_ERROR (-1) #define SWIG_IsOK(r) (r >= 0) -#define SWIG_ArgError(r) ((r != SWIG_ERROR) ? r : SWIG_TypeError) +#define SWIG_ArgError(r) ((r != SWIG_ERROR) ? r : SWIG_TypeError) /* The CastRankLimit says how many bits are used for the cast rank */ #define SWIG_CASTRANKLIMIT (1 << 8) @@ -272,18 +272,21 @@ # ifndef SWIG_TypeRank # define SWIG_TypeRank unsigned long # endif -# ifndef SWIG_MAXCASTRANK /* Default cast allowed */ +# ifndef SWIG_MAXCASTRANK /* Default cast allowed */ # define SWIG_MAXCASTRANK (2) # endif # define SWIG_CASTRANKMASK ((SWIG_CASTRANKLIMIT) -1) # define SWIG_CastRank(r) (r & SWIG_CASTRANKMASK) -SWIGINTERNINLINE int SWIG_AddCast(int r) { - return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r; +SWIGINTERNINLINE int SWIG_AddCast(int r) +{ + return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : + SWIG_ERROR) : r; } -SWIGINTERNINLINE int SWIG_CheckState(int r) { - return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0; +SWIGINTERNINLINE int SWIG_CheckState(int r) +{ + return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0; } -#else /* no cast-rank mode */ +#else /* no cast-rank mode */ # define SWIG_AddCast # define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0) #endif @@ -297,38 +300,38 @@ SWIGINTERNINLINE int SWIG_CheckState(int r) { extern "C" { #endif -typedef void *(*swig_converter_func)(void *); -typedef struct swig_type_info *(*swig_dycast_func)(void **); + typedef void *(*swig_converter_func) (void *); + typedef struct swig_type_info *(*swig_dycast_func) (void **); /* Structure to store inforomation on one type */ -typedef struct swig_type_info { - const char *name; /* mangled name of this type */ - const char *str; /* human readable name of this type */ - swig_dycast_func dcast; /* dynamic cast function down a hierarchy */ - struct swig_cast_info *cast; /* linked list of types that can cast into this type */ - void *clientdata; /* language specific type data */ - int owndata; /* flag if the structure owns the clientdata */ -} swig_type_info; + typedef struct swig_type_info { + const char *name; /* mangled name of this type */ + const char *str; /* human readable name of this type */ + swig_dycast_func dcast; /* dynamic cast function down a hierarchy */ + struct swig_cast_info *cast; /* linked list of types that can cast into this type */ + void *clientdata; /* language specific type data */ + int owndata; /* flag if the structure owns the clientdata */ + } swig_type_info; /* Structure to store a type and conversion function used for casting */ -typedef struct swig_cast_info { - swig_type_info *type; /* pointer to type that is equivalent to this type */ - swig_converter_func converter; /* function to cast the void pointers */ - struct swig_cast_info *next; /* pointer to next cast in linked list */ - struct swig_cast_info *prev; /* pointer to the previous cast */ -} swig_cast_info; + typedef struct swig_cast_info { + swig_type_info *type; /* pointer to type that is equivalent to this type */ + swig_converter_func converter; /* function to cast the void pointers */ + struct swig_cast_info *next; /* pointer to next cast in linked list */ + struct swig_cast_info *prev; /* pointer to the previous cast */ + } swig_cast_info; /* Structure used to store module information * Each module generates one structure like this, and the runtime collects * all of these structures and stores them in a circularly linked list.*/ -typedef struct swig_module_info { - swig_type_info **types; /* Array of pointers to swig_type_info structures that are in this module */ - size_t size; /* Number of types in this module */ - struct swig_module_info *next; /* Pointer to next element in circularly linked list */ - swig_type_info **type_initial; /* Array of initially generated type structures */ - swig_cast_info **cast_initial; /* Array of initially generated casting structures */ - void *clientdata; /* Language specific module data */ -} swig_module_info; + typedef struct swig_module_info { + swig_type_info **types; /* Array of pointers to swig_type_info structures that are in this module */ + size_t size; /* Number of types in this module */ + struct swig_module_info *next; /* Pointer to next element in circularly linked list */ + swig_type_info **type_initial; /* Array of initially generated type structures */ + swig_cast_info **cast_initial; /* Array of initially generated casting structures */ + void *clientdata; /* Language specific module data */ + } swig_module_info; /* Compare two type names skipping the space characters, therefore @@ -337,54 +340,60 @@ typedef struct swig_module_info { Return 0 when the two name types are equivalent, as in strncmp, but skipping ' '. */ -SWIGRUNTIME int -SWIG_TypeNameComp(const char *f1, const char *l1, - const char *f2, const char *l2) { - for (;(f1 != l1) && (f2 != l2); ++f1, ++f2) { - while ((*f1 == ' ') && (f1 != l1)) ++f1; - while ((*f2 == ' ') && (f2 != l2)) ++f2; - if (*f1 != *f2) return (*f1 > *f2) ? 1 : -1; + SWIGRUNTIME int + SWIG_TypeNameComp(const char *f1, const char *l1, + const char *f2, const char *l2) { + for (; (f1 != l1) && (f2 != l2); ++f1, ++f2) { + while ((*f1 == ' ') && (f1 != l1)) + ++f1; + while ((*f2 == ' ') && (f2 != l2)) + ++f2; + if (*f1 != *f2) + return (*f1 > *f2) ? 1 : -1; + } return (l1 - f1) - (l2 - f2); } - return (l1 - f1) - (l2 - f2); -} /* Check type equivalence in a name list like ||... Return 0 if not equal, 1 if equal */ -SWIGRUNTIME int -SWIG_TypeEquiv(const char *nb, const char *tb) { - int equiv = 0; - const char* te = tb + strlen(tb); - const char* ne = nb; - while (!equiv && *ne) { - for (nb = ne; *ne; ++ne) { - if (*ne == '|') break; + SWIGRUNTIME int + SWIG_TypeEquiv(const char *nb, const char *tb) { + int equiv = 0; + const char *te = tb + strlen(tb); + const char *ne = nb; + while (!equiv && *ne) { + for (nb = ne; *ne; ++ne) { + if (*ne == '|') + break; + } + equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0; + if (*ne) + ++ne; } - equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0; - if (*ne) ++ne; + return equiv; } - return equiv; -} /* Check type equivalence in a name list like ||... Return 0 if equal, -1 if nb < tb, 1 if nb > tb */ -SWIGRUNTIME int -SWIG_TypeCompare(const char *nb, const char *tb) { - int equiv = 0; - const char* te = tb + strlen(tb); - const char* ne = nb; - while (!equiv && *ne) { - for (nb = ne; *ne; ++ne) { - if (*ne == '|') break; + SWIGRUNTIME int + SWIG_TypeCompare(const char *nb, const char *tb) { + int equiv = 0; + const char *te = tb + strlen(tb); + const char *ne = nb; + while (!equiv && *ne) { + for (nb = ne; *ne; ++ne) { + if (*ne == '|') + break; + } + equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0; + if (*ne) + ++ne; } - equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0; - if (*ne) ++ne; + return equiv; } - return equiv; -} /* think of this as a c++ template<> or a scheme macro */ @@ -412,94 +421,94 @@ SWIG_TypeCompare(const char *nb, const char *tb) { /* Check the typename */ -SWIGRUNTIME swig_cast_info * -SWIG_TypeCheck(const char *c, swig_type_info *ty) { - SWIG_TypeCheck_Template(strcmp(iter->type->name, c) == 0, ty); -} + SWIGRUNTIME swig_cast_info *SWIG_TypeCheck(const char *c, + swig_type_info * ty) { + SWIG_TypeCheck_Template(strcmp(iter->type->name, c) == 0, ty); + } /* Same as previous function, except strcmp is replaced with a pointer comparison */ -SWIGRUNTIME swig_cast_info * -SWIG_TypeCheckStruct(swig_type_info *from, swig_type_info *into) { - SWIG_TypeCheck_Template(iter->type == from, into); -} + SWIGRUNTIME swig_cast_info *SWIG_TypeCheckStruct(swig_type_info * from, + swig_type_info * into) { + SWIG_TypeCheck_Template(iter->type == from, into); + } /* Cast a pointer up an inheritance hierarchy */ -SWIGRUNTIMEINLINE void * -SWIG_TypeCast(swig_cast_info *ty, void *ptr) { - return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr); -} + SWIGRUNTIMEINLINE void *SWIG_TypeCast(swig_cast_info * ty, void *ptr) { + return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter) (ptr); + } /* Dynamic pointer casting. Down an inheritance hierarchy */ -SWIGRUNTIME swig_type_info * -SWIG_TypeDynamicCast(swig_type_info *ty, void **ptr) { - swig_type_info *lastty = ty; - if (!ty || !ty->dcast) return ty; - while (ty && (ty->dcast)) { - ty = (*ty->dcast)(ptr); - if (ty) lastty = ty; + SWIGRUNTIME swig_type_info *SWIG_TypeDynamicCast(swig_type_info * ty, + void **ptr) { + swig_type_info *lastty = ty; + if (!ty || !ty->dcast) + return ty; + while (ty && (ty->dcast)) { + ty = (*ty->dcast) (ptr); + if (ty) + lastty = ty; + } + return lastty; } - return lastty; -} /* Return the name associated with this type */ -SWIGRUNTIMEINLINE const char * -SWIG_TypeName(const swig_type_info *ty) { - return ty->name; -} + SWIGRUNTIMEINLINE const char *SWIG_TypeName(const swig_type_info * ty) { + return ty->name; + } /* Return the pretty name associated with this type, that is an unmangled type name in a form presentable to the user. */ -SWIGRUNTIME const char * -SWIG_TypePrettyName(const swig_type_info *type) { - /* The "str" field contains the equivalent pretty names of the - type, separated by vertical-bar characters. We choose - to print the last name, as it is often (?) the most - specific. */ - if (!type) return NULL; - if (type->str != NULL) { - const char *last_name = type->str; - const char *s; - for (s = type->str; *s; s++) - if (*s == '|') last_name = s+1; - return last_name; + SWIGRUNTIME const char *SWIG_TypePrettyName(const swig_type_info * type) { + /* The "str" field contains the equivalent pretty names of the + type, separated by vertical-bar characters. We choose + to print the last name, as it is often (?) the most + specific. */ + if (!type) + return NULL; + if (type->str != NULL) { + const char *last_name = type->str; + const char *s; + for (s = type->str; *s; s++) + if (*s == '|') + last_name = s + 1; + return last_name; + } else + return type->name; } - else - return type->name; -} /* Set the clientdata field for a type */ -SWIGRUNTIME void -SWIG_TypeClientData(swig_type_info *ti, void *clientdata) { - swig_cast_info *cast = ti->cast; - /* if (ti->clientdata == clientdata) return; */ - ti->clientdata = clientdata; - - while (cast) { - if (!cast->converter) { - swig_type_info *tc = cast->type; - if (!tc->clientdata) { - SWIG_TypeClientData(tc, clientdata); + SWIGRUNTIME void + SWIG_TypeClientData(swig_type_info * ti, void *clientdata) { + swig_cast_info *cast = ti->cast; + /* if (ti->clientdata == clientdata) return; */ + ti->clientdata = clientdata; + + while (cast) { + if (!cast->converter) { + swig_type_info *tc = cast->type; + if (!tc->clientdata) { + SWIG_TypeClientData(tc, clientdata); + } } - } - cast = cast->next; + cast = cast->next; + } } -} -SWIGRUNTIME void -SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) { - SWIG_TypeClientData(ti, clientdata); - ti->owndata = 1; -} - + SWIGRUNTIME void + SWIG_TypeNewClientData(swig_type_info * ti, void *clientdata) { + SWIG_TypeClientData(ti, clientdata); + ti->owndata = 1; + } + /* Search for a swig_type_info structure only by mangled name Search is a O(log #types) @@ -508,41 +517,43 @@ SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) { Note: if start == end at the beginning of the function, we go all the way around the circular list. */ -SWIGRUNTIME swig_type_info * -SWIG_MangledTypeQueryModule(swig_module_info *start, - swig_module_info *end, - const char *name) { - swig_module_info *iter = start; - do { - if (iter->size) { - register size_t l = 0; - register size_t r = iter->size - 1; - do { - /* since l+r >= 0, we can (>> 1) instead (/ 2) */ - register size_t i = (l + r) >> 1; - const char *iname = iter->types[i]->name; - if (iname) { - register int compare = strcmp(name, iname); - if (compare == 0) { - return iter->types[i]; - } else if (compare < 0) { - if (i) { - r = i - 1; - } else { - break; - } - } else if (compare > 0) { - l = i + 1; - } - } else { - break; /* should never happen */ - } - } while (l <= r); - } - iter = iter->next; - } while (iter != end); - return 0; -} + SWIGRUNTIME swig_type_info *SWIG_MangledTypeQueryModule(swig_module_info + * start, + swig_module_info + * end, + const char *name) + { + swig_module_info *iter = start; + do { + if (iter->size) { + register size_t l = 0; + register size_t r = iter->size - 1; + do { + /* since l+r >= 0, we can (>> 1) instead (/ 2) */ + register size_t i = (l + r) >> 1; + const char *iname = iter->types[i]->name; + if (iname) { + register int compare = strcmp(name, iname); + if (compare == 0) { + return iter->types[i]; + } else if (compare < 0) { + if (i) { + r = i - 1; + } else { + break; + } + } else if (compare > 0) { + l = i + 1; + } + } else { + break; /* should never happen */ + } + } while (l <= r); + } + iter = iter->next; + } while (iter != end); + return 0; + } /* Search for a swig_type_info structure for either a mangled name or a human readable name. @@ -553,148 +564,152 @@ SWIG_MangledTypeQueryModule(swig_module_info *start, Note: if start == end at the beginning of the function, we go all the way around the circular list. */ -SWIGRUNTIME swig_type_info * -SWIG_TypeQueryModule(swig_module_info *start, - swig_module_info *end, - const char *name) { - /* STEP 1: Search the name field using binary search */ - swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name); - if (ret) { - return ret; - } else { - /* STEP 2: If the type hasn't been found, do a complete search - of the str field (the human readable name) */ - swig_module_info *iter = start; - do { - register size_t i = 0; - for (; i < iter->size; ++i) { - if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name))) - return iter->types[i]; - } - iter = iter->next; - } while (iter != end); + SWIGRUNTIME swig_type_info *SWIG_TypeQueryModule(swig_module_info * + start, + swig_module_info * end, + const char *name) { + /* STEP 1: Search the name field using binary search */ + swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name); + if (ret) { + return ret; + } else { + /* STEP 2: If the type hasn't been found, do a complete search + of the str field (the human readable name) */ + swig_module_info *iter = start; + do { + register size_t i = 0; + for (; i < iter->size; ++i) { + if (iter->types[i]->str + && (SWIG_TypeEquiv(iter->types[i]->str, name))) + return iter->types[i]; + } + iter = iter->next; + } while (iter != end); + } + + /* neither found a match */ + return 0; } - - /* neither found a match */ - return 0; -} /* Pack binary data into a string */ -SWIGRUNTIME char * -SWIG_PackData(char *c, void *ptr, size_t sz) { - static const char hex[17] = "0123456789abcdef"; - register const unsigned char *u = (unsigned char *) ptr; - register const unsigned char *eu = u + sz; - for (; u != eu; ++u) { - register unsigned char uu = *u; - *(c++) = hex[(uu & 0xf0) >> 4]; - *(c++) = hex[uu & 0xf]; + SWIGRUNTIME char *SWIG_PackData(char *c, void *ptr, size_t sz) { + static const char hex[17] = "0123456789abcdef"; + register const unsigned char *u = (unsigned char *) ptr; + register const unsigned char *eu = u + sz; + for (; u != eu; ++u) { + register unsigned char uu = *u; + *(c++) = hex[(uu & 0xf0) >> 4]; + *(c++) = hex[uu & 0xf]; + } + return c; } - return c; -} /* Unpack binary data from a string */ -SWIGRUNTIME const char * -SWIG_UnpackData(const char *c, void *ptr, size_t sz) { - register unsigned char *u = (unsigned char *) ptr; - register const unsigned char *eu = u + sz; - for (; u != eu; ++u) { - register char d = *(c++); - register unsigned char uu; - if ((d >= '0') && (d <= '9')) - uu = ((d - '0') << 4); - else if ((d >= 'a') && (d <= 'f')) - uu = ((d - ('a'-10)) << 4); - else - return (char *) 0; - d = *(c++); - if ((d >= '0') && (d <= '9')) - uu |= (d - '0'); - else if ((d >= 'a') && (d <= 'f')) - uu |= (d - ('a'-10)); - else - return (char *) 0; - *u = uu; + SWIGRUNTIME const char *SWIG_UnpackData(const char *c, void *ptr, + size_t sz) { + register unsigned char *u = (unsigned char *) ptr; + register const unsigned char *eu = u + sz; + for (; u != eu; ++u) { + register char d = *(c++); + register unsigned char uu; + if ((d >= '0') && (d <= '9')) + uu = ((d - '0') << 4); + else if ((d >= 'a') && (d <= 'f')) + uu = ((d - ('a' - 10)) << 4); + else + return (char *) 0; + d = *(c++); + if ((d >= '0') && (d <= '9')) + uu |= (d - '0'); + else if ((d >= 'a') && (d <= 'f')) + uu |= (d - ('a' - 10)); + else + return (char *) 0; + *u = uu; + } + return c; } - return c; -} /* Pack 'void *' into a string buffer. */ -SWIGRUNTIME char * -SWIG_PackVoidPtr(char *buff, void *ptr, const char *name, size_t bsz) { - char *r = buff; - if ((2*sizeof(void *) + 2) > bsz) return 0; - *(r++) = '_'; - r = SWIG_PackData(r,&ptr,sizeof(void *)); - if (strlen(name) + 1 > (bsz - (r - buff))) return 0; - strcpy(r,name); - return buff; -} - -SWIGRUNTIME const char * -SWIG_UnpackVoidPtr(const char *c, void **ptr, const char *name) { - if (*c != '_') { - if (strcmp(c,"NULL") == 0) { - *ptr = (void *) 0; - return name; - } else { + SWIGRUNTIME char *SWIG_PackVoidPtr(char *buff, void *ptr, + const char *name, size_t bsz) { + char *r = buff; + if ((2 * sizeof(void *) + 2) > bsz) return 0; - } - } - return SWIG_UnpackData(++c,ptr,sizeof(void *)); -} - -SWIGRUNTIME char * -SWIG_PackDataName(char *buff, void *ptr, size_t sz, const char *name, size_t bsz) { - char *r = buff; - size_t lname = (name ? strlen(name) : 0); - if ((2*sz + 2 + lname) > bsz) return 0; - *(r++) = '_'; - r = SWIG_PackData(r,ptr,sz); - if (lname) { - strncpy(r,name,lname+1); - } else { - *r = 0; - } - return buff; -} - -SWIGRUNTIME const char * -SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) { - if (*c != '_') { - if (strcmp(c,"NULL") == 0) { - memset(ptr,0,sz); - return name; - } else { + *(r++) = '_'; + r = SWIG_PackData(r, &ptr, sizeof(void *)); + if (strlen(name) + 1 > (bsz - (r - buff))) return 0; - } + strcpy(r, name); + return buff; + } + + SWIGRUNTIME const char *SWIG_UnpackVoidPtr(const char *c, void **ptr, + const char *name) { + if (*c != '_') { + if (strcmp(c, "NULL") == 0) { + *ptr = (void *) 0; + return name; + } else { + return 0; + } + } + return SWIG_UnpackData(++c, ptr, sizeof(void *)); + } + + SWIGRUNTIME char *SWIG_PackDataName(char *buff, void *ptr, size_t sz, + const char *name, size_t bsz) { + char *r = buff; + size_t lname = (name ? strlen(name) : 0); + if ((2 * sz + 2 + lname) > bsz) + return 0; + *(r++) = '_'; + r = SWIG_PackData(r, ptr, sz); + if (lname) { + strncpy(r, name, lname + 1); + } else { + *r = 0; + } + return buff; + } + + SWIGRUNTIME const char *SWIG_UnpackDataName(const char *c, void *ptr, + size_t sz, + const char *name) { + if (*c != '_') { + if (strcmp(c, "NULL") == 0) { + memset(ptr, 0, sz); + return name; + } else { + return 0; + } + } + return SWIG_UnpackData(++c, ptr, sz); } - return SWIG_UnpackData(++c,ptr,sz); -} #ifdef __cplusplus } #endif /* Errors in SWIG */ -#define SWIG_UnknownError -1 -#define SWIG_IOError -2 -#define SWIG_RuntimeError -3 -#define SWIG_IndexError -4 -#define SWIG_TypeError -5 -#define SWIG_DivisionByZero -6 -#define SWIG_OverflowError -7 -#define SWIG_SyntaxError -8 -#define SWIG_ValueError -9 +#define SWIG_UnknownError -1 +#define SWIG_IOError -2 +#define SWIG_RuntimeError -3 +#define SWIG_IndexError -4 +#define SWIG_TypeError -5 +#define SWIG_DivisionByZero -6 +#define SWIG_OverflowError -7 +#define SWIG_SyntaxError -8 +#define SWIG_ValueError -9 #define SWIG_SystemError -10 #define SWIG_AttributeError -11 -#define SWIG_MemoryError -12 +#define SWIG_MemoryError -12 #define SWIG_NullReferenceError -13 @@ -703,10 +718,10 @@ SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) { * error manipulation * ----------------------------------------------------------------------------- */ -SWIGINTERN const char* -SWIG_Tcl_ErrorType(int code) { - const char* type = 0; - switch(code) { +SWIGINTERN const char *SWIG_Tcl_ErrorType(int code) +{ + const char *type = 0; + switch (code) { case SWIG_MemoryError: type = "MemoryError"; break; @@ -748,7 +763,7 @@ SWIG_Tcl_ErrorType(int code) { SWIGINTERN void -SWIG_Tcl_SetErrorObj(Tcl_Interp *interp, const char *ctype, Tcl_Obj *obj) +SWIG_Tcl_SetErrorObj(Tcl_Interp * interp, const char *ctype, Tcl_Obj * obj) { Tcl_ResetResult(interp); Tcl_SetObjResult(interp, obj); @@ -756,20 +771,21 @@ SWIG_Tcl_SetErrorObj(Tcl_Interp *interp, const char *ctype, Tcl_Obj *obj) } SWIGINTERN void -SWIG_Tcl_SetErrorMsg(Tcl_Interp *interp, const char *ctype, const char *mesg) +SWIG_Tcl_SetErrorMsg(Tcl_Interp * interp, const char *ctype, + const char *mesg) { Tcl_ResetResult(interp); Tcl_SetErrorCode(interp, "SWIG", ctype, NULL); Tcl_AppendResult(interp, ctype, " ", mesg, NULL); /* - Tcl_AddErrorInfo(interp, ctype); - Tcl_AddErrorInfo(interp, " "); - Tcl_AddErrorInfo(interp, mesg); - */ + Tcl_AddErrorInfo(interp, ctype); + Tcl_AddErrorInfo(interp, " "); + Tcl_AddErrorInfo(interp, mesg); + */ } SWIGINTERNINLINE void -SWIG_Tcl_AddErrorMsg(Tcl_Interp *interp, const char* mesg) +SWIG_Tcl_AddErrorMsg(Tcl_Interp * interp, const char *mesg) { Tcl_AddErrorInfo(interp, mesg); } @@ -792,91 +808,95 @@ extern "C" { #define SWIG_TCL_BINARY 5 /* Constant information structure */ -typedef struct swig_const_info { + typedef struct swig_const_info { int type; char *name; long lvalue; double dvalue; - void *pvalue; + void *pvalue; swig_type_info **ptype; -} swig_const_info; + } swig_const_info; -typedef int (*swig_wrapper)(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []); -typedef int (*swig_wrapper_func)(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []); -typedef char *(*swig_variable_func)(ClientData, Tcl_Interp *, char *, char *, int); -typedef void (*swig_delete_func)(ClientData); + typedef int (*swig_wrapper) (ClientData, Tcl_Interp *, int, + Tcl_Obj * CONST[]); + typedef int (*swig_wrapper_func) (ClientData, Tcl_Interp *, int, + Tcl_Obj * CONST[]); + typedef char *(*swig_variable_func) (ClientData, Tcl_Interp *, char *, + char *, int); + typedef void (*swig_delete_func) (ClientData); -typedef struct swig_method { - const char *name; - swig_wrapper method; -} swig_method; + typedef struct swig_method { + const char *name; + swig_wrapper method; + } swig_method; -typedef struct swig_attribute { - const char *name; - swig_wrapper getmethod; - swig_wrapper setmethod; -} swig_attribute; + typedef struct swig_attribute { + const char *name; + swig_wrapper getmethod; + swig_wrapper setmethod; + } swig_attribute; -typedef struct swig_class { - const char *name; - swig_type_info **type; - swig_wrapper constructor; - void (*destructor)(void *); - swig_method *methods; - swig_attribute *attributes; - struct swig_class **bases; - char **base_names; - swig_module_info *module; -} swig_class; + typedef struct swig_class { + const char *name; + swig_type_info **type; + swig_wrapper constructor; + void (*destructor) (void *); + swig_method *methods; + swig_attribute *attributes; + struct swig_class **bases; + char **base_names; + swig_module_info *module; + } swig_class; -typedef struct swig_instance { - Tcl_Obj *thisptr; - void *thisvalue; - swig_class *classptr; - int destroy; - Tcl_Command cmdtok; -} swig_instance; + typedef struct swig_instance { + Tcl_Obj *thisptr; + void *thisvalue; + swig_class *classptr; + int destroy; + Tcl_Command cmdtok; + } swig_instance; /* Structure for command table */ -typedef struct { - const char *name; - int (*wrapper)(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []); - ClientData clientdata; -} swig_command_info; + typedef struct { + const char *name; + int (*wrapper) (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]); + ClientData clientdata; + } swig_command_info; /* Structure for variable linking table */ -typedef struct { - const char *name; - void *addr; - char * (*get)(ClientData, Tcl_Interp *, char *, char *, int); - char * (*set)(ClientData, Tcl_Interp *, char *, char *, int); -} swig_var_info; + typedef struct { + const char *name; + void *addr; + char *(*get) (ClientData, Tcl_Interp *, char *, char *, int); + char *(*set) (ClientData, Tcl_Interp *, char *, char *, int); + } swig_var_info; /* -----------------------------------------------------------------------------* * Install a constant object * -----------------------------------------------------------------------------*/ -static Tcl_HashTable swigconstTable; -static int swigconstTableinit = 0; + static Tcl_HashTable swigconstTable; + static int swigconstTableinit = 0; -SWIGINTERN void -SWIG_Tcl_SetConstantObj(Tcl_Interp *interp, const char* name, Tcl_Obj *obj) { - int newobj; - Tcl_ObjSetVar2(interp,Tcl_NewStringObj(name,-1), NULL, obj, TCL_GLOBAL_ONLY); - Tcl_SetHashValue(Tcl_CreateHashEntry(&swigconstTable, name, &newobj), (ClientData) obj); -} - -SWIGINTERN Tcl_Obj * -SWIG_Tcl_GetConstantObj(const char *key) { - Tcl_HashEntry *entryPtr; - if (!swigconstTableinit) return 0; - entryPtr = Tcl_FindHashEntry(&swigconstTable, key); - if (entryPtr) { - return (Tcl_Obj *) Tcl_GetHashValue(entryPtr); + SWIGINTERN void + SWIG_Tcl_SetConstantObj(Tcl_Interp * interp, const char *name, + Tcl_Obj * obj) { + int newobj; + Tcl_ObjSetVar2(interp, Tcl_NewStringObj(name, -1), NULL, obj, + TCL_GLOBAL_ONLY); + Tcl_SetHashValue(Tcl_CreateHashEntry(&swigconstTable, name, &newobj), + (ClientData) obj); + } SWIGINTERN Tcl_Obj *SWIG_Tcl_GetConstantObj(const char *key) { + Tcl_HashEntry *entryPtr; + if (!swigconstTableinit) + return 0; + entryPtr = Tcl_FindHashEntry(&swigconstTable, key); + if (entryPtr) { + return (Tcl_Obj *) Tcl_GetHashValue(entryPtr); + } + return 0; } - return 0; -} #ifdef __cplusplus } @@ -919,30 +939,30 @@ SWIG_Tcl_GetConstantObj(const char *key) { /* Runtime API */ -#define SWIG_GetModule(clientdata) SWIG_Tcl_GetModule((Tcl_Interp *) (clientdata)) +#define SWIG_GetModule(clientdata) SWIG_Tcl_GetModule((Tcl_Interp *) (clientdata)) #define SWIG_SetModule(clientdata, pointer) SWIG_Tcl_SetModule((Tcl_Interp *) (clientdata), pointer) /* Error manipulation */ -#define SWIG_ErrorType(code) SWIG_Tcl_ErrorType(code) +#define SWIG_ErrorType(code) SWIG_Tcl_ErrorType(code) #define SWIG_Error(code, msg) SWIG_Tcl_SetErrorMsg(interp, SWIG_Tcl_ErrorType(code), msg) -#define SWIG_fail goto fail +#define SWIG_fail goto fail /* Tcl-specific SWIG API */ -#define SWIG_Acquire(ptr) SWIG_Tcl_Acquire(ptr) -#define SWIG_MethodCommand SWIG_Tcl_MethodCommand -#define SWIG_Disown(ptr) SWIG_Tcl_Disown(ptr) -#define SWIG_ConvertPtrFromString(c, ptr, ty, flags) SWIG_Tcl_ConvertPtrFromString(interp, c, ptr, ty, flags) -#define SWIG_MakePtr(c, ptr, ty, flags) SWIG_Tcl_MakePtr(c, ptr, ty, flags) -#define SWIG_PointerTypeFromString(c) SWIG_Tcl_PointerTypeFromString(c) -#define SWIG_GetArgs SWIG_Tcl_GetArgs -#define SWIG_GetConstantObj(key) SWIG_Tcl_GetConstantObj(key) -#define SWIG_ObjectConstructor SWIG_Tcl_ObjectConstructor -#define SWIG_Thisown(ptr) SWIG_Tcl_Thisown(ptr) -#define SWIG_ObjectDelete SWIG_Tcl_ObjectDelete +#define SWIG_Acquire(ptr) SWIG_Tcl_Acquire(ptr) +#define SWIG_MethodCommand SWIG_Tcl_MethodCommand +#define SWIG_Disown(ptr) SWIG_Tcl_Disown(ptr) +#define SWIG_ConvertPtrFromString(c, ptr, ty, flags) SWIG_Tcl_ConvertPtrFromString(interp, c, ptr, ty, flags) +#define SWIG_MakePtr(c, ptr, ty, flags) SWIG_Tcl_MakePtr(c, ptr, ty, flags) +#define SWIG_PointerTypeFromString(c) SWIG_Tcl_PointerTypeFromString(c) +#define SWIG_GetArgs SWIG_Tcl_GetArgs +#define SWIG_GetConstantObj(key) SWIG_Tcl_GetConstantObj(key) +#define SWIG_ObjectConstructor SWIG_Tcl_ObjectConstructor +#define SWIG_Thisown(ptr) SWIG_Tcl_Thisown(ptr) +#define SWIG_ObjectDelete SWIG_Tcl_ObjectDelete #define SWIG_TCL_DECL_ARGS_2(arg1, arg2) (Tcl_Interp *interp SWIGUNUSED, arg1, arg2) @@ -960,16 +980,14 @@ SWIG_Tcl_GetConstantObj(const char *key) { #ifdef __cplusplus extern "C" { #if 0 -} /* cc-mode */ +} /* cc-mode */ #endif #endif - -/* Object support */ - -SWIGRUNTIME Tcl_HashTable* -SWIG_Tcl_ObjectTable(void) { - static Tcl_HashTable swigobjectTable; - static int swigobjectTableinit = 0; +/* Object support */ SWIGRUNTIME Tcl_HashTable * +SWIG_Tcl_ObjectTable(void) +{ + static Tcl_HashTable swigobjectTable; + static int swigobjectTableinit = 0; if (!swigobjectTableinit) { Tcl_InitHashTable(&swigobjectTable, TCL_ONE_WORD_KEYS); swigobjectTableinit = 1; @@ -978,14 +996,14 @@ SWIG_Tcl_ObjectTable(void) { } /* Acquire ownership of a pointer */ -SWIGRUNTIME void -SWIG_Tcl_Acquire(void *ptr) { +SWIGRUNTIME void SWIG_Tcl_Acquire(void *ptr) +{ int newobj; Tcl_CreateHashEntry(SWIG_Tcl_ObjectTable(), (char *) ptr, &newobj); } -SWIGRUNTIME int -SWIG_Tcl_Thisown(void *ptr) { +SWIGRUNTIME int SWIG_Tcl_Thisown(void *ptr) +{ if (Tcl_FindHashEntry(SWIG_Tcl_ObjectTable(), (char *) ptr)) { return 1; } @@ -993,9 +1011,10 @@ SWIG_Tcl_Thisown(void *ptr) { } /* Disown a pointer. Returns 1 if we owned it to begin with */ -SWIGRUNTIME int -SWIG_Tcl_Disown(void *ptr) { - Tcl_HashEntry *entryPtr = Tcl_FindHashEntry(SWIG_Tcl_ObjectTable(), (char *) ptr); +SWIGRUNTIME int SWIG_Tcl_Disown(void *ptr) +{ + Tcl_HashEntry *entryPtr = + Tcl_FindHashEntry(SWIG_Tcl_ObjectTable(), (char *) ptr); if (entryPtr) { Tcl_DeleteHashEntry(entryPtr); return 1; @@ -1005,14 +1024,17 @@ SWIG_Tcl_Disown(void *ptr) { /* Convert a pointer value */ SWIGRUNTIME int -SWIG_Tcl_ConvertPtrFromString(Tcl_Interp *interp, const char *c, void **ptr, swig_type_info *ty, int flags) { +SWIG_Tcl_ConvertPtrFromString(Tcl_Interp * interp, const char *c, + void **ptr, swig_type_info * ty, int flags) +{ swig_cast_info *tc; /* Pointer values must start with leading underscore */ while (*c != '_') { *ptr = (void *) 0; - if (strcmp(c,"NULL") == 0) return SWIG_OK; + if (strcmp(c, "NULL") == 0) + return SWIG_OK; /* Hmmm. It could be an object name. */ - if (Tcl_VarEval(interp,c," cget -this", (char *) NULL) == TCL_OK) { + if (Tcl_VarEval(interp, c, " cget -this", (char *) NULL) == TCL_OK) { Tcl_Obj *result = Tcl_GetObjResult(interp); c = Tcl_GetStringFromObj(result, NULL); continue; @@ -1021,29 +1043,33 @@ SWIG_Tcl_ConvertPtrFromString(Tcl_Interp *interp, const char *c, void **ptr, swi return SWIG_ERROR; } c++; - c = SWIG_UnpackData(c,ptr,sizeof(void *)); + c = SWIG_UnpackData(c, ptr, sizeof(void *)); if (ty) { - tc = c ? SWIG_TypeCheck(c,ty) : 0; + tc = c ? SWIG_TypeCheck(c, ty) : 0; if (!tc) { return SWIG_ERROR; } if (flags & SWIG_POINTER_DISOWN) { SWIG_Disown((void *) *ptr); } - *ptr = SWIG_TypeCast(tc,(void *) *ptr); + *ptr = SWIG_TypeCast(tc, (void *) *ptr); } return SWIG_OK; } /* Convert a pointer value */ SWIGRUNTIMEINLINE int -SWIG_Tcl_ConvertPtr(Tcl_Interp *interp, Tcl_Obj *oc, void **ptr, swig_type_info *ty, int flags) { - return SWIG_Tcl_ConvertPtrFromString(interp, Tcl_GetStringFromObj(oc,NULL), ptr, ty, flags); +SWIG_Tcl_ConvertPtr(Tcl_Interp * interp, Tcl_Obj * oc, void **ptr, + swig_type_info * ty, int flags) +{ + return SWIG_Tcl_ConvertPtrFromString(interp, + Tcl_GetStringFromObj(oc, NULL), ptr, + ty, flags); } /* Convert a pointer value */ -SWIGRUNTIME char * -SWIG_Tcl_PointerTypeFromString(char *c) { +SWIGRUNTIME char *SWIG_Tcl_PointerTypeFromString(char *c) +{ char d; /* Pointer values must start with leading underscore. NULL has no type */ if (*c != '_') { @@ -1052,7 +1078,8 @@ SWIG_Tcl_PointerTypeFromString(char *c) { c++; /* Extract hex value from pointer */ while ((d = *c)) { - if (!(((d >= '0') && (d <= '9')) || ((d >= 'a') && (d <= 'f')))) break; + if (!(((d >= '0') && (d <= '9')) || ((d >= 'a') && (d <= 'f')))) + break; c++; } return c; @@ -1060,23 +1087,28 @@ SWIG_Tcl_PointerTypeFromString(char *c) { /* Convert a packed value value */ SWIGRUNTIME int -SWIG_Tcl_ConvertPacked(Tcl_Interp *SWIGUNUSEDPARM(interp) , Tcl_Obj *obj, void *ptr, int sz, swig_type_info *ty) { +SWIG_Tcl_ConvertPacked(Tcl_Interp * SWIGUNUSEDPARM(interp), Tcl_Obj * obj, + void *ptr, int sz, swig_type_info * ty) +{ swig_cast_info *tc; - const char *c; + const char *c; - if (!obj) goto type_error; - c = Tcl_GetStringFromObj(obj,NULL); + if (!obj) + goto type_error; + c = Tcl_GetStringFromObj(obj, NULL); /* Pointer values must start with leading underscore */ - if (*c != '_') goto type_error; + if (*c != '_') + goto type_error; c++; - c = SWIG_UnpackData(c,ptr,sz); + c = SWIG_UnpackData(c, ptr, sz); if (ty) { - tc = SWIG_TypeCheck(c,ty); - if (!tc) goto type_error; + tc = SWIG_TypeCheck(c, ty); + if (!tc) + goto type_error; } return SWIG_OK; - type_error: +type_error: return SWIG_ERROR; } @@ -1084,49 +1116,58 @@ SWIG_Tcl_ConvertPacked(Tcl_Interp *SWIGUNUSEDPARM(interp) , Tcl_Obj *obj, void * /* Take a pointer and convert it to a string */ SWIGRUNTIME void -SWIG_Tcl_MakePtr(char *c, void *ptr, swig_type_info *ty, int flags) { +SWIG_Tcl_MakePtr(char *c, void *ptr, swig_type_info * ty, int flags) +{ if (ptr) { *(c++) = '_'; - c = SWIG_PackData(c,&ptr,sizeof(void *)); - strcpy(c,ty->name); + c = SWIG_PackData(c, &ptr, sizeof(void *)); + strcpy(c, ty->name); } else { - strcpy(c,(char *)"NULL"); + strcpy(c, (char *) "NULL"); } flags = 0; } /* Create a new pointer object */ -SWIGRUNTIMEINLINE Tcl_Obj * -SWIG_Tcl_NewPointerObj(void *ptr, swig_type_info *type, int flags) { +SWIGRUNTIMEINLINE Tcl_Obj *SWIG_Tcl_NewPointerObj(void *ptr, + swig_type_info * type, + int flags) +{ Tcl_Obj *robj; char result[SWIG_BUFFER_SIZE]; - SWIG_MakePtr(result,ptr,type,flags); - robj = Tcl_NewStringObj(result,-1); + SWIG_MakePtr(result, ptr, type, flags); + robj = Tcl_NewStringObj(result, -1); return robj; } -SWIGRUNTIME Tcl_Obj * -SWIG_Tcl_NewPackedObj(void *ptr, int sz, swig_type_info *type) { +SWIGRUNTIME Tcl_Obj *SWIG_Tcl_NewPackedObj(void *ptr, int sz, + swig_type_info * type) +{ char result[1024]; char *r = result; - if ((2*sz + 1 + strlen(type->name)) > 1000) return 0; + if ((2 * sz + 1 + strlen(type->name)) > 1000) + return 0; *(r++) = '_'; - r = SWIG_PackData(r,ptr,sz); - strcpy(r,type->name); - return Tcl_NewStringObj(result,-1); + r = SWIG_PackData(r, ptr, sz); + strcpy(r, type->name); + return Tcl_NewStringObj(result, -1); } /* -----------------------------------------------------------------------------* * Get type list * -----------------------------------------------------------------------------*/ -SWIGRUNTIME swig_module_info * -SWIG_Tcl_GetModule(Tcl_Interp *interp) { +SWIGRUNTIME swig_module_info *SWIG_Tcl_GetModule(Tcl_Interp * interp) +{ const char *data; swig_module_info *ret = 0; - + /* first check if pointer already created */ - data = Tcl_GetVar(interp, (char *)"swig_runtime_data_type_pointer" SWIG_RUNTIME_VERSION SWIG_TYPE_TABLE_NAME, TCL_GLOBAL_ONLY); + data = + Tcl_GetVar(interp, + (char *) "swig_runtime_data_type_pointer" + SWIG_RUNTIME_VERSION SWIG_TYPE_TABLE_NAME, + TCL_GLOBAL_ONLY); if (data) { SWIG_UnpackData(data, &ret, sizeof(swig_type_info **)); } @@ -1135,14 +1176,17 @@ SWIG_Tcl_GetModule(Tcl_Interp *interp) { } SWIGRUNTIME void -SWIG_Tcl_SetModule(Tcl_Interp *interp, swig_module_info *module) { +SWIG_Tcl_SetModule(Tcl_Interp * interp, swig_module_info * module) +{ char buf[SWIG_BUFFER_SIZE]; char *data; /* create a new pointer */ data = SWIG_PackData(buf, &module, sizeof(swig_type_info **)); *data = 0; - Tcl_SetVar(interp, (char *)"swig_runtime_data_type_pointer" SWIG_RUNTIME_VERSION SWIG_TYPE_TABLE_NAME, buf, 0); + Tcl_SetVar(interp, + (char *) "swig_runtime_data_type_pointer" SWIG_RUNTIME_VERSION + SWIG_TYPE_TABLE_NAME, buf, 0); } /* -----------------------------------------------------------------------------* @@ -1150,12 +1194,12 @@ SWIG_Tcl_SetModule(Tcl_Interp *interp, swig_module_info *module) { * -----------------------------------------------------------------------------*/ -SWIGRUNTIME void -SWIG_Tcl_ObjectDelete(ClientData clientData) { +SWIGRUNTIME void SWIG_Tcl_ObjectDelete(ClientData clientData) +{ swig_instance *si = (swig_instance *) clientData; if ((si) && (si->destroy) && (SWIG_Disown(si->thisvalue))) { if (si->classptr->destructor) { - (si->classptr->destructor)(si->thisvalue); + (si->classptr->destructor) (si->thisvalue); } } Tcl_DecrRefCount(si->thisptr); @@ -1164,41 +1208,43 @@ SWIG_Tcl_ObjectDelete(ClientData clientData) { /* Function to invoke object methods given an instance */ SWIGRUNTIME int -SWIG_Tcl_MethodCommand(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST _objv[]) { - char *method, *attrname; - swig_instance *inst = (swig_instance *) clientData; - swig_method *meth; - swig_attribute *attr; - Tcl_Obj *oldarg; - Tcl_Obj **objv; - int rcode; - swig_class *cls; - swig_class *cls_stack[64]; - int cls_stack_bi[64]; - int cls_stack_top = 0; - int numconf = 2; - int bi; +SWIG_Tcl_MethodCommand(ClientData clientData, Tcl_Interp * interp, + int objc, Tcl_Obj * CONST _objv[]) +{ + char *method, *attrname; + swig_instance *inst = (swig_instance *) clientData; + swig_method *meth; + swig_attribute *attr; + Tcl_Obj *oldarg; + Tcl_Obj **objv; + int rcode; + swig_class *cls; + swig_class *cls_stack[64]; + int cls_stack_bi[64]; + int cls_stack_top = 0; + int numconf = 2; + int bi; objv = (Tcl_Obj **) _objv; if (objc < 2) { Tcl_SetResult(interp, (char *) "wrong # args.", TCL_STATIC); return TCL_ERROR; } - method = Tcl_GetStringFromObj(objv[1],NULL); - if (strcmp(method,"-acquire") == 0) { + method = Tcl_GetStringFromObj(objv[1], NULL); + if (strcmp(method, "-acquire") == 0) { inst->destroy = 1; SWIG_Acquire(inst->thisvalue); return TCL_OK; } - if (strcmp(method,"-disown") == 0) { + if (strcmp(method, "-disown") == 0) { if (inst->destroy) { SWIG_Disown(inst->thisvalue); } inst->destroy = 0; return TCL_OK; } - if (strcmp(method,"-delete") == 0) { - Tcl_DeleteCommandFromToken(interp,inst->cmdtok); + if (strcmp(method, "-delete") == 0) { + Tcl_DeleteCommandFromToken(interp, inst->cmdtok); return TCL_OK; } cls_stack[cls_stack_top] = inst->classptr; @@ -1210,8 +1256,11 @@ SWIG_Tcl_MethodCommand(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_ if (bi != -1) { if (!cls->bases[bi] && cls->base_names[bi]) { /* lookup and cache the base class */ - swig_type_info *info = SWIG_TypeQueryModule(cls->module, cls->module, cls->base_names[bi]); - if (info) cls->bases[bi] = (swig_class *) info->clientdata; + swig_type_info *info = + SWIG_TypeQueryModule(cls->module, cls->module, + cls->base_names[bi]); + if (info) + cls->bases[bi] = (swig_class *) info->clientdata; } cls = cls->bases[bi]; if (cls) { @@ -1224,19 +1273,21 @@ SWIG_Tcl_MethodCommand(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_ } if (!cls) { cls_stack_top--; - if (cls_stack_top < 0) break; - else continue; + if (cls_stack_top < 0) + break; + else + continue; } cls_stack_bi[cls_stack_top]++; meth = cls->methods; /* Check for methods */ while (meth && meth->name) { - if (strcmp(meth->name,method) == 0) { + if (strcmp(meth->name, method) == 0) { oldarg = objv[1]; objv[1] = inst->thisptr; Tcl_IncrRefCount(inst->thisptr); - rcode = (*meth->method)(clientData,interp,objc,objv); + rcode = (*meth->method) (clientData, interp, objc, objv); objv[1] = oldarg; Tcl_DecrRefCount(inst->thisptr); return rcode; @@ -1244,19 +1295,19 @@ SWIG_Tcl_MethodCommand(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_ meth++; } /* Check class methods for a match */ - if (strcmp(method,"cget") == 0) { + if (strcmp(method, "cget") == 0) { if (objc < 3) { Tcl_SetResult(interp, (char *) "wrong # args.", TCL_STATIC); return TCL_ERROR; } - attrname = Tcl_GetStringFromObj(objv[2],NULL); + attrname = Tcl_GetStringFromObj(objv[2], NULL); attr = cls->attributes; while (attr && attr->name) { if ((strcmp(attr->name, attrname) == 0) && (attr->getmethod)) { oldarg = objv[1]; objv[1] = inst->thisptr; Tcl_IncrRefCount(inst->thisptr); - rcode = (*attr->getmethod)(clientData,interp,2, objv); + rcode = (*attr->getmethod) (clientData, interp, 2, objv); objv[1] = oldarg; Tcl_DecrRefCount(inst->thisptr); return rcode; @@ -1269,9 +1320,9 @@ SWIG_Tcl_MethodCommand(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_ } if (strcmp(attrname, "-thisown") == 0) { if (SWIG_Thisown(inst->thisvalue)) { - Tcl_SetResult(interp,(char*)"1",TCL_STATIC); + Tcl_SetResult(interp, (char *) "1", TCL_STATIC); } else { - Tcl_SetResult(interp,(char*)"0",TCL_STATIC); + Tcl_SetResult(interp, (char *) "0", TCL_STATIC); } return TCL_OK; } @@ -1283,38 +1334,44 @@ SWIG_Tcl_MethodCommand(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_ } i = 2; while (i < objc) { - attrname = Tcl_GetStringFromObj(objv[i],NULL); + attrname = Tcl_GetStringFromObj(objv[i], NULL); attr = cls->attributes; while (attr && attr->name) { if ((strcmp(attr->name, attrname) == 0) && (attr->setmethod)) { oldarg = objv[i]; objv[i] = inst->thisptr; Tcl_IncrRefCount(inst->thisptr); - rcode = (*attr->setmethod)(clientData,interp,3, &objv[i-1]); + rcode = + (*attr->setmethod) (clientData, interp, 3, &objv[i - 1]); objv[i] = oldarg; Tcl_DecrRefCount(inst->thisptr); - if (rcode != TCL_OK) return rcode; + if (rcode != TCL_OK) + return rcode; numconf += 2; } attr++; } - i+=2; + i += 2; } } } - if (strcmp(method,"configure") == 0) { + if (strcmp(method, "configure") == 0) { if (numconf >= objc) { return TCL_OK; } else { - Tcl_SetResult(interp,(char *) "Invalid attribute name.", TCL_STATIC); + Tcl_SetResult(interp, (char *) "Invalid attribute name.", + TCL_STATIC); return TCL_ERROR; } } - if (strcmp(method,"cget") == 0) { - Tcl_SetResult(interp,(char *) "Invalid attribute name.", TCL_STATIC); + if (strcmp(method, "cget") == 0) { + Tcl_SetResult(interp, (char *) "Invalid attribute name.", TCL_STATIC); return TCL_ERROR; } - Tcl_SetResult(interp, (char *) "Invalid method. Must be one of: configure cget -acquire -disown -delete", TCL_STATIC); + Tcl_SetResult(interp, + (char *) + "Invalid method. Must be one of: configure cget -acquire -disown -delete", + TCL_STATIC); cls = inst->classptr; bi = 0; while (cls) { @@ -1322,11 +1379,12 @@ SWIG_Tcl_MethodCommand(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_ while (meth && meth->name) { char *cr = (char *) Tcl_GetStringResult(interp); int meth_len = strlen(meth->name); - char* where = strchr(cr,':'); - while(where) { + char *where = strchr(cr, ':'); + while (where) { where = strstr(where, meth->name); - if(where) { - if(where[-1] == ' ' && (where[meth_len] == ' ' || where[meth_len]==0)) { + if (where) { + if (where[-1] == ' ' + && (where[meth_len] == ' ' || where[meth_len] == 0)) { break; } else { where++; @@ -1344,22 +1402,30 @@ SWIG_Tcl_MethodCommand(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_ } /* This function takes the current result and turns it into an object command */ -SWIGRUNTIME Tcl_Obj * -SWIG_Tcl_NewInstanceObj(Tcl_Interp *interp, void *thisvalue, swig_type_info *type, int flags) { - Tcl_Obj *robj = SWIG_NewPointerObj(thisvalue, type,0); +SWIGRUNTIME Tcl_Obj *SWIG_Tcl_NewInstanceObj(Tcl_Interp * interp, + void *thisvalue, + swig_type_info * type, + int flags) +{ + Tcl_Obj *robj = SWIG_NewPointerObj(thisvalue, type, 0); /* Check to see if this pointer belongs to a class or not */ if ((type->clientdata) && (interp)) { - Tcl_CmdInfo ci; - char *name; - name = Tcl_GetStringFromObj(robj,NULL); - if (!Tcl_GetCommandInfo(interp,name, &ci) || (flags)) { - swig_instance *newinst = (swig_instance *) malloc(sizeof(swig_instance)); + Tcl_CmdInfo ci; + char *name; + name = Tcl_GetStringFromObj(robj, NULL); + if (!Tcl_GetCommandInfo(interp, name, &ci) || (flags)) { + swig_instance *newinst = + (swig_instance *) malloc(sizeof(swig_instance)); newinst->thisptr = Tcl_DuplicateObj(robj); Tcl_IncrRefCount(newinst->thisptr); newinst->thisvalue = thisvalue; newinst->classptr = (swig_class *) type->clientdata; newinst->destroy = flags; - newinst->cmdtok = Tcl_CreateObjCommand(interp, Tcl_GetStringFromObj(robj,NULL), (swig_wrapper_func) SWIG_MethodCommand, (ClientData) newinst, (swig_delete_func) SWIG_ObjectDelete); + newinst->cmdtok = + Tcl_CreateObjCommand(interp, Tcl_GetStringFromObj(robj, NULL), + (swig_wrapper_func) SWIG_MethodCommand, + (ClientData) newinst, + (swig_delete_func) SWIG_ObjectDelete); if (flags) { SWIG_Acquire(thisvalue); } @@ -1370,28 +1436,33 @@ SWIG_Tcl_NewInstanceObj(Tcl_Interp *interp, void *thisvalue, swig_type_info *typ /* Function to create objects */ SWIGRUNTIME int -SWIG_Tcl_ObjectConstructor(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - Tcl_Obj *newObj = 0; - void *thisvalue = 0; - swig_instance *newinst = 0; - swig_class *classptr = (swig_class *) clientData; - swig_wrapper cons = 0; - char *name = 0; - int firstarg = 0; - int thisarg = 0; - int destroy = 1; +SWIG_Tcl_ObjectConstructor(ClientData clientData, Tcl_Interp * interp, + int objc, Tcl_Obj * CONST objv[]) +{ + Tcl_Obj *newObj = 0; + void *thisvalue = 0; + swig_instance *newinst = 0; + swig_class *classptr = (swig_class *) clientData; + swig_wrapper cons = 0; + char *name = 0; + int firstarg = 0; + int thisarg = 0; + int destroy = 1; if (!classptr) { - Tcl_SetResult(interp, (char *) "swig: internal runtime error. No class object defined.", TCL_STATIC); + Tcl_SetResult(interp, + (char *) + "swig: internal runtime error. No class object defined.", + TCL_STATIC); return TCL_ERROR; } cons = classptr->constructor; if (objc > 1) { - char *s = Tcl_GetStringFromObj(objv[1],NULL); - if (strcmp(s,"-this") == 0) { + char *s = Tcl_GetStringFromObj(objv[1], NULL); + if (strcmp(s, "-this") == 0) { thisarg = 2; cons = 0; - } else if (strcmp(s,"-args") == 0) { + } else if (strcmp(s, "-args") == 0) { firstarg = 1; } else if (objc == 2) { firstarg = 1; @@ -1399,37 +1470,42 @@ SWIG_Tcl_ObjectConstructor(ClientData clientData, Tcl_Interp *interp, int objc, } else if (objc >= 3) { char *s1; name = s; - s1 = Tcl_GetStringFromObj(objv[2],NULL); - if (strcmp(s1,"-this") == 0) { - thisarg = 3; - cons = 0; + s1 = Tcl_GetStringFromObj(objv[2], NULL); + if (strcmp(s1, "-this") == 0) { + thisarg = 3; + cons = 0; } else { - firstarg = 1; + firstarg = 1; } } } if (cons) { int result; - result = (*cons)(0, interp, objc-firstarg, &objv[firstarg]); + result = (*cons) (0, interp, objc - firstarg, &objv[firstarg]); if (result != TCL_OK) { return result; } newObj = Tcl_DuplicateObj(Tcl_GetObjResult(interp)); - if (!name) name = Tcl_GetStringFromObj(newObj,NULL); + if (!name) + name = Tcl_GetStringFromObj(newObj, NULL); } else if (thisarg > 0) { if (thisarg < objc) { destroy = 0; newObj = Tcl_DuplicateObj(objv[thisarg]); - if (!name) name = Tcl_GetStringFromObj(newObj,NULL); + if (!name) + name = Tcl_GetStringFromObj(newObj, NULL); } else { Tcl_SetResult(interp, (char *) "wrong # args.", TCL_STATIC); return TCL_ERROR; } } else { - Tcl_SetResult(interp, (char *) "No constructor available.", TCL_STATIC); + Tcl_SetResult(interp, (char *) "No constructor available.", + TCL_STATIC); return TCL_ERROR; } - if (SWIG_Tcl_ConvertPtr(interp,newObj, (void **) &thisvalue, *(classptr->type), 0) != SWIG_OK) { + if (SWIG_Tcl_ConvertPtr + (interp, newObj, (void **) &thisvalue, *(classptr->type), + 0) != SWIG_OK) { Tcl_DecrRefCount(newObj); return TCL_ERROR; } @@ -1442,7 +1518,10 @@ SWIG_Tcl_ObjectConstructor(ClientData clientData, Tcl_Interp *interp, int objc, if (destroy) { SWIG_Acquire(thisvalue); } - newinst->cmdtok = Tcl_CreateObjCommand(interp,name, (swig_wrapper) SWIG_MethodCommand, (ClientData) newinst, (swig_delete_func) SWIG_ObjectDelete); + newinst->cmdtok = + Tcl_CreateObjCommand(interp, name, (swig_wrapper) SWIG_MethodCommand, + (ClientData) newinst, + (swig_delete_func) SWIG_ObjectDelete); return TCL_OK; } @@ -1450,25 +1529,28 @@ SWIG_Tcl_ObjectConstructor(ClientData clientData, Tcl_Interp *interp, int objc, * Get arguments * -----------------------------------------------------------------------------*/ SWIGRUNTIME int -SWIG_Tcl_GetArgs(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], const char *fmt, ...) { - int argno = 0, opt = 0; - long tempi; - double tempd; +SWIG_Tcl_GetArgs(Tcl_Interp * interp, int objc, Tcl_Obj * CONST objv[], + const char *fmt, ...) +{ + int argno = 0, opt = 0; + long tempi; + double tempd; const char *c; - va_list ap; - void *vptr; - Tcl_Obj *obj = 0; + va_list ap; + void *vptr; + Tcl_Obj *obj = 0; swig_type_info *ty; - va_start(ap,fmt); - for (c = fmt; (*c && (*c != ':') && (*c != ';')); c++,argno++) { + va_start(ap, fmt); + for (c = fmt; (*c && (*c != ':') && (*c != ';')); c++, argno++) { if (*c == '|') { opt = 1; c++; } - if (argno >= (objc-1)) { + if (argno >= (objc - 1)) { if (!opt) { - Tcl_SetResult(interp, (char *) "Wrong number of arguments ", TCL_STATIC); + Tcl_SetResult(interp, (char *) "Wrong number of arguments ", + TCL_STATIC); goto argerror; } else { va_end(ap); @@ -1476,49 +1558,72 @@ SWIG_Tcl_GetArgs(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], const char } } - vptr = va_arg(ap,void *); + vptr = va_arg(ap, void *); if (vptr) { if (isupper(*c)) { - obj = SWIG_Tcl_GetConstantObj(Tcl_GetStringFromObj(objv[argno+1],0)); - if (!obj) obj = objv[argno+1]; + obj = + SWIG_Tcl_GetConstantObj(Tcl_GetStringFromObj + (objv[argno + 1], 0)); + if (!obj) + obj = objv[argno + 1]; } else { - obj = objv[argno+1]; + obj = objv[argno + 1]; } - switch(*c) { - case 'i': case 'I': - case 'l': case 'L': - case 'h': case 'H': - case 'b': case 'B': - if (Tcl_GetLongFromObj(interp,obj,&tempi) != TCL_OK) goto argerror; - if ((*c == 'i') || (*c == 'I')) *((int *)vptr) = (int)tempi; - else if ((*c == 'l') || (*c == 'L')) *((long *)vptr) = (long)tempi; - else if ((*c == 'h') || (*c == 'H')) *((short*)vptr) = (short)tempi; - else if ((*c == 'b') || (*c == 'B')) *((unsigned char *)vptr) = (unsigned char)tempi; + switch (*c) { + case 'i': + case 'I': + case 'l': + case 'L': + case 'h': + case 'H': + case 'b': + case 'B': + if (Tcl_GetLongFromObj(interp, obj, &tempi) != TCL_OK) + goto argerror; + if ((*c == 'i') || (*c == 'I')) + *((int *) vptr) = (int) tempi; + else if ((*c == 'l') || (*c == 'L')) + *((long *) vptr) = (long) tempi; + else if ((*c == 'h') || (*c == 'H')) + *((short *) vptr) = (short) tempi; + else if ((*c == 'b') || (*c == 'B')) + *((unsigned char *) vptr) = (unsigned char) tempi; break; - case 'f': case 'F': - case 'd': case 'D': - if (Tcl_GetDoubleFromObj(interp,obj,&tempd) != TCL_OK) goto argerror; - if ((*c == 'f') || (*c == 'F')) *((float *) vptr) = (float)tempd; - else if ((*c == 'd') || (*c == 'D')) *((double*) vptr) = tempd; + case 'f': + case 'F': + case 'd': + case 'D': + if (Tcl_GetDoubleFromObj(interp, obj, &tempd) != TCL_OK) + goto argerror; + if ((*c == 'f') || (*c == 'F')) + *((float *) vptr) = (float) tempd; + else if ((*c == 'd') || (*c == 'D')) + *((double *) vptr) = tempd; break; - case 's': case 'S': - if (*(c+1) == '#') { + case 's': + case 'S': + if (*(c + 1) == '#') { int *vlptr = (int *) va_arg(ap, void *); *((char **) vptr) = Tcl_GetStringFromObj(obj, vlptr); c++; } else { - *((char **)vptr) = Tcl_GetStringFromObj(obj,NULL); + *((char **) vptr) = Tcl_GetStringFromObj(obj, NULL); } break; - case 'c': case 'C': - *((char *)vptr) = *(Tcl_GetStringFromObj(obj,NULL)); + case 'c': + case 'C': + *((char *) vptr) = *(Tcl_GetStringFromObj(obj, NULL)); break; - case 'p': case 'P': + case 'p': + case 'P': ty = (swig_type_info *) va_arg(ap, void *); - if (SWIG_Tcl_ConvertPtr(interp, obj, (void **) vptr, ty, 0) != SWIG_OK) goto argerror; + if (SWIG_Tcl_ConvertPtr(interp, obj, (void **) vptr, ty, 0) != + SWIG_OK) + goto argerror; break; - case 'o': case 'O': - *((Tcl_Obj **)vptr) = objv[argno+1]; + case 'o': + case 'O': + *((Tcl_Obj **) vptr) = objv[argno + 1]; break; default: break; @@ -1526,21 +1631,23 @@ SWIG_Tcl_GetArgs(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], const char } } - if ((*c != ';') && ((objc-1) > argno)) { + if ((*c != ';') && ((objc - 1) > argno)) { Tcl_SetResult(interp, (char *) "Wrong # args.", TCL_STATIC); goto argerror; } va_end(ap); return TCL_OK; - argerror: +argerror: { char temp[32]; - sprintf(temp,"%d", argno+1); - c = strchr(fmt,':'); - if (!c) c = strchr(fmt,';'); - if (!c) c = (char *)""; - Tcl_AppendResult(interp,c," argument ", temp, NULL); + sprintf(temp, "%d", argno + 1); + c = strchr(fmt, ':'); + if (!c) + c = strchr(fmt, ';'); + if (!c) + c = (char *) ""; + Tcl_AppendResult(interp, c, " argument ", temp, NULL); va_end(ap); return TCL_ERROR; } @@ -1548,16 +1655,16 @@ SWIG_Tcl_GetArgs(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], const char #ifdef __cplusplus #if 0 -{ /* cc-mode */ +{ /* cc-mode */ #endif } #endif -#define SWIG_exception_fail(code, msg) do { SWIG_Error(code, msg); SWIG_fail; } while(0) +#define SWIG_exception_fail(code, msg) do { SWIG_Error(code, msg); SWIG_fail; } while(0) -#define SWIG_contract_assert(expr, msg) if (!(expr)) { SWIG_Error(SWIG_RuntimeError, msg); SWIG_fail; } else +#define SWIG_contract_assert(expr, msg) if (!(expr)) { SWIG_Error(SWIG_RuntimeError, msg); SWIG_fail; } else @@ -1566,7 +1673,8 @@ SWIG_Tcl_GetArgs(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], const char #define SWIGTYPE_p_char swig_types[0] #define SWIGTYPE_p_void swig_types[1] static swig_type_info *swig_types[3]; -static swig_module_info swig_module = {swig_types, 2, 0, 0, 0, 0}; +static swig_module_info swig_module = { swig_types, 2, 0, 0, 0, 0 }; + #define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name) #define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name) @@ -1577,12 +1685,12 @@ static swig_module_info swig_module = {swig_types, 2, 0, 0, 0, 0}; #define SWIG_prefix "" #define SWIG_version "0.0" -#define SWIGVERSION 0x010331 +#define SWIGVERSION 0x010331 #define SWIG_VERSION SWIGVERSION -#define SWIG_as_voidptr(a) (void *)((const void *)(a)) -#define SWIG_as_voidptrptr(a) ((void)SWIG_as_voidptr(*a),(void**)(a)) +#define SWIG_as_voidptr(a) (void *)((const void *)(a)) +#define SWIG_as_voidptrptr(a) ((void)SWIG_as_voidptr(*a),(void**)(a)) @@ -1592,20 +1700,14 @@ extern "C" { #ifdef MAC_TCL #pragma export on #endif -SWIGEXPORT int SWIG_init(Tcl_Interp *); + SWIGEXPORT int SWIG_init(Tcl_Interp *); #ifdef MAC_TCL #pragma export off #endif #ifdef __cplusplus } #endif - - - #include "nxinterhelper.h" - - - #include #ifndef LLONG_MIN # define LLONG_MIN LONG_LONG_MIN @@ -1616,23 +1718,19 @@ SWIGEXPORT int SWIG_init(Tcl_Interp *); #ifndef ULLONG_MAX # define ULLONG_MAX ULONG_LONG_MAX #endif - - -SWIGINTERNINLINE Tcl_Obj* -SWIG_From_long (long value) +SWIGINTERNINLINE Tcl_Obj *SWIG_From_long(long value) { if (((long) INT_MIN <= value) && (value <= (long) INT_MAX)) { - return Tcl_NewIntObj((int)(value)); + return Tcl_NewIntObj((int) (value)); } else { return Tcl_NewLongObj(value); } } -SWIGINTERNINLINE Tcl_Obj * -SWIG_From_int (int value) -{ - return SWIG_From_long (value); +SWIGINTERNINLINE Tcl_Obj *SWIG_From_int(int value) +{ + return SWIG_From_long(value); } @@ -1640,83 +1738,93 @@ SWIG_From_int (int value) #define MAXDIM 7 -void *create_nxds(int rank, int type, int dim0, int dim1, int dim2, - int dim3, int dim4, int dim5,int dim6){ - int dim[MAXDIM],i; +void *create_nxds(int rank, int type, int dim0, int dim1, int dim2, + int dim3, int dim4, int dim5, int dim6) +{ + int64_t dim[MAXDIM], i; - dim[0] = dim0; - dim[1] = dim1; - dim[2] = dim2; - dim[3] = dim3; - dim[4] = dim4; - dim[5] = dim5; - dim[6] = dim6; + dim[0] = dim0; + dim[1] = dim1; + dim[2] = dim2; + dim[3] = dim3; + dim[4] = dim4; + dim[5] = dim5; + dim[6] = dim6; - return createNXDataset(rank,type,dim); + return createNXDataset(rank, type, dim); } -void *create_text_nxds(char *name){ - return (void *)createTextNXDataset(name); +void *create_text_nxds(char *name) +{ + return (void *) createTextNXDataset(name); } -void drop_nxds(void *ptr){ - dropNXDataset( (pNXDS) ptr); +void drop_nxds(void *ptr) +{ + dropNXDataset((pNXDS) ptr); } -int get_nxds_rank(void *ptr){ - return getNXDatasetRank((pNXDS) ptr); +int get_nxds_rank(void *ptr) +{ + return getNXDatasetRank((pNXDS) ptr); } -int get_nxds_type(void *ptr){ - return getNXDatasetType((pNXDS) ptr); +int get_nxds_type(void *ptr) +{ + return getNXDatasetType((pNXDS) ptr); } -int get_nxds_dim(void *ptr, int which){ - return getNXDatasetDim((pNXDS) ptr, which); +int get_nxds_dim(void *ptr, int which) +{ + return getNXDatasetDim((pNXDS) ptr, which); } -double get_nxds_value(void *ptr,int dim0, int dim1, int dim2, - int dim3, int dim4, int dim5,int dim6){ - int dim[MAXDIM]; +double get_nxds_value(void *ptr, int dim0, int dim1, int dim2, + int dim3, int dim4, int dim5, int dim6) +{ + int64_t dim[MAXDIM]; - dim[0] = dim0; - dim[1] = dim1; - dim[2] = dim2; - dim[3] = dim3; - dim[4] = dim4; - dim[5] = dim5; - dim[6] = dim6; + dim[0] = dim0; + dim[1] = dim1; + dim[2] = dim2; + dim[3] = dim3; + dim[4] = dim4; + dim[5] = dim5; + dim[6] = dim6; - return getNXDatasetValue((pNXDS)ptr,dim); + return getNXDatasetValue((pNXDS) ptr, dim); } -char *get_nxds_text(void *ptr){ - return getNXDatasetText((pNXDS) ptr); +char *get_nxds_text(void *ptr) +{ + return getNXDatasetText((pNXDS) ptr); } -int put_nxds_value(void *ptr, double value, int dim0, int dim1, int dim2, - int dim3, int dim4, int dim5,int dim6){ - int dim[MAXDIM]; +int put_nxds_value(void *ptr, double value, int dim0, int dim1, int dim2, + int dim3, int dim4, int dim5, int dim6) +{ + int64_t dim[MAXDIM]; - dim[0] = dim0; - dim[1] = dim1; - dim[2] = dim2; - dim[3] = dim3; - dim[4] = dim4; - dim[5] = dim5; - dim[6] = dim6; + dim[0] = dim0; + dim[1] = dim1; + dim[2] = dim2; + dim[3] = dim3; + dim[4] = dim4; + dim[5] = dim5; + dim[6] = dim6; - return putNXDatasetValue((pNXDS)ptr,dim,value); + return putNXDatasetValue((pNXDS) ptr, dim, value); } SWIGINTERN int -SWIG_AsVal_long SWIG_TCL_DECL_ARGS_2(Tcl_Obj *obj, long* val) +SWIG_AsVal_long SWIG_TCL_DECL_ARGS_2(Tcl_Obj * obj, long *val) { long v; - if (Tcl_GetLongFromObj(0,obj, &v) == TCL_OK) { - if (val) *val = (long) v; + if (Tcl_GetLongFromObj(0, obj, &v) == TCL_OK) { + if (val) + *val = (long) v; return SWIG_OK; } return SWIG_TypeError; @@ -1732,22 +1840,27 @@ SWIG_AsVal_int SWIG_TCL_DECL_ARGS_2(Tcl_Obj * obj, int *val) if ((v < INT_MIN || v > INT_MAX)) { return SWIG_OverflowError; } else { - if (val) *val = (int)(v); + if (val) + *val = (int) (v); } - } + } return res; } SWIGINTERN int -SWIG_AsCharPtrAndSize(Tcl_Obj *obj, char** cptr, size_t* psize, int *alloc) -{ +SWIG_AsCharPtrAndSize(Tcl_Obj * obj, char **cptr, size_t * psize, + int *alloc) +{ int len = 0; char *cstr = Tcl_GetStringFromObj(obj, &len); if (cstr) { - if (cptr) *cptr = cstr; - if (psize) *psize = len + 1; - if (alloc) *alloc = SWIG_OLDOBJ; + if (cptr) + *cptr = cstr; + if (psize) + *psize = len + 1; + if (alloc) + *alloc = SWIG_OLDOBJ; return SWIG_OK; } return SWIG_TypeError; @@ -1757,54 +1870,59 @@ SWIG_AsCharPtrAndSize(Tcl_Obj *obj, char** cptr, size_t* psize, int *alloc) - #define SWIG_From_double Tcl_NewDoubleObj +#define SWIG_From_double Tcl_NewDoubleObj -SWIGINTERNINLINE Tcl_Obj * -SWIG_FromCharPtrAndSize(const char* carray, size_t size) +SWIGINTERNINLINE Tcl_Obj *SWIG_FromCharPtrAndSize(const char *carray, + size_t size) { - return (size < INT_MAX) ? Tcl_NewStringObj(carray, (int)(size)) : NULL; + return (size < INT_MAX) ? Tcl_NewStringObj(carray, (int) (size)) : NULL; } -SWIGINTERNINLINE Tcl_Obj * -SWIG_FromCharPtr(const char *cptr) -{ +SWIGINTERNINLINE Tcl_Obj *SWIG_FromCharPtr(const char *cptr) +{ return SWIG_FromCharPtrAndSize(cptr, (cptr ? strlen(cptr) : 0)); } SWIGINTERN int -SWIG_AsVal_double SWIG_TCL_DECL_ARGS_2(Tcl_Obj *obj, double *val) +SWIG_AsVal_double SWIG_TCL_DECL_ARGS_2(Tcl_Obj * obj, double *val) { double v; if (Tcl_GetDoubleFromObj(0, obj, &v) == TCL_OK) { - if (val) *val = v; + if (val) + *val = v; return SWIG_OK; } return SWIG_TypeError; } -SWIGINTERN int -SWIG_AsCharArray(Tcl_Obj * obj, char *val, size_t size) -{ - char* cptr = 0; size_t csize = 0; int alloc = SWIG_OLDOBJ; +SWIGINTERN int SWIG_AsCharArray(Tcl_Obj * obj, char *val, size_t size) +{ + char *cptr = 0; + size_t csize = 0; + int alloc = SWIG_OLDOBJ; int res = SWIG_AsCharPtrAndSize(obj, &cptr, &csize, &alloc); if (SWIG_IsOK(res)) { - if ((csize == size + 1) && cptr && !(cptr[csize-1])) --csize; + if ((csize == size + 1) && cptr && !(cptr[csize - 1])) + --csize; if (csize <= size) { if (val) { - if (csize) memcpy(val, cptr, csize*sizeof(char)); - if (csize < size) memset(val + csize, 0, (size - csize)*sizeof(char)); + if (csize) + memcpy(val, cptr, csize * sizeof(char)); + if (csize < size) + memset(val + csize, 0, (size - csize) * sizeof(char)); } if (alloc == SWIG_NEWOBJ) { - free((char*)cptr); - res = SWIG_DelNewMask(res); - } + free((char *) cptr); + res = SWIG_DelNewMask(res); + } return res; } - if (alloc == SWIG_NEWOBJ) free((char*)cptr); + if (alloc == SWIG_NEWOBJ) + free((char *) cptr); } return SWIG_TypeError; } @@ -1812,16 +1930,17 @@ SWIG_AsCharArray(Tcl_Obj * obj, char *val, size_t size) SWIGINTERN int SWIG_AsVal_char SWIG_TCL_DECL_ARGS_2(Tcl_Obj * obj, char *val) -{ +{ int res = SWIG_AsCharArray(obj, val, 1); if (!SWIG_IsOK(res)) { long v; res = SWIG_AddCast(SWIG_AsVal_long SWIG_TCL_CALL_ARGS_2(obj, &v)); if (SWIG_IsOK(res)) { if ((CHAR_MIN <= v) && (v <= CHAR_MAX)) { - if (val) *val = (char)(v); + if (val) + *val = (char) (v); } else { - res = SWIG_OverflowError; + res = SWIG_OverflowError; } } } @@ -1843,12 +1962,13 @@ char *SWIG_RcFileName = "~/.myapprc"; #ifdef MAC_TCL -extern int MacintoshInit _ANSI_ARGS_((void)); +extern int MacintoshInit _ANSI_ARGS_((void)); #endif -int Tcl_AppInit(Tcl_Interp *interp){ +int Tcl_AppInit(Tcl_Interp * interp) +{ - if (Tcl_Init(interp) == TCL_ERROR) + if (Tcl_Init(interp) == TCL_ERROR) return TCL_ERROR; /* Now initialize our functions */ @@ -1856,14 +1976,16 @@ int Tcl_AppInit(Tcl_Interp *interp){ if (SWIG_init(interp) == TCL_ERROR) return TCL_ERROR; #if TCL_MAJOR_VERSION > 7 || TCL_MAJOR_VERSION == 7 && TCL_MINOR_VERSION >= 5 - Tcl_SetVar(interp, (char *) "tcl_rcFileName",SWIG_RcFileName,TCL_GLOBAL_ONLY); + Tcl_SetVar(interp, (char *) "tcl_rcFileName", SWIG_RcFileName, + TCL_GLOBAL_ONLY); #else - tcl_RcFileName = SWIG_RcFileName; + tcl_RcFileName = SWIG_RcFileName; #endif #ifdef SWIG_RcRsrcName - Tcl_SetVar(interp, (char *) "tcl_rcRsrcName",SWIG_RcRsrcName,TCL_GLOBAL); + Tcl_SetVar(interp, (char *) "tcl_rcRsrcName", SWIG_RcRsrcName, + TCL_GLOBAL); #endif - + return TCL_OK; } @@ -1871,1315 +1993,1779 @@ int Tcl_AppInit(Tcl_Interp *interp){ #ifdef __cplusplus extern "C" { #endif -SWIGINTERN int -_wrap_create_nxds(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - int arg1 ; - int arg2 ; - int arg3 = (int) 0 ; - int arg4 = (int) 0 ; - int arg5 = (int) 0 ; - int arg6 = (int) 0 ; - int arg7 = (int) 0 ; - int arg8 = (int) 0 ; - int arg9 = (int) 0 ; - void *result = 0 ; - int val1 ; - int ecode1 = 0 ; - int val2 ; - int ecode2 = 0 ; - int val3 ; - int ecode3 = 0 ; - int val4 ; - int ecode4 = 0 ; - int val5 ; - int ecode5 = 0 ; - int val6 ; - int ecode6 = 0 ; - int val7 ; - int ecode7 = 0 ; - int val8 ; - int ecode8 = 0 ; - int val9 ; - int ecode9 = 0 ; - - if (SWIG_GetArgs(interp, objc, objv,"oo|ooooooo:create_nxds rank type ?dim0? ?dim1? ?dim2? ?dim3? ?dim4? ?dim5? ?dim6? ",(void *)0,(void *)0,(void *)0,(void *)0,(void *)0,(void *)0,(void *)0,(void *)0,(void *)0) == TCL_ERROR) SWIG_fail; - ecode1 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[1], &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "create_nxds" "', argument " "1"" of type '" "int""'"); - } - arg1 = (int)(val1); - ecode2 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[2], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "create_nxds" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - if (objc > 3) { - ecode3 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[3], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "create_nxds" "', argument " "3"" of type '" "int""'"); - } - arg3 = (int)(val3); - } - if (objc > 4) { - ecode4 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[4], &val4); - if (!SWIG_IsOK(ecode4)) { - SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "create_nxds" "', argument " "4"" of type '" "int""'"); - } - arg4 = (int)(val4); - } - if (objc > 5) { - ecode5 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[5], &val5); - if (!SWIG_IsOK(ecode5)) { - SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "create_nxds" "', argument " "5"" of type '" "int""'"); - } - arg5 = (int)(val5); - } - if (objc > 6) { - ecode6 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[6], &val6); - if (!SWIG_IsOK(ecode6)) { - SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "create_nxds" "', argument " "6"" of type '" "int""'"); - } - arg6 = (int)(val6); - } - if (objc > 7) { - ecode7 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[7], &val7); - if (!SWIG_IsOK(ecode7)) { - SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "create_nxds" "', argument " "7"" of type '" "int""'"); - } - arg7 = (int)(val7); - } - if (objc > 8) { - ecode8 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[8], &val8); - if (!SWIG_IsOK(ecode8)) { - SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "create_nxds" "', argument " "8"" of type '" "int""'"); - } - arg8 = (int)(val8); - } - if (objc > 9) { - ecode9 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[9], &val9); - if (!SWIG_IsOK(ecode9)) { - SWIG_exception_fail(SWIG_ArgError(ecode9), "in method '" "create_nxds" "', argument " "9"" of type '" "int""'"); - } - arg9 = (int)(val9); - } - result = (void *)create_nxds(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9); - Tcl_SetObjResult(interp, SWIG_NewInstanceObj( SWIG_as_voidptr(result), SWIGTYPE_p_void,0)); - return TCL_OK; -fail: - return TCL_ERROR; -} + SWIGINTERN int + _wrap_create_nxds(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + int arg1; + int arg2; + int arg3 = (int) 0; + int arg4 = (int) 0; + int arg5 = (int) 0; + int arg6 = (int) 0; + int arg7 = (int) 0; + int arg8 = (int) 0; + int arg9 = (int) 0; + void *result = 0; + int val1; + int ecode1 = 0; + int val2; + int ecode2 = 0; + int val3; + int ecode3 = 0; + int val4; + int ecode4 = 0; + int val5; + int ecode5 = 0; + int val6; + int ecode6 = 0; + int val7; + int ecode7 = 0; + int val8; + int ecode8 = 0; + int val9; + int ecode9 = 0; - -SWIGINTERN int -_wrap_create_text_nxds(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - char *arg1 = (char *) 0 ; - void *result = 0 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - - if (SWIG_GetArgs(interp, objc, objv,"o:create_text_nxds name ",(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_AsCharPtrAndSize(objv[1], &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "create_text_nxds" "', argument " "1"" of type '" "char *""'"); - } - arg1 = (char *)(buf1); - result = (void *)create_text_nxds(arg1); - Tcl_SetObjResult(interp, SWIG_NewInstanceObj( SWIG_as_voidptr(result), SWIGTYPE_p_void,0)); - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return TCL_OK; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return TCL_ERROR; -} - - -SWIGINTERN int -_wrap_drop_nxds(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - int res1 ; - - if (SWIG_GetArgs(interp, objc, objv,"o:drop_nxds ptr ",(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "drop_nxds" "', argument " "1"" of type '" "void *""'"); - } - drop_nxds(arg1); - - return TCL_OK; -fail: - return TCL_ERROR; -} - - -SWIGINTERN int -_wrap_get_nxds_rank(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - int result; - int res1 ; - - if (SWIG_GetArgs(interp, objc, objv,"o:get_nxds_rank ptr ",(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "get_nxds_rank" "', argument " "1"" of type '" "void *""'"); - } - result = (int)get_nxds_rank(arg1); - Tcl_SetObjResult(interp,SWIG_From_int((int)(result))); - return TCL_OK; -fail: - return TCL_ERROR; -} - - -SWIGINTERN int -_wrap_get_nxds_type(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - int result; - int res1 ; - - if (SWIG_GetArgs(interp, objc, objv,"o:get_nxds_type ptr ",(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "get_nxds_type" "', argument " "1"" of type '" "void *""'"); - } - result = (int)get_nxds_type(arg1); - Tcl_SetObjResult(interp,SWIG_From_int((int)(result))); - return TCL_OK; -fail: - return TCL_ERROR; -} - - -SWIGINTERN int -_wrap_get_nxds_dim(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - int arg2 ; - int result; - int res1 ; - int val2 ; - int ecode2 = 0 ; - - if (SWIG_GetArgs(interp, objc, objv,"oo:get_nxds_dim ptr which ",(void *)0,(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "get_nxds_dim" "', argument " "1"" of type '" "void *""'"); - } - ecode2 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[2], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "get_nxds_dim" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - result = (int)get_nxds_dim(arg1,arg2); - Tcl_SetObjResult(interp,SWIG_From_int((int)(result))); - return TCL_OK; -fail: - return TCL_ERROR; -} - - -SWIGINTERN int -_wrap_get_nxds_value(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - int arg2 = (int) 0 ; - int arg3 = (int) 0 ; - int arg4 = (int) 0 ; - int arg5 = (int) 0 ; - int arg6 = (int) 0 ; - int arg7 = (int) 0 ; - int arg8 = (int) 0 ; - double result; - int res1 ; - int val2 ; - int ecode2 = 0 ; - int val3 ; - int ecode3 = 0 ; - int val4 ; - int ecode4 = 0 ; - int val5 ; - int ecode5 = 0 ; - int val6 ; - int ecode6 = 0 ; - int val7 ; - int ecode7 = 0 ; - int val8 ; - int ecode8 = 0 ; - - if (SWIG_GetArgs(interp, objc, objv,"o|ooooooo:get_nxds_value ptr ?dim0? ?dim1? ?dim2? ?dim3? ?dim4? ?dim5? ?dim6? ",(void *)0,(void *)0,(void *)0,(void *)0,(void *)0,(void *)0,(void *)0,(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "get_nxds_value" "', argument " "1"" of type '" "void *""'"); - } - if (objc > 2) { + if (SWIG_GetArgs + (interp, objc, objv, + "oo|ooooooo:create_nxds rank type ?dim0? ?dim1? ?dim2? ?dim3? ?dim4? ?dim5? ?dim6? ", + (void *) 0, (void *) 0, (void *) 0, (void *) 0, (void *) 0, + (void *) 0, (void *) 0, (void *) 0, (void *) 0) == TCL_ERROR) + SWIG_fail; + ecode1 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[1], &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), + "in method '" "create_nxds" "', argument " "1" + " of type '" "int" "'"); + } + arg1 = (int) (val1); ecode2 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[2], &val2); if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "get_nxds_value" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); + SWIG_exception_fail(SWIG_ArgError(ecode2), + "in method '" "create_nxds" "', argument " "2" + " of type '" "int" "'"); + } + arg2 = (int) (val2); + if (objc > 3) { + ecode3 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[3], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), + "in method '" "create_nxds" "', argument " "3" + " of type '" "int" "'"); + } + arg3 = (int) (val3); + } + if (objc > 4) { + ecode4 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[4], &val4); + if (!SWIG_IsOK(ecode4)) { + SWIG_exception_fail(SWIG_ArgError(ecode4), + "in method '" "create_nxds" "', argument " "4" + " of type '" "int" "'"); + } + arg4 = (int) (val4); + } + if (objc > 5) { + ecode5 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[5], &val5); + if (!SWIG_IsOK(ecode5)) { + SWIG_exception_fail(SWIG_ArgError(ecode5), + "in method '" "create_nxds" "', argument " "5" + " of type '" "int" "'"); + } + arg5 = (int) (val5); + } + if (objc > 6) { + ecode6 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[6], &val6); + if (!SWIG_IsOK(ecode6)) { + SWIG_exception_fail(SWIG_ArgError(ecode6), + "in method '" "create_nxds" "', argument " "6" + " of type '" "int" "'"); + } + arg6 = (int) (val6); + } + if (objc > 7) { + ecode7 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[7], &val7); + if (!SWIG_IsOK(ecode7)) { + SWIG_exception_fail(SWIG_ArgError(ecode7), + "in method '" "create_nxds" "', argument " "7" + " of type '" "int" "'"); + } + arg7 = (int) (val7); + } + if (objc > 8) { + ecode8 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[8], &val8); + if (!SWIG_IsOK(ecode8)) { + SWIG_exception_fail(SWIG_ArgError(ecode8), + "in method '" "create_nxds" "', argument " "8" + " of type '" "int" "'"); + } + arg8 = (int) (val8); + } + if (objc > 9) { + ecode9 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[9], &val9); + if (!SWIG_IsOK(ecode9)) { + SWIG_exception_fail(SWIG_ArgError(ecode9), + "in method '" "create_nxds" "', argument " "9" + " of type '" "int" "'"); + } + arg9 = (int) (val9); + } + result = + (void *) create_nxds(arg1, arg2, arg3, arg4, arg5, arg6, arg7, + arg8, arg9); + Tcl_SetObjResult(interp, + SWIG_NewInstanceObj(SWIG_as_voidptr(result), + SWIGTYPE_p_void, 0)); + return TCL_OK; + fail: + return TCL_ERROR; } - if (objc > 3) { + + + SWIGINTERN int + _wrap_create_text_nxds(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + char *arg1 = (char *) 0; + void *result = 0; + int res1; + char *buf1 = 0; + int alloc1 = 0; + + if (SWIG_GetArgs + (interp, objc, objv, "o:create_text_nxds name ", + (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_AsCharPtrAndSize(objv[1], &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "create_text_nxds" "', argument " + "1" " of type '" "char *" "'"); + } + arg1 = (char *) (buf1); + result = (void *) create_text_nxds(arg1); + Tcl_SetObjResult(interp, + SWIG_NewInstanceObj(SWIG_as_voidptr(result), + SWIGTYPE_p_void, 0)); + if (alloc1 == SWIG_NEWOBJ) + free((char *) buf1); + return TCL_OK; + fail: + if (alloc1 == SWIG_NEWOBJ) + free((char *) buf1); + return TCL_ERROR; + } + + + SWIGINTERN int + _wrap_drop_nxds(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + int res1; + + if (SWIG_GetArgs(interp, objc, objv, "o:drop_nxds ptr ", (void *) 0) == + TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "drop_nxds" "', argument " "1" + " of type '" "void *" "'"); + } + drop_nxds(arg1); + + return TCL_OK; + fail: + return TCL_ERROR; + } + + + SWIGINTERN int + _wrap_get_nxds_rank(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + int result; + int res1; + + if (SWIG_GetArgs + (interp, objc, objv, "o:get_nxds_rank ptr ", + (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "get_nxds_rank" "', argument " "1" + " of type '" "void *" "'"); + } + result = (int) get_nxds_rank(arg1); + Tcl_SetObjResult(interp, SWIG_From_int((int) (result))); + return TCL_OK; + fail: + return TCL_ERROR; + } + + + SWIGINTERN int + _wrap_get_nxds_type(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + int result; + int res1; + + if (SWIG_GetArgs + (interp, objc, objv, "o:get_nxds_type ptr ", + (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "get_nxds_type" "', argument " "1" + " of type '" "void *" "'"); + } + result = (int) get_nxds_type(arg1); + Tcl_SetObjResult(interp, SWIG_From_int((int) (result))); + return TCL_OK; + fail: + return TCL_ERROR; + } + + + SWIGINTERN int + _wrap_get_nxds_dim(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + int arg2; + int result; + int res1; + int val2; + int ecode2 = 0; + + if (SWIG_GetArgs + (interp, objc, objv, "oo:get_nxds_dim ptr which ", (void *) 0, + (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "get_nxds_dim" "', argument " "1" + " of type '" "void *" "'"); + } + ecode2 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[2], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), + "in method '" "get_nxds_dim" "', argument " "2" + " of type '" "int" "'"); + } + arg2 = (int) (val2); + result = (int) get_nxds_dim(arg1, arg2); + Tcl_SetObjResult(interp, SWIG_From_int((int) (result))); + return TCL_OK; + fail: + return TCL_ERROR; + } + + + SWIGINTERN int + _wrap_get_nxds_value(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + int arg2 = (int) 0; + int arg3 = (int) 0; + int arg4 = (int) 0; + int arg5 = (int) 0; + int arg6 = (int) 0; + int arg7 = (int) 0; + int arg8 = (int) 0; + double result; + int res1; + int val2; + int ecode2 = 0; + int val3; + int ecode3 = 0; + int val4; + int ecode4 = 0; + int val5; + int ecode5 = 0; + int val6; + int ecode6 = 0; + int val7; + int ecode7 = 0; + int val8; + int ecode8 = 0; + + if (SWIG_GetArgs + (interp, objc, objv, + "o|ooooooo:get_nxds_value ptr ?dim0? ?dim1? ?dim2? ?dim3? ?dim4? ?dim5? ?dim6? ", + (void *) 0, (void *) 0, (void *) 0, (void *) 0, (void *) 0, + (void *) 0, (void *) 0, (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "get_nxds_value" "', argument " "1" + " of type '" "void *" "'"); + } + if (objc > 2) { + ecode2 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[2], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), + "in method '" "get_nxds_value" "', argument " + "2" " of type '" "int" "'"); + } + arg2 = (int) (val2); + } + if (objc > 3) { + ecode3 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[3], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), + "in method '" "get_nxds_value" "', argument " + "3" " of type '" "int" "'"); + } + arg3 = (int) (val3); + } + if (objc > 4) { + ecode4 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[4], &val4); + if (!SWIG_IsOK(ecode4)) { + SWIG_exception_fail(SWIG_ArgError(ecode4), + "in method '" "get_nxds_value" "', argument " + "4" " of type '" "int" "'"); + } + arg4 = (int) (val4); + } + if (objc > 5) { + ecode5 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[5], &val5); + if (!SWIG_IsOK(ecode5)) { + SWIG_exception_fail(SWIG_ArgError(ecode5), + "in method '" "get_nxds_value" "', argument " + "5" " of type '" "int" "'"); + } + arg5 = (int) (val5); + } + if (objc > 6) { + ecode6 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[6], &val6); + if (!SWIG_IsOK(ecode6)) { + SWIG_exception_fail(SWIG_ArgError(ecode6), + "in method '" "get_nxds_value" "', argument " + "6" " of type '" "int" "'"); + } + arg6 = (int) (val6); + } + if (objc > 7) { + ecode7 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[7], &val7); + if (!SWIG_IsOK(ecode7)) { + SWIG_exception_fail(SWIG_ArgError(ecode7), + "in method '" "get_nxds_value" "', argument " + "7" " of type '" "int" "'"); + } + arg7 = (int) (val7); + } + if (objc > 8) { + ecode8 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[8], &val8); + if (!SWIG_IsOK(ecode8)) { + SWIG_exception_fail(SWIG_ArgError(ecode8), + "in method '" "get_nxds_value" "', argument " + "8" " of type '" "int" "'"); + } + arg8 = (int) (val8); + } + result = + (double) get_nxds_value(arg1, arg2, arg3, arg4, arg5, arg6, arg7, + arg8); + Tcl_SetObjResult(interp, SWIG_From_double((double) (result))); + return TCL_OK; + fail: + return TCL_ERROR; + } + + + SWIGINTERN int + _wrap_get_nxds_text(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + char *result = 0; + int res1; + + if (SWIG_GetArgs + (interp, objc, objv, "o:get_nxds_text ptr ", + (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "get_nxds_text" "', argument " "1" + " of type '" "void *" "'"); + } + result = (char *) get_nxds_text(arg1); + Tcl_SetObjResult(interp, SWIG_FromCharPtr((const char *) result)); + return TCL_OK; + fail: + return TCL_ERROR; + } + + + SWIGINTERN int + _wrap_put_nxds_value(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + double arg2; + int arg3 = (int) 0; + int arg4 = (int) 0; + int arg5 = (int) 0; + int arg6 = (int) 0; + int arg7 = (int) 0; + int arg8 = (int) 0; + int arg9 = (int) 0; + int result; + int res1; + double val2; + int ecode2 = 0; + int val3; + int ecode3 = 0; + int val4; + int ecode4 = 0; + int val5; + int ecode5 = 0; + int val6; + int ecode6 = 0; + int val7; + int ecode7 = 0; + int val8; + int ecode8 = 0; + int val9; + int ecode9 = 0; + + if (SWIG_GetArgs + (interp, objc, objv, + "oo|ooooooo:put_nxds_value ptr value ?dim0? ?dim1? ?dim2? ?dim3? ?dim4? ?dim5? ?dim6? ", + (void *) 0, (void *) 0, (void *) 0, (void *) 0, (void *) 0, + (void *) 0, (void *) 0, (void *) 0, (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "put_nxds_value" "', argument " "1" + " of type '" "void *" "'"); + } + ecode2 = SWIG_AsVal_double SWIG_TCL_CALL_ARGS_2(objv[2], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), + "in method '" "put_nxds_value" "', argument " "2" + " of type '" "double" "'"); + } + arg2 = (double) (val2); + if (objc > 3) { + ecode3 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[3], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), + "in method '" "put_nxds_value" "', argument " + "3" " of type '" "int" "'"); + } + arg3 = (int) (val3); + } + if (objc > 4) { + ecode4 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[4], &val4); + if (!SWIG_IsOK(ecode4)) { + SWIG_exception_fail(SWIG_ArgError(ecode4), + "in method '" "put_nxds_value" "', argument " + "4" " of type '" "int" "'"); + } + arg4 = (int) (val4); + } + if (objc > 5) { + ecode5 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[5], &val5); + if (!SWIG_IsOK(ecode5)) { + SWIG_exception_fail(SWIG_ArgError(ecode5), + "in method '" "put_nxds_value" "', argument " + "5" " of type '" "int" "'"); + } + arg5 = (int) (val5); + } + if (objc > 6) { + ecode6 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[6], &val6); + if (!SWIG_IsOK(ecode6)) { + SWIG_exception_fail(SWIG_ArgError(ecode6), + "in method '" "put_nxds_value" "', argument " + "6" " of type '" "int" "'"); + } + arg6 = (int) (val6); + } + if (objc > 7) { + ecode7 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[7], &val7); + if (!SWIG_IsOK(ecode7)) { + SWIG_exception_fail(SWIG_ArgError(ecode7), + "in method '" "put_nxds_value" "', argument " + "7" " of type '" "int" "'"); + } + arg7 = (int) (val7); + } + if (objc > 8) { + ecode8 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[8], &val8); + if (!SWIG_IsOK(ecode8)) { + SWIG_exception_fail(SWIG_ArgError(ecode8), + "in method '" "put_nxds_value" "', argument " + "8" " of type '" "int" "'"); + } + arg8 = (int) (val8); + } + if (objc > 9) { + ecode9 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[9], &val9); + if (!SWIG_IsOK(ecode9)) { + SWIG_exception_fail(SWIG_ArgError(ecode9), + "in method '" "put_nxds_value" "', argument " + "9" " of type '" "int" "'"); + } + arg9 = (int) (val9); + } + result = + (int) put_nxds_value(arg1, arg2, arg3, arg4, arg5, arg6, arg7, + arg8, arg9); + Tcl_SetObjResult(interp, SWIG_From_int((int) (result))); + return TCL_OK; + fail: + return TCL_ERROR; + } + + + SWIGINTERN int + _wrap_nx_getlasterror(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + char *result = 0; + + if (SWIG_GetArgs(interp, objc, objv, ":nx_getlasterror ") == TCL_ERROR) + SWIG_fail; + result = (char *) nx_getlasterror(); + Tcl_SetObjResult(interp, SWIG_FromCharPtr((const char *) result)); + return TCL_OK; + fail: + return TCL_ERROR; + } + + + SWIGINTERN int + _wrap_nx_open(ClientData clientData SWIGUNUSED, Tcl_Interp * interp, + int objc, Tcl_Obj * CONST objv[]) { + char *arg1 = (char *) 0; + int arg2; + void *result = 0; + int res1; + char *buf1 = 0; + int alloc1 = 0; + int val2; + int ecode2 = 0; + + if (SWIG_GetArgs + (interp, objc, objv, "oo:nx_open filename accessCode ", (void *) 0, + (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_AsCharPtrAndSize(objv[1], &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_open" "', argument " "1" + " of type '" "char *" "'"); + } + arg1 = (char *) (buf1); + ecode2 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[2], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), + "in method '" "nx_open" "', argument " "2" + " of type '" "int" "'"); + } + arg2 = (int) (val2); + result = (void *) nx_open(arg1, arg2); + Tcl_SetObjResult(interp, + SWIG_NewInstanceObj(SWIG_as_voidptr(result), + SWIGTYPE_p_void, 0)); + if (alloc1 == SWIG_NEWOBJ) + free((char *) buf1); + return TCL_OK; + fail: + if (alloc1 == SWIG_NEWOBJ) + free((char *) buf1); + return TCL_ERROR; + } + + + SWIGINTERN int + _wrap_nx_flush(ClientData clientData SWIGUNUSED, Tcl_Interp * interp, + int objc, Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + void *result = 0; + int res1; + + if (SWIG_GetArgs(interp, objc, objv, "o:nx_flush handle ", (void *) 0) + == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_flush" "', argument " "1" + " of type '" "void *" "'"); + } + result = (void *) nx_flush(arg1); + Tcl_SetObjResult(interp, + SWIG_NewInstanceObj(SWIG_as_voidptr(result), + SWIGTYPE_p_void, 0)); + return TCL_OK; + fail: + return TCL_ERROR; + } + + + SWIGINTERN int + _wrap_nx_close(ClientData clientData SWIGUNUSED, Tcl_Interp * interp, + int objc, Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + int res1; + + if (SWIG_GetArgs(interp, objc, objv, "o:nx_close handle ", (void *) 0) + == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_close" "', argument " "1" + " of type '" "void *" "'"); + } + nx_close(arg1); + + return TCL_OK; + fail: + return TCL_ERROR; + } + + + SWIGINTERN int + _wrap_nx_makegroup(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + char *arg2 = (char *) 0; + char *arg3 = (char *) 0; + int result; + int res1; + int res2; + char *buf2 = 0; + int alloc2 = 0; + int res3; + char *buf3 = 0; + int alloc3 = 0; + + if (SWIG_GetArgs + (interp, objc, objv, "ooo:nx_makegroup handle name nxclass ", + (void *) 0, (void *) 0, (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_makegroup" "', argument " "1" + " of type '" "void *" "'"); + } + res2 = SWIG_AsCharPtrAndSize(objv[2], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), + "in method '" "nx_makegroup" "', argument " "2" + " of type '" "char *" "'"); + } + arg2 = (char *) (buf2); + res3 = SWIG_AsCharPtrAndSize(objv[3], &buf3, NULL, &alloc3); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), + "in method '" "nx_makegroup" "', argument " "3" + " of type '" "char *" "'"); + } + arg3 = (char *) (buf3); + result = (int) nx_makegroup(arg1, arg2, arg3); + Tcl_SetObjResult(interp, SWIG_From_int((int) (result))); + if (alloc2 == SWIG_NEWOBJ) + free((char *) buf2); + if (alloc3 == SWIG_NEWOBJ) + free((char *) buf3); + return TCL_OK; + fail: + if (alloc2 == SWIG_NEWOBJ) + free((char *) buf2); + if (alloc3 == SWIG_NEWOBJ) + free((char *) buf3); + return TCL_ERROR; + } + + + SWIGINTERN int + _wrap_nx_opengroup(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + char *arg2 = (char *) 0; + char *arg3 = (char *) 0; + int result; + int res1; + int res2; + char *buf2 = 0; + int alloc2 = 0; + int res3; + char *buf3 = 0; + int alloc3 = 0; + + if (SWIG_GetArgs + (interp, objc, objv, "ooo:nx_opengroup handle name nxclass ", + (void *) 0, (void *) 0, (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_opengroup" "', argument " "1" + " of type '" "void *" "'"); + } + res2 = SWIG_AsCharPtrAndSize(objv[2], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), + "in method '" "nx_opengroup" "', argument " "2" + " of type '" "char *" "'"); + } + arg2 = (char *) (buf2); + res3 = SWIG_AsCharPtrAndSize(objv[3], &buf3, NULL, &alloc3); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), + "in method '" "nx_opengroup" "', argument " "3" + " of type '" "char *" "'"); + } + arg3 = (char *) (buf3); + result = (int) nx_opengroup(arg1, arg2, arg3); + Tcl_SetObjResult(interp, SWIG_From_int((int) (result))); + if (alloc2 == SWIG_NEWOBJ) + free((char *) buf2); + if (alloc3 == SWIG_NEWOBJ) + free((char *) buf3); + return TCL_OK; + fail: + if (alloc2 == SWIG_NEWOBJ) + free((char *) buf2); + if (alloc3 == SWIG_NEWOBJ) + free((char *) buf3); + return TCL_ERROR; + } + + + SWIGINTERN int + _wrap_nx_openpath(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + char *arg2 = (char *) 0; + int result; + int res1; + int res2; + char *buf2 = 0; + int alloc2 = 0; + + if (SWIG_GetArgs + (interp, objc, objv, "oo:nx_openpath handle path ", (void *) 0, + (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_openpath" "', argument " "1" + " of type '" "void *" "'"); + } + res2 = SWIG_AsCharPtrAndSize(objv[2], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), + "in method '" "nx_openpath" "', argument " "2" + " of type '" "char *" "'"); + } + arg2 = (char *) (buf2); + result = (int) nx_openpath(arg1, arg2); + Tcl_SetObjResult(interp, SWIG_From_int((int) (result))); + if (alloc2 == SWIG_NEWOBJ) + free((char *) buf2); + return TCL_OK; + fail: + if (alloc2 == SWIG_NEWOBJ) + free((char *) buf2); + return TCL_ERROR; + } + + + SWIGINTERN int + _wrap_nx_opengrouppath(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + char *arg2 = (char *) 0; + int result; + int res1; + int res2; + char *buf2 = 0; + int alloc2 = 0; + + if (SWIG_GetArgs + (interp, objc, objv, "oo:nx_opengrouppath handle path ", + (void *) 0, (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_opengrouppath" "', argument " + "1" " of type '" "void *" "'"); + } + res2 = SWIG_AsCharPtrAndSize(objv[2], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), + "in method '" "nx_opengrouppath" "', argument " + "2" " of type '" "char *" "'"); + } + arg2 = (char *) (buf2); + result = (int) nx_opengrouppath(arg1, arg2); + Tcl_SetObjResult(interp, SWIG_From_int((int) (result))); + if (alloc2 == SWIG_NEWOBJ) + free((char *) buf2); + return TCL_OK; + fail: + if (alloc2 == SWIG_NEWOBJ) + free((char *) buf2); + return TCL_ERROR; + } + + + SWIGINTERN int + _wrap_nx_closegroup(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + int result; + int res1; + + if (SWIG_GetArgs + (interp, objc, objv, "o:nx_closegroup handle ", + (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_closegroup" "', argument " "1" + " of type '" "void *" "'"); + } + result = (int) nx_closegroup(arg1); + Tcl_SetObjResult(interp, SWIG_From_int((int) (result))); + return TCL_OK; + fail: + return TCL_ERROR; + } + + + SWIGINTERN int + _wrap_nx_getnextentry(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + char arg2; + char *result = 0; + int res1; + char val2; + int ecode2 = 0; + + if (SWIG_GetArgs + (interp, objc, objv, "oo:nx_getnextentry handle separator ", + (void *) 0, (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_getnextentry" "', argument " + "1" " of type '" "void *" "'"); + } + ecode2 = SWIG_AsVal_char SWIG_TCL_CALL_ARGS_2(objv[2], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), + "in method '" "nx_getnextentry" "', argument " + "2" " of type '" "char" "'"); + } + arg2 = (char) (val2); + result = (char *) nx_getnextentry(arg1, arg2); + Tcl_SetObjResult(interp, SWIG_FromCharPtr((const char *) result)); + return TCL_OK; + fail: + return TCL_ERROR; + } + + + SWIGINTERN int + _wrap_nx_getgroupID(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + void *result = 0; + int res1; + + if (SWIG_GetArgs + (interp, objc, objv, "o:nx_getgroupID handle ", + (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_getgroupID" "', argument " "1" + " of type '" "void *" "'"); + } + result = (void *) nx_getgroupID(arg1); + Tcl_SetObjResult(interp, + SWIG_NewInstanceObj(SWIG_as_voidptr(result), + SWIGTYPE_p_void, 0)); + return TCL_OK; + fail: + return TCL_ERROR; + } + + + SWIGINTERN int + _wrap_nx_initgroupdir(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + int result; + int res1; + + if (SWIG_GetArgs + (interp, objc, objv, "o:nx_initgroupdir handle ", + (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_initgroupdir" "', argument " + "1" " of type '" "void *" "'"); + } + result = (int) nx_initgroupdir(arg1); + Tcl_SetObjResult(interp, SWIG_From_int((int) (result))); + return TCL_OK; + fail: + return TCL_ERROR; + } + + + SWIGINTERN int + _wrap_nx_makedata(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + char *arg2 = (char *) 0; + int arg3; + int arg4; + void *arg5 = (void *) 0; + int result; + int res1; + int res2; + char *buf2 = 0; + int alloc2 = 0; + int val3; + int ecode3 = 0; + int val4; + int ecode4 = 0; + int res5; + + if (SWIG_GetArgs + (interp, objc, objv, + "ooooo:nx_makedata handle name rank type dimPtr ", (void *) 0, + (void *) 0, (void *) 0, (void *) 0, (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_makedata" "', argument " "1" + " of type '" "void *" "'"); + } + res2 = SWIG_AsCharPtrAndSize(objv[2], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), + "in method '" "nx_makedata" "', argument " "2" + " of type '" "char *" "'"); + } + arg2 = (char *) (buf2); ecode3 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[3], &val3); if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "get_nxds_value" "', argument " "3"" of type '" "int""'"); - } - arg3 = (int)(val3); - } - if (objc > 4) { + SWIG_exception_fail(SWIG_ArgError(ecode3), + "in method '" "nx_makedata" "', argument " "3" + " of type '" "int" "'"); + } + arg3 = (int) (val3); ecode4 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[4], &val4); if (!SWIG_IsOK(ecode4)) { - SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "get_nxds_value" "', argument " "4"" of type '" "int""'"); - } - arg4 = (int)(val4); + SWIG_exception_fail(SWIG_ArgError(ecode4), + "in method '" "nx_makedata" "', argument " "4" + " of type '" "int" "'"); + } + arg4 = (int) (val4); + res5 = SWIG_ConvertPtr(objv[5], SWIG_as_voidptrptr(&arg5), 0, 0); + if (!SWIG_IsOK(res5)) { + SWIG_exception_fail(SWIG_ArgError(res5), + "in method '" "nx_makedata" "', argument " "5" + " of type '" "void *" "'"); + } + result = (int) nx_makedata(arg1, arg2, arg3, arg4, arg5); + Tcl_SetObjResult(interp, SWIG_From_int((int) (result))); + if (alloc2 == SWIG_NEWOBJ) + free((char *) buf2); + return TCL_OK; + fail: + if (alloc2 == SWIG_NEWOBJ) + free((char *) buf2); + return TCL_ERROR; } - if (objc > 5) { - ecode5 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[5], &val5); - if (!SWIG_IsOK(ecode5)) { - SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "get_nxds_value" "', argument " "5"" of type '" "int""'"); - } - arg5 = (int)(val5); - } - if (objc > 6) { - ecode6 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[6], &val6); - if (!SWIG_IsOK(ecode6)) { - SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "get_nxds_value" "', argument " "6"" of type '" "int""'"); - } - arg6 = (int)(val6); - } - if (objc > 7) { - ecode7 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[7], &val7); - if (!SWIG_IsOK(ecode7)) { - SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "get_nxds_value" "', argument " "7"" of type '" "int""'"); - } - arg7 = (int)(val7); - } - if (objc > 8) { - ecode8 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[8], &val8); - if (!SWIG_IsOK(ecode8)) { - SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "get_nxds_value" "', argument " "8"" of type '" "int""'"); - } - arg8 = (int)(val8); - } - result = (double)get_nxds_value(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); - Tcl_SetObjResult(interp,SWIG_From_double((double)(result))); - return TCL_OK; -fail: - return TCL_ERROR; -} -SWIGINTERN int -_wrap_get_nxds_text(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - char *result = 0 ; - int res1 ; - - if (SWIG_GetArgs(interp, objc, objv,"o:get_nxds_text ptr ",(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "get_nxds_text" "', argument " "1"" of type '" "void *""'"); - } - result = (char *)get_nxds_text(arg1); - Tcl_SetObjResult(interp,SWIG_FromCharPtr((const char *)result)); - return TCL_OK; -fail: - return TCL_ERROR; -} + SWIGINTERN int + _wrap_nx_compmakedata(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + char *arg2 = (char *) 0; + int arg3; + int arg4; + void *arg5 = (void *) 0; + void *arg6 = (void *) 0; + int result; + int res1; + int res2; + char *buf2 = 0; + int alloc2 = 0; + int val3; + int ecode3 = 0; + int val4; + int ecode4 = 0; + int res5; + int res6; - -SWIGINTERN int -_wrap_put_nxds_value(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - double arg2 ; - int arg3 = (int) 0 ; - int arg4 = (int) 0 ; - int arg5 = (int) 0 ; - int arg6 = (int) 0 ; - int arg7 = (int) 0 ; - int arg8 = (int) 0 ; - int arg9 = (int) 0 ; - int result; - int res1 ; - double val2 ; - int ecode2 = 0 ; - int val3 ; - int ecode3 = 0 ; - int val4 ; - int ecode4 = 0 ; - int val5 ; - int ecode5 = 0 ; - int val6 ; - int ecode6 = 0 ; - int val7 ; - int ecode7 = 0 ; - int val8 ; - int ecode8 = 0 ; - int val9 ; - int ecode9 = 0 ; - - if (SWIG_GetArgs(interp, objc, objv,"oo|ooooooo:put_nxds_value ptr value ?dim0? ?dim1? ?dim2? ?dim3? ?dim4? ?dim5? ?dim6? ",(void *)0,(void *)0,(void *)0,(void *)0,(void *)0,(void *)0,(void *)0,(void *)0,(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "put_nxds_value" "', argument " "1"" of type '" "void *""'"); - } - ecode2 = SWIG_AsVal_double SWIG_TCL_CALL_ARGS_2(objv[2], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "put_nxds_value" "', argument " "2"" of type '" "double""'"); - } - arg2 = (double)(val2); - if (objc > 3) { + if (SWIG_GetArgs + (interp, objc, objv, + "oooooo:nx_compmakedata handle name rank type dimPtr bufPtr ", + (void *) 0, (void *) 0, (void *) 0, (void *) 0, (void *) 0, + (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_compmakedata" "', argument " + "1" " of type '" "void *" "'"); + } + res2 = SWIG_AsCharPtrAndSize(objv[2], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), + "in method '" "nx_compmakedata" "', argument " + "2" " of type '" "char *" "'"); + } + arg2 = (char *) (buf2); ecode3 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[3], &val3); if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "put_nxds_value" "', argument " "3"" of type '" "int""'"); - } - arg3 = (int)(val3); - } - if (objc > 4) { + SWIG_exception_fail(SWIG_ArgError(ecode3), + "in method '" "nx_compmakedata" "', argument " + "3" " of type '" "int" "'"); + } + arg3 = (int) (val3); ecode4 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[4], &val4); if (!SWIG_IsOK(ecode4)) { - SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "put_nxds_value" "', argument " "4"" of type '" "int""'"); - } - arg4 = (int)(val4); + SWIG_exception_fail(SWIG_ArgError(ecode4), + "in method '" "nx_compmakedata" "', argument " + "4" " of type '" "int" "'"); + } + arg4 = (int) (val4); + res5 = SWIG_ConvertPtr(objv[5], SWIG_as_voidptrptr(&arg5), 0, 0); + if (!SWIG_IsOK(res5)) { + SWIG_exception_fail(SWIG_ArgError(res5), + "in method '" "nx_compmakedata" "', argument " + "5" " of type '" "void *" "'"); + } + res6 = SWIG_ConvertPtr(objv[6], SWIG_as_voidptrptr(&arg6), 0, 0); + if (!SWIG_IsOK(res6)) { + SWIG_exception_fail(SWIG_ArgError(res6), + "in method '" "nx_compmakedata" "', argument " + "6" " of type '" "void *" "'"); + } + result = (int) nx_compmakedata(arg1, arg2, arg3, arg4, arg5, arg6); + Tcl_SetObjResult(interp, SWIG_From_int((int) (result))); + if (alloc2 == SWIG_NEWOBJ) + free((char *) buf2); + return TCL_OK; + fail: + if (alloc2 == SWIG_NEWOBJ) + free((char *) buf2); + return TCL_ERROR; } - if (objc > 5) { - ecode5 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[5], &val5); - if (!SWIG_IsOK(ecode5)) { - SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "put_nxds_value" "', argument " "5"" of type '" "int""'"); - } - arg5 = (int)(val5); + + + SWIGINTERN int + _wrap_nx_opendata(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + char *arg2 = (char *) 0; + int result; + int res1; + int res2; + char *buf2 = 0; + int alloc2 = 0; + + if (SWIG_GetArgs + (interp, objc, objv, "oo:nx_opendata handle name ", (void *) 0, + (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_opendata" "', argument " "1" + " of type '" "void *" "'"); + } + res2 = SWIG_AsCharPtrAndSize(objv[2], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), + "in method '" "nx_opendata" "', argument " "2" + " of type '" "char *" "'"); + } + arg2 = (char *) (buf2); + result = (int) nx_opendata(arg1, arg2); + Tcl_SetObjResult(interp, SWIG_From_int((int) (result))); + if (alloc2 == SWIG_NEWOBJ) + free((char *) buf2); + return TCL_OK; + fail: + if (alloc2 == SWIG_NEWOBJ) + free((char *) buf2); + return TCL_ERROR; } - if (objc > 6) { - ecode6 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[6], &val6); - if (!SWIG_IsOK(ecode6)) { - SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "put_nxds_value" "', argument " "6"" of type '" "int""'"); - } - arg6 = (int)(val6); + + + SWIGINTERN int + _wrap_nx_closedata(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + int result; + int res1; + + if (SWIG_GetArgs + (interp, objc, objv, "o:nx_closedata handle ", + (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_closedata" "', argument " "1" + " of type '" "void *" "'"); + } + result = (int) nx_closedata(arg1); + Tcl_SetObjResult(interp, SWIG_From_int((int) (result))); + return TCL_OK; + fail: + return TCL_ERROR; } - if (objc > 7) { - ecode7 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[7], &val7); - if (!SWIG_IsOK(ecode7)) { - SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "put_nxds_value" "', argument " "7"" of type '" "int""'"); - } - arg7 = (int)(val7); + + + SWIGINTERN int + _wrap_nx_putslab(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + void *arg2 = (void *) 0; + void *arg3 = (void *) 0; + int result; + int res1; + int res2; + int res3; + + if (SWIG_GetArgs + (interp, objc, objv, "ooo:nx_putslab handle dataset startDim ", + (void *) 0, (void *) 0, (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_putslab" "', argument " "1" + " of type '" "void *" "'"); + } + res2 = SWIG_ConvertPtr(objv[2], SWIG_as_voidptrptr(&arg2), 0, 0); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), + "in method '" "nx_putslab" "', argument " "2" + " of type '" "void *" "'"); + } + res3 = SWIG_ConvertPtr(objv[3], SWIG_as_voidptrptr(&arg3), 0, 0); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), + "in method '" "nx_putslab" "', argument " "3" + " of type '" "void *" "'"); + } + result = (int) nx_putslab(arg1, arg2, arg3); + Tcl_SetObjResult(interp, SWIG_From_int((int) (result))); + return TCL_OK; + fail: + return TCL_ERROR; } - if (objc > 8) { - ecode8 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[8], &val8); - if (!SWIG_IsOK(ecode8)) { - SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "put_nxds_value" "', argument " "8"" of type '" "int""'"); - } - arg8 = (int)(val8); + + + SWIGINTERN int + _wrap_nx_getslab(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + void *arg2 = (void *) 0; + void *arg3 = (void *) 0; + void *result = 0; + int res1; + int res2; + int res3; + + if (SWIG_GetArgs + (interp, objc, objv, "ooo:nx_getslab handle startdim size ", + (void *) 0, (void *) 0, (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_getslab" "', argument " "1" + " of type '" "void *" "'"); + } + res2 = SWIG_ConvertPtr(objv[2], SWIG_as_voidptrptr(&arg2), 0, 0); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), + "in method '" "nx_getslab" "', argument " "2" + " of type '" "void *" "'"); + } + res3 = SWIG_ConvertPtr(objv[3], SWIG_as_voidptrptr(&arg3), 0, 0); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), + "in method '" "nx_getslab" "', argument " "3" + " of type '" "void *" "'"); + } + result = (void *) nx_getslab(arg1, arg2, arg3); + Tcl_SetObjResult(interp, + SWIG_NewInstanceObj(SWIG_as_voidptr(result), + SWIGTYPE_p_void, 0)); + return TCL_OK; + fail: + return TCL_ERROR; } - if (objc > 9) { - ecode9 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[9], &val9); - if (!SWIG_IsOK(ecode9)) { - SWIG_exception_fail(SWIG_ArgError(ecode9), "in method '" "put_nxds_value" "', argument " "9"" of type '" "int""'"); - } - arg9 = (int)(val9); + + + SWIGINTERN int + _wrap_nx_getds(ClientData clientData SWIGUNUSED, Tcl_Interp * interp, + int objc, Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + char *arg2 = (char *) 0; + void *result = 0; + int res1; + int res2; + char *buf2 = 0; + int alloc2 = 0; + + if (SWIG_GetArgs + (interp, objc, objv, "oo:nx_getds handle name ", (void *) 0, + (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_getds" "', argument " "1" + " of type '" "void *" "'"); + } + res2 = SWIG_AsCharPtrAndSize(objv[2], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), + "in method '" "nx_getds" "', argument " "2" + " of type '" "char *" "'"); + } + arg2 = (char *) (buf2); + result = (void *) nx_getds(arg1, arg2); + Tcl_SetObjResult(interp, + SWIG_NewInstanceObj(SWIG_as_voidptr(result), + SWIGTYPE_p_void, 0)); + if (alloc2 == SWIG_NEWOBJ) + free((char *) buf2); + return TCL_OK; + fail: + if (alloc2 == SWIG_NEWOBJ) + free((char *) buf2); + return TCL_ERROR; } - result = (int)put_nxds_value(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9); - Tcl_SetObjResult(interp,SWIG_From_int((int)(result))); - return TCL_OK; -fail: - return TCL_ERROR; -} -SWIGINTERN int -_wrap_nx_getlasterror(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - char *result = 0 ; - - if (SWIG_GetArgs(interp, objc, objv,":nx_getlasterror ") == TCL_ERROR) SWIG_fail; - result = (char *)nx_getlasterror(); - Tcl_SetObjResult(interp,SWIG_FromCharPtr((const char *)result)); - return TCL_OK; -fail: - return TCL_ERROR; -} + SWIGINTERN int + _wrap_nx_putds(ClientData clientData SWIGUNUSED, Tcl_Interp * interp, + int objc, Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + char *arg2 = (char *) 0; + void *arg3 = (void *) 0; + int result; + int res1; + int res2; + char *buf2 = 0; + int alloc2 = 0; + int res3; - -SWIGINTERN int -_wrap_nx_open(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - char *arg1 = (char *) 0 ; - int arg2 ; - void *result = 0 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - int val2 ; - int ecode2 = 0 ; - - if (SWIG_GetArgs(interp, objc, objv,"oo:nx_open filename accessCode ",(void *)0,(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_AsCharPtrAndSize(objv[1], &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_open" "', argument " "1"" of type '" "char *""'"); + if (SWIG_GetArgs + (interp, objc, objv, "ooo:nx_putds handle name dataset ", + (void *) 0, (void *) 0, (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_putds" "', argument " "1" + " of type '" "void *" "'"); + } + res2 = SWIG_AsCharPtrAndSize(objv[2], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), + "in method '" "nx_putds" "', argument " "2" + " of type '" "char *" "'"); + } + arg2 = (char *) (buf2); + res3 = SWIG_ConvertPtr(objv[3], SWIG_as_voidptrptr(&arg3), 0, 0); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), + "in method '" "nx_putds" "', argument " "3" + " of type '" "void *" "'"); + } + result = (int) nx_putds(arg1, arg2, arg3); + Tcl_SetObjResult(interp, SWIG_From_int((int) (result))); + if (alloc2 == SWIG_NEWOBJ) + free((char *) buf2); + return TCL_OK; + fail: + if (alloc2 == SWIG_NEWOBJ) + free((char *) buf2); + return TCL_ERROR; } - arg1 = (char *)(buf1); - ecode2 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[2], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nx_open" "', argument " "2"" of type '" "int""'"); - } - arg2 = (int)(val2); - result = (void *)nx_open(arg1,arg2); - Tcl_SetObjResult(interp, SWIG_NewInstanceObj( SWIG_as_voidptr(result), SWIGTYPE_p_void,0)); - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return TCL_OK; -fail: - if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); - return TCL_ERROR; -} -SWIGINTERN int -_wrap_nx_flush(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - void *result = 0 ; - int res1 ; - - if (SWIG_GetArgs(interp, objc, objv,"o:nx_flush handle ",(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_flush" "', argument " "1"" of type '" "void *""'"); + SWIGINTERN int + _wrap_nx_getdata(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + void *result = 0; + int res1; + + if (SWIG_GetArgs + (interp, objc, objv, "o:nx_getdata handle ", + (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_getdata" "', argument " "1" + " of type '" "void *" "'"); + } + result = (void *) nx_getdata(arg1); + Tcl_SetObjResult(interp, + SWIG_NewInstanceObj(SWIG_as_voidptr(result), + SWIGTYPE_p_void, 0)); + return TCL_OK; + fail: + return TCL_ERROR; } - result = (void *)nx_flush(arg1); - Tcl_SetObjResult(interp, SWIG_NewInstanceObj( SWIG_as_voidptr(result), SWIGTYPE_p_void,0)); - return TCL_OK; -fail: - return TCL_ERROR; -} -SWIGINTERN int -_wrap_nx_close(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - int res1 ; - - if (SWIG_GetArgs(interp, objc, objv,"o:nx_close handle ",(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_close" "', argument " "1"" of type '" "void *""'"); + SWIGINTERN int + _wrap_nx_putdata(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + void *arg2 = (void *) 0; + int result; + int res1; + int res2; + + if (SWIG_GetArgs + (interp, objc, objv, "oo:nx_putdata handle dataset ", (void *) 0, + (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_putdata" "', argument " "1" + " of type '" "void *" "'"); + } + res2 = SWIG_ConvertPtr(objv[2], SWIG_as_voidptrptr(&arg2), 0, 0); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), + "in method '" "nx_putdata" "', argument " "2" + " of type '" "void *" "'"); + } + result = (int) nx_putdata(arg1, arg2); + Tcl_SetObjResult(interp, SWIG_From_int((int) (result))); + return TCL_OK; + fail: + return TCL_ERROR; } - nx_close(arg1); - - return TCL_OK; -fail: - return TCL_ERROR; -} -SWIGINTERN int -_wrap_nx_makegroup(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - char *arg2 = (char *) 0 ; - char *arg3 = (char *) 0 ; - int result; - int res1 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - int res3 ; - char *buf3 = 0 ; - int alloc3 = 0 ; - - if (SWIG_GetArgs(interp, objc, objv,"ooo:nx_makegroup handle name nxclass ",(void *)0,(void *)0,(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_makegroup" "', argument " "1"" of type '" "void *""'"); + SWIGINTERN int + _wrap_nx_getinfo(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + void *result = 0; + int res1; + + if (SWIG_GetArgs + (interp, objc, objv, "o:nx_getinfo handle ", + (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_getinfo" "', argument " "1" + " of type '" "void *" "'"); + } + result = (void *) nx_getinfo(arg1); + Tcl_SetObjResult(interp, + SWIG_NewInstanceObj(SWIG_as_voidptr(result), + SWIGTYPE_p_void, 0)); + return TCL_OK; + fail: + return TCL_ERROR; } - res2 = SWIG_AsCharPtrAndSize(objv[2], &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nx_makegroup" "', argument " "2"" of type '" "char *""'"); + + + SWIGINTERN int + _wrap_nx_getdataID(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + void *result = 0; + int res1; + + if (SWIG_GetArgs + (interp, objc, objv, "o:nx_getdataID handle ", + (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_getdataID" "', argument " "1" + " of type '" "void *" "'"); + } + result = (void *) nx_getdataID(arg1); + Tcl_SetObjResult(interp, + SWIG_NewInstanceObj(SWIG_as_voidptr(result), + SWIGTYPE_p_void, 0)); + return TCL_OK; + fail: + return TCL_ERROR; } - arg2 = (char *)(buf2); - res3 = SWIG_AsCharPtrAndSize(objv[3], &buf3, NULL, &alloc3); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "nx_makegroup" "', argument " "3"" of type '" "char *""'"); + + + SWIGINTERN int + _wrap_nx_getnextattr(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + char arg2; + char *result = 0; + int res1; + char val2; + int ecode2 = 0; + + if (SWIG_GetArgs + (interp, objc, objv, "oo:nx_getnextattr handle separator ", + (void *) 0, (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_getnextattr" "', argument " "1" + " of type '" "void *" "'"); + } + ecode2 = SWIG_AsVal_char SWIG_TCL_CALL_ARGS_2(objv[2], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), + "in method '" "nx_getnextattr" "', argument " "2" + " of type '" "char" "'"); + } + arg2 = (char) (val2); + result = (char *) nx_getnextattr(arg1, arg2); + Tcl_SetObjResult(interp, SWIG_FromCharPtr((const char *) result)); + return TCL_OK; + fail: + return TCL_ERROR; } - arg3 = (char *)(buf3); - result = (int)nx_makegroup(arg1,arg2,arg3); - Tcl_SetObjResult(interp,SWIG_From_int((int)(result))); - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - if (alloc3 == SWIG_NEWOBJ) free((char*)buf3); - return TCL_OK; -fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - if (alloc3 == SWIG_NEWOBJ) free((char*)buf3); - return TCL_ERROR; -} -SWIGINTERN int -_wrap_nx_opengroup(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - char *arg2 = (char *) 0 ; - char *arg3 = (char *) 0 ; - int result; - int res1 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - int res3 ; - char *buf3 = 0 ; - int alloc3 = 0 ; - - if (SWIG_GetArgs(interp, objc, objv,"ooo:nx_opengroup handle name nxclass ",(void *)0,(void *)0,(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_opengroup" "', argument " "1"" of type '" "void *""'"); + SWIGINTERN int + _wrap_nx_putattr(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + char *arg2 = (char *) 0; + void *arg3 = (void *) 0; + int result; + int res1; + int res2; + char *buf2 = 0; + int alloc2 = 0; + int res3; + + if (SWIG_GetArgs + (interp, objc, objv, "ooo:nx_putattr handle name ds ", (void *) 0, + (void *) 0, (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_putattr" "', argument " "1" + " of type '" "void *" "'"); + } + res2 = SWIG_AsCharPtrAndSize(objv[2], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), + "in method '" "nx_putattr" "', argument " "2" + " of type '" "char *" "'"); + } + arg2 = (char *) (buf2); + res3 = SWIG_ConvertPtr(objv[3], SWIG_as_voidptrptr(&arg3), 0, 0); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), + "in method '" "nx_putattr" "', argument " "3" + " of type '" "void *" "'"); + } + result = (int) nx_putattr(arg1, arg2, arg3); + Tcl_SetObjResult(interp, SWIG_From_int((int) (result))); + if (alloc2 == SWIG_NEWOBJ) + free((char *) buf2); + return TCL_OK; + fail: + if (alloc2 == SWIG_NEWOBJ) + free((char *) buf2); + return TCL_ERROR; } - res2 = SWIG_AsCharPtrAndSize(objv[2], &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nx_opengroup" "', argument " "2"" of type '" "char *""'"); + + + SWIGINTERN int + _wrap_nx_getattr(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + char *arg2 = (char *) 0; + int arg3; + int arg4; + void *result = 0; + int res1; + int res2; + char *buf2 = 0; + int alloc2 = 0; + int val3; + int ecode3 = 0; + int val4; + int ecode4 = 0; + + if (SWIG_GetArgs + (interp, objc, objv, "oooo:nx_getattr handle name type length ", + (void *) 0, (void *) 0, (void *) 0, (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_getattr" "', argument " "1" + " of type '" "void *" "'"); + } + res2 = SWIG_AsCharPtrAndSize(objv[2], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), + "in method '" "nx_getattr" "', argument " "2" + " of type '" "char *" "'"); + } + arg2 = (char *) (buf2); + ecode3 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[3], &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), + "in method '" "nx_getattr" "', argument " "3" + " of type '" "int" "'"); + } + arg3 = (int) (val3); + ecode4 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[4], &val4); + if (!SWIG_IsOK(ecode4)) { + SWIG_exception_fail(SWIG_ArgError(ecode4), + "in method '" "nx_getattr" "', argument " "4" + " of type '" "int" "'"); + } + arg4 = (int) (val4); + result = (void *) nx_getattr(arg1, arg2, arg3, arg4); + Tcl_SetObjResult(interp, + SWIG_NewInstanceObj(SWIG_as_voidptr(result), + SWIGTYPE_p_void, 0)); + if (alloc2 == SWIG_NEWOBJ) + free((char *) buf2); + return TCL_OK; + fail: + if (alloc2 == SWIG_NEWOBJ) + free((char *) buf2); + return TCL_ERROR; } - arg2 = (char *)(buf2); - res3 = SWIG_AsCharPtrAndSize(objv[3], &buf3, NULL, &alloc3); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "nx_opengroup" "', argument " "3"" of type '" "char *""'"); + + + SWIGINTERN int + _wrap_nx_makelink(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + void *arg2 = (void *) 0; + int result; + int res1; + int res2; + + if (SWIG_GetArgs + (interp, objc, objv, "oo:nx_makelink handle link ", (void *) 0, + (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_makelink" "', argument " "1" + " of type '" "void *" "'"); + } + res2 = SWIG_ConvertPtr(objv[2], SWIG_as_voidptrptr(&arg2), 0, 0); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), + "in method '" "nx_makelink" "', argument " "2" + " of type '" "void *" "'"); + } + result = (int) nx_makelink(arg1, arg2); + Tcl_SetObjResult(interp, SWIG_From_int((int) (result))); + return TCL_OK; + fail: + return TCL_ERROR; } - arg3 = (char *)(buf3); - result = (int)nx_opengroup(arg1,arg2,arg3); - Tcl_SetObjResult(interp,SWIG_From_int((int)(result))); - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - if (alloc3 == SWIG_NEWOBJ) free((char*)buf3); - return TCL_OK; -fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - if (alloc3 == SWIG_NEWOBJ) free((char*)buf3); - return TCL_ERROR; -} -SWIGINTERN int -_wrap_nx_openpath(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - char *arg2 = (char *) 0 ; - int result; - int res1 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - - if (SWIG_GetArgs(interp, objc, objv,"oo:nx_openpath handle path ",(void *)0,(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_openpath" "', argument " "1"" of type '" "void *""'"); + SWIGINTERN int + _wrap_nx_opensourcegroup(ClientData clientData SWIGUNUSED, + Tcl_Interp * interp, int objc, + Tcl_Obj * CONST objv[]) { + void *arg1 = (void *) 0; + int result; + int res1; + + if (SWIG_GetArgs + (interp, objc, objv, "o:nx_opensourcegroup handle ", + (void *) 0) == TCL_ERROR) + SWIG_fail; + res1 = SWIG_ConvertPtr(objv[1], SWIG_as_voidptrptr(&arg1), 0, 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), + "in method '" "nx_opensourcegroup" "', argument " + "1" " of type '" "void *" "'"); + } + result = (int) nx_opensourcegroup(arg1); + Tcl_SetObjResult(interp, SWIG_From_int((int) (result))); + return TCL_OK; + fail: + return TCL_ERROR; } - res2 = SWIG_AsCharPtrAndSize(objv[2], &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nx_openpath" "', argument " "2"" of type '" "char *""'"); - } - arg2 = (char *)(buf2); - result = (int)nx_openpath(arg1,arg2); - Tcl_SetObjResult(interp,SWIG_From_int((int)(result))); - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return TCL_OK; -fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return TCL_ERROR; -} - - -SWIGINTERN int -_wrap_nx_opengrouppath(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - char *arg2 = (char *) 0 ; - int result; - int res1 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - - if (SWIG_GetArgs(interp, objc, objv,"oo:nx_opengrouppath handle path ",(void *)0,(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_opengrouppath" "', argument " "1"" of type '" "void *""'"); - } - res2 = SWIG_AsCharPtrAndSize(objv[2], &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nx_opengrouppath" "', argument " "2"" of type '" "char *""'"); - } - arg2 = (char *)(buf2); - result = (int)nx_opengrouppath(arg1,arg2); - Tcl_SetObjResult(interp,SWIG_From_int((int)(result))); - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return TCL_OK; -fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return TCL_ERROR; -} - - -SWIGINTERN int -_wrap_nx_closegroup(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - int result; - int res1 ; - - if (SWIG_GetArgs(interp, objc, objv,"o:nx_closegroup handle ",(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_closegroup" "', argument " "1"" of type '" "void *""'"); - } - result = (int)nx_closegroup(arg1); - Tcl_SetObjResult(interp,SWIG_From_int((int)(result))); - return TCL_OK; -fail: - return TCL_ERROR; -} - - -SWIGINTERN int -_wrap_nx_getnextentry(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - char arg2 ; - char *result = 0 ; - int res1 ; - char val2 ; - int ecode2 = 0 ; - - if (SWIG_GetArgs(interp, objc, objv,"oo:nx_getnextentry handle separator ",(void *)0,(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_getnextentry" "', argument " "1"" of type '" "void *""'"); - } - ecode2 = SWIG_AsVal_char SWIG_TCL_CALL_ARGS_2(objv[2], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nx_getnextentry" "', argument " "2"" of type '" "char""'"); - } - arg2 = (char)(val2); - result = (char *)nx_getnextentry(arg1,arg2); - Tcl_SetObjResult(interp,SWIG_FromCharPtr((const char *)result)); - return TCL_OK; -fail: - return TCL_ERROR; -} - - -SWIGINTERN int -_wrap_nx_getgroupID(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - void *result = 0 ; - int res1 ; - - if (SWIG_GetArgs(interp, objc, objv,"o:nx_getgroupID handle ",(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_getgroupID" "', argument " "1"" of type '" "void *""'"); - } - result = (void *)nx_getgroupID(arg1); - Tcl_SetObjResult(interp, SWIG_NewInstanceObj( SWIG_as_voidptr(result), SWIGTYPE_p_void,0)); - return TCL_OK; -fail: - return TCL_ERROR; -} - - -SWIGINTERN int -_wrap_nx_initgroupdir(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - int result; - int res1 ; - - if (SWIG_GetArgs(interp, objc, objv,"o:nx_initgroupdir handle ",(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_initgroupdir" "', argument " "1"" of type '" "void *""'"); - } - result = (int)nx_initgroupdir(arg1); - Tcl_SetObjResult(interp,SWIG_From_int((int)(result))); - return TCL_OK; -fail: - return TCL_ERROR; -} - - -SWIGINTERN int -_wrap_nx_makedata(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - char *arg2 = (char *) 0 ; - int arg3 ; - int arg4 ; - void *arg5 = (void *) 0 ; - int result; - int res1 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - int val3 ; - int ecode3 = 0 ; - int val4 ; - int ecode4 = 0 ; - int res5 ; - - if (SWIG_GetArgs(interp, objc, objv,"ooooo:nx_makedata handle name rank type dimPtr ",(void *)0,(void *)0,(void *)0,(void *)0,(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_makedata" "', argument " "1"" of type '" "void *""'"); - } - res2 = SWIG_AsCharPtrAndSize(objv[2], &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nx_makedata" "', argument " "2"" of type '" "char *""'"); - } - arg2 = (char *)(buf2); - ecode3 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[3], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "nx_makedata" "', argument " "3"" of type '" "int""'"); - } - arg3 = (int)(val3); - ecode4 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[4], &val4); - if (!SWIG_IsOK(ecode4)) { - SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "nx_makedata" "', argument " "4"" of type '" "int""'"); - } - arg4 = (int)(val4); - res5 = SWIG_ConvertPtr(objv[5],SWIG_as_voidptrptr(&arg5), 0, 0); - if (!SWIG_IsOK(res5)) { - SWIG_exception_fail(SWIG_ArgError(res5), "in method '" "nx_makedata" "', argument " "5"" of type '" "void *""'"); - } - result = (int)nx_makedata(arg1,arg2,arg3,arg4,arg5); - Tcl_SetObjResult(interp,SWIG_From_int((int)(result))); - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return TCL_OK; -fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return TCL_ERROR; -} - - -SWIGINTERN int -_wrap_nx_compmakedata(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - char *arg2 = (char *) 0 ; - int arg3 ; - int arg4 ; - void *arg5 = (void *) 0 ; - void *arg6 = (void *) 0 ; - int result; - int res1 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - int val3 ; - int ecode3 = 0 ; - int val4 ; - int ecode4 = 0 ; - int res5 ; - int res6 ; - - if (SWIG_GetArgs(interp, objc, objv,"oooooo:nx_compmakedata handle name rank type dimPtr bufPtr ",(void *)0,(void *)0,(void *)0,(void *)0,(void *)0,(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_compmakedata" "', argument " "1"" of type '" "void *""'"); - } - res2 = SWIG_AsCharPtrAndSize(objv[2], &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nx_compmakedata" "', argument " "2"" of type '" "char *""'"); - } - arg2 = (char *)(buf2); - ecode3 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[3], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "nx_compmakedata" "', argument " "3"" of type '" "int""'"); - } - arg3 = (int)(val3); - ecode4 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[4], &val4); - if (!SWIG_IsOK(ecode4)) { - SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "nx_compmakedata" "', argument " "4"" of type '" "int""'"); - } - arg4 = (int)(val4); - res5 = SWIG_ConvertPtr(objv[5],SWIG_as_voidptrptr(&arg5), 0, 0); - if (!SWIG_IsOK(res5)) { - SWIG_exception_fail(SWIG_ArgError(res5), "in method '" "nx_compmakedata" "', argument " "5"" of type '" "void *""'"); - } - res6 = SWIG_ConvertPtr(objv[6],SWIG_as_voidptrptr(&arg6), 0, 0); - if (!SWIG_IsOK(res6)) { - SWIG_exception_fail(SWIG_ArgError(res6), "in method '" "nx_compmakedata" "', argument " "6"" of type '" "void *""'"); - } - result = (int)nx_compmakedata(arg1,arg2,arg3,arg4,arg5,arg6); - Tcl_SetObjResult(interp,SWIG_From_int((int)(result))); - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return TCL_OK; -fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return TCL_ERROR; -} - - -SWIGINTERN int -_wrap_nx_opendata(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - char *arg2 = (char *) 0 ; - int result; - int res1 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - - if (SWIG_GetArgs(interp, objc, objv,"oo:nx_opendata handle name ",(void *)0,(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_opendata" "', argument " "1"" of type '" "void *""'"); - } - res2 = SWIG_AsCharPtrAndSize(objv[2], &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nx_opendata" "', argument " "2"" of type '" "char *""'"); - } - arg2 = (char *)(buf2); - result = (int)nx_opendata(arg1,arg2); - Tcl_SetObjResult(interp,SWIG_From_int((int)(result))); - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return TCL_OK; -fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return TCL_ERROR; -} - - -SWIGINTERN int -_wrap_nx_closedata(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - int result; - int res1 ; - - if (SWIG_GetArgs(interp, objc, objv,"o:nx_closedata handle ",(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_closedata" "', argument " "1"" of type '" "void *""'"); - } - result = (int)nx_closedata(arg1); - Tcl_SetObjResult(interp,SWIG_From_int((int)(result))); - return TCL_OK; -fail: - return TCL_ERROR; -} - - -SWIGINTERN int -_wrap_nx_putslab(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - void *arg2 = (void *) 0 ; - void *arg3 = (void *) 0 ; - int result; - int res1 ; - int res2 ; - int res3 ; - - if (SWIG_GetArgs(interp, objc, objv,"ooo:nx_putslab handle dataset startDim ",(void *)0,(void *)0,(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_putslab" "', argument " "1"" of type '" "void *""'"); - } - res2 = SWIG_ConvertPtr(objv[2],SWIG_as_voidptrptr(&arg2), 0, 0); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nx_putslab" "', argument " "2"" of type '" "void *""'"); - } - res3 = SWIG_ConvertPtr(objv[3],SWIG_as_voidptrptr(&arg3), 0, 0); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "nx_putslab" "', argument " "3"" of type '" "void *""'"); - } - result = (int)nx_putslab(arg1,arg2,arg3); - Tcl_SetObjResult(interp,SWIG_From_int((int)(result))); - return TCL_OK; -fail: - return TCL_ERROR; -} - - -SWIGINTERN int -_wrap_nx_getslab(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - void *arg2 = (void *) 0 ; - void *arg3 = (void *) 0 ; - void *result = 0 ; - int res1 ; - int res2 ; - int res3 ; - - if (SWIG_GetArgs(interp, objc, objv,"ooo:nx_getslab handle startdim size ",(void *)0,(void *)0,(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_getslab" "', argument " "1"" of type '" "void *""'"); - } - res2 = SWIG_ConvertPtr(objv[2],SWIG_as_voidptrptr(&arg2), 0, 0); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nx_getslab" "', argument " "2"" of type '" "void *""'"); - } - res3 = SWIG_ConvertPtr(objv[3],SWIG_as_voidptrptr(&arg3), 0, 0); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "nx_getslab" "', argument " "3"" of type '" "void *""'"); - } - result = (void *)nx_getslab(arg1,arg2,arg3); - Tcl_SetObjResult(interp, SWIG_NewInstanceObj( SWIG_as_voidptr(result), SWIGTYPE_p_void,0)); - return TCL_OK; -fail: - return TCL_ERROR; -} - - -SWIGINTERN int -_wrap_nx_getds(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - char *arg2 = (char *) 0 ; - void *result = 0 ; - int res1 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - - if (SWIG_GetArgs(interp, objc, objv,"oo:nx_getds handle name ",(void *)0,(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_getds" "', argument " "1"" of type '" "void *""'"); - } - res2 = SWIG_AsCharPtrAndSize(objv[2], &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nx_getds" "', argument " "2"" of type '" "char *""'"); - } - arg2 = (char *)(buf2); - result = (void *)nx_getds(arg1,arg2); - Tcl_SetObjResult(interp, SWIG_NewInstanceObj( SWIG_as_voidptr(result), SWIGTYPE_p_void,0)); - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return TCL_OK; -fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return TCL_ERROR; -} - - -SWIGINTERN int -_wrap_nx_putds(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - char *arg2 = (char *) 0 ; - void *arg3 = (void *) 0 ; - int result; - int res1 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - int res3 ; - - if (SWIG_GetArgs(interp, objc, objv,"ooo:nx_putds handle name dataset ",(void *)0,(void *)0,(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_putds" "', argument " "1"" of type '" "void *""'"); - } - res2 = SWIG_AsCharPtrAndSize(objv[2], &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nx_putds" "', argument " "2"" of type '" "char *""'"); - } - arg2 = (char *)(buf2); - res3 = SWIG_ConvertPtr(objv[3],SWIG_as_voidptrptr(&arg3), 0, 0); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "nx_putds" "', argument " "3"" of type '" "void *""'"); - } - result = (int)nx_putds(arg1,arg2,arg3); - Tcl_SetObjResult(interp,SWIG_From_int((int)(result))); - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return TCL_OK; -fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return TCL_ERROR; -} - - -SWIGINTERN int -_wrap_nx_getdata(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - void *result = 0 ; - int res1 ; - - if (SWIG_GetArgs(interp, objc, objv,"o:nx_getdata handle ",(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_getdata" "', argument " "1"" of type '" "void *""'"); - } - result = (void *)nx_getdata(arg1); - Tcl_SetObjResult(interp, SWIG_NewInstanceObj( SWIG_as_voidptr(result), SWIGTYPE_p_void,0)); - return TCL_OK; -fail: - return TCL_ERROR; -} - - -SWIGINTERN int -_wrap_nx_putdata(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - void *arg2 = (void *) 0 ; - int result; - int res1 ; - int res2 ; - - if (SWIG_GetArgs(interp, objc, objv,"oo:nx_putdata handle dataset ",(void *)0,(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_putdata" "', argument " "1"" of type '" "void *""'"); - } - res2 = SWIG_ConvertPtr(objv[2],SWIG_as_voidptrptr(&arg2), 0, 0); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nx_putdata" "', argument " "2"" of type '" "void *""'"); - } - result = (int)nx_putdata(arg1,arg2); - Tcl_SetObjResult(interp,SWIG_From_int((int)(result))); - return TCL_OK; -fail: - return TCL_ERROR; -} - - -SWIGINTERN int -_wrap_nx_getinfo(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - void *result = 0 ; - int res1 ; - - if (SWIG_GetArgs(interp, objc, objv,"o:nx_getinfo handle ",(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_getinfo" "', argument " "1"" of type '" "void *""'"); - } - result = (void *)nx_getinfo(arg1); - Tcl_SetObjResult(interp, SWIG_NewInstanceObj( SWIG_as_voidptr(result), SWIGTYPE_p_void,0)); - return TCL_OK; -fail: - return TCL_ERROR; -} - - -SWIGINTERN int -_wrap_nx_getdataID(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - void *result = 0 ; - int res1 ; - - if (SWIG_GetArgs(interp, objc, objv,"o:nx_getdataID handle ",(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_getdataID" "', argument " "1"" of type '" "void *""'"); - } - result = (void *)nx_getdataID(arg1); - Tcl_SetObjResult(interp, SWIG_NewInstanceObj( SWIG_as_voidptr(result), SWIGTYPE_p_void,0)); - return TCL_OK; -fail: - return TCL_ERROR; -} - - -SWIGINTERN int -_wrap_nx_getnextattr(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - char arg2 ; - char *result = 0 ; - int res1 ; - char val2 ; - int ecode2 = 0 ; - - if (SWIG_GetArgs(interp, objc, objv,"oo:nx_getnextattr handle separator ",(void *)0,(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_getnextattr" "', argument " "1"" of type '" "void *""'"); - } - ecode2 = SWIG_AsVal_char SWIG_TCL_CALL_ARGS_2(objv[2], &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "nx_getnextattr" "', argument " "2"" of type '" "char""'"); - } - arg2 = (char)(val2); - result = (char *)nx_getnextattr(arg1,arg2); - Tcl_SetObjResult(interp,SWIG_FromCharPtr((const char *)result)); - return TCL_OK; -fail: - return TCL_ERROR; -} - - -SWIGINTERN int -_wrap_nx_putattr(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - char *arg2 = (char *) 0 ; - void *arg3 = (void *) 0 ; - int result; - int res1 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - int res3 ; - - if (SWIG_GetArgs(interp, objc, objv,"ooo:nx_putattr handle name ds ",(void *)0,(void *)0,(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_putattr" "', argument " "1"" of type '" "void *""'"); - } - res2 = SWIG_AsCharPtrAndSize(objv[2], &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nx_putattr" "', argument " "2"" of type '" "char *""'"); - } - arg2 = (char *)(buf2); - res3 = SWIG_ConvertPtr(objv[3],SWIG_as_voidptrptr(&arg3), 0, 0); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "nx_putattr" "', argument " "3"" of type '" "void *""'"); - } - result = (int)nx_putattr(arg1,arg2,arg3); - Tcl_SetObjResult(interp,SWIG_From_int((int)(result))); - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return TCL_OK; -fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return TCL_ERROR; -} - - -SWIGINTERN int -_wrap_nx_getattr(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - char *arg2 = (char *) 0 ; - int arg3 ; - int arg4 ; - void *result = 0 ; - int res1 ; - int res2 ; - char *buf2 = 0 ; - int alloc2 = 0 ; - int val3 ; - int ecode3 = 0 ; - int val4 ; - int ecode4 = 0 ; - - if (SWIG_GetArgs(interp, objc, objv,"oooo:nx_getattr handle name type length ",(void *)0,(void *)0,(void *)0,(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_getattr" "', argument " "1"" of type '" "void *""'"); - } - res2 = SWIG_AsCharPtrAndSize(objv[2], &buf2, NULL, &alloc2); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nx_getattr" "', argument " "2"" of type '" "char *""'"); - } - arg2 = (char *)(buf2); - ecode3 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[3], &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "nx_getattr" "', argument " "3"" of type '" "int""'"); - } - arg3 = (int)(val3); - ecode4 = SWIG_AsVal_int SWIG_TCL_CALL_ARGS_2(objv[4], &val4); - if (!SWIG_IsOK(ecode4)) { - SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "nx_getattr" "', argument " "4"" of type '" "int""'"); - } - arg4 = (int)(val4); - result = (void *)nx_getattr(arg1,arg2,arg3,arg4); - Tcl_SetObjResult(interp, SWIG_NewInstanceObj( SWIG_as_voidptr(result), SWIGTYPE_p_void,0)); - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return TCL_OK; -fail: - if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); - return TCL_ERROR; -} - - -SWIGINTERN int -_wrap_nx_makelink(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - void *arg2 = (void *) 0 ; - int result; - int res1 ; - int res2 ; - - if (SWIG_GetArgs(interp, objc, objv,"oo:nx_makelink handle link ",(void *)0,(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_makelink" "', argument " "1"" of type '" "void *""'"); - } - res2 = SWIG_ConvertPtr(objv[2],SWIG_as_voidptrptr(&arg2), 0, 0); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "nx_makelink" "', argument " "2"" of type '" "void *""'"); - } - result = (int)nx_makelink(arg1,arg2); - Tcl_SetObjResult(interp,SWIG_From_int((int)(result))); - return TCL_OK; -fail: - return TCL_ERROR; -} - - -SWIGINTERN int -_wrap_nx_opensourcegroup(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - void *arg1 = (void *) 0 ; - int result; - int res1 ; - - if (SWIG_GetArgs(interp, objc, objv,"o:nx_opensourcegroup handle ",(void *)0) == TCL_ERROR) SWIG_fail; - res1 = SWIG_ConvertPtr(objv[1],SWIG_as_voidptrptr(&arg1), 0, 0); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "nx_opensourcegroup" "', argument " "1"" of type '" "void *""'"); - } - result = (int)nx_opensourcegroup(arg1); - Tcl_SetObjResult(interp,SWIG_From_int((int)(result))); - return TCL_OK; -fail: - return TCL_ERROR; -} -static swig_command_info swig_commands[] = { - { SWIG_prefix "create_nxds", (swig_wrapper_func) _wrap_create_nxds, NULL}, - { SWIG_prefix "create_text_nxds", (swig_wrapper_func) _wrap_create_text_nxds, NULL}, - { SWIG_prefix "drop_nxds", (swig_wrapper_func) _wrap_drop_nxds, NULL}, - { SWIG_prefix "get_nxds_rank", (swig_wrapper_func) _wrap_get_nxds_rank, NULL}, - { SWIG_prefix "get_nxds_type", (swig_wrapper_func) _wrap_get_nxds_type, NULL}, - { SWIG_prefix "get_nxds_dim", (swig_wrapper_func) _wrap_get_nxds_dim, NULL}, - { SWIG_prefix "get_nxds_value", (swig_wrapper_func) _wrap_get_nxds_value, NULL}, - { SWIG_prefix "get_nxds_text", (swig_wrapper_func) _wrap_get_nxds_text, NULL}, - { SWIG_prefix "put_nxds_value", (swig_wrapper_func) _wrap_put_nxds_value, NULL}, - { SWIG_prefix "nx_getlasterror", (swig_wrapper_func) _wrap_nx_getlasterror, NULL}, - { SWIG_prefix "nx_open", (swig_wrapper_func) _wrap_nx_open, NULL}, - { SWIG_prefix "nx_flush", (swig_wrapper_func) _wrap_nx_flush, NULL}, - { SWIG_prefix "nx_close", (swig_wrapper_func) _wrap_nx_close, NULL}, - { SWIG_prefix "nx_makegroup", (swig_wrapper_func) _wrap_nx_makegroup, NULL}, - { SWIG_prefix "nx_opengroup", (swig_wrapper_func) _wrap_nx_opengroup, NULL}, - { SWIG_prefix "nx_openpath", (swig_wrapper_func) _wrap_nx_openpath, NULL}, - { SWIG_prefix "nx_opengrouppath", (swig_wrapper_func) _wrap_nx_opengrouppath, NULL}, - { SWIG_prefix "nx_closegroup", (swig_wrapper_func) _wrap_nx_closegroup, NULL}, - { SWIG_prefix "nx_getnextentry", (swig_wrapper_func) _wrap_nx_getnextentry, NULL}, - { SWIG_prefix "nx_getgroupID", (swig_wrapper_func) _wrap_nx_getgroupID, NULL}, - { SWIG_prefix "nx_initgroupdir", (swig_wrapper_func) _wrap_nx_initgroupdir, NULL}, - { SWIG_prefix "nx_makedata", (swig_wrapper_func) _wrap_nx_makedata, NULL}, - { SWIG_prefix "nx_compmakedata", (swig_wrapper_func) _wrap_nx_compmakedata, NULL}, - { SWIG_prefix "nx_opendata", (swig_wrapper_func) _wrap_nx_opendata, NULL}, - { SWIG_prefix "nx_closedata", (swig_wrapper_func) _wrap_nx_closedata, NULL}, - { SWIG_prefix "nx_putslab", (swig_wrapper_func) _wrap_nx_putslab, NULL}, - { SWIG_prefix "nx_getslab", (swig_wrapper_func) _wrap_nx_getslab, NULL}, - { SWIG_prefix "nx_getds", (swig_wrapper_func) _wrap_nx_getds, NULL}, - { SWIG_prefix "nx_putds", (swig_wrapper_func) _wrap_nx_putds, NULL}, - { SWIG_prefix "nx_getdata", (swig_wrapper_func) _wrap_nx_getdata, NULL}, - { SWIG_prefix "nx_putdata", (swig_wrapper_func) _wrap_nx_putdata, NULL}, - { SWIG_prefix "nx_getinfo", (swig_wrapper_func) _wrap_nx_getinfo, NULL}, - { SWIG_prefix "nx_getdataID", (swig_wrapper_func) _wrap_nx_getdataID, NULL}, - { SWIG_prefix "nx_getnextattr", (swig_wrapper_func) _wrap_nx_getnextattr, NULL}, - { SWIG_prefix "nx_putattr", (swig_wrapper_func) _wrap_nx_putattr, NULL}, - { SWIG_prefix "nx_getattr", (swig_wrapper_func) _wrap_nx_getattr, NULL}, - { SWIG_prefix "nx_makelink", (swig_wrapper_func) _wrap_nx_makelink, NULL}, - { SWIG_prefix "nx_opensourcegroup", (swig_wrapper_func) _wrap_nx_opensourcegroup, NULL}, + static swig_command_info swig_commands[] = { + {SWIG_prefix "create_nxds", (swig_wrapper_func) _wrap_create_nxds, + NULL}, + {SWIG_prefix "create_text_nxds", + (swig_wrapper_func) _wrap_create_text_nxds, NULL}, + {SWIG_prefix "drop_nxds", (swig_wrapper_func) _wrap_drop_nxds, NULL}, + {SWIG_prefix "get_nxds_rank", (swig_wrapper_func) _wrap_get_nxds_rank, + NULL}, + {SWIG_prefix "get_nxds_type", (swig_wrapper_func) _wrap_get_nxds_type, + NULL}, + {SWIG_prefix "get_nxds_dim", (swig_wrapper_func) _wrap_get_nxds_dim, + NULL}, + {SWIG_prefix "get_nxds_value", + (swig_wrapper_func) _wrap_get_nxds_value, NULL}, + {SWIG_prefix "get_nxds_text", (swig_wrapper_func) _wrap_get_nxds_text, + NULL}, + {SWIG_prefix "put_nxds_value", + (swig_wrapper_func) _wrap_put_nxds_value, NULL}, + {SWIG_prefix "nx_getlasterror", + (swig_wrapper_func) _wrap_nx_getlasterror, NULL}, + {SWIG_prefix "nx_open", (swig_wrapper_func) _wrap_nx_open, NULL}, + {SWIG_prefix "nx_flush", (swig_wrapper_func) _wrap_nx_flush, NULL}, + {SWIG_prefix "nx_close", (swig_wrapper_func) _wrap_nx_close, NULL}, + {SWIG_prefix "nx_makegroup", (swig_wrapper_func) _wrap_nx_makegroup, + NULL}, + {SWIG_prefix "nx_opengroup", (swig_wrapper_func) _wrap_nx_opengroup, + NULL}, + {SWIG_prefix "nx_openpath", (swig_wrapper_func) _wrap_nx_openpath, + NULL}, + {SWIG_prefix "nx_opengrouppath", + (swig_wrapper_func) _wrap_nx_opengrouppath, NULL}, + {SWIG_prefix "nx_closegroup", (swig_wrapper_func) _wrap_nx_closegroup, + NULL}, + {SWIG_prefix "nx_getnextentry", + (swig_wrapper_func) _wrap_nx_getnextentry, NULL}, + {SWIG_prefix "nx_getgroupID", (swig_wrapper_func) _wrap_nx_getgroupID, + NULL}, + {SWIG_prefix "nx_initgroupdir", + (swig_wrapper_func) _wrap_nx_initgroupdir, NULL}, + {SWIG_prefix "nx_makedata", (swig_wrapper_func) _wrap_nx_makedata, + NULL}, + {SWIG_prefix "nx_compmakedata", + (swig_wrapper_func) _wrap_nx_compmakedata, NULL}, + {SWIG_prefix "nx_opendata", (swig_wrapper_func) _wrap_nx_opendata, + NULL}, + {SWIG_prefix "nx_closedata", (swig_wrapper_func) _wrap_nx_closedata, + NULL}, + {SWIG_prefix "nx_putslab", (swig_wrapper_func) _wrap_nx_putslab, NULL}, + {SWIG_prefix "nx_getslab", (swig_wrapper_func) _wrap_nx_getslab, NULL}, + {SWIG_prefix "nx_getds", (swig_wrapper_func) _wrap_nx_getds, NULL}, + {SWIG_prefix "nx_putds", (swig_wrapper_func) _wrap_nx_putds, NULL}, + {SWIG_prefix "nx_getdata", (swig_wrapper_func) _wrap_nx_getdata, NULL}, + {SWIG_prefix "nx_putdata", (swig_wrapper_func) _wrap_nx_putdata, NULL}, + {SWIG_prefix "nx_getinfo", (swig_wrapper_func) _wrap_nx_getinfo, NULL}, + {SWIG_prefix "nx_getdataID", (swig_wrapper_func) _wrap_nx_getdataID, + NULL}, + {SWIG_prefix "nx_getnextattr", + (swig_wrapper_func) _wrap_nx_getnextattr, NULL}, + {SWIG_prefix "nx_putattr", (swig_wrapper_func) _wrap_nx_putattr, NULL}, + {SWIG_prefix "nx_getattr", (swig_wrapper_func) _wrap_nx_getattr, NULL}, + {SWIG_prefix "nx_makelink", (swig_wrapper_func) _wrap_nx_makelink, + NULL}, + {SWIG_prefix "nx_opensourcegroup", + (swig_wrapper_func) _wrap_nx_opensourcegroup, NULL}, {0, 0, 0} -}; + }; -static swig_var_info swig_variables[] = { - {0,0,0,0} -}; + static swig_var_info swig_variables[] = { + {0, 0, 0, 0} + }; -static swig_const_info swig_constants[] = { - {0,0,0,0,0,0} -}; + static swig_const_info swig_constants[] = { + {0, 0, 0, 0, 0, 0} + }; /* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */ -static swig_type_info _swigt__p_char = {"_p_char", "char *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_void = {"_p_void", "void *", 0, 0, (void*)0, 0}; + static swig_type_info _swigt__p_char = + { "_p_char", "char *", 0, 0, (void *) 0, 0 }; + static swig_type_info _swigt__p_void = + { "_p_void", "void *", 0, 0, (void *) 0, 0 }; -static swig_type_info *swig_type_initial[] = { - &_swigt__p_char, - &_swigt__p_void, -}; + static swig_type_info *swig_type_initial[] = { + &_swigt__p_char, + &_swigt__p_void, + }; -static swig_cast_info _swigc__p_char[] = { {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_void[] = { {&_swigt__p_void, 0, 0, 0},{0, 0, 0, 0}}; + static swig_cast_info _swigc__p_char[] = + { {&_swigt__p_char, 0, 0, 0}, {0, 0, 0, 0} }; + static swig_cast_info _swigc__p_void[] = + { {&_swigt__p_void, 0, 0, 0}, {0, 0, 0, 0} }; -static swig_cast_info *swig_cast_initial[] = { - _swigc__p_char, - _swigc__p_void, -}; + static swig_cast_info *swig_cast_initial[] = { + _swigc__p_char, + _swigc__p_void, + }; /* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */ @@ -3231,31 +3817,28 @@ static swig_cast_info *swig_cast_initial[] = { #ifdef __cplusplus extern "C" { #if 0 -} /* c-mode */ +} /* c-mode */ #endif #endif - #if 0 #define SWIGRUNTIME_DEBUG #endif - - -SWIGRUNTIME void -SWIG_InitializeModule(void *clientdata) { +SWIGRUNTIME void SWIG_InitializeModule(void *clientdata) +{ size_t i; swig_module_info *module_head, *iter; int found; - + clientdata = clientdata; - + /* check to see if the circular list has been setup, if not, set it up */ - if (swig_module.next==0) { + if (swig_module.next == 0) { /* Initialize the swig_module */ swig_module.type_initial = swig_type_initial; swig_module.cast_initial = swig_cast_initial; swig_module.next = &swig_module; } - + /* Try and load any already created modules */ module_head = SWIG_GetModule(clientdata); if (!module_head) { @@ -3265,23 +3848,24 @@ SWIG_InitializeModule(void *clientdata) { module_head = &swig_module; } else { /* the interpreter has loaded a SWIG module, but has it loaded this one? */ - found=0; - iter=module_head; + found = 0; + iter = module_head; do { - if (iter==&swig_module) { - found=1; + if (iter == &swig_module) { + found = 1; break; } - iter=iter->next; - } while (iter!= module_head); - + iter = iter->next; + } while (iter != module_head); + /* if the is found in the list, then all is done and we may leave */ - if (found) return; + if (found) + return; /* otherwise we must add out module into the list */ swig_module.next = module_head->next; module_head->next = &swig_module; } - + /* Now work on filling in swig_module.types */ #ifdef SWIGRUNTIME_DEBUG printf("SWIG_InitializeModule: size %d\n", swig_module.size); @@ -3290,14 +3874,17 @@ SWIG_InitializeModule(void *clientdata) { swig_type_info *type = 0; swig_type_info *ret; swig_cast_info *cast; - + #ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name); + printf("SWIG_InitializeModule: type %d %s\n", i, + swig_module.type_initial[i]->name); #endif - + /* if there is another module already loaded */ if (swig_module.next != &swig_module) { - type = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, swig_module.type_initial[i]->name); + type = + SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, + swig_module.type_initial[i]->name); } if (type) { /* Overwrite clientdata field */ @@ -3307,13 +3894,14 @@ SWIG_InitializeModule(void *clientdata) { if (swig_module.type_initial[i]->clientdata) { type->clientdata = swig_module.type_initial[i]->clientdata; #ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: found and overwrite type %s \n", type->name); + printf("SWIG_InitializeModule: found and overwrite type %s \n", + type->name); #endif } } else { type = swig_module.type_initial[i]; } - + /* Insert casting types */ cast = swig_module.cast_initial[i]; while (cast->type) { @@ -3323,9 +3911,12 @@ SWIG_InitializeModule(void *clientdata) { printf("SWIG_InitializeModule: look cast %s\n", cast->type->name); #endif if (swig_module.next != &swig_module) { - ret = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, cast->type->name); + ret = + SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, + cast->type->name); #ifdef SWIGRUNTIME_DEBUG - if (ret) printf("SWIG_InitializeModule: found cast %s\n", ret->name); + if (ret) + printf("SWIG_InitializeModule: found cast %s\n", ret->name); #endif } if (ret) { @@ -3339,15 +3930,18 @@ SWIG_InitializeModule(void *clientdata) { /* Check for casting already in the list */ swig_cast_info *ocast = SWIG_TypeCheck(ret->name, type); #ifdef SWIGRUNTIME_DEBUG - if (ocast) printf("SWIG_InitializeModule: skip old cast %s\n", ret->name); + if (ocast) + printf("SWIG_InitializeModule: skip old cast %s\n", ret->name); #endif - if (!ocast) ret = 0; + if (!ocast) + ret = 0; } } - + if (!ret) { #ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: adding cast %s\n", cast->type->name); + printf("SWIG_InitializeModule: adding cast %s\n", + cast->type->name); #endif if (type->cast) { type->cast->prev = cast; @@ -3361,19 +3955,20 @@ SWIG_InitializeModule(void *clientdata) { swig_module.types[i] = type; } swig_module.types[i] = 0; - + #ifdef SWIGRUNTIME_DEBUG printf("**** SWIG_InitializeModule: Cast List ******\n"); for (i = 0; i < swig_module.size; ++i) { int j = 0; swig_cast_info *cast = swig_module.cast_initial[i]; - printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name); + printf("SWIG_InitializeModule: type %d %s\n", i, + swig_module.type_initial[i]->name); while (cast->type) { printf("SWIG_InitializeModule: cast type %s\n", cast->type->name); cast++; ++j; } - printf("---- Total casts: %d\n",j); + printf("---- Total casts: %d\n", j); } printf("**** SWIG_InitializeModule: Cast List ******\n"); #endif @@ -3384,22 +3979,24 @@ SWIG_InitializeModule(void *clientdata) { * of equivalent types. It is like calling * SWIG_TypeClientData(type, clientdata) a second time. */ -SWIGRUNTIME void -SWIG_PropagateClientData(void) { +SWIGRUNTIME void SWIG_PropagateClientData(void) +{ size_t i; swig_cast_info *equiv; static int init_run = 0; - - if (init_run) return; + + if (init_run) + return; init_run = 1; - + for (i = 0; i < swig_module.size; i++) { if (swig_module.types[i]->clientdata) { equiv = swig_module.types[i]->cast; while (equiv) { if (!equiv->converter) { if (equiv->type && !equiv->type->clientdata) - SWIG_TypeClientData(equiv->type, swig_module.types[i]->clientdata); + SWIG_TypeClientData(equiv->type, + swig_module.types[i]->clientdata); } equiv = equiv->next; } @@ -3419,29 +4016,34 @@ SWIG_PropagateClientData(void) { #ifdef __cplusplus extern "C" { #endif - + /* ----------------------------------------------------------------------------- * constants/methods manipulation * ----------------------------------------------------------------------------- */ - + /* Install Constants */ - + SWIGINTERN void - SWIG_Tcl_InstallConstants(Tcl_Interp *interp, swig_const_info constants[]) { + SWIG_Tcl_InstallConstants(Tcl_Interp * interp, + swig_const_info constants[]) { int i; Tcl_Obj *obj; - + if (!swigconstTableinit) { Tcl_InitHashTable(&swigconstTable, TCL_STRING_KEYS); swigconstTableinit = 1; } for (i = 0; constants[i].type; i++) { - switch(constants[i].type) { + switch (constants[i].type) { case SWIG_TCL_POINTER: - obj = SWIG_NewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0); + obj = + SWIG_NewPointerObj(constants[i].pvalue, *(constants[i]).ptype, + 0); break; case SWIG_TCL_BINARY: - obj = SWIG_NewPackedObj(constants[i].pvalue, constants[i].lvalue, *(constants[i].ptype)); + obj = + SWIG_NewPackedObj(constants[i].pvalue, constants[i].lvalue, + *(constants[i].ptype)); break; default: obj = 0; @@ -3452,7 +4054,7 @@ extern "C" { } } } - + #ifdef __cplusplus } #endif @@ -3461,56 +4063,67 @@ extern "C" { * Partial Init method * -----------------------------------------------------------------------------*/ -SWIGEXPORT int SWIG_init(Tcl_Interp *interp) { +SWIGEXPORT int SWIG_init(Tcl_Interp * interp) +{ int i; - if (interp == 0) return TCL_ERROR; + if (interp == 0) + return TCL_ERROR; #ifdef USE_TCL_STUBS - if (Tcl_InitStubs(interp, (char*)"8.1", 0) == NULL) { + if (Tcl_InitStubs(interp, (char *) "8.1", 0) == NULL) { return TCL_ERROR; } -#endif - Tcl_PkgProvide(interp, (char*)SWIG_name, (char*)SWIG_version); - +#endif + Tcl_PkgProvide(interp, (char *) SWIG_name, (char *) SWIG_version); + #ifdef SWIG_namespace Tcl_Eval(interp, "namespace eval " SWIG_namespace " { }"); #endif - + SWIG_InitializeModule((void *) interp); SWIG_PropagateClientData(); - + for (i = 0; swig_commands[i].name; i++) { - Tcl_CreateObjCommand(interp, (char *) swig_commands[i].name, (swig_wrapper_func) swig_commands[i].wrapper, - swig_commands[i].clientdata, NULL); + Tcl_CreateObjCommand(interp, (char *) swig_commands[i].name, + (swig_wrapper_func) swig_commands[i].wrapper, + swig_commands[i].clientdata, NULL); } for (i = 0; swig_variables[i].name; i++) { - Tcl_SetVar(interp, (char *) swig_variables[i].name, (char *) "", TCL_GLOBAL_ONLY); - Tcl_TraceVar(interp, (char *) swig_variables[i].name, TCL_TRACE_READS | TCL_GLOBAL_ONLY, - (Tcl_VarTraceProc *) swig_variables[i].get, (ClientData) swig_variables[i].addr); - Tcl_TraceVar(interp, (char *) swig_variables[i].name, TCL_TRACE_WRITES | TCL_GLOBAL_ONLY, - (Tcl_VarTraceProc *) swig_variables[i].set, (ClientData) swig_variables[i].addr); + Tcl_SetVar(interp, (char *) swig_variables[i].name, (char *) "", + TCL_GLOBAL_ONLY); + Tcl_TraceVar(interp, (char *) swig_variables[i].name, + TCL_TRACE_READS | TCL_GLOBAL_ONLY, + (Tcl_VarTraceProc *) swig_variables[i].get, + (ClientData) swig_variables[i].addr); + Tcl_TraceVar(interp, (char *) swig_variables[i].name, + TCL_TRACE_WRITES | TCL_GLOBAL_ONLY, + (Tcl_VarTraceProc *) swig_variables[i].set, + (ClientData) swig_variables[i].addr); } - + SWIG_Tcl_InstallConstants(interp, swig_constants); - - - SWIG_Tcl_SetConstantObj(interp, "NXACC_READ", SWIG_From_int((int)(1))); - SWIG_Tcl_SetConstantObj(interp, "NXACC_RDWR", SWIG_From_int((int)(2))); - SWIG_Tcl_SetConstantObj(interp, "NXACC_CREATE", SWIG_From_int((int)(3))); - SWIG_Tcl_SetConstantObj(interp, "NXACC_CREATE4", SWIG_From_int((int)(4))); - SWIG_Tcl_SetConstantObj(interp, "NXACC_CREATE5", SWIG_From_int((int)(5))); - SWIG_Tcl_SetConstantObj(interp, "NX_FLOAT32", SWIG_From_int((int)(5))); - SWIG_Tcl_SetConstantObj(interp, "NX_FLOAT64", SWIG_From_int((int)(6))); - SWIG_Tcl_SetConstantObj(interp, "NX_INT8", SWIG_From_int((int)(20))); - SWIG_Tcl_SetConstantObj(interp, "NX_UINT8", SWIG_From_int((int)(21))); - SWIG_Tcl_SetConstantObj(interp, "NX_BOOLEAN", SWIG_From_int((int)(21))); - SWIG_Tcl_SetConstantObj(interp, "NX_INT16", SWIG_From_int((int)(22))); - SWIG_Tcl_SetConstantObj(interp, "NX_UINT16", SWIG_From_int((int)(23))); - SWIG_Tcl_SetConstantObj(interp, "NX_INT32", SWIG_From_int((int)(24))); - SWIG_Tcl_SetConstantObj(interp, "NX_UINT32", SWIG_From_int((int)(25))); - SWIG_Tcl_SetConstantObj(interp, "NX_CHAR", SWIG_From_int((int)(4))); + + + SWIG_Tcl_SetConstantObj(interp, "NXACC_READ", SWIG_From_int((int) (1))); + SWIG_Tcl_SetConstantObj(interp, "NXACC_RDWR", SWIG_From_int((int) (2))); + SWIG_Tcl_SetConstantObj(interp, "NXACC_CREATE", + SWIG_From_int((int) (3))); + SWIG_Tcl_SetConstantObj(interp, "NXACC_CREATE4", + SWIG_From_int((int) (4))); + SWIG_Tcl_SetConstantObj(interp, "NXACC_CREATE5", + SWIG_From_int((int) (5))); + SWIG_Tcl_SetConstantObj(interp, "NX_FLOAT32", SWIG_From_int((int) (5))); + SWIG_Tcl_SetConstantObj(interp, "NX_FLOAT64", SWIG_From_int((int) (6))); + SWIG_Tcl_SetConstantObj(interp, "NX_INT8", SWIG_From_int((int) (20))); + SWIG_Tcl_SetConstantObj(interp, "NX_UINT8", SWIG_From_int((int) (21))); + SWIG_Tcl_SetConstantObj(interp, "NX_BOOLEAN", SWIG_From_int((int) (21))); + SWIG_Tcl_SetConstantObj(interp, "NX_INT16", SWIG_From_int((int) (22))); + SWIG_Tcl_SetConstantObj(interp, "NX_UINT16", SWIG_From_int((int) (23))); + SWIG_Tcl_SetConstantObj(interp, "NX_INT32", SWIG_From_int((int) (24))); + SWIG_Tcl_SetConstantObj(interp, "NX_UINT32", SWIG_From_int((int) (25))); + SWIG_Tcl_SetConstantObj(interp, "NX_CHAR", SWIG_From_int((int) (4))); return TCL_OK; } -SWIGEXPORT int Nxinter_SafeInit(Tcl_Interp *interp) { +SWIGEXPORT int Nxinter_SafeInit(Tcl_Interp * interp) +{ return SWIG_init(interp); } - diff --git a/nxinterhelper.c b/nxinterhelper.c index 723e0adf..06aecfc4 100644 --- a/nxinterhelper.c +++ b/nxinterhelper.c @@ -18,320 +18,361 @@ An own error handler. nx_getlasterror will return the test of the last NeXus error. --------------------------------------------------------------------*/ -static char errorText[256]= ""; +static char errorText[256] = ""; -static void nxinterError(void *pData, char *error){ - strncpy(errorText,error,255); +static void nxinterError(void *pData, char *error) +{ + strncpy(errorText, error, 255); } + /*-----------------------------------------------------------------------*/ -char *nx_getlasterror(void){ +char *nx_getlasterror(void) +{ return strdup(errorText); } + /*-------------------- opening and closing -------------------------------*/ -void *nx_open(char *filename, int accessMethod){ +void *nx_open(char *filename, int accessMethod) +{ NXhandle handle = NULL; int status; - NXMSetError(NULL,nxinterError); - status = NXopen(filename,(NXaccess)accessMethod, &handle); - if(status == NX_OK){ - return handle; - }else{ - return NULL; - } -} -/*------------------------------------------------------------------------*/ -void *nx_flush(void *hundle){ - NXhandle handle; - int status; - - handle = (NXhandle)hundle; - status = NXflush(&handle); - if(status == NX_OK){ + NXMSetError(NULL, nxinterError); + status = NXopen(filename, (NXaccess) accessMethod, &handle); + if (status == NX_OK) { return handle; } else { return NULL; } } + +/*------------------------------------------------------------------------*/ +void *nx_flush(void *hundle) +{ + NXhandle handle; + int status; + + handle = (NXhandle) hundle; + status = NXflush(&handle); + if (status == NX_OK) { + return handle; + } else { + return NULL; + } +} + /*-----------------------------------------------------------------------*/ -void nx_close(void *hundle){ +void nx_close(void *hundle) +{ NXhandle handle; - handle = (NXhandle)hundle; + handle = (NXhandle) hundle; NXclose(&handle); } + /*=================== group handling functions ========================*/ -int nx_makegroup(void *handle, char *name, char *nxclass){ +int nx_makegroup(void *handle, char *name, char *nxclass) +{ int status; NXhandle hfil; - hfil = (NXhandle)handle; - status = NXmakegroup(hfil,name, nxclass); - if(status == NX_OK){ + hfil = (NXhandle) handle; + status = NXmakegroup(hfil, name, nxclass); + if (status == NX_OK) { return 1; } else { return 0; } } + /*---------------------------------------------------------------------*/ -int nx_opengroup(void *handle, char *name, char *nxclass){ +int nx_opengroup(void *handle, char *name, char *nxclass) +{ int status; NXhandle hfil; - hfil = (NXhandle)handle; - status = NXopengroup(hfil,name, nxclass); - if(status == NX_OK){ + hfil = (NXhandle) handle; + status = NXopengroup(hfil, name, nxclass); + if (status == NX_OK) { return 1; } else { return 0; } } + /*---------------------------------------------------------------------*/ -int nx_openpath(void *handle, char *path){ +int nx_openpath(void *handle, char *path) +{ int status; NXhandle hfil; - hfil = (NXhandle)handle; - status = NXopenpath(hfil,path); - if(status == NX_OK){ + hfil = (NXhandle) handle; + status = NXopenpath(hfil, path); + if (status == NX_OK) { return 1; } else { return 0; } } + /*---------------------------------------------------------------------*/ -int nx_opengrouppath(void *handle, char *path){ +int nx_opengrouppath(void *handle, char *path) +{ int status; NXhandle hfil; - hfil = (NXhandle)handle; - status = NXopengrouppath(hfil,path); - if(status == NX_OK){ + hfil = (NXhandle) handle; + status = NXopengrouppath(hfil, path); + if (status == NX_OK) { return 1; } else { return 0; } } + /*--------------------------------------------------------------------*/ -int nx_closegroup(void *handle){ +int nx_closegroup(void *handle) +{ int status; NXhandle hfil; - hfil = (NXhandle)handle; + hfil = (NXhandle) handle; status = NXclosegroup(hfil); - if(status == NX_OK){ + if (status == NX_OK) { return 1; } else { return 0; } } + /*-------------------------------------------------------------------*/ -char *nx_getnextentry(void *handle, char separator){ +char *nx_getnextentry(void *handle, char separator) +{ int status, length, type; NXhandle hfil; char *resultBuffer = NULL; - NXname group,nxclass; + NXname group, nxclass; - hfil = (NXhandle)handle; - status = NXgetnextentry(hfil,group, nxclass,&type); - if(status == NX_OK){ + hfil = (NXhandle) handle; + status = NXgetnextentry(hfil, group, nxclass, &type); + if (status == NX_OK) { length = 30 + strlen(group) + strlen(nxclass); /* - This introduces a memory leak. I had hoped, that swig would - kill it for me after use, but I'am afraid, this is not the - case. Unfortately I do not know how to fix the issue. - */ - resultBuffer = (char *)malloc(length*sizeof(char)); - if(resultBuffer == NULL){ + This introduces a memory leak. I had hoped, that swig would + kill it for me after use, but I'am afraid, this is not the + case. Unfortately I do not know how to fix the issue. + */ + resultBuffer = (char *) malloc(length * sizeof(char)); + if (resultBuffer == NULL) { return NULL; } - sprintf(resultBuffer,"%s%c%s%c%d",group,separator,nxclass, - separator,type); + sprintf(resultBuffer, "%s%c%s%c%d", group, separator, nxclass, + separator, type); return resultBuffer; } else { return NULL; } } + /*-------------------------------------------------------------------*/ -void *nx_getgroupID(void *handle){ +void *nx_getgroupID(void *handle) +{ int status; NXhandle hfil; NXlink *linki; - linki = (NXlink *)malloc(sizeof(NXlink)); - if(linki == NULL){ + linki = (NXlink *) malloc(sizeof(NXlink)); + if (linki == NULL) { return NULL; } - hfil = (NXhandle)handle; - status = NXgetgroupID(hfil,linki); - if(status == NX_OK){ + hfil = (NXhandle) handle; + status = NXgetgroupID(hfil, linki); + if (status == NX_OK) { return linki; } else { return NULL; } } + /*------------------------------------------------------------------*/ -int nx_initgroupdir(void *handle){ +int nx_initgroupdir(void *handle) +{ int status; NXhandle hfil; - hfil = (NXhandle)handle; + hfil = (NXhandle) handle; status = NXinitgroupdir(hfil); - if(status == NX_OK){ + if (status == NX_OK) { return 1; } else { return 0; } } + /*========================== dataset handling =======================*/ -int nx_makedata(void *ptr, char *name, int rank, int type, - void *dimPtr){ +int nx_makedata(void *ptr, char *name, int rank, int type, void *dimPtr) +{ int status; NXhandle hfil; pNXDS dimData; - hfil = (NXhandle)ptr; - dimData = (pNXDS)dimPtr; - if(dimData->type != NX_INT32){ - NXIReportError(NULL,"ERROR: dimension data not integer"); + hfil = (NXhandle) ptr; + dimData = (pNXDS) dimPtr; + if (dimData->type != NX_INT32) { + NXIReportError(NULL, "ERROR: dimension data not integer"); return 0; } - status = NXmakedata(hfil, name, type, rank, - dimData->u.iPtr); - if(status == NX_OK){ + status = NXmakedata(hfil, name, type, rank, dimData->u.iPtr); + if (status == NX_OK) { return 1; } else { return 0; } } + /*--------------------------------------------------------------------*/ -int nx_compmakedata(void *ptr, char *name, int rank, int type, - void *dimPtr, void *bufPtr){ +int nx_compmakedata(void *ptr, char *name, int rank, int type, + void *dimPtr, void *bufPtr) +{ int status; NXhandle hfil; pNXDS dimData, bufData; - hfil = (NXhandle)ptr; - dimData = (pNXDS)dimPtr; - if(dimData->type != NX_INT32){ - NXIReportError(NULL,"ERROR: dimension data not integer"); + hfil = (NXhandle) ptr; + dimData = (pNXDS) dimPtr; + if (dimData->type != NX_INT32) { + NXIReportError(NULL, "ERROR: dimension data not integer"); return 0; } - bufData = (pNXDS)bufPtr; - status = NXcompmakedata(hfil, name, type, rank, - dimData->u.iPtr, NX_COMP_LZW,bufData->u.iPtr); - if(status == NX_OK){ + bufData = (pNXDS) bufPtr; + status = NXcompmakedata(hfil, name, type, rank, + dimData->u.iPtr, NX_COMP_LZW, bufData->u.iPtr); + if (status == NX_OK) { return 1; } else { return 0; } } + /*----------------------------------------------------------------------*/ -int nx_opendata(void *handle, char *name){ +int nx_opendata(void *handle, char *name) +{ int status; NXhandle hfil; - hfil = (NXhandle)handle; - status = NXopendata(hfil,name); - if(status == NX_OK){ + hfil = (NXhandle) handle; + status = NXopendata(hfil, name); + if (status == NX_OK) { return 1; } else { return 0; } } + /*----------------------------------------------------------------------*/ -int nx_closedata(void *handle){ +int nx_closedata(void *handle) +{ int status; NXhandle hfil; - hfil = (NXhandle)handle; + hfil = (NXhandle) handle; status = NXclosedata(hfil); - if(status == NX_OK){ + if (status == NX_OK) { return 1; } else { return 0; } } + /*------------------------------------------------------------------------*/ -int nx_putslab(void *handle, void *dataset, void *startDim){ +int nx_putslab(void *handle, void *dataset, void *startDim) +{ int status; NXhandle hfil; pNXDS data; pNXDS start; - int end[NX_MAXRANK], i; + int end[NX_MAXRANK], i; - hfil = (NXhandle)handle; - data = (pNXDS)dataset; - start = (pNXDS)startDim; - for(i = 0; i < data->rank;i++){ + hfil = (NXhandle) handle; + data = (pNXDS) dataset; + start = (pNXDS) startDim; + for (i = 0; i < data->rank; i++) { end[i] = data->dim[i]; } - status = NXputslab(hfil,data->u.ptr,start->u.iPtr,end); - if(status == NX_OK){ + status = NXputslab(hfil, data->u.ptr, start->u.iPtr, end); + if (status == NX_OK) { return 1; } else { return 0; } } + /*-----------------------------------------------------------------------*/ -void *nx_getslab(void *handle, void *startdim, void *sizedim){ +void *nx_getslab(void *handle, void *startdim, void *sizedim) +{ pNXDS resultdata; pNXDS start, size; int status, rank, type, dim[NX_MAXRANK]; + int64_t cdim[NX_MAXRANK], i; NXhandle hfil; - hfil = (NXhandle)handle; - start = (pNXDS)startdim; - size = (pNXDS)sizedim; + hfil = (NXhandle) handle; + start = (pNXDS) startdim; + size = (pNXDS) sizedim; /* - get info first, then allocate data - */ - status = NXgetinfo(hfil, &rank,dim,&type); - if(status != NX_OK){ - return NULL; - } - - resultdata = createNXDataset(rank,type,size->u.iPtr); - if(resultdata == NULL){ + get info first, then allocate data + */ + status = NXgetinfo(hfil, &rank, dim, &type); + if (status != NX_OK) { return NULL; } - status = NXgetslab(hfil,resultdata->u.ptr,start->u.iPtr, - size->u.iPtr); - if(status == NX_OK){ + for(i = 0; i < rank; i++){ + cdim[i] = size->u.iPtr[i]; + } + resultdata = createNXDataset(rank, type, cdim); + if (resultdata == NULL) { + return NULL; + } + + status = NXgetslab(hfil, resultdata->u.ptr, start->u.iPtr, size->u.iPtr); + if (status == NX_OK) { return resultdata; - }else{ + } else { dropNXDataset(resultdata); return NULL; } } + /*------------------------------------------------------------------------*/ -void *nx_getds(void *handle, char *name){ +void *nx_getds(void *handle, char *name) +{ pNXDS result = NULL; - int rank, type,dim[NX_MAXRANK],status; + int rank, type,status; + int64_t dim[NX_MAXRANK]; NXhandle hfil; - hfil = (NXhandle)handle; - status = NXopendata(hfil,name); - if(status != NX_OK){ + hfil = (NXhandle) handle; + status = NXopendata(hfil, name); + if (status != NX_OK) { return NULL; } - status = NXgetinfo(hfil,&rank,dim,&type); - if(status != NX_OK){ + status = NXgetinfo64(hfil, &rank, dim, &type); + if (status != NX_OK) { return NULL; } - result = createNXDataset(rank,type,dim); - if(result == NULL){ + result = createNXDataset(rank, type, dim); + if (result == NULL) { NXclosedata(hfil); return NULL; } - status = NXgetdata(hfil,result->u.ptr); - if(result == NULL){ + status = NXgetdata(hfil, result->u.ptr); + if (result == NULL) { NXclosedata(hfil); dropNXDataset(result); return NULL; @@ -339,223 +380,243 @@ void *nx_getds(void *handle, char *name){ NXclosedata(hfil); return result; } + /*----------------------------------------------------------------------*/ -int nx_putds(void *handle, char *name, void *dataset){ +int nx_putds(void *handle, char *name, void *dataset) +{ NXhandle hfil; int status; pNXDS data; - hfil = (NXhandle)handle; - data = (pNXDS)dataset; + hfil = (NXhandle) handle; + data = (pNXDS) dataset; - status = NXopendata(hfil,name); - if(status != NX_OK){ - status = NXmakedata(hfil,name,data->type,data->rank,data->dim); - if(status != NX_OK){ + status = NXopendata(hfil, name); + if (status != NX_OK) { + status = NXmakedata64(hfil, name, data->type, data->rank, data->dim); + if (status != NX_OK) { return 0; } - NXopendata(hfil,name); + NXopendata(hfil, name); } - status = NXputdata(hfil,data->u.ptr); + status = NXputdata(hfil, data->u.ptr); NXclosedata(hfil); - if(status != NX_OK){ + if (status != NX_OK) { return 0; - }else{ + } else { return 1; } } + /*------------------------------------------------------------------------*/ -void *nx_getdata(void *handle){ +void *nx_getdata(void *handle) +{ pNXDS result = NULL; - int rank, type,dim[NX_MAXRANK],status; + int rank, type, status; + int64_t dim[NX_MAXRANK]; NXhandle hfil; - hfil = (NXhandle)handle; - status = NXgetinfo(hfil,&rank,dim,&type); - if(status != NX_OK){ + hfil = (NXhandle) handle; + status = NXgetinfo64(hfil, &rank, dim, &type); + if (status != NX_OK) { return NULL; } - result = createNXDataset(rank,type,dim); - if(result == NULL){ + result = createNXDataset(rank, type, dim); + if (result == NULL) { NXclosedata(hfil); return NULL; } - status = NXgetdata(hfil,result->u.ptr); - if(result == NULL){ + status = NXgetdata(hfil, result->u.ptr); + if (result == NULL) { dropNXDataset(result); return NULL; } return result; } + /*----------------------------------------------------------------------*/ -int nx_putdata(void *handle, void *dataset){ +int nx_putdata(void *handle, void *dataset) +{ NXhandle hfil; int status; pNXDS data; - hfil = (NXhandle)handle; - data = (pNXDS)dataset; + hfil = (NXhandle) handle; + data = (pNXDS) dataset; - if(data == NULL){ - NXIReportError(NULL,"ERROR: NULL data pointer in nx_putdata"); + if (data == NULL) { + NXIReportError(NULL, "ERROR: NULL data pointer in nx_putdata"); return 0; } - status = NXputdata(hfil,data->u.ptr); - if(status != NX_OK){ + status = NXputdata(hfil, data->u.ptr); + if (status != NX_OK) { return 0; - }else{ + } else { return 1; } } + /*----------------------------------------------------------------------*/ -void *nx_getinfo(void *handle){ +void *nx_getinfo(void *handle) +{ NXhandle hfil; - int status, type, rank, dim[NX_MAXRANK], rdim[1], i; + int status, type, rank, dim[NX_MAXRANK], i; + int64_t rdim[1]; pNXDS data = NULL; - hfil = (NXhandle)handle; + hfil = (NXhandle) handle; - status = NXgetinfo(handle,&rank,dim,&type); - if(status != NX_OK){ + status = NXgetinfo(handle, &rank, dim, &type); + if (status != NX_OK) { return NULL; } rdim[0] = 2 + rank; - data = createNXDataset(1,NX_INT32,rdim); + data = createNXDataset(1, NX_INT32, rdim); data->u.iPtr[0] = type; data->u.iPtr[1] = rank; - for(i = 0; i < rank; i++){ - data->u.iPtr[2+i] = dim[i]; + for (i = 0; i < rank; i++) { + data->u.iPtr[2 + i] = dim[i]; } return data; } + /*----------------------------------------------------------------------*/ -void *nx_getdataID(void *handle){ +void *nx_getdataID(void *handle) +{ NXhandle hfil; int status; NXlink *linki; - linki = (NXlink *)malloc(sizeof(NXlink)); - if(linki == NULL){ + linki = (NXlink *) malloc(sizeof(NXlink)); + if (linki == NULL) { return NULL; } - hfil = (NXhandle)handle; - status = NXgetdataID(hfil,linki); - if(status == NX_OK){ + hfil = (NXhandle) handle; + status = NXgetdataID(hfil, linki); + if (status == NX_OK) { return linki; } else { free(linki); return NULL; } } + /*-------------------------------------------------------------------*/ -char *nx_getnextattr(void *handle, char separator){ +char *nx_getnextattr(void *handle, char separator) +{ int status, length, type; char *result; NXhandle hfil; NXname aName; - hfil = (NXhandle)handle; - status = NXgetnextattr(hfil,aName, &length, &type); - if(status == NX_OK){ + hfil = (NXhandle) handle; + status = NXgetnextattr(hfil, aName, &length, &type); + if (status == NX_OK) { /* - This introduces a memory leak. I had hoped, that swig would - kill it for me after use, but I'am afraid, this is not the - case. Unfortately I do not know how to fix the issue. - */ - result = (char *)malloc((20+strlen(aName))*sizeof(char)); - if(result == NULL){ + This introduces a memory leak. I had hoped, that swig would + kill it for me after use, but I'am afraid, this is not the + case. Unfortately I do not know how to fix the issue. + */ + result = (char *) malloc((20 + strlen(aName)) * sizeof(char)); + if (result == NULL) { return NULL; } - memset(result,0,(20+strlen(aName))*sizeof(char)); - sprintf(result,"%s%c%d%c%d", aName,separator, - length,separator,type); + memset(result, 0, (20 + strlen(aName)) * sizeof(char)); + sprintf(result, "%s%c%d%c%d", aName, separator, + length, separator, type); return result; } else { return NULL; } } + /*-------------------------------------------------------------------*/ -int nx_putattr(void *handle, char *name, void *ds){ +int nx_putattr(void *handle, char *name, void *ds) +{ int status; NXhandle hfil; pNXDS data; - hfil = (NXhandle)handle; - data = (pNXDS)ds; - status = NXputattr(hfil,name,data->u.ptr,data->dim[0],data->type); - if(status == NX_OK){ + hfil = (NXhandle) handle; + data = (pNXDS) ds; + status = NXputattr(hfil, name, data->u.ptr, data->dim[0], data->type); + if (status == NX_OK) { return 1; - }else{ + } else { return 0; } } + /*-------------------------------------------------------------------*/ -void *nx_getattr(void *handle, char *name, int type, int length){ +void *nx_getattr(void *handle, char *name, int type, int length) +{ NXhandle hfil; - int status, tp, ll, dim[1]; + int status, tp, ll; + int64_t dim[1]; pNXDS data = NULL; - hfil = (NXhandle)handle; + hfil = (NXhandle) handle; /* - prepare dataset - */ - dim[0] = length+1; - data = createNXDataset(1,type,dim); - if(data == NULL){ + prepare dataset + */ + dim[0] = length + 1; + data = createNXDataset(1, type, dim); + if (data == NULL) { return NULL; } - + /* - finally read the real data - */ + finally read the real data + */ ll = length; tp = type; - status = NXgetattr(hfil,name,data->u.ptr,&ll,&tp); - if(status != NX_OK){ + status = NXgetattr(hfil, name, data->u.ptr, &ll, &tp); + if (status != NX_OK) { dropNXDataset(data); return NULL; } return data; } + /*-----------------------------------------------------------------------*/ -int nx_makelink(void *handle, void *link){ +int nx_makelink(void *handle, void *link) +{ NXhandle hfil; - NXlink* lk; + NXlink *lk; int status; - hfil = (NXhandle)handle; - lk = (NXlink *)link; + hfil = (NXhandle) handle; + lk = (NXlink *) link; - status = NXmakelink(hfil,lk); - if(status == NX_OK){ + status = NXmakelink(hfil, lk); + if (status == NX_OK) { return 1; - }else{ + } else { return 0; } } + /*-----------------------------------------------------------------------*/ -int nx_opensourcegroup(void *handle){ +int nx_opensourcegroup(void *handle) +{ NXhandle hfil; int status; - hfil = (NXhandle)handle; + hfil = (NXhandle) handle; status = NXopensourcegroup(hfil); - if(status == NX_OK){ + if (status == NX_OK) { return 1; - }else{ + } else { return 0; } } - - - diff --git a/nxinterhelper.h b/nxinterhelper.h index 7c2e280c..2b0d0b12 100644 --- a/nxinterhelper.h +++ b/nxinterhelper.h @@ -16,7 +16,7 @@ /*------------- opening and closing section ---------------------*/ void *nx_open(char *filename, int accessMethod); void *nx_flush(void *handle); -void nx_close(void *handle); +void nx_close(void *handle); /*--------------- group handling section ------------------------*/ int nx_makegroup(void *handle, char *name, char *nxclass); int nx_opengroup(void *handle, char *name, char *nxclass); @@ -29,8 +29,8 @@ int nx_initgroupdir(void *handle); /*---------------- dataset handling -----------------------------*/ int nx_makedata(void *ptr, char *name, int rank, int type, void *dimPtr); -int nx_compmakedata(void *ptr, char *name, int rank, int type, - void *dimPtr, void *bufPtr); +int nx_compmakedata(void *ptr, char *name, int rank, int type, + void *dimPtr, void *bufPtr); int nx_opendata(void *handle, char *name); int nx_closedata(void *handle); @@ -39,18 +39,18 @@ int nx_putslab(void *handle, void *dataset, void *startDim); void *nx_getslab(void *handle, void *startdim, void *size); void *nx_getds(void *handle, char *name); -int nx_putds(void *handle, char *name, void *dataset); +int nx_putds(void *handle, char *name, void *dataset); void *nx_getdata(void *handle); -int nx_putdata(void *handle,void *dataset); +int nx_putdata(void *handle, void *dataset); void *nx_getinfo(void *handle); void *nx_getdataID(void *handle); /*-------------------- attributes --------------------------------*/ char *nx_getnextattr(void *handle, char separator); -int nx_putattr(void *handle, char *name, void *ds); -void *nx_getattr(void *handle, char *name, int type, int length); +int nx_putattr(void *handle, char *name, void *ds); +void *nx_getattr(void *handle, char *name, int type, int length); /*---------------------- link -----------------------------------*/ @@ -60,9 +60,3 @@ int nx_opensourcegroup(void *handle); char *nx_getlasterror(void); #endif - - - - - - diff --git a/nxio.c b/nxio.c index a74145e9..eed88b54 100644 --- a/nxio.c +++ b/nxio.c @@ -21,9 +21,12 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * For further information, see + * For further information, see */ -#include + +#ifdef NXXML + +#include #include #include "napi.h" #include "nxio.h" @@ -35,6 +38,10 @@ #define MXML_WRAP 79 #endif +#ifdef _MSC_VER +#define snprintf _snprintf +#endif /* _MSC_VER */ + /* #define TESTMAIN 1 */ /*=================== type code handling ================================= */ typedef struct { @@ -90,12 +97,12 @@ void initializeNumberFormats(){ typecode[7] = myCode; strcpy(myCode.name,"NX_INT64"); - strcpy(myCode.format,"%24" PRINTF_INT64 ); + strcpy(myCode.format,"%24lld"); myCode.nx_type = NX_INT64; typecode[8] = myCode; strcpy(myCode.name,"NX_UINT64"); - strcpy(myCode.format,"%24" PRINTF_UINT64); + strcpy(myCode.format,"%24llu"); myCode.nx_type = NX_UINT64; typecode[9] = myCode; @@ -144,7 +151,7 @@ static int /* O - 0 on success, -1 on error */ myxml_add_char(int ch, /* I - Character to add */ char **bufptr, /* IO - Current position in buffer */ char **buffer, /* IO - Current buffer */ - int *bufsize) /* IO - Current buffer size */ + size_t *bufsize) /* IO - Current buffer size */ { char *newbuffer; /* New buffer value */ @@ -227,14 +234,21 @@ extern char *stptok(char *s, char *tok, size_t toklen, char *brk); /*===================================================================== actual stuff for implementing the callback functions =====================================================================*/ + +/* + * if passed NX_CHAR, then returns dimension of -1 and the caller + * needs to do a strlen() or equivalent + */ void analyzeDim(const char *typeString, int *rank, - int *iDim, int *type){ + int64_t *iDim, int *type){ char dimString[132]; char dim[20]; - char *dimStart, *dimEnd; + const char *dimStart, *dimEnd; + char* dimTemp; int myRank; if(strchr(typeString,(int)'[') == NULL){ + *rank = 1; switch(*type){ case NX_INT8: case NX_UINT8: @@ -249,7 +263,10 @@ void analyzeDim(const char *typeString, int *rank, iDim[0] = 1; break; case NX_CHAR: - iDim[0] = -1; + iDim[0] = -1; /* length unknown, caller needs to determine later */ + break; + default: + mxml_error("ERROR: (analyzeDim) unknown type code %d for typeString %s", *type, typeString); break; } } else { @@ -269,18 +286,18 @@ void analyzeDim(const char *typeString, int *rank, } memset(dimString,0,132); memcpy(dimString,dimStart,(dimEnd-dimStart)*sizeof(char)); - dimStart = stptok(dimString,dim,19,","); + dimTemp = stptok(dimString,dim,19,","); myRank = 0; - while(dimStart != NULL){ + while(dimTemp != NULL){ iDim[myRank] = atoi(dim); - dimStart = stptok(dimStart,dim,19,","); + dimTemp = stptok(dimTemp,dim,19,","); myRank++; } *rank = myRank; } } /*--------------------------------------------------------------------*/ -int translateTypeCode(char *code){ +int translateTypeCode(const char *code){ int i, result = -1; for(i = 0; i < NTYPECODE; i++){ @@ -291,12 +308,33 @@ int translateTypeCode(char *code){ } return result; } + +/* + * This is used to locate an Idims node from the new style table data layout + */ +static mxml_node_t* findDimsNode(mxml_node_t *node) +{ + mxml_node_t *tnode = NULL; + const char* name = node->value.element.name; + if ( (node->parent != NULL) && !strcmp(node->parent->value.element.name, DATA_NODE_NAME) ) + { + tnode = mxmlFindElement(node->parent->parent, node->parent->parent, DIMS_NODE_NAME, NULL, NULL, MXML_DESCEND_FIRST); + if (tnode != NULL) + { + tnode = mxmlFindElement(tnode,tnode,name,NULL,NULL,MXML_DESCEND_FIRST); + } + } + return tnode; +} + /*---------------------------------------------------------------------*/ +/*return 1 if in table mode , 0 if not */ static void analyzeDataType(mxml_node_t *parent, int *rank, int *type, - int *iDim){ + int64_t *iDim){ const char *typeString; - mxml_type_t myType; - int i, nx_type = -1; + mxml_node_t* tnode; + int nx_type = -1; + int table_mode = 0; *rank = 1; *type = NX_CHAR; @@ -305,6 +343,12 @@ static void analyzeDataType(mxml_node_t *parent, int *rank, int *type, /* get the type attribute. No attribute means: plain text */ + tnode = findDimsNode(parent); + if (tnode != NULL) + { + table_mode = 1; + parent = tnode; + } typeString = mxmlElementGetAttr(parent,TYPENAME); if(typeString == NULL){ return; @@ -326,6 +370,12 @@ static void analyzeDataType(mxml_node_t *parent, int *rank, int *type, *type = nx_type; analyzeDim(typeString, rank, iDim, type); + if (table_mode) + { + *rank = 1; + iDim[0] = 1; + } + return; } /*-------------------------------------------------------------------*/ void destroyDataset(void *data){ @@ -360,9 +410,20 @@ mxml_type_t nexusTypeCallback(mxml_node_t *parent){ const char *typeString; if(strstr(parent->value.element.name,"?xml") != NULL || - strstr(parent->value.element.name,"NX") != NULL){ + !strncmp(parent->value.element.name,"NX",2) || + !strcmp(parent->value.element.name,DATA_NODE_NAME) || + !strcmp(parent->value.element.name,DIMS_NODE_NAME)){ return MXML_ELEMENT; } else { + /* data nodes do not habe TYPENAME in table style but are always CUSTOM */ + if (parent->parent != NULL && !strcmp(parent->parent->value.element.name, DATA_NODE_NAME)) + { + return MXML_CUSTOM; + } + if (parent->parent != NULL && !strcmp(parent->parent->value.element.name, DIMS_NODE_NAME)) + { + return MXML_OPAQUE; + } typeString = mxmlElementGetAttr(parent,TYPENAME); if(typeString == NULL){ /* @@ -382,15 +443,15 @@ mxml_type_t nexusTypeCallback(mxml_node_t *parent){ /*----------------------------------------------------------------------*/ int nexusLoadCallback(mxml_node_t *node, const char *buffer){ mxml_node_t *parent = NULL; - int rank, type, iDim[NX_MAXRANK]; + int rank, type; + int64_t iDim[NX_MAXRANK]; char pNumber[80], *pStart; long address, maxAddress; pNXDS dataset = NULL; - int i; parent = node->parent; analyzeDataType(parent,&rank,&type,iDim); - if(iDim[0] == -1){ + if(iDim[0] == -1 || !strcmp(parent->parent->value.element.name, DIMS_NODE_NAME)){ iDim[0] = strlen(buffer); node->value.custom.data = strdup(buffer); node->value.custom.destroy = free; @@ -420,9 +481,9 @@ int nexusLoadCallback(mxml_node_t *node, const char *buffer){ return 0; } /*---------------------------------------------------------------------*/ -static void stringIntoBuffer(char **buffer, char **bufPtr, int *bufSize, +static void stringIntoBuffer(char **buffer, char **bufPtr, size_t *bufSize, char *string){ - int i; + size_t i; for(i = 0; i < strlen(string); i++){ myxml_add_char(string[i],bufPtr,buffer,bufSize); @@ -475,8 +536,16 @@ char *nexusWriteCallback(mxml_node_t *node){ char pNumber[80], indent[80], format[30]; char *buffer, *bufPtr; pNXDS dataset; - int bufsize, i, length, currentLen; + int currentLen, table_style = 0; + size_t i, bufsize, length; + int is_definition = 0; + /* this is set by nxconvert when making a definiton */ + is_definition = (getenv("NX_IS_DEFINITION") != NULL); + if (!strcmp(node->parent->parent->value.element.name, DATA_NODE_NAME)) + { + table_style = 1; + } /* allocate output buffer */ @@ -504,7 +573,11 @@ char *nexusWriteCallback(mxml_node_t *node){ get dataset info */ type = getNXDatasetType(dataset); - length = getNXDatasetLength(dataset); + if (is_definition) { + length = 1; + } else { + length = getNXDatasetLength(dataset); + } if(dataset->format != NULL){ strcpy(format,dataset->format); } else { @@ -514,22 +587,32 @@ char *nexusWriteCallback(mxml_node_t *node){ /* actually get the data out */ - currentLen = col; - myxml_add_char('\n',&bufPtr,&buffer,&bufsize); - stringIntoBuffer(&buffer,&bufPtr,&bufsize,indent); - for(i = 0; i < length; i++){ - formatNumber(getNXDatasetValueAt(dataset,i),pNumber,79,format,type); - if(currentLen + strlen(pNumber) > MXML_WRAP){ - /* - wrap line - */ + if (table_style) + { + for(i = 0; i < length; i++){ + formatNumber(getNXDatasetValueAt(dataset,i),pNumber,79,format,type); + stringIntoBuffer(&buffer,&bufPtr,&bufsize,pNumber); + } + } + else + { + currentLen = col; myxml_add_char('\n',&bufPtr,&buffer,&bufsize); stringIntoBuffer(&buffer,&bufPtr,&bufsize,indent); - currentLen = col; - } - stringIntoBuffer(&buffer,&bufPtr,&bufsize,pNumber); - myxml_add_char(' ',&bufPtr,&buffer,&bufsize); - currentLen += strlen(pNumber) + 1; + for(i = 0; i < length; i++){ + formatNumber(getNXDatasetValueAt(dataset,i),pNumber,79,format,type); + if(currentLen + strlen(pNumber) > MXML_WRAP){ + /* + wrap line + */ + myxml_add_char('\n',&bufPtr,&buffer,&bufsize); + stringIntoBuffer(&buffer,&bufPtr,&bufsize,indent); + currentLen = col; + } + stringIntoBuffer(&buffer,&bufPtr,&bufsize,pNumber); + myxml_add_char(' ',&bufPtr,&buffer,&bufsize); + currentLen += strlen(pNumber) + 1; + } } myxml_add_char('\0',&bufPtr,&buffer,&bufsize); return (char *)buffer; @@ -542,6 +625,12 @@ int isDataNode(mxml_node_t *node){ if(strcmp(node->value.element.name,"NXroot") == 0){ return 0; } + if(strcmp(node->value.element.name,DIMS_NODE_NAME) == 0){ + return 0; + } + if(strcmp(node->value.element.name,DATA_NODE_NAME) == 0){ + return 0; + } if(strcmp(node->value.element.name,"NAPIlink") == 0){ return 0; } @@ -550,7 +639,6 @@ int isDataNode(mxml_node_t *node){ /*--------------------------------------------------------------------*/ static int isTextData(mxml_node_t *node){ const char *attr = NULL; - int rank, type = 0, iDim[NX_MAXRANK]; if(!isDataNode(node)){ return 0; @@ -562,8 +650,7 @@ static int isTextData(mxml_node_t *node){ if(attr == NULL){ return 1; } - analyzeDim(attr,&rank,iDim,&type); - if(type == NX_CHAR){ + if(strstr(attr,"NX_CHAR") != NULL){ return 1; } else { return 0; @@ -581,6 +668,14 @@ const char *NXwhitespaceCallback(mxml_node_t *node, int where){ if(strstr(node->value.element.name,"?xml") != NULL){ return NULL; } + if (node->parent != NULL && !strcmp(node->parent->value.element.name, DATA_NODE_NAME)) + { + return NULL; + } + if (where == MXML_WS_BEFORE_CLOSE && !strcmp(node->value.element.name, DATA_NODE_NAME)) + { + return NULL; + } if(isTextData(node)){ if(where == MXML_WS_BEFORE_OPEN){ @@ -647,3 +742,6 @@ int main(int argc, char *argv[]){ } #endif + + +#endif /*NXXML*/ diff --git a/nxio.h b/nxio.h index 0de80474..1788762a 100644 --- a/nxio.h +++ b/nxio.h @@ -20,7 +20,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * For further information, see + * For further information, see */ #ifndef __NXIO @@ -29,6 +29,9 @@ #define TYPENAME "NAPItype" +#define DIMS_NODE_NAME "columns" +#define DATA_NODE_NAME "row" + mxml_type_t nexusTypeCallback(mxml_node_t *parent); const char *NXwhitespaceCallback(mxml_node_t *node, int where); int nexusLoadCallback(mxml_node_t *node, const char *buffer); @@ -38,10 +41,10 @@ void setNumberFormat(int dataType, char *formatString); void initializeNumberFormats(); void getNumberText(int nx_type, char *typestring, int typeLen); void destroyDataset(void *data); -int translateTypeCode(char *code); +int translateTypeCode(const char *code); int isDataNode(mxml_node_t *node); void analyzeDim(const char *typeString, int *rank, - int *iDim, int *type); + int64_t *iDim, int *type); #endif diff --git a/nxscript.c b/nxscript.c index ddf89287..fc6277b1 100644 --- a/nxscript.c +++ b/nxscript.c @@ -8,6 +8,7 @@ Mark Koennecke, February 2003 Mark Koennecke, January 2004 + added putHdb and putHdbSlab, Mark Koennecke, December 2008 ------------------------------------------------------------------------*/ #include #include @@ -37,229 +38,266 @@ extern char *trim(char *str); /* missing in nxdict.h: */ NXstatus NXDdefget(NXdict handle, char *pKey, char *pBuffer, int iBufLen); /*------------------------------------------------------------------------*/ -char *makeFilename(SicsInterp *pSics, SConnection *pCon) { +char *makeFilename(SicsInterp * pSics, SConnection * pCon) +{ pSicsVariable pPath = NULL, pPref = NULL, pEnd = NULL; char *pRes = NULL; int iLen, iNum, iYear, thousand; char pNumText[10], pBueffel[256]; CommandList *pCom = NULL; DIR *dir = NULL; - + /* Try, get all the Variables */ - pPath = FindVariable(pSics,"sicsdatapath"); - pPref = FindVariable(pSics,"sicsdataprefix"); - pCom = FindCommand(pSics,"sicsdatanumber"); - pEnd = FindVariable(pSics,"sicsdatapostfix"); - - if( (!pPath) || (!pPref) || (!pCom) || (!pEnd) ){ + pPath = FindVariable(pSics, "sicsdatapath"); + pPref = FindVariable(pSics, "sicsdataprefix"); + pCom = FindCommand(pSics, "sicsdatanumber"); + pEnd = FindVariable(pSics, "sicsdatapostfix"); + + if ((!pPath) || (!pPref) || (!pCom) || (!pEnd)) { SCWrite(pCon, - "ERROR: cannot read variables for automatic data file name creation", + "ERROR: cannot read variables for automatic data file name creation", eError); SCWrite(pCon, - "ERROR: This is a VERY, VERY, VERY serious installation problem", - eError); - SCWrite(pCon,"ERROR: your data will be dumped into emergency.hdf",eError); - return NULL; + "ERROR: This is a VERY, VERY, VERY serious installation problem", + eError); + SCWrite(pCon, "ERROR: your data will be dumped into emergency.hdf", + eError); + return NULL; } /* find length */ - iLen = strlen(pPath->text) + 4; /* extra 4 for dir number */ + iLen = strlen(pPath->text) + 4; /* extra 4 for dir number */ iLen += strlen(pPref->text); - iLen += 10; /* for number + year */ + iLen += 10; /* for number + year */ iLen += strlen(pEnd->text); - iLen += 10; /* safety margin */ - + iLen += 10; /* safety margin */ + /* allocate memory */ - pRes = (char *)malloc(iLen*sizeof(char)); - if(!pRes){ - SCWrite(pCon,"ERROR: no memory in makeFilename",eError); + pRes = (char *) malloc(iLen * sizeof(char)); + if (!pRes) { + SCWrite(pCon, "ERROR: no memory in makeFilename", eError); return NULL; - } - memset(pRes,0,iLen); - + } + memset(pRes, 0, iLen); + /* increment the data file number */ - iNum = IncrementDataNumber(pCom->pData,&iYear); - if(iNum < 0){ - SCWrite(pCon,"ERROR: cannot increment data number!",eError); - SCWrite(pCon,"ERROR: your data will be dumped to emergency.hdf",eError); + iNum = IncrementDataNumber(pCom->pData, &iYear); + if (iNum < 0) { + SCWrite(pCon, "ERROR: cannot increment data number!", eError); + SCWrite(pCon, "ERROR: your data will be dumped to emergency.hdf", + eError); free(pRes); return NULL; } - strcpy(pRes,pPath->text); - thousand = (int)floor(iNum/1000.); - snprintf(pNumText,9,"%3.3d",thousand); - strcat(pRes,pNumText); + strcpy(pRes, pPath->text); + thousand = (int) floor(iNum / 1000.); + snprintf(pNumText, 9, "%3.3d", thousand); + strcat(pRes, pNumText); /* - check for existence of directory and create if neccessary - */ + check for existence of directory and create if neccessary + */ dir = opendir(pRes); - if(dir == NULL){ - mkdir(pRes,S_IRWXU | S_IRGRP | S_IXGRP); - snprintf(pBueffel,255,"Creating dir: %s", pRes); - SCWrite(pCon,pBueffel,eWarning); + if (dir == NULL) { + mkdir(pRes, S_IRWXU | S_IRGRP | S_IXGRP); + snprintf(pBueffel, 255, "Creating dir: %s", pRes); + SCWrite(pCon, pBueffel, eLog); } else { closedir(dir); } /* - build the rest of the filename - */ - strcat(pRes,"/"); - strcat(pRes,pPref->text); - sprintf(pNumText,"%4.4d",iYear); - strcat(pRes,pNumText); - strcat(pRes,"n"); - sprintf(pNumText,"%6.6d",iNum); - strcat(pRes,pNumText); - strcat(pRes,pEnd->text); - + build the rest of the filename + */ + strcat(pRes, "/"); + strcat(pRes, pPref->text); + snprintf(pNumText,sizeof(pNumText)-1, "%4.4d", iYear); + strcat(pRes, pNumText); + strcat(pRes, "n"); + snprintf(pNumText,sizeof(pNumText)-1, "%6.6d", iNum); + strcat(pRes, pNumText); + strcat(pRes, pEnd->text); + return pRes; } + /*---------------------------------------------------------------------*/ -void changeExtension(char *filename, char *newExtension){ +void changeExtension(char *filename, char *newExtension) +{ char *pPtr = NULL; - pPtr = strrchr(filename,(int)'.'); + pPtr = strrchr(filename, (int) '.'); assert(pPtr != NULL); - + pPtr++; assert(strlen(pPtr) >= strlen(newExtension)); - strcpy(pPtr,newExtension); + strcpy(pPtr, newExtension); } + +/*----------------------------------------------------------------------*/ +static int listToArray(SicsInterp * pSics, char *list, + int intar[NX_MAXRANK]) +{ + int argc, status, i, val; + CONST char **argv; + Tcl_Interp *pTcl = InterpGetTcl(pSics); + + status = Tcl_SplitList(pTcl, list, &argc, &argv); + if (status != TCL_OK) { + return status; + } + + for (i = 0; i < argc; i++) { + status = Tcl_GetInt(pTcl, argv[i], &val); + if (status != TCL_OK) { + return status; + } + intar[i] = val; + } + Tcl_Free((char *) argv); + return TCL_OK; +} + /*======================== Action =======================================*/ -static int handleFileOperations(SConnection *pCon, pNXScript self, - int argc, char *argv[]){ - int status,i, iVal; +static int handleFileOperations(SConnection * pCon, pNXScript self, + int argc, char *argv[]) +{ + int status, i, iVal; NXaccess access; char buffer[512]; - if(strcmp(argv[1],"close") == 0){ + if (strcmp(argv[1], "close") == 0) { /* - close everything! and send a message to trigger file synchronisation - to the central server - */ - if(self->fileHandle == NULL){ + close everything! and send a message to trigger file synchronisation + to the central server + */ + if (self->fileHandle == NULL) { SCSendOK(pCon); return 1; } i = 511; iVal = NX_CHAR; - NXgetattr(self->fileHandle,"file_name",buffer,&i,&iVal); + NXgetattr(self->fileHandle, "file_name", buffer, &i, &iVal); NXclose(&self->fileHandle); - NXDclose(self->dictHandle,NULL); + NXDclose(self->dictHandle, NULL); self->fileHandle = NULL; self->dictHandle = NULL; - SendQuieck(QUIECK,buffer); + SendQuieck(QUIECK, buffer); SCSendOK(pCon); return 1; - } else if(strcmp(argv[1],"reopen") == 0){ + } else if (strcmp(argv[1], "reopen") == 0) { access = NXACC_RDWR; - } else if(strcmp(argv[1],"create4") == 0){ + } else if (strcmp(argv[1], "create4") == 0) { access = NXACC_CREATE4; - unlink(argv[2]); /* kill file for overwrite */ - } else if(strcmp(argv[1],"create5") == 0){ + unlink(argv[2]); /* kill file for overwrite */ + } else if (strcmp(argv[1], "create5") == 0) { access = NXACC_CREATE5; - unlink(argv[2]); /* kill file for overwrite */ - } else if(strcmp(argv[1],"createxml") == 0){ + unlink(argv[2]); /* kill file for overwrite */ + } else if (strcmp(argv[1], "createxml") == 0) { access = NXACC_CREATEXML; } else { return 0; } - if(argc < 4){ - SCWrite(pCon,"ERROR: insufficient number of arguments for file operation", - eError); + if (argc < 4) { + SCWrite(pCon, + "ERROR: insufficient number of arguments for file operation", + eError); return -1; } /* - be considerate: close files left open - */ - if(self->fileHandle != NULL){ + be considerate: close files left open + */ + if (self->fileHandle != NULL) { NXclose(&self->fileHandle); self->fileHandle = NULL; } - if(self->dictHandle != NULL){ + if (self->dictHandle != NULL) { NXDclose(self->dictHandle, NULL); self->dictHandle = NULL; } /* - now initialize ourselves - */ - status = NXopen(argv[2],access,&self->fileHandle); - if(status != NX_OK){ - sprintf(buffer,"ERROR: failed to open %s",argv[2]); - SCWrite(pCon,buffer,eError); + now initialize ourselves + */ + status = NXopen(argv[2], access, &self->fileHandle); + if (status != NX_OK) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to open %s", argv[2]); + SCWrite(pCon, buffer, eError); return -1; } - status = NXDinitfromfile(argv[3],&self->dictHandle); - if(status != NX_OK){ - sprintf(buffer,"ERROR: failed to open dictionary %s",argv[3]); - SCWrite(pCon,buffer,eError); + status = NXDinitfromfile(argv[3], &self->dictHandle); + if (status != NX_OK) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to open dictionary %s", argv[3]); + SCWrite(pCon, buffer, eError); return -1; } SCSendOK(pCon); return 1; } + /*----------------------------------------------------------------------*/ -static void putMotor(SConnection *pCon, SicsInterp *pSics, pNXScript self, - int argc, char *argv[]){ +static void putMotor(SConnection * pCon, SicsInterp * pSics, + pNXScript self, int argc, char *argv[]) +{ int status; pMotor brumm = NULL; float fVal; char buffer[132], dummy[256]; - if(argc < 4){ - SCWrite(pCon,"ERROR: insufficient number of arguments to putmotor", - eError); - return; - } - - /* - find motor - */ - brumm = (pMotor)FindCommandData(pSics,argv[3],"Motor"); - if(!brumm){ - sprintf(buffer,"ERROR: motor %s not found!", argv[3]); - SCWrite(pCon,buffer,eError); + if (argc < 4) { + SCWrite(pCon, "ERROR: insufficient number of arguments to putmotor", + eLogError); return; } /* - do position - */ - status = MotorGetSoftPosition(brumm, pCon,&fVal); - if(!status){ - sprintf(buffer,"ERROR: failed to read position of %s", argv[3]); - SCWrite(pCon,buffer,eError); - return; - } - status = NXDputalias(self->fileHandle,self->dictHandle,argv[2],&fVal); - if(status != NX_OK){ - sprintf(buffer,"ERROR: failed to write %s with alias %s", - argv[3],argv[2]); - SCWrite(pCon,buffer,eError); + find motor + */ + brumm = (pMotor) FindCommandData(pSics, argv[3], "Motor"); + if (!brumm) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: motor %s not found!", argv[3]); + SCWrite(pCon, buffer, eLogError); return; } /* - if alias_null is available: write zero point - */ - strcpy(buffer,argv[2]); - strcat(buffer,"_null"); - if(NXDdefget(self->dictHandle,buffer,dummy,255)){ - MotorGetPar(brumm,"softzero",&fVal); - status = NXDputalias(self->fileHandle,self->dictHandle,buffer, &fVal); - if(status != NX_OK){ - sprintf(buffer,"ERROR: failed to write %s zero with alias %s", - argv[3],argv[2]); - SCWrite(pCon,buffer,eError); + do position + */ + status = MotorGetSoftPosition(brumm, pCon, &fVal); + if (!status) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to read position of %s", argv[3]); + SCWrite(pCon, buffer, eLogError); + return; + } + status = NXDputalias(self->fileHandle, self->dictHandle, argv[2], &fVal); + if (status != NX_OK) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to write %s with alias %s", + argv[3], argv[2]); + SCWrite(pCon, buffer, eLogError); + return; + } + + /* + if alias_null is available: write zero point + */ + strlcpy(buffer, argv[2],131); + strlcat(buffer, "_null",131); + if (NXDdefget(self->dictHandle, buffer, dummy, 255)) { + MotorGetPar(brumm, "softzero", &fVal); + status = + NXDputalias(self->fileHandle, self->dictHandle, buffer, &fVal); + if (status != NX_OK) { + snprintf(buffer,131, "ERROR: failed to write %s zero with alias %s", + argv[3], argv[2]); + SCWrite(pCon, buffer, eLogError); return; } } } + /*---------------------------------------------------------------------*/ -static void putCounter(SConnection *pCon, SicsInterp *pSics, pNXScript self, - int argc, char *argv[]){ +static void putCounter(SConnection * pCon, SicsInterp * pSics, + pNXScript self, int argc, char *argv[]) +{ pCounter cter = NULL; float fVal; long counts; @@ -267,659 +305,886 @@ static void putCounter(SConnection *pCon, SicsInterp *pSics, pNXScript self, int status, i, icounts; CounterMode eMode; - if(argc < 4){ - SCWrite(pCon,"ERROR: insufficient number of arguments to putcounter", - eError); + if (argc < 4) { + SCWrite(pCon, "ERROR: insufficient number of arguments to putcounter", + eLogError); return; } - memset(dummy,0,80*sizeof(char)); - + memset(dummy, 0, 80 * sizeof(char)); + /* - find counter - */ - cter = (pCounter)FindCommandData(pSics,argv[3],"SingleCounter"); - if(!cter){ - sprintf(buffer,"ERROR: counter %s not found!", argv[3]); - SCWrite(pCon,buffer,eError); + find counter + */ + cter = (pCounter) FindCommandData(pSics, argv[3], "SingleCounter"); + if (!cter) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: counter %s not found!", argv[3]); + SCWrite(pCon, buffer, eLogError); return; } /* - do preset - */ + do preset + */ fVal = GetCounterPreset(cter); - strcpy(newAlias,argv[2]); - strcat(newAlias,"_preset"); - status = NXDputalias(self->fileHandle,self->dictHandle,newAlias,&fVal); - if(status != NX_OK){ - sprintf(buffer,"ERROR: failed to write preset to %s", newAlias); - SCWrite(pCon,buffer,eError); + strlcpy(newAlias, argv[2],255); + strlcat(newAlias, "_preset",255); + status = + NXDputalias(self->fileHandle, self->dictHandle, newAlias, &fVal); + if (status != NX_OK) { + snprintf(buffer,255, "ERROR: failed to write preset to %s", newAlias); + SCWrite(pCon, buffer, eLogError); } /* - do countmode - */ + do countmode + */ eMode = GetCounterMode(cter); - strcpy(newAlias,argv[2]); - strcat(newAlias,"_mode"); - if(eMode == eTimer){ - strcpy(dummy,"timer"); + strcpy(newAlias, argv[2]); + strcat(newAlias, "_mode"); + if (eMode == eTimer) { + strcpy(dummy, "timer"); } else { - strcpy(dummy,"monitor"); + strcpy(dummy, "monitor"); } - status = NXDputalias(self->fileHandle,self->dictHandle,newAlias,dummy); - if(status != NX_OK){ - sprintf(buffer,"ERROR: failed to write counter mode to %s", newAlias); - SCWrite(pCon,buffer,eError); + status = + NXDputalias(self->fileHandle, self->dictHandle, newAlias, dummy); + if (status != NX_OK) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to write counter mode to %s", newAlias); + SCWrite(pCon, buffer, eLogError); } /* - do time - */ - fVal = GetCountTime(cter,pCon); - strcpy(newAlias,argv[2]); - strcat(newAlias,"_time"); - if(NXDdefget(self->dictHandle,newAlias,dummy,79)){ - status = NXDputalias(self->fileHandle,self->dictHandle,newAlias,&fVal); - if(status != NX_OK){ - sprintf(buffer,"ERROR: failed to write count time to %s", newAlias); - SCWrite(pCon,buffer,eError); + do time + */ + fVal = GetCountTime(cter, pCon); + strlcpy(newAlias, argv[2],255); + strlcat(newAlias, "_time",255); + if (NXDdefget(self->dictHandle, newAlias, dummy, 79)) { + status = + NXDputalias(self->fileHandle, self->dictHandle, newAlias, &fVal); + if (status != NX_OK) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to write count time to %s", newAlias); + SCWrite(pCon, buffer, eLogError); } } /* - do counter and monitors - */ - for(i = 0; i < 10; i++){ - sprintf(newAlias,"%s_%2.2d",argv[2],i); - if(NXDdefget(self->dictHandle,newAlias,dummy,79)){ - counts = GetMonitor(cter,i,pCon); - icounts = (int)counts; - status = NXDputalias(self->fileHandle,self->dictHandle,newAlias, - &icounts); + do counter and monitors + */ + for (i = 0; i < 10; i++) { + snprintf(newAlias,255, "%s_%2.2d", argv[2], i); + if (NXDdefget(self->dictHandle, newAlias, dummy, 79)) { + counts = GetMonitor(cter, i, pCon); + icounts = (int) counts; + status = NXDputalias(self->fileHandle, self->dictHandle, newAlias, + &icounts); } } return; } -/*----------------------------------------------------------------------*/ -static void putSicsData(SConnection *pCon, SicsInterp *pSics, - pNXScript self, int argc, char *argv[]){ - - pSICSData data = NULL; - int status; - char buffer[256]; - - if(argc < 4){ - SCWrite(pCon,"ERROR: insufficient number of arguments to putSicsData", - eError); - return; - } - /* - find data - */ - data = (pSICSData)FindCommandData(pSics,argv[3],"SICSData"); - if(data == NULL){ - snprintf(buffer,255,"ERROR: sicsdata %s not found!", argv[3]); - SCWrite(pCon,buffer,eError); - return; - } - - status = NXDputalias(self->fileHandle,self->dictHandle,argv[2],data->data); - if(status != NX_OK){ - sprintf(buffer,"ERROR: failed to write sicsdata to %s", argv[2]); - SCWrite(pCon,buffer,eError); - } -} /*----------------------------------------------------------------------*/ -static void putAttribute(SConnection *pCon, SicsInterp *pSics, - pNXScript self, int argc, char *argv[]){ - int status, type = NX_CHAR; - char buffer[256]; - - if(argc < 5){ - SCWrite(pCon,"ERROR: insufficient number of arguments to putAttribute", - eError); - return; - } +static void putSicsData(SConnection * pCon, SicsInterp * pSics, + pNXScript self, int argc, char *argv[]) +{ - status = NXDopenalias(self->fileHandle,self->dictHandle,argv[2]); - if(status != NX_OK){ - sprintf(buffer,"ERROR: failed to open alias %s", argv[2]); - SCWrite(pCon,buffer,eError); - return; - } - status = NXputattr(self->fileHandle,argv[3],(void *)argv[4], - strlen(argv[4])+1, type); - if(status != NX_OK){ - sprintf(buffer,"ERROR: failed to write attribute %s", argv[3]); - SCWrite(pCon,buffer,eError); - } - NXopenpath(self->fileHandle,"/"); -} -/*----------------------------------------------------------------------*/ -static void putHdb(SConnection *pCon, SicsInterp *pSics, pNXScript self, - int argc, char *argv[]){ - pHdb node = NULL; - char alias[512]; - hdbValue v; - float fVal, *floatAr = NULL; - int i; - int start[5],size[5]; - - if(argc < 3){ - SCWrite(pCon,"ERROR: putHdb needs at least node name", - eError); - return; - } - node = FindHdbNode(NULL,argv[2], pCon); - if(node == NULL){ - SCPrintf(pCon,eError,"ERROR: node %s not found", argv[2]); - return; - } - memset(alias,0,512*sizeof(char)); - if(!GetHdbProperty(node,"nxalias", alias, 512)){ - if(argc < 4) { - SCPrintf(pCon,eError,"ERROR: neither nxalias property nor alias on command line found for %s", - argv[2]); - return; - } else { - strncpy(alias, argv[3],512); - } - } - GetHipadabaPar(node,&v,pCon); - if (argc > 3 && strcmp(argv[3],"point")==0) { - NXDopenalias(self->fileHandle, self->dictHandle,alias); - start[0]=atoi(argv[4]); size[0]=1; - switch(v.dataType){ - case HIPINT: - NXputslab(self->fileHandle,&v.v.intValue,start,size); - break; - case HIPFLOAT: - fVal = v.v.doubleValue; - NXputslab(self->fileHandle,&fVal,start,size); - break; - } - ReleaseHdbValue(&v); - NXopenpath(self->fileHandle,"/"); + pSICSData data = NULL; + int status; + char buffer[256]; + + if (argc < 4) { + SCWrite(pCon, "ERROR: insufficient number of arguments to putSicsData", + eLogError); return; } - switch(v.dataType){ - case HIPNONE: - return; - break; - case HIPINT: - NXDputalias(self->fileHandle, self->dictHandle, alias, - &v.v.intValue); - break; - case HIPFLOAT: - fVal = v.v.doubleValue; - NXDputalias(self->fileHandle, self->dictHandle, alias, - &fVal); - break; - case HIPTEXT: - NXDputalias(self->fileHandle, self->dictHandle, alias, - v.v.text); - break; - case HIPINTAR: - case HIPINTVARAR: - NXDputalias(self->fileHandle, self->dictHandle, alias, - v.v.intArray); - break; - case HIPFLOATAR: - case HIPFLOATVARAR: - floatAr = malloc(v.arrayLength*sizeof(float)); - if(floatAr == NULL){ - SCPrintf(pCon,eError,"ERROR: out of memory writing %s", node->name); - return; - } - for(i = 0; i < v.arrayLength; i++){ - floatAr[i] = v.v.floatArray[i]; - } - NXDputalias(self->fileHandle, self->dictHandle, alias, - floatAr); - free(floatAr); - break; - } - ReleaseHdbValue(&v); + + /* + find data + */ + data = (pSICSData) FindCommandData(pSics, argv[3], "SICSData"); + if (data == NULL) { + snprintf(buffer, 255, "ERROR: sicsdata %s not found!", argv[3]); + SCWrite(pCon, buffer, eLogError); + return; + } + + status = + NXDputalias(self->fileHandle, self->dictHandle, argv[2], data->data); + if (status != NX_OK) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to write sicsdata to %s", argv[2]); + SCWrite(pCon, buffer, eLogError); + } +} + +/*----------------------------------------------------------------------*/ +static void putAttribute(SConnection * pCon, SicsInterp * pSics, + pNXScript self, int argc, char *argv[]) +{ + int status, type = NX_CHAR; + char buffer[256]; + + if (argc < 5) { + SCWrite(pCon, + "ERROR: insufficient number of arguments to putAttribute", + eLogError); + return; + } + + status = NXDopenalias(self->fileHandle, self->dictHandle, argv[2]); + if (status != NX_OK) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to open alias %s", argv[2]); + SCWrite(pCon, buffer, eLogError); + return; + } + status = NXputattr(self->fileHandle, argv[3], (void *) argv[4], + strlen(argv[4]) + 1, type); + if (status != NX_OK) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to write attribute %s", argv[3]); + SCWrite(pCon, buffer, eLogError); + } + NXopenpath(self->fileHandle, "/"); +} + +/*----------------------------------------------------------------------*/ +static void putHdb(SConnection * pCon, SicsInterp * pSics, pNXScript self, + int argc, char *argv[]) +{ + pHdb node = NULL; + char alias[512]; + hdbValue v; + float fVal, *floatAr = NULL; + int i; + + if (argc < 3) { + SCWrite(pCon, "ERROR: putHdb needs at least node name", eLogError); + return; + } + node = FindHdbNode(NULL, argv[2], pCon); + if (node == NULL) { + SCPrintf(pCon, eLogError, "ERROR: node %s not found", argv[2]); + return; + } + memset(alias, 0, 512 * sizeof(char)); + if (!GetHdbProperty(node, "nxalias", alias, 512)) { + if (argc < 4) { + SCPrintf(pCon, eLogError, + "ERROR: neither nxalias property nor alias on command line found for %s", + argv[2]); + return; + } else { + strlcpy(alias, argv[3], 512); + } + } + GetHipadabaPar(node, &v, pCon); + switch (v.dataType) { + case HIPNONE: + return; + break; + case HIPINT: + NXDputalias(self->fileHandle, self->dictHandle, alias, &v.v.intValue); + break; + case HIPFLOAT: + fVal = v.v.doubleValue; + NXDputalias(self->fileHandle, self->dictHandle, alias, &fVal); + break; + case HIPTEXT: + NXDputalias(self->fileHandle, self->dictHandle, alias, v.v.text); + break; + case HIPINTAR: + case HIPINTVARAR: + NXDputalias(self->fileHandle, self->dictHandle, alias, v.v.intArray); + break; + case HIPFLOATAR: + case HIPFLOATVARAR: + floatAr = malloc(v.arrayLength * sizeof(float)); + if (floatAr == NULL) { + SCPrintf(pCon, eLogError, "ERROR: out of memory writing %s", + node->name); + return; + } + for (i = 0; i < v.arrayLength; i++) { + floatAr[i] = (float)v.v.floatArray[i]; + } + NXDputalias(self->fileHandle, self->dictHandle, alias, floatAr); + free(floatAr); + break; + } + ReleaseHdbValue(&v); } /*----------------------------------------------------------------------*/ -static void updateHMDim(NXScript *self, pHistMem mem){ +static void putHdbOff(SConnection * pCon, SicsInterp * pSics, pNXScript self, + int argc, char *argv[]) +{ + pHdb node = NULL; + char alias[512]; + hdbValue v; + float fVal, *floatAr = NULL; + int i, offset; + + if (argc < 4) { + SCWrite(pCon, "ERROR: putHdbOff needs at least a node name and an offset", eLogError); + return; + } + node = FindHdbNode(NULL, argv[2], pCon); + if (node == NULL) { + SCPrintf(pCon, eLogError, "ERROR: node %s not found", argv[2]); + return; + } + memset(alias, 0, 512 * sizeof(char)); + if (!GetHdbProperty(node, "nxalias", alias, 512)) { + if (argc < 5) { + SCPrintf(pCon, eLogError, + "ERROR: neither nxalias property nor alias on command line found for %s", + argv[2]); + return; + } else { + strlcpy(alias, argv[4], 512); + } + } + offset = atoi(argv[3]); + + GetHipadabaPar(node, &v, pCon); + if(offset < 0 || offset > v.arrayLength){ + SCPrintf(pCon,eLogError,"ERROR: invalid offset %d specified", offset ); + return; + } + switch (v.dataType) { + case HIPNONE: + return; + break; + case HIPINTAR: + case HIPINTVARAR: + NXDputalias(self->fileHandle, self->dictHandle, alias, v.v.intArray+offset); + break; + case HIPFLOATAR: + case HIPFLOATVARAR: + floatAr = malloc(v.arrayLength * sizeof(float)); + if (floatAr == NULL) { + SCPrintf(pCon, eLogError, "ERROR: out of memory writing %s", + node->name); + return; + } + for (i = 0; i < v.arrayLength; i++) { + floatAr[i] = v.v.floatArray[i]; + } + NXDputalias(self->fileHandle, self->dictHandle, alias, floatAr+offset); + free(floatAr); + break; + default: + SCPrintf(pCon,eLogError,"ERROR: offsets can only be used with array data types"); + return; + } + ReleaseHdbValue(&v); +} +/*----------------------------------------------------------------------*/ +static void putHdbSlab(SConnection * pCon, SicsInterp * pSics, + pNXScript self, int argc, char *argv[]) +{ + pHdb node = NULL; + char alias[512]; + hdbValue v; + float fVal, *floatAr = NULL; + int start[NX_MAXRANK], size[NX_MAXRANK]; + int i, status; + + if (argc < 5) { + SCWrite(pCon, + "ERROR: putHdbSlab needs at least node name start, size", + eLogError); + return; + } + node = FindHdbNode(NULL, argv[2], pCon); + if (node == NULL) { + SCPrintf(pCon, eLogError, "ERROR: node %s not found", argv[2]); + return; + } + memset(alias, 0, 512 * sizeof(char)); + if (!GetHdbProperty(node, "nxalias", alias, 512)) { + SCPrintf(pCon, eLogError, + "ERROR: nxalias property not found for %s", argv[2]); + return; + } + status = NXDopenalias(self->fileHandle, self->dictHandle, alias); + if (status != NX_OK) { + SCPrintf(pCon, eLogError, "ERROR: failed to open alias for %s", + argv[2]); + return; + } + + status = listToArray(pSics, argv[3], start); + if (status != TCL_OK) { + SCWrite(pCon, "ERROR: failed to convert start value list", eLogError); + return; + } + + status = listToArray(pSics, argv[4], size); + if (status != TCL_OK) { + SCWrite(pCon, "ERROR: failed to convert size value list", eLogError); + return; + } + + GetHipadabaPar(node, &v, pCon); + switch (v.dataType) { + case HIPNONE: + return; + break; + case HIPINT: + status = NXputslab(self->fileHandle, &v.v.intValue, start, size); + break; + case HIPFLOAT: + fVal = v.v.doubleValue; + status = NXputslab(self->fileHandle, &fVal, start, size); + break; + case HIPTEXT: + status = NXputslab(self->fileHandle, v.v.text, start, size); + break; + case HIPINTAR: + case HIPINTVARAR: + status = NXputslab(self->fileHandle, v.v.intArray, start, size); + break; + case HIPFLOATAR: + case HIPFLOATVARAR: + floatAr = malloc(v.arrayLength * sizeof(float)); + if (floatAr == NULL) { + SCPrintf(pCon, eLogError, "ERROR: out of memory writing %s", + node->name); + return; + } + for (i = 0; i < v.arrayLength; i++) { + floatAr[i] = v.v.floatArray[i]; + } + status = NXputslab(self->fileHandle, floatAr, start, size); + free(floatAr); + break; + } + if (status != NX_OK) { + SCPrintf(pCon, eLogError, "ERROR: failed to write slab for node %s", + argv[2]); + } + ReleaseHdbValue(&v); +} + +/*----------------------------------------------------------------------*/ +static void updateHMDim(NXScript * self, pHistMem mem) +{ int iDim[MAXDIM]; int i, rank, timeLength, status; - char dummy[40], value[20]; + char dummy[40], value[20]; const float *timeBin; /* - update the dimension variables in the dictionary - */ - GetHistDim(mem,iDim,&rank); - for(i = 0; i < rank; i++){ - sprintf(dummy,"dim%1.1d", i); - sprintf(value,"%d",iDim[i]); - status = NXDupdate(self->dictHandle,dummy,value); - if(status == 0) { - NXDadd(self->dictHandle,dummy,value); + update the dimension variables in the dictionary + */ + GetHistDim(mem, iDim, &rank); + for (i = 0; i < rank; i++) { + snprintf(dummy,sizeof(dummy)-1, "dim%1.1d", i); + snprintf(value,sizeof(value)-1, "%d", iDim[i]); + status = NXDupdate(self->dictHandle, dummy, value); + if (status == 0) { + NXDadd(self->dictHandle, dummy, value); } } - timeBin = GetHistTimeBin(mem,&timeLength); - if(timeLength > 2){ - sprintf(dummy,"%d",timeLength); + timeBin = GetHistTimeBin(mem, &timeLength); + if (timeLength > 2) { + snprintf(dummy,sizeof(dummy)-1, "%d", timeLength); } else { - sprintf(dummy,"%d",1); + snprintf(dummy,sizeof(dummy)-1, "%d", 1); } - status = NXDupdate(self->dictHandle,"timedim",dummy); - if(status == 0) { - NXDadd(self->dictHandle,"timedim",dummy); + status = NXDupdate(self->dictHandle, "timedim", dummy); + if (status == 0) { + NXDadd(self->dictHandle, "timedim", dummy); } } + /*---------------------------------------------------------------------- The sequence of things is important in here: The code for updating the dimensions variables also applies the time binning to the length. Thus subsets can only be checked for after that. And then we can allocate memory. -------------------------------------------------------------------------*/ -static void putHistogramMemory(SConnection *pCon, SicsInterp *pSics, - pNXScript self, - int argc, char *argv[]){ +static void putHistogramMemory(SConnection * pCon, SicsInterp * pSics, + pNXScript self, int argc, char *argv[]) +{ pHistMem mem = NULL; int status, start, length, i, subset = 0, bank = 0; HistInt *iData = NULL; char buffer[256]; - if(argc < 4){ - SCWrite(pCon,"ERROR: insufficient number of arguments to puthm", - eError); - return; - } - - /* - find Histogram Memory - */ - mem = (pHistMem)FindCommandData(pSics,argv[3],"HistMem"); - if(!mem){ - sprintf(buffer,"ERROR: HistMem %s not found!", argv[3]); - SCWrite(pCon,buffer,eError); + if (argc < 4) { + SCWrite(pCon, "ERROR: insufficient number of arguments to puthm", + eLogError); return; } /* - default: everything - */ + find Histogram Memory + */ + mem = (pHistMem) FindCommandData(pSics, argv[3], "HistMem"); + if (!mem) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: HistMem %s not found!", argv[3]); + SCWrite(pCon, buffer, eLogError); + return; + } + + /* + default: everything + */ start = 0; length = GetHistLength(mem); - - updateHMDim(self,mem); + updateHMDim(self, mem); /* check for further arguments specifying a subset */ - if(argc > 5){ + if (argc > 5) { subset = 1; - status = Tcl_GetInt(InterpGetTcl(pSics),argv[4],&start); - if(status != TCL_OK){ - sprintf(buffer,"ERROR: failed to convert %s to integer", - argv[4]); - SCWrite(pCon,buffer,eError); + status = Tcl_GetInt(InterpGetTcl(pSics), argv[4], &start); + if (status != TCL_OK) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to convert %s to integer", argv[4]); + SCWrite(pCon, buffer, eLogError); return; } - status = Tcl_GetInt(InterpGetTcl(pSics),argv[5],&length); - if(status != TCL_OK){ - sprintf(buffer,"ERROR: failed to convert %s to integer", - argv[5]); - SCWrite(pCon,buffer,eError); + status = Tcl_GetInt(InterpGetTcl(pSics), argv[5], &length); + if (status != TCL_OK) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to convert %s to integer", argv[5]); + SCWrite(pCon, buffer, eLogError); return; } } - + /* * check for additional bank number */ - if(argc > 6){ - status = Tcl_GetInt(InterpGetTcl(pSics),argv[6],&bank); - if(status != TCL_OK){ - sprintf(buffer,"ERROR: failed to convert %s to integer", - argv[6]); - SCWrite(pCon,buffer,eError); + if (argc > 6) { + status = Tcl_GetInt(InterpGetTcl(pSics), argv[6], &bank); + if (status != TCL_OK) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to convert %s to integer", argv[6]); + SCWrite(pCon, buffer, eLogError); return; } - } + } /* - read HM - */ - if(subset){ - iData = (HistInt *)malloc(length*sizeof(HistInt)); - if(!iData){ - SCWrite(pCon,"ERROR: out of memory for reading histogram memory", - eError); + read HM + */ + if (subset) { + iData = (HistInt *) malloc(length * sizeof(HistInt)); + if (!iData) { + SCWrite(pCon, "ERROR: out of memory for reading histogram memory", + eLogError); return; } - memset(iData,0,length*sizeof(HistInt)); - status = GetHistogramDirect(mem,pCon,bank,start,start+length,iData, - length*sizeof(HistInt)); - }else{ + memset(iData, 0, length * sizeof(HistInt)); + status = + GetHistogramDirect(mem, pCon, bank, start, start + length, iData, + length * sizeof(HistInt)); + } else { /* - status = GetHistogram(mem,pCon,0,start,length,iData, - length*sizeof(HistInt)); - */ - iData = GetHistogramPointer(mem,pCon); - if(iData == NULL){ + status = GetHistogram(mem,pCon,0,start,length,iData, + length*sizeof(HistInt)); + */ + iData = GetHistogramPointer(mem, pCon); + if (iData == NULL) { status = 0; } else { status = 1; } } - if(!status){ - SCWrite(pCon,"ERROR: failed to read histogram memory",eError); - if(subset){ + if (!status) { + SCWrite(pCon, "ERROR: failed to read histogram memory", eLogError); + if (subset) { free(iData); - } + } return; } /* - finally: write - */ - status = NXDputalias(self->fileHandle, self->dictHandle,argv[2],iData); - if(status != NX_OK){ - sprintf(buffer,"ERROR: failed to write histogram memory data"); - SCWrite(pCon,buffer,eError); + finally: write + */ + status = NXDputalias(self->fileHandle, self->dictHandle, argv[2], iData); + if (status != NX_OK) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to write histogram memory data"); + SCWrite(pCon, buffer, eLogError); } - - if(subset){ + + if (subset) { free(iData); } SCSendOK(pCon); return; } + /*--------------------------------------------------------------------- defunct as of december 2003 */ -static void putHistogramMemoryChunked(SConnection *pCon, SicsInterp *pSics, - pNXScript self, - int argc, char *argv[]){ +static void putHistogramMemoryChunked(SConnection * pCon, + SicsInterp * pSics, pNXScript self, + int argc, char *argv[]) +{ pHistMem mem = NULL; int status, start, length, i, noChunks, chunkDim[MAXDIM], rank; HistInt *iData = NULL; char buffer[256]; - int subset; + int subset =0; - if(argc < 5){ - SCWrite(pCon,"ERROR: insufficient number of arguments to puthmchunked", - eError); - return; - } - - /* - find Histogram Memory - */ - mem = (pHistMem)FindCommandData(pSics,argv[3],"HistMem"); - if(!mem){ - sprintf(buffer,"ERROR: HistMem %s not found!", argv[3]); - SCWrite(pCon,buffer,eError); + if (argc < 5) { + SCWrite(pCon, + "ERROR: insufficient number of arguments to puthmchunked", + eLogError); return; } /* - default: everything - */ + find Histogram Memory + */ + mem = (pHistMem) FindCommandData(pSics, argv[3], "HistMem"); + if (!mem) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: HistMem %s not found!", argv[3]); + SCWrite(pCon, buffer, eLogError); + return; + } + + /* + default: everything + */ start = 0; length = GetHistLength(mem); - updateHMDim(self,mem); + updateHMDim(self, mem); /* - check for an argument defining the number of chunks - */ - status = Tcl_GetInt(InterpGetTcl(pSics),argv[4],&noChunks); - if(status != TCL_OK){ - sprintf(buffer,"ERROR: failed to convert %s to integer", - argv[4]); - SCWrite(pCon,buffer,eError); + check for an argument defining the number of chunks + */ + status = Tcl_GetInt(InterpGetTcl(pSics), argv[4], &noChunks); + if (status != TCL_OK) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to convert %s to integer", argv[4]); + SCWrite(pCon, buffer, eLogError); return; } - + /* - read HM - */ - if(subset){ - iData = (HistInt *)malloc(length*sizeof(HistInt)); - if(!iData){ - SCWrite(pCon,"ERROR: out of memory for reading histogram memory", - eError); + read HM + */ + if (subset) { + iData = (HistInt *) malloc(length * sizeof(HistInt)); + if (!iData) { + SCWrite(pCon, "ERROR: out of memory for reading histogram memory", + eLogError); return; } - memset(iData,0,length*sizeof(HistInt)); - status = GetHistogramDirect(mem,pCon,0,start,start+length,iData, - length*sizeof(HistInt)); - }else{ + memset(iData, 0, length * sizeof(HistInt)); + status = GetHistogramDirect(mem, pCon, 0, start, start + length, iData, + length * sizeof(HistInt)); + } else { /* - status = GetHistogram(mem,pCon,0,start,length,iData, - length*sizeof(HistInt)); - */ - iData = GetHistogramPointer(mem,pCon); - if(iData == NULL){ + status = GetHistogram(mem,pCon,0,start,length,iData, + length*sizeof(HistInt)); + */ + iData = GetHistogramPointer(mem, pCon); + if (iData == NULL) { status = 0; } else { status = 1; } } - if(!status){ - SCWrite(pCon,"ERROR: failed to read histogram memory",eError); - if(subset){ + if (!status) { + SCWrite(pCon, "ERROR: failed to read histogram memory", eLogError); + if (subset) { free(iData); - } + } return; } /* - finally: write - */ - status = NXDputalias(self->fileHandle, self->dictHandle,argv[2],iData); - if(status != NX_OK){ - sprintf(buffer,"ERROR: failed to write histogram memory data"); - SCWrite(pCon,buffer,eError); + finally: write + */ + status = NXDputalias(self->fileHandle, self->dictHandle, argv[2], iData); + if (status != NX_OK) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to write histogram memory data"); + SCWrite(pCon, buffer, eLogError); } - - if(subset){ + + if (subset) { free(iData); } SCSendOK(pCon); return; } -/*----------------------------------------------------------------------*/ -static int listToArray(SicsInterp *pSics, char *list, - int intar[NX_MAXRANK]){ - int argc, status, i, val; - CONST char **argv; - Tcl_Interp *pTcl = InterpGetTcl(pSics); - - status = Tcl_SplitList(pTcl, list, &argc, &argv); - if(status != TCL_OK){ - return status; - } - - for(i = 0; i < argc; i++){ - status = Tcl_GetInt(pTcl,argv[i],&val); - if(status != TCL_OK){ - return status; - } - intar[i] = val; - } - Tcl_Free((char *)argv); - return TCL_OK; -} -/*----------------------------------------------------------------------*/ -#define HANUM 3 -static void putSlab(SConnection *pCon, SicsInterp *pSics, pNXScript self, - int argc, char *argv[]){ - int start[NX_MAXRANK], size[NX_MAXRANK]; - int status, written = 0; - pHistMem mem = NULL; - HistInt *histData = NULL; - pSICSData data = NULL; - char buffer[256]; - enum histargs {haStart, haLength, haBank}; - int i, haIndex, hpars[HANUM], haFirst=6; - - if(argc < 6){ - SCWrite(pCon,"ERROR: insufficient number of arguments to putslab", - eError); - return; - } - status = NXDopenalias(self->fileHandle, self->dictHandle,argv[2]); - if(status != NX_OK){ - SCPrintf(pCon,eError,"ERROR: failed to open alias %s", argv[2]); - return; - } - - status = listToArray(pSics,argv[3],start); - if(status != TCL_OK){ - SCWrite(pCon,"ERROR: failed to convert start value list", eError); - return; - } +/*----------------------------------------------------------------------*/ +static void putSlab(SConnection * pCon, SicsInterp * pSics, pNXScript self, + int argc, char *argv[]) +{ + int start[NX_MAXRANK], size[NX_MAXRANK]; + int status, written = 0; + pHistMem mem = NULL; + HistInt *histData = NULL; + pSICSData data = NULL; + pCounter memsec = NULL; + pHdb node = NULL; - status = listToArray(pSics,argv[4],size); - if(status != TCL_OK){ - SCWrite(pCon,"ERROR: failed to convert size value list", eError); - return; - } - - /* - * try to write HM data - */ - mem = (pHistMem)FindCommandData(pSics,argv[5],"HistMem"); - if(mem != NULL){ - if (argc == 6) { - histData = GetHistogramPointer(mem,pCon); - } else if (argc > 6) { - for (i=0, haIndex=haFirst; i < HANUM; i++, haIndex++) { - status = Tcl_GetInt(InterpGetTcl(pSics),argv[haIndex],&hpars[i]); - if(status != TCL_OK){ - sprintf(buffer,"ERROR: failed to convert %s to integer", - argv[haIndex]); - SCWrite(pCon,buffer,eError); - return; - } - } - histData = (HistInt *)malloc(hpars[haLength]*sizeof(HistInt)); - if(!histData){ - SCWrite(pCon,"ERROR: out of memory for reading histogram memory", - eError); - return; - } - memset(histData,0,hpars[haLength]*sizeof(HistInt)); - status = GetHistogramDirect(mem,pCon,hpars[haBank], - hpars[haStart],hpars[haStart]+hpars[haLength],histData, - hpars[haLength]*sizeof(HistInt)); - } - if(histData){ + if (argc < 6) { + SCWrite(pCon, "ERROR: insufficient number of arguments to putslab", + eLogError); + return; + } + + status = NXDopenalias(self->fileHandle, self->dictHandle, argv[2]); + if (status != NX_OK) { + SCPrintf(pCon, eLogError, "ERROR: failed to open alias %s", argv[2]); + return; + } + + status = listToArray(pSics, argv[3], start); + if (status != TCL_OK) { + SCWrite(pCon, "ERROR: failed to convert start value list", eLogError); + return; + } + + status = listToArray(pSics, argv[4], size); + if (status != TCL_OK) { + SCWrite(pCon, "ERROR: failed to convert size value list", eLogError); + return; + } + + /* + * try to write HM data + */ + mem = (pHistMem) FindCommandData(pSics, argv[5], "HistMem"); + if (mem != NULL) { + histData = GetHistogramPointer(mem, pCon); + if (histData) { status = NXputslab(self->fileHandle, histData, start, size); - if(status == NX_OK){ + if (status == NX_OK) { written = 1; } - if (argc > 6) - free(histData); + } + } + + /* + * try to write second gen histogram data + */ + memsec = (pCounter) FindCommandData(pSics, argv[5], "HistMemSec"); + if(memsec != NULL){ + node = GetHipadabaNode(memsec->pDes->parNode,"data"); + if(node == NULL){ + SCWrite(pCon,"ERROR: ?? data node to second gen HM not found", eError); + return; + } + status = NXputslab(self->fileHandle, node->value.v.intArray, start, size); + if (status == NX_OK) { + written = 1; } + } + + /* + * try to look for sicsdata + */ + data = (pSICSData) FindCommandData(pSics, argv[5], "SICSData"); + if (data != NULL) { + status = NXputslab(self->fileHandle, data->data, start, size); + if (status == NX_OK) { + written = 1; } - - /* - * try to look for sicsdata - */ - data = (pSICSData)FindCommandData(pSics,argv[5],"SICSData"); - if(data != NULL){ - status = NXputslab(self->fileHandle,data->data,start,size); - if(status == NX_OK){ - written = 1; - } - } - /* - * drop out of hierarchy - */ - NXopenpath(self->fileHandle,"/"); - - if(written == 0){ - SCWrite(pCon,"ERROR: failed to write data, data not recognised", - eError); - } + } + /* + * drop out of hierarchy + */ + NXopenpath(self->fileHandle, "/"); + + if (written == 0) { + SCWrite(pCon, "ERROR: failed to write data, data not recognised", + eLogError); + } } +/*----------------------------------------------------------------------*/ +static short *HistInt2Short(HistInt *data, int length) +{ + int i; + + int16_t *shdata = NULL; + shdata = malloc(length*sizeof(int16_t)); + if(shdata == NULL){ + return NULL; + } + memset(shdata,0,length*sizeof(int16_t)); + for(i = 0; i < length; i++){ + shdata[i] = (short)data[i]; + } + return shdata; +} +/*----------------------------------------------------------------------*/ +static void putSlab16(SConnection * pCon, SicsInterp * pSics, pNXScript self, + int argc, char *argv[]) +{ + int start[NX_MAXRANK], size[NX_MAXRANK], dim[MAXDIM]; + int status, written = 0, rank, i; + pHistMem mem = NULL; + HistInt *histData = NULL; + int16_t *shortData = NULL; + pHdb node = NULL; + unsigned int length; + pCounter memsec = NULL; + + if (argc < 6) { + SCWrite(pCon, "ERROR: insufficient number of arguments to putslab", + eLogError); + return; + } + + status = NXDopenalias(self->fileHandle, self->dictHandle, argv[2]); + if (status != NX_OK) { + SCPrintf(pCon, eLogError, "ERROR: failed to open alias %s", argv[2]); + return; + } + + status = listToArray(pSics, argv[3], start); + if (status != TCL_OK) { + SCWrite(pCon, "ERROR: failed to convert start value list", eLogError); + return; + } + + status = listToArray(pSics, argv[4], size); + if (status != TCL_OK) { + SCWrite(pCon, "ERROR: failed to convert size value list", eLogError); + return; + } + + + /* + * try to write HM data + */ + mem = (pHistMem) FindCommandData(pSics, argv[5], "HistMem"); + if (mem != NULL) { + histData = GetHistogramPointer(mem, pCon); + if (histData) { + GetHistDim(mem, dim,&rank); + for(i = 0, length = 1; i < rank; i++){ + length *= dim[i]; + } + shortData = HistInt2Short(histData,length); + if(shortData != NULL){ + status = NXputslab(self->fileHandle, shortData, start, size); + free(shortData); + } + if (status == NX_OK) { + written = 1; + } + } + } + + /* + * try to write second gen histogram data + */ + memsec = (pCounter) FindCommandData(pSics, argv[5], "HistMemSec"); + if(memsec != NULL){ + node = GetHipadabaNode(memsec->pDes->parNode,"data"); + if(node == NULL){ + SCWrite(pCon,"ERROR: ?? data node to second gen HM not found", eError); + return; + } + GetHistDim((pHistMem)memsec, dim,&rank); + for(i = 0, length = 1; i < rank; i++){ + length *= dim[i]; + } + shortData = HistInt2Short(node->value.v.intArray,length); + if(shortData != NULL){ + status = NXputslab(self->fileHandle, shortData, start, size); + free(shortData); + } + if (status == NX_OK) { + written = 1; + } + } + + /* + * drop out of hierarchy + */ + NXopenpath(self->fileHandle, "/"); + + if (written == 0) { + SCWrite(pCon, "ERROR: failed to write data, data not recognised", + eLogError); + } +} + /*-------------------------------------------------------------------*/ -static void putTimeBinning(SConnection *pCon, SicsInterp *pSics, - pNXScript self, - int argc, char *argv[]){ +static void putTimeBinning(SConnection * pCon, SicsInterp * pSics, + pNXScript self, int argc, char *argv[]) +{ pHistMem mem = NULL; int i, status, timeLength; char buffer[256], defString[512], dummy[40]; const float *timeBin; float *timeCopy = NULL; - if(argc < 4){ - SCWrite(pCon,"ERROR: insufficient number of arguments to puttimebinning", - eError); - return; - } - - /* - find Histogram Memory - */ - mem = (pHistMem)FindCommandData(pSics,argv[3],"HistMem"); - if(!mem){ - sprintf(buffer,"ERROR: HistMem %s not found!", argv[3]); - SCWrite(pCon,buffer,eError); + if (argc < 4) { + SCWrite(pCon, + "ERROR: insufficient number of arguments to puttimebinning", + eLogError); return; } - /* - build definition string - */ - status = NXDdefget(self->dictHandle,argv[2],buffer,254); - if(!status){ - sprintf(buffer,"ERROR: alias %s for time binning not found", - argv[2]); - SCWrite(pCon,buffer,eError); - return; - } - timeBin = GetHistTimeBin(mem,&timeLength); - sprintf(defString,"%s -dim {%d} ",buffer,timeLength); - - /* - Divide the time binning when appropriate and write + find Histogram Memory */ - if(self->timeDivisor != 1){ - timeCopy = (float *)malloc(timeLength*sizeof(float)); - if(timeCopy == NULL){ - SCWrite(pCon,"ERROR: out of memory writing time binning",eError); + mem = (pHistMem) FindCommandData(pSics, argv[3], "HistMem"); + if (!mem) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: HistMem %s not found!", argv[3]); + SCWrite(pCon, buffer, eLogError); + return; + } + + + /* + build definition string + */ + status = NXDdefget(self->dictHandle, argv[2], buffer, 254); + if (!status) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: alias %s for time binning not found", argv[2]); + SCWrite(pCon, buffer, eLogError); + return; + } + timeBin = GetHistTimeBin(mem, &timeLength); + snprintf(defString,sizeof(defString)-1, "%s -dim {%d} ", buffer, timeLength); + + /* + Divide the time binning when appropriate and write + */ + if (self->timeDivisor != 1) { + timeCopy = (float *) malloc(timeLength * sizeof(float)); + if (timeCopy == NULL) { + SCWrite(pCon, "ERROR: out of memory writing time binning", + eLogError); return; } - for(i = 0; i < timeLength; i++){ - timeCopy[i] = timeBin[i]/self->timeDivisor; + for (i = 0; i < timeLength; i++) { + timeCopy[i] = timeBin[i] / self->timeDivisor; } status = NXDputdef(self->fileHandle, self->dictHandle, - defString,(void *)timeCopy); + defString, (void *) timeCopy); free(timeCopy); } else { status = NXDputdef(self->fileHandle, self->dictHandle, - defString,(void *)timeBin); + defString, (void *) timeBin); } - if(status != NX_OK){ - sprintf(buffer,"ERROR: failed to write time binning"); - SCWrite(pCon,buffer,eError); + if (status != NX_OK) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to write time binning"); + SCWrite(pCon, buffer, eLogError); } SCSendOK(pCon); return; } + /*----------------------------------------------------------------------*/ -static void putArray(SConnection *pCon, SicsInterp *pSics, - pNXScript self, - int argc, char *argv[]){ +static void putArray(SConnection * pCon, SicsInterp * pSics, + pNXScript self, int argc, char *argv[]) +{ float *data = NULL; int length, i, status; char num[20]; @@ -927,87 +1192,91 @@ static void putArray(SConnection *pCon, SicsInterp *pSics, Tcl_Interp *tcl = NULL; double dVal; - if(argc < 5){ - SCWrite(pCon,"ERROR: insufficient number of arguments to array", - eError); + if (argc < 5) { + SCWrite(pCon, "ERROR: insufficient number of arguments to array", + eLogError); return; } tcl = InterpGetTcl(pSics); assert(tcl != NULL); /* - get array length - */ - status = Tcl_GetInt(tcl,argv[4],&length); - if(status != TCL_OK){ - sprintf(buffer,"ERROR: failed to convert %s to integer",argv[4]); - SCWrite(pCon,buffer,eError); + get array length + */ + status = Tcl_GetInt(tcl, argv[4], &length); + if (status != TCL_OK) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to convert %s to integer in putarray", + argv[4]); + SCWrite(pCon, buffer, eLogError); return; } /* - allocate - */ - if(length > 0){ - data = (float *)malloc(length*sizeof(float)); + allocate + */ + if (length > 0) { + data = (float *) malloc(length * sizeof(float)); } - if(data == NULL){ - snprintf(buffer,255, - "ERROR: out of memory or invalid length at %s, length = %s", - argv[2],argv[4]); - SCWrite(pCon,buffer,eError); + if (data == NULL) { + snprintf(buffer, 255, + "ERROR: out of memory or invalid length in putarray at %s, length = %s", + argv[2], argv[4]); + SCWrite(pCon, buffer, eLogError); return; } - memset(data,0,length*sizeof(float)); + memset(data, 0, length * sizeof(float)); /* - try getting data - */ - for(i = 0; i < length; i++){ - sprintf(num,"%d",i); - varData = (char *)Tcl_GetVar2(tcl,argv[3],num,0); - if(varData != NULL){ - status = Tcl_GetDouble(tcl,varData,&dVal); - if(status != TCL_OK){ - sprintf(buffer,"ERROR: failed to convert %s to double", - varData); - SCWrite(pCon,buffer,eError); + try getting data + */ + for (i = 0; i < length; i++) { + snprintf(num,sizeof(num)-1, "%d", i); + varData = (char *) Tcl_GetVar2(tcl, argv[3], num, 0); + if (varData != NULL) { + status = Tcl_GetDouble(tcl, varData, &dVal); + if (status != TCL_OK) { + snprintf(buffer,sizeof(buffer)-1, + "ERROR: failed to convert %s to double in putarray", + varData); + SCWrite(pCon, buffer, eLogError); } - data[i] = (float)dVal; + data[i] = (float) dVal; } else { - snprintf(buffer,254,"WARNING: failed to find array element %d", i); - SCWrite(pCon,buffer,eError); + snprintf(buffer, 254, + "WARNING: failed to find array element %d in putarray", i); + SCWrite(pCon, buffer, eLogError); } } /* - build definition string - */ - status = NXDdefget(self->dictHandle,argv[2],buffer,254); - if(!status){ - sprintf(buffer,"ERROR: alias %s for array not found", - argv[2]); - SCWrite(pCon,buffer,eError); + build definition string + */ + status = NXDdefget(self->dictHandle, argv[2], buffer, 254); + if (!status) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: alias %s for array not found in putarray", + argv[2]); + SCWrite(pCon, buffer, eLogError); free(data); return; } - snprintf(defString,511,"%s -dim {%d} ",buffer,length); + snprintf(defString, 511, "%s -dim {%d} ", buffer, length); /* - write it! - */ - status = NXDputdef(self->fileHandle,self->dictHandle,defString,data); - if(status != NX_OK){ - sprintf(buffer,"ERROR: failed to write array"); - SCWrite(pCon,buffer,eError); + write it! + */ + status = NXDputdef(self->fileHandle, self->dictHandle, defString, data); + if (status != NX_OK) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to write array in putarray"); + SCWrite(pCon, buffer, eLogError); } free(data); SCSendOK(pCon); } + /*----------------------------------------------------------------------*/ -static void putIntArray(SConnection *pCon, SicsInterp *pSics, - pNXScript self, - int argc, char *argv[]){ +static void putIntArray(SConnection * pCon, SicsInterp * pSics, + pNXScript self, int argc, char *argv[]) +{ int *data = NULL; int length, i, status; char num[20]; @@ -1015,410 +1284,429 @@ static void putIntArray(SConnection *pCon, SicsInterp *pSics, Tcl_Interp *tcl = NULL; int iVal; - if(argc < 5){ - SCWrite(pCon,"ERROR: insufficient number of arguments to array", - eError); + if (argc < 5) { + SCWrite(pCon, "ERROR: insufficient number of arguments to array", + eLogError); return; } tcl = InterpGetTcl(pSics); assert(tcl != NULL); /* - get array length - */ - status = Tcl_GetInt(tcl,argv[4],&length); - if(status != TCL_OK){ - sprintf(buffer,"ERROR: failed to convert %s to integer",argv[4]); - SCWrite(pCon,buffer,eError); + get array length + */ + status = Tcl_GetInt(tcl, argv[4], &length); + if (status != TCL_OK) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to convert %s to integer", argv[4]); + SCWrite(pCon, buffer, eLogError); return; } /* - allocate - */ - if(length > 0){ - data = (int *)malloc(length*sizeof(int)); + allocate + */ + if (length > 0) { + data = (int *) malloc(length * sizeof(int)); } - if(data == NULL){ - SCWrite(pCon,"ERROR: out of memory or invalid length",eError); + if (data == NULL) { + SCWrite(pCon, "ERROR: out of memory or invalid length", eLogError); return; } - memset(data,0,length*sizeof(int)); + memset(data, 0, length * sizeof(int)); /* - try getting data - */ - for(i = 0; i < length; i++){ - sprintf(num,"%d",i); - varData = (char *)Tcl_GetVar2(tcl,argv[3],num,0); - if(varData != NULL){ - status = Tcl_GetInt(tcl,varData,&iVal); - if(status != TCL_OK){ - sprintf(buffer,"ERROR: failed to convert %s to int", - varData); - SCWrite(pCon,buffer,eError); + try getting data + */ + for (i = 0; i < length; i++) { + snprintf(num,sizeof(num)-1, "%d", i); + varData = (char *) Tcl_GetVar2(tcl, argv[3], num, 0); + if (varData != NULL) { + status = Tcl_GetInt(tcl, varData, &iVal); + if (status != TCL_OK) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to convert %s to int", varData); + SCWrite(pCon, buffer, eLogError); } data[i] = iVal; } else { - snprintf(buffer,254,"WARNING: failed to find array element %d", i); - SCWrite(pCon,buffer,eError); + snprintf(buffer, 254, "WARNING: failed to find array element %d", i); + SCWrite(pCon, buffer, eLogError); } } /* - build definition string - */ - status = NXDdefget(self->dictHandle,argv[2],buffer,254); - if(!status){ - sprintf(buffer,"ERROR: alias %s for array not found", - argv[2]); - SCWrite(pCon,buffer,eError); + build definition string + */ + status = NXDdefget(self->dictHandle, argv[2], buffer, 254); + if (!status) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: alias %s for array not found", argv[2]); + SCWrite(pCon, buffer, eLogError); free(data); return; } - snprintf(defString,511,"%s -dim {%d} ",buffer,length); + snprintf(defString, 511, "%s -dim {%d} ", buffer, length); /* - write it! - */ - status = NXDputdef(self->fileHandle,self->dictHandle,defString,data); - if(status != NX_OK){ - sprintf(buffer,"ERROR: failed to write array"); - SCWrite(pCon,buffer,eError); + write it! + */ + status = NXDputdef(self->fileHandle, self->dictHandle, defString, data); + if (status != NX_OK) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to write array"); + SCWrite(pCon, buffer, eLogError); } free(data); SCSendOK(pCon); } + /*----------------------------------------------------------------------*/ -static void putGlobal(SConnection *pCon, SicsInterp *pSics, - pNXScript self, - int argc, char *argv[]){ +static void putGlobal(SConnection * pCon, SicsInterp * pSics, + pNXScript self, int argc, char *argv[]) +{ char value[1024]; int status; - if(argc < 4){ - SCWrite(pCon,"ERROR: insufficient number of arguments to putglobal", - eError); + if (argc < 4) { + SCWrite(pCon, "ERROR: insufficient number of arguments to putglobal", + eLogError); return; } - Arg2Text(argc-3,&argv[3],value,1023); - status = NXputattr(self->fileHandle,argv[2],value,strlen(value), - NX_CHAR); - if(status != NX_OK){ - SCWrite(pCon,"ERROR: failed to write attribute",eError); + Arg2Text(argc - 3, &argv[3], value, 1023); + status = NXputattr(self->fileHandle, argv[2], value, strlen(value), + NX_CHAR); + if (status != NX_OK) { + SCWrite(pCon, "ERROR: failed to write attribute", eLogError); } SCSendOK(pCon); } + /*-----------------------------------------------------------------------*/ -static int handlePut(SConnection *pCon, SicsInterp *pSics, pNXScript self, - int argc, char *argv[]){ +static int handlePut(SConnection * pCon, SicsInterp * pSics, + pNXScript self, int argc, char *argv[]) +{ int status, iVal; char buffer[1024], defString[1024], numBuf[25]; double dVal; float fVal; /*============ */ - if(strcmp(argv[1],"putfloat") == 0){ - if(argc < 4){ - SCWrite(pCon,"ERROR: insufficient number of arguments to putfloat", - eError); + if (strcmp(argv[1], "putfloat") == 0) { + if (argc < 4) { + SCWrite(pCon, "ERROR: insufficient number of arguments to putfloat", + eLogError); return 1; } - status = Tcl_GetDouble(InterpGetTcl(pSics),argv[3],&dVal); - if(status != TCL_OK){ - sprintf(buffer,"ERROR: failed to convert %s to float", - argv[3]); - SCWrite(pCon,buffer,eError); + status = Tcl_GetDouble(InterpGetTcl(pSics), argv[3], &dVal); + if (status != TCL_OK) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to convert %s to float", argv[3]); + SCWrite(pCon, buffer, eLogError); return 1; } - fVal = (float)dVal; + fVal = (float) dVal; status = NXDputalias(self->fileHandle, self->dictHandle, - argv[2],&fVal); - if(status != NX_OK){ - sprintf(buffer,"ERROR: failed to write %f to alias %s", - fVal, argv[2]); - SCWrite(pCon,buffer,eError); + argv[2], &fVal); + if (status != NX_OK) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to write %f to alias %s", + fVal, argv[2]); + SCWrite(pCon, buffer, eLogError); } return 1; - } else if(strcmp(argv[1],"putint") == 0){ - if(argc < 4){ - SCWrite(pCon,"ERROR: insufficient number of arguments to putint", - eError); + } else if (strcmp(argv[1], "putint") == 0) { + if (argc < 4) { + SCWrite(pCon, "ERROR: insufficient number of arguments to putint", + eLogError); return 1; } - status = Tcl_GetInt(InterpGetTcl(pSics),argv[3],&iVal); - if(status != TCL_OK){ - sprintf(buffer,"ERROR: failed to convert %s to int", - argv[3]); - SCWrite(pCon,buffer,eError); - return 1; + status = Tcl_GetInt(InterpGetTcl(pSics), argv[3], &iVal); + if (status != TCL_OK) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to convert %s to int", argv[3]); + SCWrite(pCon, buffer, eLogError); + return 1; } status = NXDputalias(self->fileHandle, self->dictHandle, - argv[2],&iVal); - if(status != NX_OK){ - sprintf(buffer,"ERROR: failed to write %d to alias %s", - iVal, argv[2]); - SCWrite(pCon,buffer,eError); + argv[2], &iVal); + if (status != NX_OK) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to write %d to alias %s", + iVal, argv[2]); + SCWrite(pCon, buffer, eLogError); } return 1; - } else if (strcmp(argv[1],"puttext") == 0){ + } else if (strcmp(argv[1], "puttext") == 0) { /*====================*/ - if(argc < 4){ - SCWrite(pCon,"ERROR: insufficient number of arguments to puttext", - eError); + if (argc < 4) { + SCWrite(pCon, "ERROR: insufficient number of arguments to puttext", + eLogError); return 1; } - Arg2Text(argc-3,&argv[3],buffer,1023); + Arg2Text(argc - 3, &argv[3], buffer, 1023); trim(buffer); - status = NXDdefget(self->dictHandle,argv[2],defString,1023); - if(status != NX_OK){ - sprintf(buffer,"ERROR: alias %s not found in puttext", - argv[2]); - SCWrite(pCon,buffer,eError); + status = NXDdefget(self->dictHandle, argv[2], defString, 1023); + if (status != NX_OK) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: alias %s not found in puttext", argv[2]); + SCWrite(pCon, buffer, eLogError); return 1; } - if(strlen(defString) < 900){ - strcat(defString," -dim {"); - sprintf(numBuf,"%d",(int)strlen(buffer)+1); - strcat(defString,numBuf); - strcat(defString," }"); + if (strlen(defString) < 900) { + strlcat(defString, " -dim {",1024); + snprintf(numBuf,sizeof(numBuf)-1, "%d", (int) strlen(buffer) + 1); + strlcat(defString, numBuf,1024); + strlcat(defString, " }",1024); } else { - SCWrite(pCon,"ERROR: out of definition string space in puttext", - eError); + SCWrite(pCon, "ERROR: out of definition string space in puttext", + eLogError); return 1; } - status = NXDputdef(self->fileHandle,self->dictHandle, - defString,buffer); - if(status != NX_OK){ - sprintf(buffer,"ERROR: failed to write alias %s", - argv[2]); - SCWrite(pCon,buffer,eError); + status = NXDputdef(self->fileHandle, self->dictHandle, + defString, buffer); + if (status != NX_OK) { + snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to write alias %s", argv[2]); + SCWrite(pCon, buffer, eLogError); } return 1; - } else if(strcmp(argv[1],"putmot") == 0){ + } else if (strcmp(argv[1], "putmot") == 0) { /*=========== */ - putMotor(pCon,pSics,self,argc,argv); + putMotor(pCon, pSics, self, argc, argv); return 1; - } else if(strcmp(argv[1],"putcounter") == 0){ - /* ================*/ - putCounter(pCon,pSics,self, argc,argv); + } else if (strcmp(argv[1], "putcounter") == 0) { + /* ================ */ + putCounter(pCon, pSics, self, argc, argv); return 1; - } else if(strcmp(argv[1],"puthdb") == 0){ - /* ================*/ - putHdb(pCon,pSics,self, argc,argv); + } else if (strcmp(argv[1], "puthdb") == 0) { + /* ================ */ + putHdb(pCon, pSics, self, argc, argv); return 1; - }else if(strcmp(argv[1],"puthm") == 0){ + } else if (strcmp(argv[1], "puthdboff") == 0) { + /* ================ */ + putHdbOff(pCon, pSics, self, argc, argv); + return 1; + } else if (strcmp(argv[1], "puthdbslab") == 0) { + /* ================ */ + putHdbSlab(pCon, pSics, self, argc, argv); + return 1; + } else if (strcmp(argv[1], "puthm") == 0) { /*=================*/ - putHistogramMemory(pCon,pSics,self,argc, argv); + putHistogramMemory(pCon, pSics, self, argc, argv); return 1; - }else if(strcmp(argv[1],"puttimebinning") == 0){ + } else if (strcmp(argv[1], "puttimebinning") == 0) { /*=================*/ - putTimeBinning(pCon,pSics,self,argc,argv); - }else if(strcmp(argv[1],"putarray") == 0){ + putTimeBinning(pCon, pSics, self, argc, argv); + } else if (strcmp(argv[1], "putarray") == 0) { /*================*/ - putArray(pCon,pSics,self,argc,argv); - }else if(strcmp(argv[1],"putintarray") == 0){ + putArray(pCon, pSics, self, argc, argv); + } else if (strcmp(argv[1], "putintarray") == 0) { /*================*/ - putIntArray(pCon,pSics,self,argc,argv); - }else if(strcmp(argv[1],"putglobal") == 0){ + putIntArray(pCon, pSics, self, argc, argv); + } else if (strcmp(argv[1], "putglobal") == 0) { /*===============*/ - putGlobal(pCon,pSics,self,argc,argv); - }else if(strcmp(argv[1],"putsicsdata") == 0){ + putGlobal(pCon, pSics, self, argc, argv); + } else if (strcmp(argv[1], "putsicsdata") == 0) { /*===============*/ - putSicsData(pCon,pSics,self,argc,argv); - }else if(strcmp(argv[1],"putattribute") == 0){ + putSicsData(pCon, pSics, self, argc, argv); + } else if (strcmp(argv[1], "putattribute") == 0) { /*===============*/ - putAttribute(pCon,pSics,self,argc,argv); - }else if(strcmp(argv[1],"putslab") == 0){ + putAttribute(pCon, pSics, self, argc, argv); + } else if (strcmp(argv[1], "putslab") == 0) { /*===============*/ - putSlab(pCon,pSics,self,argc,argv); + putSlab(pCon, pSics, self, argc, argv); + } else if (strcmp(argv[1], "putslab16") == 0) { + /*===============*/ + putSlab16(pCon, pSics, self, argc, argv); } else { - SCWrite(pCon,"ERROR: put command not recognised",eError); + SCPrintf(pCon, eLogError, "ERROR: put command %s not recognised", argv[1] ); } return 1; -} +} + /*----------------------------------------------------------------------*/ -static void makeLink(SConnection *pCon, SicsInterp *pSics, - pNXScript self, - int argc, char *argv[]){ +static void makeLink(SConnection * pCon, SicsInterp * pSics, + pNXScript self, int argc, char *argv[]) +{ int status; char pBueffel[256]; - if(argc < 4){ - SCWrite(pCon,"ERROR: insufficient number of arguments to makelink", - eError); + if (argc < 4) { + SCWrite(pCon, "ERROR: insufficient number of arguments to makelink", + eLogError); return; } status = NXDaliaslink(self->fileHandle, self->dictHandle, - argv[2],argv[3]); - if(status != NX_OK){ - snprintf(pBueffel,255,"ERROR: linking %s against %s failed", - argv[2], argv[3]); - SCWrite(pCon,pBueffel,eError); + argv[2], argv[3]); + if (status != NX_OK) { + snprintf(pBueffel, 255, "ERROR: linking %s against %s failed", + argv[2], argv[3]); + SCWrite(pCon, pBueffel, eLogError); return; } SCSendOK(pCon); } + /*----------------------------------------------------------------------*/ -static void updateDictVar(SConnection *pCon, pNXScript self, int argc, - char *argv[]){ +static void updateDictVar(SConnection * pCon, pNXScript self, int argc, + char *argv[]) +{ int status; - if(self->dictHandle == NULL){ - SCWrite(pCon,"ERROR: cannot update variable, dictionary not open", - eError); + if (self->dictHandle == NULL) { + SCWrite(pCon, "ERROR: cannot update variable, dictionary not open", + eLogError); return; } - if(argc < 4){ - SCWrite(pCon,"ERROR: insufficient number of arguments to updateDictVar", - eError); + if (argc < 4) { + SCWrite(pCon, + "ERROR: insufficient number of arguments to updateDictVar", + eLogError); return; } - NXDupdate(self->dictHandle,argv[2],argv[3]); + NXDupdate(self->dictHandle, argv[2], argv[3]); } + /*-----------------------------------------------------------------------*/ -int NXScriptAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]){ - pNXScript self = (pNXScript)pData; +int NXScriptAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pNXScript self = (pNXScript) pData; char *pFile = NULL; int status; char buffer[132]; /* - preliminary checks - */ + preliminary checks + */ assert(self); - if(!SCMatchRights(pCon,usUser)){ + if (!SCMatchRights(pCon, usUser)) { return 1; } - if(argc < 2){ - SCWrite(pCon,"ERROR: no keyword found",eError); + if (argc < 2) { + SCWrite(pCon, "ERROR: no keyword found", eLogError); return 1; } strtolower(argv[1]); - if(strcmp(argv[1],"makefilename") == 0){ - pFile = makeFilename(pSics,pCon); - if(pFile != NULL){ - SCWrite(pCon,pFile,eValue); + if (strcmp(argv[1], "makefilename") == 0) { + pFile = makeFilename(pSics, pCon); + if (pFile != NULL) { + SCWrite(pCon, pFile, eValue); free(pFile); return 1; } else { - SCWrite(pCon,"ERROR: failed to create filename",eError); + SCWrite(pCon, "ERROR: failed to create filename", eError); return 0; } - } else if(strcmp(argv[1],"divisor") == 0){ - if(argc < 3) { - SCWrite(pCon,"ERROR: no diviso found",eError); + } else if (strcmp(argv[1], "divisor") == 0) { + if (argc < 3) { + SCWrite(pCon, "ERROR: no divisor found", eLogError); return 1; } - if(!SCMatchRights(pCon,usMugger)){ + if (!SCMatchRights(pCon, usMugger)) { return 1; } self->timeDivisor = atoi(argv[2]); return 1; } - - status = handleFileOperations(pCon,self,argc,argv); - if(status < 0){ + + status = handleFileOperations(pCon, self, argc, argv); + if (status < 0) { return 0; - } else if(status == 1){ + } else if (status == 1) { return 1; } /* - if we are here, we can only continue if files are open - */ - if(self->fileHandle == NULL || self->dictHandle == NULL){ - SCWrite(pCon,"ERROR: cannot write, files not open",eError); + if we are here, we can only continue if files are open + */ + if (self->fileHandle == NULL || self->dictHandle == NULL) { + SCWrite(pCon, "ERROR: cannot write, files not open", eLogError); return 1; } - if(strcmp(argv[1],"updatedictvar") == 0){ - updateDictVar(pCon,self,argc,argv); + if (strcmp(argv[1], "updatedictvar") == 0) { + updateDictVar(pCon, self, argc, argv); return 1; } - if(strstr(argv[1],"put") != NULL){ - handlePut(pCon,pSics,self,argc,argv); + if (strstr(argv[1], "put") != NULL) { + handlePut(pCon, pSics, self, argc, argv); return 1; } - if(strcmp(argv[1],"isalias") == 0) { - if(argc < 3) { - SCWrite(pCon,"ERROR: need alias to test",eError); - return 1; + if (strcmp(argv[1], "isalias") == 0) { + if (argc < 3) { + SCWrite(pCon, "ERROR: need alias to test", eLogError); + return 1; } - if(NXDget(self->dictHandle,argv[2],buffer,131) == NX_OK){ - snprintf(buffer,131,"%s = 1", argv[2]); + if (NXDget(self->dictHandle, argv[2], buffer, 131) == NX_OK) { + snprintf(buffer, 131, "%s = 1", argv[2]); } else { - snprintf(buffer,131,"%s = 0", argv[2]); + snprintf(buffer, 131, "%s = 0", argv[2]); } - SCWrite(pCon,buffer,eValue); + SCWrite(pCon, buffer, eValue); return 1; } - if(strcmp(argv[1],"makelink") == 0){ - makeLink(pCon,pSics,self,argc,argv); + if (strcmp(argv[1], "makelink") == 0) { + makeLink(pCon, pSics, self, argc, argv); return 1; } return 1; } + /*=============== make it ==============================================*/ -static void KillNXScript(void *pData){ - pNXScript self = (pNXScript)pData; - if(self == NULL){ +static void KillNXScript(void *pData) +{ + pNXScript self = (pNXScript) pData; + if (self == NULL) { return; } - if(self->pDes){ + if (self->pDes) { DeleteDescriptor(self->pDes); } - if(self->fileHandle){ + if (self->fileHandle) { NXclose(&self->fileHandle); } - if(self->dictHandle){ + if (self->dictHandle) { NXDclose(self->dictHandle, NULL); } free(self); } + /*----------------------------------------------------------------------*/ -int MakeNXScript(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]){ +int MakeNXScript(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ pNXScript self = NULL; int status; - self = (pNXScript)malloc(sizeof(NXScript)); - if(self == NULL){ - SCWrite(pCon,"ERROR: no memory for NXscript creation",eError); + self = (pNXScript) malloc(sizeof(NXScript)); + if (self == NULL) { + SCWrite(pCon, "ERROR: no memory for NXscript creation", eError); return 0; } - memset(self,0,sizeof(NXScript)); + memset(self, 0, sizeof(NXScript)); self->pDes = CreateDescriptor("NXScript"); - if(self->pDes == NULL){ - SCWrite(pCon,"ERROR: no memory for NXscript creation",eError); + if (self->pDes == NULL) { + SCWrite(pCon, "ERROR: no memory for NXscript creation", eError); free(self); return 0; } self->timeDivisor = 1; - + /* - create with with a default name if none specified - */ - if(argc > 1){ - status = AddCommand(pSics,argv[1],NXScriptAction,KillNXScript,self); + create with with a default name if none specified + */ + if (argc > 1) { + status = + AddCommand(pSics, argv[1], NXScriptAction, KillNXScript, self); } else { - status = AddCommand(pSics,"nxscript",NXScriptAction,KillNXScript,self); + status = + AddCommand(pSics, "nxscript", NXScriptAction, KillNXScript, self); } - if(!status){ - SCWrite(pCon,"ERROR: duplicate NXScript object not created",eError); + if (!status) { + SCWrite(pCon, "ERROR: duplicate NXScript object not created", eError); KillNXScript(self); return 0; } return 1; } - diff --git a/nxscript.h b/nxscript.h index 5acf16b0..08b8290a 100644 --- a/nxscript.h +++ b/nxscript.h @@ -14,12 +14,12 @@ #include "napi.h" #include "nxdict.h" -int MakeNXScript(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); -int NXScriptAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); +int MakeNXScript(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); +int NXScriptAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); -char *makeFilename(SicsInterp *pSics, SConnection *pCon); +char *makeFilename(SicsInterp * pSics, SConnection * pCon); void changeExtension(char *filename, char *newExtension); /*============== a personal data structure ============================*/ typedef struct { diff --git a/nxstack.c b/nxstack.c index bd2f492c..a5ba2bd7 100644 --- a/nxstack.c +++ b/nxstack.c @@ -18,7 +18,10 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - For further information, see + For further information, see + + Added code to support the path stack for NXgetpath, + Mark Koennecke, October 2009 */ #include #include @@ -39,17 +42,20 @@ typedef struct { typedef struct __fileStack { int fileStackPointer; fileStackEntry fileStack[MAXEXTERNALDEPTH]; + int pathPointer; + char pathStack[NXMAXSTACK][NX_MAXNAMELEN]; }fileStack; /*---------------------------------------------------------------------*/ pFileStack makeFileStack(){ pFileStack pNew = NULL; - pNew = malloc(sizeof(fileStack)); + pNew = (pFileStack)malloc(sizeof(fileStack)); if(pNew == NULL){ return NULL; } memset(pNew,0,sizeof(fileStack)); pNew->fileStackPointer = -1; + pNew->pathPointer = -1; return pNew; } /*---------------------------------------------------------------------*/ @@ -58,9 +64,13 @@ void killFileStack(pFileStack self){ free(self); } } +/*---------------------------------------------------------------------*/ +int getFileStackSize(){ + return sizeof(fileStack); +} /*----------------------------------------------------------------------*/ void pushFileStack(pFileStack self, pNexusFunction pDriv, char *file){ - int length; + size_t length; self->fileStackPointer++; self->fileStack[self->fileStackPointer].pDriver = pDriv; @@ -98,3 +108,38 @@ void setCloseID(pFileStack self, NXlink id){ int fileStackDepth(pFileStack self){ return self->fileStackPointer; } +/*----------------------------------------------------------------------*/ +void pushPath(pFileStack self, const char *name){ + self->pathPointer++; + strncpy(self->pathStack[self->pathPointer],name,NX_MAXNAMELEN-1); +} +/*-----------------------------------------------------------------------*/ +void popPath(pFileStack self){ + self->pathPointer--; + if(self->pathPointer < -1){ + self->pathPointer = -1; + } +} +/*-----------------------------------------------------------------------*/ +int buildPath(pFileStack self, char *path, int pathlen){ + int i; + size_t totalPathLength; + char *totalPath; + + for(i = 0, totalPathLength = 5; i <= self->pathPointer; i++){ + totalPathLength += strlen(self->pathStack[i]) + 1; + } + totalPath = (char*)malloc(totalPathLength*sizeof(char)); + if(totalPath == NULL){ + return 0; + } + memset(totalPath,0,totalPathLength*sizeof(char)); + for(i = 0; i <= self->pathPointer; i++){ + strcat(totalPath,"/"); + strcat(totalPath,self->pathStack[i]); + } + + strncpy(path,totalPath,pathlen-1); + free(totalPath); + return 1; +} diff --git a/nxstack.h b/nxstack.h index e7a9568b..2faaf041 100755 --- a/nxstack.h +++ b/nxstack.h @@ -18,7 +18,11 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - For further information, see + For further information, see + + Added functions to deal with the path stack for NXgetpath + Mark Koennecke, October 2009 + */ #ifndef NEXUSFILESTACK #define NEXUSFILESTACK @@ -28,6 +32,7 @@ typedef struct __fileStack *pFileStack; pFileStack makeFileStack(); void killFileStack(pFileStack self); +int getFileStackSize(); void pushFileStack(pFileStack self, pNexusFunction pDriv, char *filename); void popFileStack(pFileStack self); @@ -39,5 +44,9 @@ void setCloseID(pFileStack self, NXlink id); int fileStackDepth(pFileStack self); +void pushPath(pFileStack self, const char *name); +void popPath(pFileStack self); +int buildPath(pFileStack self, char *path, int pathlen); + #endif diff --git a/nxupdate.c b/nxupdate.c index 0bd0e028..67ec0773 100644 --- a/nxupdate.c +++ b/nxupdate.c @@ -16,198 +16,211 @@ #include "nxupdate.h" #include "nxupdate.i" /*-------------------------------------------------------------------*/ -static int UpdateTask(void *pData){ +static int UpdateTask(void *pData) +{ pNXupdate self = NULL; - self = (pNXupdate)pData; - if(self == NULL){ + self = (pNXupdate) pData; + if (self == NULL) { return 0; } - if(self->onOff == 0){ + if (self->onOff == 0) { return 0; } /* - update when intervall reached or when end - */ - if(time(NULL) >= self->nextUpdate || self->iEnd == 1){ - if(self->updateScript != NULL && self->pCon != NULL){ - InterpExecute(pServ->pSics,self->pCon,self->updateScript); + update when intervall reached or when end + */ + if (time(NULL) >= self->nextUpdate || self->iEnd == 1) { + if (self->updateScript != NULL && self->pCon != NULL) { + InterpExecute(pServ->pSics, self->pCon, self->updateScript); } self->nextUpdate = time(NULL) + self->updateIntervall; } - if(self->iEnd == 1){ + if (self->iEnd == 1) { self->pCon = NULL; return 0; } else { return 1; } } + /*--------------------------------------------------------------------*/ -static int CountCallback(int iEvent, void *pEventData, void *pUser, - commandContext cc){ +static int CountCallback(int iEvent, void *pEventData, void *pUser) +{ pNXupdate self = NULL; SConnection *pCon = NULL; - self = (pNXupdate)pUser; - pCon = (SConnection *)pEventData; + self = (pNXupdate) pUser; + pCon = (SConnection *) pEventData; - if(self->onOff == 0){ + if (self->onOff == 0) { return 1; } - if(iEvent == COUNTSTART){ + if (iEvent == COUNTSTART) { assert(pCon); assert(self); /* - start file - */ - if(self->startScript != NULL){ - InterpExecute(pServ->pSics,pCon,self->startScript); + start file + */ + if (self->startScript != NULL) { + InterpExecute(pServ->pSics, pCon, self->startScript); } - if(self->updateScript != NULL){ - InterpExecute(pServ->pSics,pCon,self->updateScript); + if (self->updateScript != NULL) { + InterpExecute(pServ->pSics, pCon, self->updateScript); } - if(self->linkScript != NULL){ - InterpExecute(pServ->pSics,pCon,self->linkScript); + if (self->linkScript != NULL) { + InterpExecute(pServ->pSics, pCon, self->linkScript); } /* - register update function - */ + register update function + */ self->nextUpdate = time(NULL) + self->updateIntervall; self->iEnd = 0; self->pCon = pCon; - TaskRegister(pServ->pTasker,UpdateTask,NULL,NULL,self,1); + TaskRegister(pServ->pTasker, UpdateTask, NULL, NULL, self, 1); return 1; - } else if(iEvent == COUNTEND){ + } else if (iEvent == COUNTEND) { self->iEnd = 1; assert(self); return 1; } return 1; } + /*----------------------------------------------------------------------*/ -void KillUpdate(void *pData){ +void KillUpdate(void *pData) +{ pNXupdate self = NULL; - self = (pNXupdate)pData; - if(self == NULL){ + self = (pNXupdate) pData; + if (self == NULL) { return; } - if(self->startScript != NULL){ + if (self->startScript != NULL) { free(self->startScript); self->startScript = NULL; } - if(self->updateScript != NULL){ + if (self->updateScript != NULL) { free(self->updateScript); self->updateScript = NULL; } - if(self->linkScript != NULL){ + if (self->linkScript != NULL) { free(self->linkScript); self->linkScript = NULL; } free(self); } + /*-------------------------------------------------------------------*/ -static void printUpdateList(SConnection *pCon, pNXupdate self, char *name){ +static void printUpdateList(SConnection * pCon, pNXupdate self, char *name) +{ char pBueffel[256]; - snprintf(pBueffel,255,"%s.startScript = %s",name, self->startScript); - SCWrite(pCon,pBueffel,eValue); - snprintf(pBueffel,255,"%s.updateScript = %s",name, self->updateScript); - SCWrite(pCon,pBueffel,eValue); - snprintf(pBueffel,255,"%s.linkScript = %s",name, self->linkScript); - SCWrite(pCon,pBueffel,eValue); - snprintf(pBueffel,255,"%s.updateIntervall = %d",name, - self->updateIntervall); - SCWrite(pCon,pBueffel,eValue); - snprintf(pBueffel,255,"%s.onOff = %d",name, - self->onOff); - SCWrite(pCon,pBueffel,eValue); + snprintf(pBueffel, 255, "%s.startScript = %s", name, self->startScript); + SCWrite(pCon, pBueffel, eValue); + snprintf(pBueffel, 255, "%s.updateScript = %s", name, + self->updateScript); + SCWrite(pCon, pBueffel, eValue); + snprintf(pBueffel, 255, "%s.linkScript = %s", name, self->linkScript); + SCWrite(pCon, pBueffel, eValue); + snprintf(pBueffel, 255, "%s.updateIntervall = %d", name, + self->updateIntervall); + SCWrite(pCon, pBueffel, eValue); + snprintf(pBueffel, 255, "%s.onOff = %d", name, self->onOff); + SCWrite(pCon, pBueffel, eValue); } + /*--------------------------------------------------------------------*/ -static int printUpdateParameters(SConnection *pCon, pNXupdate self, - char *name, char *param){ +static int printUpdateParameters(SConnection * pCon, pNXupdate self, + char *name, char *param) +{ char pBueffel[256]; - if(strcmp(param,"list") == 0){ - printUpdateList(pCon,self, name); + if (strcmp(param, "list") == 0) { + printUpdateList(pCon, self, name); return 1; - } else if(strcmp(param,"startscript") == 0){ - snprintf(pBueffel,255,"%s.startScript = %s",name, self->startScript); - SCWrite(pCon,pBueffel,eValue); + } else if (strcmp(param, "startscript") == 0) { + snprintf(pBueffel, 255, "%s.startScript = %s", name, + self->startScript); + SCWrite(pCon, pBueffel, eValue); return 1; - } else if(strcmp(param,"updatescript")== 0){ - snprintf(pBueffel,255,"%s.updateScript = %s",name, self->updateScript); - SCWrite(pCon,pBueffel,eValue); + } else if (strcmp(param, "updatescript") == 0) { + snprintf(pBueffel, 255, "%s.updateScript = %s", name, + self->updateScript); + SCWrite(pCon, pBueffel, eValue); return 1; - } else if(strcmp(param,"linkscript") == 0){ - snprintf(pBueffel,255,"%s.linkScript = %s",name, self->linkScript); - SCWrite(pCon,pBueffel,eValue); + } else if (strcmp(param, "linkscript") == 0) { + snprintf(pBueffel, 255, "%s.linkScript = %s", name, self->linkScript); + SCWrite(pCon, pBueffel, eValue); return 1; - } else if(strcmp(param,"updateintervall") == 0){ - snprintf(pBueffel,255,"%s.updateIntervall = %d",name, - self->updateIntervall); - SCWrite(pCon,pBueffel,eValue); + } else if (strcmp(param, "updateintervall") == 0) { + snprintf(pBueffel, 255, "%s.updateIntervall = %d", name, + self->updateIntervall); + SCWrite(pCon, pBueffel, eValue); return 1; - } else if(strcmp(param,"onoff") == 0){ - snprintf(pBueffel,255,"%s.onoff = %d",name, - self->onOff); - SCWrite(pCon,pBueffel,eValue); + } else if (strcmp(param, "onoff") == 0) { + snprintf(pBueffel, 255, "%s.onoff = %d", name, self->onOff); + SCWrite(pCon, pBueffel, eValue); return 1; } else { - snprintf(pBueffel,255,"ERROR: parameter %s not known", param); - SCWrite(pCon,pBueffel,eValue); + snprintf(pBueffel, 255, "ERROR: parameter %s not known", param); + SCWrite(pCon, pBueffel, eValue); return 0; } } + /*---------------------------------------------------------------------*/ -static int configureUpdate(SConnection *pCon, pNXupdate self, - char *param, char *value){ +static int configureUpdate(SConnection * pCon, pNXupdate self, + char *param, char *value) +{ char pBueffel[256]; int newUpdate; - if(strcmp(param,"startscript") == 0){ - if(self->startScript != NULL){ + if (strcmp(param, "startscript") == 0) { + if (self->startScript != NULL) { free(self->startScript); } self->startScript = strdup(value); SCSendOK(pCon); return 1; - } else if(strcmp(param,"updatescript")== 0){ - if(self->updateScript != NULL){ + } else if (strcmp(param, "updatescript") == 0) { + if (self->updateScript != NULL) { free(self->updateScript); } self->updateScript = strdup(value); SCSendOK(pCon); return 1; - } else if(strcmp(param,"linkscript") == 0){ - if(self->linkScript != NULL){ + } else if (strcmp(param, "linkscript") == 0) { + if (self->linkScript != NULL) { free(self->linkScript); } self->linkScript = strdup(value); SCSendOK(pCon); return 1; - } else if(strcmp(param,"updateintervall") == 0){ - if(Tcl_GetInt(InterpGetTcl(pServ->pSics),value,&newUpdate) != TCL_OK){ - snprintf(pBueffel,255, - "ERROR: %s not an int, cannot set updateIntervall", value); - SCWrite(pCon,pBueffel,eError); + } else if (strcmp(param, "updateintervall") == 0) { + if (Tcl_GetInt(InterpGetTcl(pServ->pSics), value, &newUpdate) != + TCL_OK) { + snprintf(pBueffel, 255, + "ERROR: %s not an int, cannot set updateIntervall", value); + SCWrite(pCon, pBueffel, eError); return 0; } self->updateIntervall = newUpdate; SCSendOK(pCon); return 1; - } else if(strcmp(param,"onoff") == 0){ - if(Tcl_GetInt(InterpGetTcl(pServ->pSics),value,&newUpdate) != TCL_OK){ - snprintf(pBueffel,255, - "ERROR: %s not an int, cannot set onoff", value); - SCWrite(pCon,pBueffel,eError); + } else if (strcmp(param, "onoff") == 0) { + if (Tcl_GetInt(InterpGetTcl(pServ->pSics), value, &newUpdate) != + TCL_OK) { + snprintf(pBueffel, 255, "ERROR: %s not an int, cannot set onoff", + value); + SCWrite(pCon, pBueffel, eError); return 0; } - if(newUpdate >= 1){ + if (newUpdate >= 1) { self->onOff = 1; } else { self->onOff = 0; @@ -215,90 +228,94 @@ static int configureUpdate(SConnection *pCon, pNXupdate self, SCSendOK(pCon); return 1; } else { - snprintf(pBueffel,255,"ERROR: parameter %s not known", param); - SCWrite(pCon,pBueffel,eValue); + snprintf(pBueffel, 255, "ERROR: parameter %s not known", param); + SCWrite(pCon, pBueffel, eValue); return 0; } } + /*----------------------------------------------------------------------*/ -int UpdateAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]){ +int UpdateAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ pNXupdate self = NULL; char pBueffel[132]; - self = (pNXupdate)pData; + self = (pNXupdate) pData; assert(self); - if(argc < 2){ - snprintf(pBueffel,131,"ERROR: need argument to %s", argv[0]); - SCWrite(pCon,pBueffel,eError); + if (argc < 2) { + snprintf(pBueffel, 131, "ERROR: need argument to %s", argv[0]); + SCWrite(pCon, pBueffel, eError); return 0; } - - if(argc < 3){ + + if (argc < 3) { strtolower(argv[1]); - return printUpdateParameters(pCon,self,argv[0], argv[1]); + return printUpdateParameters(pCon, self, argv[0], argv[1]); } else { - Arg2Text(argc-2,&argv[2],pBueffel,131); - return configureUpdate(pCon,self,argv[1],pBueffel); + Arg2Text(argc - 2, &argv[2], pBueffel, 131); + return configureUpdate(pCon, self, argv[1], pBueffel); } /* - not reached - */ + not reached + */ assert(0); return 0; } + /*----------------------------------------------------------------------*/ -int UpdateFactory(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]){ +int UpdateFactory(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ pICountable pCount = NULL; pICallBack pCall = NULL; void *pPtr = NULL; char pBueffel[256]; pNXupdate self = NULL; CommandList *pCom = NULL; - commandContext comCon; - if(argc < 3){ - SCWrite(pCon,"ERROR: insuffcient number of argument to UpdateFactory", - eError); + if (argc < 3) { + SCWrite(pCon, "ERROR: insuffcient number of argument to UpdateFactory", + eError); return 0; } - + /* - argv[1] = name - argv[2] = counter with which to register for automatic notifications - */ - pCom = FindCommand(pSics,argv[2]); - if(pCom){ + argv[1] = name + argv[2] = counter with which to register for automatic notifications + */ + pCom = FindCommand(pSics, argv[2]); + if (pCom) { pPtr = pCom->pData; } - if(!pPtr){ - snprintf(pBueffel,255,"ERROR: cannot find %s to register to", argv[2]); - SCWrite(pCon,pBueffel,eError); + if (!pPtr) { + snprintf(pBueffel, 255, "ERROR: cannot find %s to register to", + argv[2]); + SCWrite(pCon, pBueffel, eError); return 0; } pCount = GetCountableInterface(pPtr); - pCall = GetCallbackInterface(pPtr); - if(!pCount || !pCall){ - snprintf(pBueffel,255,"ERROR: %s is not a usable counter",argv[2]); - SCWrite(pCon,pBueffel,eError); + pCall = GetCallbackInterface(pPtr); + if (!pCount || !pCall) { + snprintf(pBueffel, 255, "ERROR: %s is not a usable counter", argv[2]); + SCWrite(pCon, pBueffel, eError); return 0; } - + /* - allocate memory and initialize - */ - self = (pNXupdate)malloc(sizeof(NXupdate)); - if(self == NULL){ - SCWrite(pCon,"ERROR: out of memory in UpdateFactory",eError); + allocate memory and initialize + */ + self = (pNXupdate) malloc(sizeof(NXupdate)); + if (self == NULL) { + SCWrite(pCon, "ERROR: out of memory in UpdateFactory", eError); return 0; } - memset(self,0,sizeof(NXupdate)); + memset(self, 0, sizeof(NXupdate)); self->pDes = CreateDescriptor("AutoUpdate"); - if(self->pDes == NULL){ - SCWrite(pCon,"ERROR: out of memory in UpdateFactory",eError); + if (self->pDes == NULL) { + SCWrite(pCon, "ERROR: out of memory in UpdateFactory", eError); return 0; } self->startScript = strdup("UNDEFINED"); @@ -309,18 +326,11 @@ int UpdateFactory(SConnection *pCon, SicsInterp *pSics, void *pData, /* - register callbacks - */ - comCon.transID = 0; - strncpy(comCon.deviceID,"internal",SCDEVIDLEN); - RegisterCallback(pCall,comCon,COUNTSTART,CountCallback, - self,NULL); - RegisterCallback(pCall,comCon,COUNTEND,CountCallback, - self,NULL); + register callbacks + */ + RegisterCallback(pCall, COUNTSTART, CountCallback, self, NULL); + RegisterCallback(pCall, COUNTEND, CountCallback, self, NULL); - AddCommand(pSics,argv[1],UpdateAction,KillUpdate,self); + AddCommand(pSics, argv[1], UpdateAction, KillUpdate, self); return 1; } - - - diff --git a/nxupdate.h b/nxupdate.h index fc584d73..b1639df6 100644 --- a/nxupdate.h +++ b/nxupdate.h @@ -10,11 +10,10 @@ #ifndef NXUPDATE #define NXUPDATE - int UpdateAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - int UpdateFactory(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); +int UpdateAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); +int UpdateFactory(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); - void KillUpdate(void *pData); +void KillUpdate(void *pData); #endif - diff --git a/nxutil.c b/nxutil.c index 07c74429..dae5f19c 100644 --- a/nxutil.c +++ b/nxutil.c @@ -18,316 +18,275 @@ #include "nxdict.h" #include "nxutil.h" /*-----------------------------------------------------------------------*/ - int SNXSPutMotor(SicsInterp *pSics, SConnection *pCon, - NXhandle hFil, NXdict pDict, - char *pAlias, char *pName) - { - pMotor pMot = NULL; - float fVal; - char pBueffel[512]; - int iRet; - - /* Find the motor */ - strncpy(pBueffel,pName,511); - strtolower(pBueffel); - pMot = FindMotor(pSics,pBueffel); - if(!pMot) - { - sprintf(pBueffel,"WARNING: cannot find motor %s",pName); - SCWrite(pCon,pBueffel,eWarning); - return 0; - } - - /* get the position */ - iRet = MotorGetSoftPosition(pMot,pCon,&fVal); - if(!iRet) /* should have been reported */ - { - return 0; - } - - /* write it */ - return NXDputalias(hFil,pDict,pAlias,&fVal); - } +int SNXSPutMotor(SicsInterp * pSics, SConnection * pCon, + NXhandle hFil, NXdict pDict, char *pAlias, char *pName) +{ + pMotor pMot = NULL; + float fVal; + char pBueffel[512]; + int iRet; + + /* Find the motor */ + strlcpy(pBueffel, pName, 511); + strtolower(pBueffel); + pMot = FindMotor(pSics, pBueffel); + if (!pMot) { + snprintf(pBueffel,sizeof(pBueffel)-1, "WARNING: cannot find motor %s", pName); + SCWrite(pCon, pBueffel, eWarning); + return 0; + } + + /* get the position */ + iRet = MotorGetSoftPosition(pMot, pCon, &fVal); + if (!iRet) { /* should have been reported */ + return 0; + } + + /* write it */ + return NXDputalias(hFil, pDict, pAlias, &fVal); +} + /*-----------------------------------------------------------------------*/ - int SNXSPutMotorNull(SicsInterp *pSics, SConnection *pCon, - NXhandle hFil, NXdict pDict, - char *pAlias, char *pName) - { - pMotor pMot = NULL; - float fVal; - char pBueffel[512]; - int iRet; - - /* Find the motor */ - strncpy(pBueffel,pName,511); - strtolower(pBueffel); - pMot = FindMotor(pSics,pBueffel); - if(!pMot) - { - sprintf(pBueffel,"WARNING: cannot find motor %s",pName); - SCWrite(pCon,pBueffel,eWarning); - return 0; - } - - /* get the null point */ - iRet = MotorGetPar(pMot,"softzero",&fVal); - if(!iRet) /* should have been reported */ - { - sprintf(pBueffel, - "WARNING: failed to find zero point for motor %s", - pName); - SCWrite(pCon,pBueffel,eWarning); - return 0; - } - - /* write it */ - return NXDputalias(hFil,pDict,pAlias,&fVal); - } +int SNXSPutMotorNull(SicsInterp * pSics, SConnection * pCon, + NXhandle hFil, NXdict pDict, + char *pAlias, char *pName) +{ + pMotor pMot = NULL; + float fVal; + char pBueffel[512]; + int iRet; + + /* Find the motor */ + strlcpy(pBueffel, pName, 511); + strtolower(pBueffel); + pMot = FindMotor(pSics, pBueffel); + if (!pMot) { + snprintf(pBueffel,sizeof(pBueffel)-1, "WARNING: cannot find motor %s", pName); + SCWrite(pCon, pBueffel, eWarning); + return 0; + } + + /* get the null point */ + iRet = MotorGetPar(pMot, "softzero", &fVal); + if (!iRet) { /* should have been reported */ + snprintf(pBueffel,sizeof(pBueffel)-1, + "WARNING: failed to find zero point for motor %s", pName); + SCWrite(pCon, pBueffel, eWarning); + return 0; + } + + /* write it */ + return NXDputalias(hFil, pDict, pAlias, &fVal); +} + /*-------------------------------------------------------------------------*/ - int SNXSPutVariable(SicsInterp *pSics,SConnection *pCon, - NXhandle hFil, NXdict pDict, - char *pAlias, char *pName) - { - pSicsVariable pVar = NULL; - int iRet; - float fVal; - int iVal; - char pBueffel[512]; - VarType eType; - char *pText = NULL; - - /* find it */ - strncpy(pBueffel,pName,511); - strtolower(pBueffel); - pVar = FindVariable(pSics,pBueffel); - if(!pVar) - { - sprintf(pBueffel,"WARNING: cannot find variable %s",pName); - SCWrite(pCon,pBueffel,eWarning); - return 0; - } +int SNXSPutVariable(SicsInterp * pSics, SConnection * pCon, + NXhandle hFil, NXdict pDict, char *pAlias, char *pName) +{ + pSicsVariable pVar = NULL; + int iRet; + float fVal; + int iVal; + char pBueffel[512]; + VarType eType; + char *pText = NULL; + + /* find it */ + strlcpy(pBueffel, pName, 511); + strtolower(pBueffel); + pVar = FindVariable(pSics, pBueffel); + if (!pVar) { + snprintf(pBueffel,sizeof(pBueffel)-1, "WARNING: cannot find variable %s", pName); + SCWrite(pCon, pBueffel, eWarning); + return 0; + } + + /* write it, depending on type */ + eType = GetVarType(pVar); + switch (eType) { + case veText: + VarGetText(pVar, &pText); + if (pText != NULL) { + memset(pBueffel, 0, 511); + strlcpy(pBueffel, pText, 511); + iRet = NXDputalias(hFil, pDict, pAlias, pBueffel); + free(pText); + return iRet; + } + break; + case veInt: + VarGetInt(pVar, &iVal); + return NXDputalias(hFil, pDict, pAlias, &iVal); + break; + case veFloat: + VarGetFloat(pVar, &fVal); + return NXDputalias(hFil, pDict, pAlias, &fVal); + break; + default: + assert(0); /* should not happen */ + + } + return 1; +} - /* write it, depending on type */ - eType = GetVarType(pVar); - switch(eType) - { - case veText: - VarGetText(pVar,&pText); - if(pText != NULL) - { - memset(pBueffel,0,511); - strncpy(pBueffel,pText,511); - iRet = NXDputalias(hFil,pDict,pAlias,pBueffel); - free(pText); - return iRet; - } - break; - case veInt: - VarGetInt(pVar,&iVal); - return NXDputalias(hFil,pDict,pAlias,&iVal); - break; - case veFloat: - VarGetFloat(pVar,&fVal); - return NXDputalias(hFil,pDict,pAlias,&fVal); - break; - default: - assert(0); /* should not happen */ - - } - return 1; - } /*------------------------------------------------------------------------*/ - void SNXFormatTime(char *pBuffer, int iBufLen) - { - time_t iDate; - struct tm *psTime; +void SNXFormatTime(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); - } /*--------------------------------------------------------------------------*/ - int SNXSPutGlobals(NXhandle hfil,char *pFilename, - char *pInst, SConnection *pCon) - { - pSicsVariable pVar = NULL; - char pBueffel[1024]; - char *pUser,*pemail,*pPhone,*pFax, *pAddress; - int iRet; - - /* write global attributes */ - strcpy(pBueffel,"UNKNOWN"); - pVar = FindVariable(pServ->pSics,"user"); - if(pVar) - { - pUser = pVar->text; - } - else - { - SCWrite(pCon,"WARNING: Variable user not found ",eWarning); - pUser = pBueffel; - } - pVar = FindVariable(pServ->pSics,"phone"); - if(pVar) - { - pPhone = pVar->text; - } - else - { - SCWrite(pCon,"WARNING: Variable phone not found ",eWarning); - pPhone = pBueffel; - } - pVar = FindVariable(pServ->pSics,"email"); - if(pVar) - { - pemail = pVar->text; - } - else - { - SCWrite(pCon,"WARNING: Variable email not found ",eWarning); - pemail = pBueffel; - } - pVar = FindVariable(pServ->pSics,"adress"); - if(pVar) - { - pAddress = pVar->text; - } - else - { - SCWrite(pCon,"WARNING: Variable adress not found ",eWarning); - pAddress = pBueffel; - } - pVar = FindVariable(pServ->pSics,"fax"); - if(pVar) - { - pFax = pVar->text; - } - else - { - SCWrite(pCon,"WARNING: Variable phone not found ",eWarning); - pFax = pBueffel; - } - iRet = NXUwriteglobals(hfil, - pFilename, - pUser, - pAddress, - pPhone, - pemail, - pFax, - pInst); - if(iRet != NX_OK) - { - SCWrite(pCon,"WARNING: failed writing global attributes to file",eWarning); - } +int SNXSPutGlobals(NXhandle hfil, char *pFilename, + char *pInst, SConnection * pCon) +{ + pSicsVariable pVar = NULL; + char pBueffel[1024]; + char *pUser, *pemail, *pPhone, *pFax, *pAddress; + int iRet; + + /* write global attributes */ + strcpy(pBueffel, "UNKNOWN"); + pVar = FindVariable(pServ->pSics, "user"); + if (pVar) { + pUser = pVar->text; + } else { + SCWrite(pCon, "WARNING: Variable user not found ", eWarning); + pUser = pBueffel; + } + pVar = FindVariable(pServ->pSics, "phone"); + if (pVar) { + pPhone = pVar->text; + } else { + SCWrite(pCon, "WARNING: Variable phone not found ", eWarning); + pPhone = pBueffel; + } + pVar = FindVariable(pServ->pSics, "email"); + if (pVar) { + pemail = pVar->text; + } else { + SCWrite(pCon, "WARNING: Variable email not found ", eWarning); + pemail = pBueffel; + } + pVar = FindVariable(pServ->pSics, "adress"); + if (pVar) { + pAddress = pVar->text; + } else { + SCWrite(pCon, "WARNING: Variable adress not found ", eWarning); + pAddress = pBueffel; + } + pVar = FindVariable(pServ->pSics, "fax"); + if (pVar) { + pFax = pVar->text; + } else { + SCWrite(pCon, "WARNING: Variable phone not found ", eWarning); + pFax = pBueffel; + } + iRet = NXUwriteglobals(hfil, + pFilename, + pUser, pAddress, pPhone, pemail, pFax, pInst); + if (iRet != NX_OK) { + SCWrite(pCon, "WARNING: failed writing global attributes to file", + eWarning); + } + + return 1; +} - return 1; - } /*---------------------------------------------------------------------------*/ - int SNXSPutEVVar(NXhandle hfil, NXdict pDict, - char *pName, SConnection *pCon, - char *pValAlias, char *pStdDevAlias) - { - CommandList *pCom = NULL; - pIDrivable pDriv = NULL; - float fMean, fStdDev; - pVarLog pLog = NULL; - int iRet; - char pBueffel[512]; - pSicsVariable pVar = NULL; +int SNXSPutEVVar(NXhandle hfil, NXdict pDict, + char *pName, SConnection * pCon, + char *pValAlias, char *pStdDevAlias) +{ + CommandList *pCom = NULL; + pIDrivable pDriv = NULL; + float fMean, fStdDev; + pVarLog pLog = NULL; + int iRet; + char pBueffel[512]; + pSicsVariable pVar = NULL; + + pCom = NULL; + fMean = -111.; + fStdDev = -111.; + pCom = FindCommand(pServ->pSics, pName); + if (pCom) { + pDriv = GetDrivableInterface(pCom->pData); + if (pDriv) { /* it is a controller */ + pLog = EVCGetVarLog((pEVControl) pCom->pData); + iRet = VarlogGetMean(pLog, &fMean, &fStdDev); + if (!iRet) { /* the data was not logged, get the value */ + iRet = EVCGetPos((pEVControl) pCom->pData, pCon, &fMean); + } + } else { + /* it can still be a simple variable */ + pVar = (pSicsVariable) pCom->pData; + fMean = pVar->fVal; + } + } + + if (fMean < -110) { + snprintf(pBueffel,sizeof(pBueffel)-1, "WARNING: %s invalid", pName); + SCWrite(pCon, pBueffel, eWarning); + } + if (pStdDevAlias) { + if (fStdDev < -110) { + snprintf(pBueffel,sizeof(pBueffel)-1, "WARNING: %s standard deviation invalid", pName); + SCWrite(pCon, pBueffel, eWarning); + } + } + /* whatever it was, write it, even if it is shit */ + iRet = NXDputalias(hfil, pDict, pValAlias, &fMean); + if (iRet != NX_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "WARNING: failed to write %s", pName); + SCWrite(pCon, pBueffel, eWarning); + } + if (pStdDevAlias) { + iRet = NXDputalias(hfil, pDict, pStdDevAlias, &fStdDev); + if (iRet != NX_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "WARNING: failed to write %s standard deviation", + pName); + SCWrite(pCon, pBueffel, eWarning); + } + } + return 1; +} - pCom = NULL; - fMean = -111.; - fStdDev = -111.; - pCom = FindCommand(pServ->pSics,pName); - if(pCom) - { - pDriv = GetDrivableInterface(pCom->pData); - if(pDriv) /* it is a controller */ - { - pLog = EVCGetVarLog((pEVControl)pCom->pData); - iRet = VarlogGetMean(pLog,&fMean, &fStdDev); - if(!iRet) - { /* the data was not logged, get the value */ - iRet = EVCGetPos((pEVControl)pCom->pData,pCon,&fMean); - } - } - else - { - /* it can still be a simple variable */ - pVar = (pSicsVariable)pCom->pData; - fMean = pVar->fVal; - } - } - - if(fMean < -110) - { - sprintf(pBueffel,"WARNING: %s invalid",pName); - SCWrite(pCon,pBueffel,eWarning); - } - if(pStdDevAlias) - { - if(fStdDev < -110) - { - sprintf(pBueffel,"WARNING: %s standard deviation invalid",pName); - SCWrite(pCon,pBueffel,eWarning); - } - } - /* whatever it was, write it, even if it is shit */ - iRet = NXDputalias(hfil,pDict,pValAlias,&fMean); - if(iRet != NX_OK) - { - sprintf(pBueffel,"WARNING: failed to write %s",pName); - SCWrite(pCon,pBueffel,eWarning); - } - if(pStdDevAlias) - { - iRet = NXDputalias(hfil,pDict,pStdDevAlias,&fStdDev); - if(iRet != NX_OK) - { - sprintf(pBueffel,"WARNING: failed to write %s standard deviation",pName); - SCWrite(pCon,pBueffel,eWarning); - } - } - return 1; - } /*---------------------------------------------------------------------------*/ - int SNXSPutDrivable(SicsInterp *pSics, SConnection *pCon, - NXhandle hfil, NXdict pDict, - char *pName, - char *pAlias) - { - CommandList *pCom = NULL; - pIDrivable pDriv = NULL; - float fVal =- -777.77; - int iRet; - char pBueffel[512]; +int SNXSPutDrivable(SicsInterp * pSics, SConnection * pCon, + NXhandle hfil, NXdict pDict, char *pName, char *pAlias) +{ + CommandList *pCom = NULL; + pIDrivable pDriv = NULL; + float fVal = -777.77; + int iRet; + char pBueffel[512]; - pCom = NULL; - pCom = FindCommand(pSics,pName); - if(pCom) - { - pDriv = GetDrivableInterface(pCom->pData); - if(pDriv) /* it is drivable */ - { - fVal = pDriv->GetValue(pCom->pData,pCon); - } - else - { - sprintf(pBueffel,"ERROR: %s is not driveable, not written",pName); - SCWrite(pCon,pBueffel,eError); - return 0; - } - } - - /* whatever it was, write it, even if it is shit */ - iRet = NXDputalias(hfil,pDict,pAlias,&fVal); - if(iRet != NX_OK) - { - sprintf(pBueffel,"WARNING: failed to write %s",pName); - SCWrite(pCon,pBueffel,eWarning); - return 0; - } - return 1; - } + pCom = NULL; + pCom = FindCommand(pSics, pName); + if (pCom) { + pDriv = GetDrivableInterface(pCom->pData); + if (pDriv) { /* it is drivable */ + fVal = pDriv->GetValue(pCom->pData, pCon); + } else { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s is not driveable, not written", pName); + SCWrite(pCon, pBueffel, eError); + return 0; + } + } + + /* whatever it was, write it, even if it is shit */ + iRet = NXDputalias(hfil, pDict, pAlias, &fVal); + if (iRet != NX_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "WARNING: failed to write %s", pName); + SCWrite(pCon, pBueffel, eWarning); + return 0; + } + return 1; +} diff --git a/nxutil.h b/nxutil.h index 87cab7f5..0c665d32 100644 --- a/nxutil.h +++ b/nxutil.h @@ -9,26 +9,26 @@ ---------------------------------------------------------------------------*/ #ifndef NXUTIL #define NXUTIL - int SNXSPutMotor(SicsInterp *pSics, SConnection *pCon, NXhandle hFil, - NXdict pDict, char *pAlias, char *pName); - int SNXSPutMotorNull(SicsInterp *pSics, SConnection *pCon, NXhandle hFil, - NXdict pDict, char *pAlias, char *pName); - int SNXSPutVariable(SicsInterp *pSics, SConnection *pCon, - NXhandle hFil, NXdict pDict, char *pAlias, - char *pName); - int SNXSPutEVVar(NXhandle hfil, NXdict pDict, - char *pName, SConnection *pCon, - char *pValAlias, char *pStdDevAlias); - int SNXSPutGlobals(NXhandle hfil, char *pFile, char *pInst, - SConnection *pCon); - void SNXFormatTime(char *pBuffer, int iLen); - - char *SNXMakeFileName(SicsInterp *pSics, SConnection *pCon); - /* - coded in nxdata.c - */ - int SNXSPutDrivable(SicsInterp *pSics, SConnection *pCon, NXhandle hFil, - NXdict pDict, char *pAlias, char *pName); +int SNXSPutMotor(SicsInterp * pSics, SConnection * pCon, NXhandle hFil, + NXdict pDict, char *pAlias, char *pName); +int SNXSPutMotorNull(SicsInterp * pSics, SConnection * pCon, NXhandle hFil, + NXdict pDict, char *pAlias, char *pName); +int SNXSPutVariable(SicsInterp * pSics, SConnection * pCon, + NXhandle hFil, NXdict pDict, char *pAlias, + char *pName); +int SNXSPutEVVar(NXhandle hfil, NXdict pDict, + char *pName, SConnection * pCon, + char *pValAlias, char *pStdDevAlias); +int SNXSPutGlobals(NXhandle hfil, char *pFile, char *pInst, + SConnection * pCon); +void SNXFormatTime(char *pBuffer, int iLen); - -#endif +char *SNXMakeFileName(SicsInterp * pSics, SConnection * pCon); + /* + coded in nxdata.c + */ +int SNXSPutDrivable(SicsInterp * pSics, SConnection * pCon, NXhandle hFil, + NXdict pDict, char *pAlias, char *pName); + + +#endif diff --git a/nxxml.c b/nxxml.c index e1ab96aa..12f4de16 100644 --- a/nxxml.c +++ b/nxxml.c @@ -20,17 +20,25 @@ * * For further information, see */ + + +#ifdef NXXML + #include -#include #include +#include #include +#include #include #include "nxio.h" #include "nxdataset.h" +#ifdef _MSC_VER +#define snprintf _snprintf +#endif /* _MSC_VER */ extern void *NXpData; - +extern int validNXName(const char* name, int allow_colon); /* from napi.c */ char *nxitrim(char *str); /* from napi.c */ /*----------------------- our data structures -------------------------- @@ -49,11 +57,33 @@ typedef struct { mxml_node_t *current; mxml_node_t *currentChild; int currentAttribute; + int options; /**< additional information about the node */ }xmlStack; + +/* + * Freddie Akeroyd, 19/03/2008 + * + * Add in support for table style data writing - this is + * indicated internally via the XMLSTACK_OPTION_TABLE flag + * and separates the dimensions and data into separate nodes contained + * in DIMS_NODE_NAME and DATA_NODE_NAME. This is a first commit and + * involves some code duplication that will need to be cleaned up later. + * Also writing in table style is only enabled for 1D arrays as + * I haven't done slab writing yet which the nexus test program uses + * for writing 2D arrays. + * + * Table output is enabled by opening a file with (NXACC_CREATEXML | NXACC_TABLE) + * + * See http://trac.nexusformat.org/code/ticket/111 for further details + */ +#define XMLSTACK_OPTION_TABLE 0x1 /**< indicates table option in xmlStack */ + + /*---------------------------------------------------------------------*/ typedef struct { mxml_node_t *root; /* root node */ int readOnly; /* read only flag */ + int tableStyle; /**< whether to output data in XML table style */ int stackPointer; /* stack pointer */ char filename[1024]; /* file name, for NXflush, NXclose */ xmlStack stack[NXMAXSTACK]; /* stack */ @@ -80,7 +110,7 @@ static mxml_node_t *getLinkTarget(pXMLNexus xmlHandle, const char *target){ testNode = mxmlFindElement(node,node,path,NULL,NULL,MXML_DESCEND_FIRST); } if(testNode == NULL){ - NXIReportError(NXpData,"Cannot follow broken link"); + NXReportError("Cannot follow broken link"); return NULL; } else { node = testNode; @@ -90,7 +120,7 @@ static mxml_node_t *getLinkTarget(pXMLNexus xmlHandle, const char *target){ } /*==================== file functions ===================================*/ static void errorCallbackForMxml(const char *txt){ - NXIReportError(NXpData,(char *)txt); + NXReportError((char *)txt); } /*-----------------------------------------------------------------------*/ NXstatus NXXopen(CONSTCHAR *filename, NXaccess am, @@ -105,7 +135,7 @@ NXstatus NXXopen(CONSTCHAR *filename, NXaccess am, */ xmlHandle = (pXMLNexus)malloc(sizeof(XMLNexus)); if(!xmlHandle){ - NXIReportError(NXpData, "Out of memory allocating XML file handle"); + NXReportError( "Out of memory allocating XML file handle"); return NX_ERROR; } memset(xmlHandle,0,sizeof(XMLNexus)); @@ -117,18 +147,19 @@ NXstatus NXXopen(CONSTCHAR *filename, NXaccess am, initializeNumberFormats(); mxmlSetErrorCallback(errorCallbackForMxml); + xmlHandle->tableStyle = ((am & NXACC_TABLE) ? 1 : 0); /* open file */ strncpy(xmlHandle->filename,filename,1023); - switch(am){ + switch(am & NXACCMASK_REMOVEFLAGS){ case NXACC_READ: xmlHandle->readOnly = 1; case NXACC_RDWR: fp = fopen(filename,"r"); if(fp == NULL){ - NXIReportError(NXpData,"Failed to open file:"); - NXIReportError(NXpData,(char *)filename); + NXReportError("Failed to open file:"); + NXReportError((char *)filename); free(xmlHandle); return NX_ERROR; } @@ -140,6 +171,7 @@ NXstatus NXXopen(CONSTCHAR *filename, NXaccess am, MXML_DESCEND); xmlHandle->stack[0].currentChild = NULL; xmlHandle->stack[0].currentAttribute = 0; + xmlHandle->stack[0].options = 0; fclose(fp); break; case NXACC_CREATEXML: @@ -149,6 +181,10 @@ NXstatus NXXopen(CONSTCHAR *filename, NXaccess am, mxmlElementSetAttr(current,"NeXus_version",NEXUS_VERSION); mxmlElementSetAttr(current,"XML_version","mxml"); mxmlElementSetAttr(current,"file_name",filename); + mxmlElementSetAttr(current,"xmlns", NEXUS_SCHEMA_NAMESPACE); + mxmlElementSetAttr(current,"xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance"); + mxmlElementSetAttr(current,"xsi:schemaLocation", + NEXUS_SCHEMA_NAMESPACE " " NEXUS_SCHEMA_URL); time_buffer = NXIformatNeXusTime(); if(time_buffer != NULL){ mxmlElementSetAttr(current,"file_time",time_buffer); @@ -157,13 +193,14 @@ NXstatus NXXopen(CONSTCHAR *filename, NXaccess am, xmlHandle->stack[0].current = current; xmlHandle->stack[0].currentChild = NULL; xmlHandle->stack[0].currentAttribute = 0; + xmlHandle->stack[0].options = 0; break; default: - NXIReportError(NXpData,"Bad access parameter specified in NXXopen"); + NXReportError("Bad access parameter specified in NXXopen"); return NX_ERROR; } if(xmlHandle->stack[0].current == NULL){ - NXIReportError(NXpData, + NXReportError( "No NXroot element in XML-file, no NeXus-XML file"); return NX_ERROR; } @@ -182,7 +219,7 @@ NXstatus NXXclose (NXhandle* fid){ if(xmlHandle->readOnly == 0) { fp = fopen(xmlHandle->filename,"w"); if(fp == NULL){ - NXIReportError(NXpData,"Failed to open NeXus XML file for writing"); + NXReportError("Failed to open NeXus XML file for writing"); return NX_ERROR; } mxmlSaveFile(xmlHandle->root,fp,NXwhitespaceCallback); @@ -204,7 +241,7 @@ NXstatus NXXflush(NXhandle *fid){ if(xmlHandle->readOnly == 0) { fp = fopen(xmlHandle->filename,"w"); if(fp == NULL){ - NXIReportError(NXpData,"Failed to open NeXus XML file for writing"); + NXReportError("Failed to open NeXus XML file for writing"); return NX_ERROR; } mxmlSaveFile(xmlHandle->root,fp,NXwhitespaceCallback); @@ -217,21 +254,29 @@ NXstatus NXXflush(NXhandle *fid){ =========================================================================*/ NXstatus NXXmakegroup (NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass){ + char buffer[256]; pXMLNexus xmlHandle = NULL; mxml_node_t *newGroup = NULL; xmlHandle = (pXMLNexus)fid; assert(xmlHandle); + if (!validNXName(name, 0)) + { + sprintf(buffer, "ERROR: invalid characters in group name \"%s\"", name); + NXReportError(buffer); + return NX_ERROR; + } + if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ - NXIReportError(NXpData,"Close dataset before trying to create a group"); + NXReportError("Close dataset before trying to create a group"); return NX_ERROR; } newGroup = mxmlNewElement(xmlHandle->stack[xmlHandle->stackPointer].current, nxclass); if(!newGroup){ - NXIReportError(NXpData,"failed to allocate new group"); + NXReportError("failed to allocate new group"); return NX_ERROR; } mxmlElementSetAttr(newGroup,"name",name); @@ -284,7 +329,7 @@ NXstatus NXXopengroup (NXhandle fid, CONSTCHAR *name, assert(xmlHandle); if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ - NXIReportError(NXpData,"Close dataset before trying to open a group"); + NXReportError("Close dataset before trying to open a group"); return NX_ERROR; } newGroup = mxmlFindElement(xmlHandle->stack[xmlHandle->stackPointer].current, @@ -298,20 +343,19 @@ NXstatus NXXopengroup (NXhandle fid, CONSTCHAR *name, } if(!newGroup){ snprintf(error,1023,"Failed to open %s, %s",name,nxclass); - NXIReportError(NXpData,error); + NXReportError(error); return NX_ERROR; } xmlHandle->stackPointer++; xmlHandle->stack[xmlHandle->stackPointer].current = newGroup; xmlHandle->stack[xmlHandle->stackPointer].currentChild = NULL; xmlHandle->stack[xmlHandle->stackPointer].currentAttribute = 0; + xmlHandle->stack[xmlHandle->stackPointer].options = 0; return NX_OK; } /*----------------------------------------------------------------------*/ NXstatus NXXclosegroup (NXhandle fid){ pXMLNexus xmlHandle = NULL; - mxml_node_t *newGroup = NULL; - char error[1024]; xmlHandle = (pXMLNexus)fid; assert(xmlHandle); @@ -330,18 +374,18 @@ NXstatus NXXclosegroup (NXhandle fid){ /*========================================================================= dataset functions =========================================================================*/ -NXstatus NXXcompmakedata (NXhandle fid, CONSTCHAR *name, +NXstatus NXXcompmakedata64 (NXhandle fid, CONSTCHAR *name, int datatype, int rank, - int dimensions[], - int compress_type, int chunk_size[]){ + int64_t dimensions[], + int compress_type, int64_t chunk_size[]){ /* compression does not relly make sense with XML */ - return NXXmakedata(fid,name,datatype,rank,dimensions); + return NXXmakedata64(fid,name,datatype,rank,dimensions); } /*-----------------------------------------------------------------------*/ -static char *buildTypeString(int datatype, int rank, int dimensions[]){ +static char *buildTypeString(int datatype, int rank, int64_t dimensions[]){ char *typestring = NULL; char pNumber[20]; int i; @@ -351,39 +395,132 @@ static char *buildTypeString(int datatype, int rank, int dimensions[]){ */ typestring = (char *)malloc(132*sizeof(char)); if(!typestring){ - NXIReportError(NXpData,"Failed to allocate typestring"); + NXReportError("Failed to allocate typestring"); return NULL; } memset(typestring,0,132*sizeof(char)); getNumberText(datatype,typestring,130); - if(rank > 1 || dimensions[0] > 1) { + if(rank > 1 || datatype == NX_CHAR || dimensions[0] > 1) { strcat(typestring,"["); - snprintf(pNumber,19,"%d",dimensions[0]); + snprintf(pNumber,19,"%lld", (long long)dimensions[0]); strncat(typestring,pNumber,130-strlen(typestring)); for(i = 1; i < rank; i++){ - snprintf(pNumber,19,",%d",dimensions[i]); + snprintf(pNumber,19,",%lld", (long long)dimensions[i]); strncat(typestring,pNumber,130-strlen(typestring)); } strcat(typestring,"]"); } return typestring; } + /*------------------------------------------------------------------------*/ -NXstatus NXXmakedata (NXhandle fid, +NXstatus NXXmakedatatable64 (NXhandle fid, CONSTCHAR *name, int datatype, - int rank, int dimensions[]){ + int rank, int64_t dimensions[]){ + pXMLNexus xmlHandle = NULL; + mxml_node_t *dataNode = NULL, *dataNodeRoot = NULL, *dimsNode = NULL, *dimsNodeRoot = NULL; + mxml_node_t *newData = NULL; + mxml_node_t *current; + char *typestring; + int i, ndata; + char buffer[256]; + static int64_t one = 1; + + xmlHandle = (pXMLNexus)fid; + assert(xmlHandle); + if (!validNXName(name, 0)) + { + sprintf(buffer, "ERROR: invalid characters in dataset name \"%s\"", name); + NXReportError(buffer); + return NX_ERROR; + } + + if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ + NXReportError("Close dataset before trying to create a dataset"); + return NX_ERROR; + } + if(dimensions[0] < 0){ + dimensions[0] = 1; + } + + current = xmlHandle->stack[xmlHandle->stackPointer].current; + + dimsNodeRoot = mxmlFindElement(current, current, DIMS_NODE_NAME, NULL, NULL, MXML_DESCEND_FIRST); + if (dimsNodeRoot == NULL) + { + dimsNodeRoot = mxmlNewElement(current, DIMS_NODE_NAME); + } + dimsNode = mxmlNewElement(dimsNodeRoot, name); + mxmlNewOpaque(dimsNode, ""); + typestring = buildTypeString(datatype,rank,dimensions); + if(typestring != NULL){ + mxmlElementSetAttr(dimsNode,TYPENAME,typestring); + free(typestring); + } else { + NXReportError("Failed to allocate typestring"); + return NX_ERROR; + } + ndata = 1; + for(i=0; itype = MXML_CUSTOM; +/* newData->value.custom.data = createNXDataset(rank,datatype,dimensions); */ + newData->value.custom.data = createNXDataset(1,datatype,&one); + if(!newData->value.custom.data){ + NXReportError("Failed to allocate space for dataset"); + return NX_ERROR; + } + newData->value.custom.destroy = destroyDataset; + } + return NX_OK; +} + +NXstatus NXXmakedata64 (NXhandle fid, + CONSTCHAR *name, int datatype, + int rank, int64_t dimensions[]){ pXMLNexus xmlHandle = NULL; mxml_node_t *dataNode = NULL; mxml_node_t *newData = NULL; mxml_node_t *current; char *typestring; + char buffer[256]; + xmlHandle = (pXMLNexus)fid; assert(xmlHandle); + if (!validNXName(name, 0)) + { + sprintf(buffer, "ERROR: invalid characters in dataset name \"%s\"", name); + NXReportError(buffer); + return NX_ERROR; + } + + if (xmlHandle->tableStyle && datatype != NX_CHAR && dimensions[0] != NX_UNLIMITED && rank == 1) + { + return NXXmakedatatable64(fid,name,datatype,rank,dimensions); + } if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ - NXIReportError(NXpData,"Close dataset before trying to create a dataset"); + NXReportError("Close dataset before trying to create a dataset"); return NX_ERROR; } if(dimensions[0] < 0){ @@ -397,7 +534,7 @@ NXstatus NXXmakedata (NXhandle fid, mxmlElementSetAttr(dataNode,TYPENAME,typestring); free(typestring); } else { - NXIReportError(NXpData,"Failed to allocate typestring"); + NXReportError("Failed to allocate typestring"); return NX_ERROR; } /* @@ -409,7 +546,7 @@ NXstatus NXXmakedata (NXhandle fid, } else { newData = (mxml_node_t *)malloc(sizeof(mxml_node_t)); if(!newData){ - NXIReportError(NXpData,"Failed to allocate space for dataset"); + NXReportError("Failed to allocate space for dataset"); return NX_ERROR; } memset(newData,0,sizeof(mxml_node_t)); @@ -417,7 +554,7 @@ NXstatus NXXmakedata (NXhandle fid, newData->type = MXML_CUSTOM; newData->value.custom.data = createNXDataset(rank,datatype,dimensions); if(!newData->value.custom.data){ - NXIReportError(NXpData,"Failed to allocate space for dataset"); + NXReportError("Failed to allocate space for dataset"); return NX_ERROR; } newData->value.custom.destroy = destroyDataset; @@ -456,14 +593,91 @@ static mxml_node_t *searchSDSLinks(pXMLNexus xmlHandle, CONSTCHAR *name){ return NULL; } /*-----------------------------------------------------------------------*/ -NXstatus NXXopendata (NXhandle fid, CONSTCHAR *name){ +NXstatus NXXopendatatable (NXhandle fid, CONSTCHAR *name){ pXMLNexus xmlHandle = NULL; - mxml_node_t *dataNode = NULL; + mxml_node_t *dataNode = NULL, *dimsNode = NULL; char error[1024]; xmlHandle = (pXMLNexus)fid; assert(xmlHandle); + + if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ + /* + silently fix this + */ + xmlHandle->stackPointer--; + if(xmlHandle->stackPointer < 0){ + xmlHandle->stackPointer = 0; + } + } + + dimsNode = mxmlFindElement(xmlHandle->stack[xmlHandle->stackPointer].current, + xmlHandle->stack[xmlHandle->stackPointer].current, + DIMS_NODE_NAME, + NULL, + NULL, + MXML_DESCEND_FIRST); + + if(!dimsNode){ + snprintf(error,1023,"Failed to open dataset %s",name); + NXReportError(error); + return NX_ERROR; + } + + dataNode = mxmlFindElement(dimsNode, + dimsNode, + name, + NULL, + NULL, + MXML_DESCEND_FIRST); + if(dataNode == NULL){ + dataNode = searchSDSLinks(xmlHandle,name); + } + if(!dataNode){ + snprintf(error,1023,"Failed to open dataset %s",name); + NXReportError(error); + return NX_ERROR; + } + xmlHandle->stackPointer++; + xmlHandle->stack[xmlHandle->stackPointer].current = dataNode; + xmlHandle->stack[xmlHandle->stackPointer].currentChild = NULL; + xmlHandle->stack[xmlHandle->stackPointer].currentAttribute = 0; + xmlHandle->stack[xmlHandle->stackPointer].options = XMLSTACK_OPTION_TABLE; + return NX_OK; +} + + +NXstatus NXXopendata (NXhandle fid, CONSTCHAR *name){ + pXMLNexus xmlHandle = NULL; + mxml_node_t *dataNode = NULL, *current = NULL; + char error[1024]; + + xmlHandle = (pXMLNexus)fid; + assert(xmlHandle); + + /* is this a table style node ? */ + current = xmlHandle->stack[xmlHandle->stackPointer].current; + dataNode = mxmlFindElement(current, + current, + DATA_NODE_NAME, + NULL, + NULL, + MXML_DESCEND_FIRST); + if (dataNode != NULL) + { + dataNode = mxmlFindElement(dataNode, + dataNode, + name, + NULL, + NULL, + MXML_DESCEND_FIRST); + } + if (dataNode != NULL) + { + return NXXopendatatable(fid, name); + } + if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ /* silently fix this @@ -485,16 +699,18 @@ NXstatus NXXopendata (NXhandle fid, CONSTCHAR *name){ } if(!dataNode){ snprintf(error,1023,"Failed to open dataset %s",name); - NXIReportError(NXpData,error); + NXReportError(error); return NX_ERROR; } xmlHandle->stackPointer++; xmlHandle->stack[xmlHandle->stackPointer].current = dataNode; xmlHandle->stack[xmlHandle->stackPointer].currentChild = NULL; xmlHandle->stack[xmlHandle->stackPointer].currentAttribute = 0; + xmlHandle->stack[xmlHandle->stackPointer].options = 0; return NX_OK; } /*----------------------------------------------------------------------*/ + NXstatus NXXclosedata (NXhandle fid){ pXMLNexus xmlHandle = NULL; @@ -520,20 +736,68 @@ static mxml_node_t *findData(mxml_node_t *node){ } return NULL; } + +/* we only havv to deal with non-character data here */ +NXstatus NXXputdatatable (NXhandle fid, const void *data){ + pXMLNexus xmlHandle = NULL; + mxml_node_t *userData = NULL; + mxml_node_t *current = NULL; + mxml_node_t *nodeRoot = NULL; + mxml_node_t *dataNodeRoot = NULL; + mxml_node_t *dataNode = NULL; + const char* name; + pNXDS dataset; + int i, offset, length; + xmlHandle = (pXMLNexus)fid; + assert(xmlHandle); + /* current points at the Idims node as done in NXXopendatatable */ + current = xmlHandle->stack[xmlHandle->stackPointer].current; + name = current->value.element.name; + /* we want to walk all Idata nodes and set name */ + nodeRoot = current->parent->parent; + dataNodeRoot = nodeRoot; + offset = 0; + for(i=0; dataNodeRoot != NULL; i++) + { + dataNodeRoot = mxmlFindElement(dataNodeRoot, nodeRoot, DATA_NODE_NAME, NULL, NULL, (i == 0 ? MXML_DESCEND_FIRST : MXML_NO_DESCEND) ); + if (dataNodeRoot != NULL) + { + dataNode = mxmlFindElement(dataNodeRoot,dataNodeRoot,name,NULL,NULL,MXML_DESCEND_FIRST); + if (dataNode != NULL) + { + userData = findData(dataNode); + assert(userData != NULL); + dataset = (pNXDS)userData->value.custom.data; + assert(dataset); + length = getNXDatasetByteLength(dataset); + memcpy(dataset->u.ptr,(char*)data + offset,length); + offset += length; + } + } + } + return NX_OK; +} + /*------------------------------------------------------------------------*/ NXstatus NXXputdata (NXhandle fid, void *data){ pXMLNexus xmlHandle = NULL; mxml_node_t *userData = NULL; mxml_node_t *current = NULL; pNXDS dataset; - int i, length, type, rank, dim[NX_MAXRANK]; + int i, length, type, rank; + int64_t dim[NX_MAXRANK]; char *pPtr = NULL; xmlHandle = (pXMLNexus)fid; assert(xmlHandle); + if (xmlHandle->stack[xmlHandle->stackPointer].options & XMLSTACK_OPTION_TABLE) + { + return NXXputdatatable(fid,data); + } + if(!isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ - NXIReportError(NXpData,"No dataset open"); + NXReportError("No dataset open"); return NX_ERROR; } @@ -545,23 +809,31 @@ NXstatus NXXputdata (NXhandle fid, void *data){ Text data. We have to make sure that the text is \0 terminated. Some language bindings do not ensure that this is the case. */ - if(NXXgetinfo(fid,&rank, dim, &type) == NX_OK){ + if(NXXgetinfo64(fid,&rank, dim, &type) == NX_OK){ length = 1; for(i=0; istack[xmlHandle->stackPointer].current; + name = current->value.element.name; + /* we want to walk all Idata nodes and set name */ + nodeRoot = current->parent->parent; + dataNodeRoot = nodeRoot; + offset = 0; + for(i=0; dataNodeRoot != NULL; i++) + { + dataNodeRoot = mxmlFindElement(dataNodeRoot, nodeRoot, DATA_NODE_NAME, NULL, NULL, (i == 0 ? MXML_DESCEND_FIRST : MXML_NO_DESCEND) ); + if (dataNodeRoot != NULL) + { + dataNode = mxmlFindElement(dataNodeRoot,dataNodeRoot,name,NULL,NULL,MXML_DESCEND_FIRST); + if (dataNode != NULL) + { + userData = findData(dataNode); + assert(userData != NULL); + dataset = (pNXDS)userData->value.custom.data; + assert(dataset); + length = getNXDatasetByteLength(dataset); + memcpy((char*)data + offset, dataset->u.ptr, length); + offset += length; + } + } + } + return NX_OK; +} + + /*------------------------------------------------------------------------*/ NXstatus NXXgetdata (NXhandle fid, void *data){ pXMLNexus xmlHandle = NULL; mxml_node_t *userData = NULL; mxml_node_t *current = NULL; pNXDS dataset; - int i, length, type, rank, dim[NX_MAXRANK]; + int i, length, type, rank; + int64_t dim[NX_MAXRANK]; xmlHandle = (pXMLNexus)fid; assert(xmlHandle); + if (xmlHandle->stack[xmlHandle->stackPointer].options & XMLSTACK_OPTION_TABLE) + { + return NXXgetdatatable(fid,data); + } + if(!isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ - NXIReportError(NXpData,"No dataset open"); + NXReportError("No dataset open"); return NX_ERROR; } @@ -595,7 +916,7 @@ NXstatus NXXgetdata (NXhandle fid, void *data){ /* text data */ - if(NXXgetinfo(fid,&rank, dim, &type) == NX_OK){ + if(NXXgetinfo64(fid,&rank, dim, &type) == NX_OK){ length = 1; for(i=0; istack[xmlHandle->stackPointer].current)){ - NXIReportError(NXpData,"No dataset open"); + NXReportError("No dataset open"); return NX_ERROR; } @@ -645,8 +966,13 @@ NXstatus NXXgetinfo (NXhandle fid, int *rank, *iType = NX_CHAR; dimension[0]= strlen(userData->value.opaque); } else { + *iType = translateTypeCode(attr); analyzeDim(attr,rank,dimension,iType); - *iType = NX_CHAR; + if (dimension[0] == -1) /* 1D strings are NX_CHAR not NX_CHAR[] so length will not be correct */ + { + dimension[0] = strlen(userData->value.opaque); + } + } } else { dataset = (pNXDS)userData->value.custom.data; @@ -664,7 +990,7 @@ NXstatus NXXgetinfo (NXhandle fid, int *rank, clone the dataset and set the data pointer. This in order to use the addressing and type conversion implemented in nxdataset ---------------------------------------------------------------------*/ -static pNXDS makeSlabData(pNXDS dataset, void *data, int size[]){ +static pNXDS makeSlabData(pNXDS dataset, const void *data, const int64_t size[]){ pNXDS slabData = NULL; int rank, i; @@ -675,12 +1001,12 @@ static pNXDS makeSlabData(pNXDS dataset, void *data, int size[]){ rank = getNXDatasetRank(dataset); slabData->rank = rank; - slabData->dim = (int *)malloc(rank*sizeof(int)); + slabData->dim = (int64_t *)malloc(rank*sizeof(int64_t)); for(i = 0; i < rank; i++){ slabData->dim[i] = size[i]; } slabData->type = getNXDatasetType(dataset); - slabData->u.ptr = data; + slabData->u.ptr = (void*)data; slabData->magic = dataset->magic; return slabData; } @@ -688,9 +1014,9 @@ static pNXDS makeSlabData(pNXDS dataset, void *data, int size[]){ This goes by recursion ----------------------------------------------------------------------*/ static void putSlabData(pNXDS dataset, pNXDS slabData, int dim, - int start[], - int sourcePos[],int targetPos[]){ - int i, rank, length; + const int64_t start[], + int64_t sourcePos[], int64_t targetPos[]){ + int64_t i, rank, length; rank = getNXDatasetRank(slabData); length = getNXDatasetDim(slabData,dim); @@ -714,8 +1040,8 @@ static void putSlabData(pNXDS dataset, pNXDS slabData, int dim, This is in order to support unlimited dimensions along the first axis -----------------------------------------------------------------------*/ static int checkAndExtendDataset(mxml_node_t *node, pNXDS dataset, - int start[], int size[]){ - int dim0, byteLength; + const int64_t start[], const int64_t size[]){ + int64_t dim0, byteLength; void *oldData = NULL; char *typestring = NULL; @@ -736,27 +1062,38 @@ static int checkAndExtendDataset(mxml_node_t *node, pNXDS dataset, mxmlElementSetAttr(node,TYPENAME,typestring); free(typestring); } else { - NXIReportError(NXpData,"Failed to allocate typestring"); + NXReportError("Failed to allocate typestring"); return 0; } } return 1; } + +NXstatus NXXputslabtable (NXhandle fid, const void *data, + const int64_t iStart[], const int64_t iSize[]){ + return NX_OK; +} /*----------------------------------------------------------------------*/ -NXstatus NXXputslab (NXhandle fid, void *data, - int iStart[], int iSize[]){ +NXstatus NXXputslab64 (NXhandle fid, void *data, + int64_t iStart[], int64_t iSize[]){ pXMLNexus xmlHandle = NULL; mxml_node_t *userData = NULL; mxml_node_t *current = NULL; pNXDS dataset, slabData; - int sourcePos[NX_MAXRANK], targetPos[NX_MAXRANK], status; + int64_t sourcePos[NX_MAXRANK], targetPos[NX_MAXRANK]; + int status; xmlHandle = (pXMLNexus)fid; assert(xmlHandle); + if (xmlHandle->stack[xmlHandle->stackPointer].options & XMLSTACK_OPTION_TABLE) + { + return NXXputslabtable(fid,data,iStart,iSize); + } + if(!isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ - NXIReportError(NXpData,"No dataset open"); + NXReportError("No dataset open"); return NX_ERROR; } @@ -764,7 +1101,7 @@ NXstatus NXXputslab (NXhandle fid, void *data, userData = findData(current); assert(userData != NULL); if(userData->type == MXML_OPAQUE){ - NXIReportError(NXpData,"This API does not support slabs on text data"); + NXReportError("This API does not support slabs on text data"); return NX_ERROR; } dataset = (pNXDS)userData->value.custom.data; @@ -772,13 +1109,13 @@ NXstatus NXXputslab (NXhandle fid, void *data, status = checkAndExtendDataset(current,dataset,iStart,iSize); if(status == 0){ - NXIReportError(NXpData,"Out of memory extending dataset"); + NXReportError("Out of memory extending dataset"); return NX_ERROR; } slabData = makeSlabData(dataset, data, iSize); if(slabData == NULL){ - NXIReportError(NXpData,"Failed to allocate slab data"); + NXReportError("Failed to allocate slab data"); return NX_ERROR; } @@ -793,9 +1130,9 @@ NXstatus NXXputslab (NXhandle fid, void *data, This goes by recursion ----------------------------------------------------------------------*/ static void getSlabData(pNXDS dataset, pNXDS slabData, int dim, - int start[], - int sourcePos[],int targetPos[]){ - int i, rank, length; + const int64_t start[], + int64_t sourcePos[],int64_t targetPos[]){ + int64_t i, rank, length; rank = getNXDatasetRank(slabData); length = getNXDatasetDim(slabData,dim); @@ -816,19 +1153,19 @@ static void getSlabData(pNXDS dataset, pNXDS slabData, int dim, } } /*----------------------------------------------------------------------*/ -NXstatus NXXgetslab (NXhandle fid, void *data, - int iStart[], int iSize[]){ +NXstatus NXXgetslab64 (NXhandle fid, void *data, + const int64_t iStart[], const int64_t iSize[]){ pXMLNexus xmlHandle = NULL; mxml_node_t *userData = NULL; mxml_node_t *current = NULL; pNXDS dataset, slabData; - int sourcePos[NX_MAXRANK], targetPos[NX_MAXRANK]; + int64_t sourcePos[NX_MAXRANK], targetPos[NX_MAXRANK]; xmlHandle = (pXMLNexus)fid; assert(xmlHandle); if(!isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ - NXIReportError(NXpData,"No dataset open"); + NXReportError("No dataset open"); return NX_ERROR; } @@ -836,14 +1173,14 @@ NXstatus NXXgetslab (NXhandle fid, void *data, userData = findData(current); assert(userData != NULL); if(userData->type == MXML_OPAQUE){ - NXIReportError(NXpData,"This API does not support slabs on text data"); + NXReportError("This API does not support slabs on text data"); return NX_ERROR; } dataset = (pNXDS)userData->value.custom.data; assert(dataset); slabData = makeSlabData(dataset, data, iSize); if(slabData == NULL){ - NXIReportError(NXpData,"Failed to allocate slab data"); + NXReportError("Failed to allocate slab data"); return NX_ERROR; } getSlabData(dataset,slabData,0,iStart,sourcePos,targetPos); @@ -882,7 +1219,7 @@ static NXstatus NXXsetnumberformat(NXhandle fid, return NX_OK; } /*============================ Attributes ============================*/ -static char *formatAttributeData(void *data, int datalen, int iType){ +static char *formatAttributeData(const void *data, int datalen, int iType){ int intData = 0; long iValue = -99999; double dValue = -1e38; @@ -900,7 +1237,7 @@ static char *formatAttributeData(void *data, int datalen, int iType){ number = (char *)malloc(132*sizeof(char)); if(!number){ - NXIReportError(NXpData,"Failed to allocate attribute number buffer"); + NXReportError("Failed to allocate attribute number buffer"); return NULL; } @@ -958,26 +1295,33 @@ static char *formatAttributeData(void *data, int datalen, int iType){ return number; } /*---------------------------------------------------------------------*/ -NXstatus NXXputattr (NXhandle fid, CONSTCHAR *name, void *data, +NXstatus NXXputattr (NXhandle fid, CONSTCHAR *name, void *data, int datalen, int iType){ + char buffer[256]; pXMLNexus xmlHandle = NULL; mxml_node_t *current = NULL; char *numberData = NULL; xmlHandle = (pXMLNexus)fid; assert(xmlHandle); + if (!validNXName(name, 1)) + { + sprintf(buffer, "ERROR: invalid characters in attribute name \"%s\"", name); + NXReportError(buffer); + return NX_ERROR; + } current = xmlHandle->stack[xmlHandle->stackPointer].current; if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ if(strcmp(name,TYPENAME) == 0){ - NXIReportError(NXpData,"type is a reserved attribute name, rejected"); + NXReportError("type is a reserved attribute name, rejected"); return NX_ERROR; } } numberData = formatAttributeData(data,datalen,iType); if(numberData == NULL){ - NXIReportError(NXpData,"This API does not support non number arrays"); + NXReportError("This API does not support non number arrays"); return NX_ERROR; } else { mxmlElementSetAttr(current,name,numberData); @@ -992,9 +1336,8 @@ NXstatus NXXgetattr (NXhandle fid, char *name, mxml_node_t *current = NULL; const char *attribute = NULL; char error[1024]; - char *attData = NULL; - int iValue, nx_type; - float fValue; + const char *attData = NULL; + int nx_type; xmlHandle = (pXMLNexus)fid; assert(xmlHandle); @@ -1004,7 +1347,7 @@ NXstatus NXXgetattr (NXhandle fid, char *name, attribute = mxmlElementGetAttr(current,name); if(!attribute){ snprintf(error,1023,"Attribute %s not found", name); - NXIReportError(NXpData,error); + NXReportError(error); return NX_ERROR; } nx_type = translateTypeCode((char *)attribute); @@ -1023,7 +1366,7 @@ NXstatus NXXgetattr (NXhandle fid, char *name, } else { attData = strchr(attribute,(int)':'); if(attData == NULL){ - NXIReportError(NXpData,"ERROR: bad attribute string, : missing"); + NXReportError("ERROR: bad attribute string, : missing"); return NX_ERROR; } attData++; @@ -1032,8 +1375,11 @@ NXstatus NXXgetattr (NXhandle fid, char *name, *iType = nx_type; switch(nx_type){ case NX_CHAR: - strncpy((char *)data, attribute, *datalen); - *datalen = strlen(attribute); + /* enforce NULL termination regardless of length of datalen */ + strncpy((char *)data, attribute, *datalen-1); + ((char*)data)[*datalen-1] = '\0'; + /* *datalen = strlen(attribute); */ + *datalen = strlen((char*)data); *iType = NX_CHAR; break; case NX_INT32: @@ -1072,11 +1418,72 @@ NXstatus NXXgetattr (NXhandle fid, char *name, return NX_OK; } + +/* find the next node, ignoring Idata */ +static mxml_node_t* find_node(mxml_node_t* node, int next) +{ + int done = 0; + mxml_node_t* parent_next = NULL; /* parent to use if we are in an Idims search */ + if (node == NULL) + { + return NULL; + } + if ( (node->parent != NULL) && !strcmp(node->parent->value.element.name, DIMS_NODE_NAME) ) + { + parent_next = node->parent->next; + } + else + { + parent_next = NULL; + } + if (next) + { + if (node->next != NULL) + { + node = node->next; + } + else + { + node = parent_next; + } + } + while(node != NULL && !done) + { + if ( (node->parent != NULL) && !strcmp(node->parent->value.element.name, DIMS_NODE_NAME) ) + { + parent_next = node->parent->next; + } + else + { + parent_next = NULL; + } + if ( (node->type != MXML_ELEMENT) || !strcmp(node->value.element.name, DATA_NODE_NAME) ) + { + if (node->next != NULL) + { + node = node->next; + } + else + { + node = parent_next; + } + continue; + } + if (!strcmp(node->value.element.name, DIMS_NODE_NAME)) + { + node = node->child; + continue; + } + done = 1; + } + return node; +} + /*====================== search functions =================================*/ NXstatus NXXgetnextentry (NXhandle fid,NXname name, NXname nxclass, int *datatype){ pXMLNexus xmlHandle = NULL; - mxml_node_t *next = NULL, *userData; + mxml_node_t *next = NULL, *userData, *node = NULL; int stackPtr; const char *target = NULL, *attname = NULL; pNXDS dataset; @@ -1098,16 +1505,15 @@ NXstatus NXXgetnextentry (NXhandle fid,NXname name, /* initialization of search */ - xmlHandle->stack[stackPtr].currentChild = - xmlHandle->stack[stackPtr].current->child; + node = find_node(xmlHandle->stack[stackPtr].current->child, 0); } else { /* proceed */ - xmlHandle->stack[stackPtr].currentChild = - xmlHandle->stack[stackPtr].currentChild->next; + node = find_node(xmlHandle->stack[stackPtr].currentChild, 1); } - next = xmlHandle->stack[stackPtr].currentChild; + xmlHandle->stack[stackPtr].currentChild = node; + next = node; if(next == NULL){ return NX_EOD; } @@ -1115,12 +1521,12 @@ NXstatus NXXgetnextentry (NXhandle fid,NXname name, target = mxmlElementGetAttr(next,"target"); linkName = mxmlElementGetAttr(next,"name"); if(target == NULL){ - NXIReportError(NXpData,"Corrupted file, NAPIlink without target"); + NXReportError("Corrupted file, NAPIlink without target"); return NX_ERROR; } next = getLinkTarget(xmlHandle,target); if(next == NULL){ - NXIReportError(NXpData,"Corrupted file, broken link"); + NXReportError("Corrupted file, broken link"); return NX_ERROR; } } @@ -1132,7 +1538,7 @@ NXstatus NXXgetnextentry (NXhandle fid,NXname name, if(userData == NULL){ snprintf(pBueffel,255,"Corrupted file, userData for %s not found", name); - NXIReportError(NXpData,pBueffel); + NXReportError(pBueffel); return NX_ERROR; } if(userData->type == MXML_OPAQUE){ @@ -1164,7 +1570,7 @@ extern NXstatus NXXinitgroupdir(NXhandle fid){ assert(xmlHandle); if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ - NXIReportError(NXpData,"Cannot search datasets"); + NXReportError("Cannot search datasets"); return NX_ERROR; } @@ -1244,7 +1650,7 @@ extern NXstatus NXXinitattrdir(NXhandle fid){ NXstatus NXXgetgroupinfo (NXhandle fid, int *iN, NXname pName, NXname pClass){ pXMLNexus xmlHandle = NULL; - mxml_node_t *child = NULL; + mxml_node_t *node = NULL, *child = NULL; mxml_node_t *current = NULL; const char *nameAtt = NULL; int childCount; @@ -1253,7 +1659,7 @@ NXstatus NXXgetgroupinfo (NXhandle fid, int *iN, assert(xmlHandle); if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ - NXIReportError(NXpData,"No group open"); + NXReportError("No group open"); return NX_ERROR; } current = xmlHandle->stack[xmlHandle->stackPointer].current; @@ -1264,11 +1670,35 @@ NXstatus NXXgetgroupinfo (NXhandle fid, int *iN, } strcpy(pClass,current->value.element.name); +/* count all child nodes, but need to ignore DATA_NODE_NAME and + * descend into DIMS_NODE_NAME + */ childCount = 0; - child = current->child; - while(child != NULL){ - childCount++; - child = child->next; + node = current->child; + while(node != NULL) + { + if (!strcmp(node->value.element.name, DATA_NODE_NAME)) + { + ; /* names also exist in DIMS_NODE_NAME so do nothing here */ + } + else if (!strcmp(node->value.element.name, DIMS_NODE_NAME)) + { + child = node->child; + while(child != NULL) + { + /* not sure why this check is needed, but you double count otherwise */ + if (child->type == MXML_ELEMENT) + { + childCount++; + } + child = child->next; + } + } + else + { + childCount++; + } + node = node->next; } *iN = childCount; return NX_OK; @@ -1277,7 +1707,7 @@ NXstatus NXXgetgroupinfo (NXhandle fid, int *iN, NXstatus NXXgetattrinfo (NXhandle fid, int *iN){ pXMLNexus xmlHandle = NULL; mxml_node_t *current = NULL; - int stackPtr, currentAtt; + int stackPtr, skip; xmlHandle = (pXMLNexus)fid; assert(xmlHandle); @@ -1289,15 +1719,15 @@ NXstatus NXXgetattrinfo (NXhandle fid, int *iN){ /* hide type and group name attributes */ - if(!isDataNode(current)) { - *iN = current->value.element.num_attrs -1; - return NX_OK; - } - if(mxmlElementGetAttr(current,TYPENAME) != NULL){ - *iN = current->value.element.num_attrs -1; + skip=0; + if(isDataNode(current)) { + /* data nodes may have type */ + if(mxmlElementGetAttr(current,TYPENAME) != NULL) skip=1; } else { - *iN = current->value.element.num_attrs; + /* group nodes (except root) have name */ + if(mxmlElementGetAttr(current,"name") != NULL) skip=1; } + *iN = current->value.element.num_attrs - skip; return NX_OK; } /*================= Linking functions =================================*/ @@ -1352,12 +1782,11 @@ static char *findLinkPath(mxml_node_t *node){ mxml_node_t **path = NULL; int stackPtr; mxml_node_t *current = NULL; - char *pathString = NULL, *result = NULL; - int count; + char *result = NULL; path = (mxml_node_t **)malloc(NXMAXSTACK*sizeof(mxml_node_t *)); if(path == NULL){ - NXIReportError(NXpData,"ERROR: out of memory follwoing link path"); + NXReportError("ERROR: out of memory following link path"); return NULL; } memset(path,0,NXMAXSTACK*sizeof(mxml_node_t *)); @@ -1399,7 +1828,7 @@ NXstatus NXXgetdataID (NXhandle fid, NXlink* sRes){ linkPath = findLinkPath(current); if(!linkPath){ - NXIReportError(NXpData,"Failed to allocate link path string"); + NXReportError("Failed to allocate link path string"); return NX_ERROR; } strncpy(sRes->targetPath,linkPath,1023); @@ -1416,7 +1845,7 @@ NXstatus NXXgetgroupID (NXhandle fid, NXlink* sRes){ assert(xmlHandle); if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ - NXIReportError(NXpData,"No group open"); + NXReportError("No group open"); return NX_ERROR; } current = xmlHandle->stack[xmlHandle->stackPointer].current; @@ -1427,7 +1856,7 @@ NXstatus NXXgetgroupID (NXhandle fid, NXlink* sRes){ linkPath = findLinkPath(current); if(!linkPath){ - NXIReportError(NXpData,"Failed to allocate link path string"); + NXReportError("Failed to allocate link path string"); return NX_ERROR; } strncpy(sRes->targetPath,linkPath,1023); @@ -1456,13 +1885,13 @@ NXstatus NXXmakelink (NXhandle fid, NXlink* sLink){ assert(xmlHandle); if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ - NXIReportError(NXpData,"No group to link to open"); + NXReportError("No group to link to open"); return NX_ERROR; } current = xmlHandle->stack[xmlHandle->stackPointer].current; linkNode = mxmlNewElement(current,"NAPIlink"); if(!linkNode){ - NXIReportError(NXpData,"Failed to allocate new link element"); + NXReportError("Failed to allocate new link element"); return NX_ERROR; } mxmlElementSetAttr(linkNode,"target",sLink->targetPath); @@ -1478,18 +1907,25 @@ NXstatus NXXmakenamedlink (NXhandle fid, CONSTCHAR *name, NXlink* sLink){ pXMLNexus xmlHandle = NULL; mxml_node_t *current = NULL, *linkNode = NULL; mxml_node_t *linkedNode = NULL; + char buffer[256]; xmlHandle = (pXMLNexus)fid; assert(xmlHandle); + if (!validNXName(name, 0)) + { + sprintf(buffer, "ERROR: invalid characters in link name \"%s\"", name); + NXReportError(buffer); + return NX_ERROR; + } if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ - NXIReportError(NXpData,"No group to link to open"); + NXReportError("No group to link to open"); return NX_ERROR; } current = xmlHandle->stack[xmlHandle->stackPointer].current; linkNode = mxmlNewElement(current,"NAPIlink"); if(!linkNode){ - NXIReportError(NXpData,"Failed to allocate new link element"); + NXReportError("Failed to allocate new link element"); return NX_ERROR; } mxmlElementSetAttr(linkNode,"target",sLink->targetPath); @@ -1511,31 +1947,33 @@ NXstatus NXXsameID (NXhandle fileid, NXlink* pFirstID, } /*--------------------------------------------------------------------*/ int NXXcompress(NXhandle fid, int comp){ - NXIReportError(NXpData,"NXcompress is deprecated, IGNORED"); + /* that will throw an exception in the Java API, errors have to be fatal */ + /* NXReportError("NXcompress is deprecated, IGNORED"); */ return NX_OK; } /*----------------------------------------------------------------------*/ void NXXassignFunctions(pNexusFunction fHandle){ fHandle->nxclose=NXXclose; + fHandle->nxreopen=NULL; fHandle->nxflush=NXXflush; fHandle->nxmakegroup=NXXmakegroup; fHandle->nxopengroup=NXXopengroup; fHandle->nxclosegroup=NXXclosegroup; - fHandle->nxmakedata=NXXmakedata; - fHandle->nxcompmakedata=NXXcompmakedata; + fHandle->nxmakedata64=NXXmakedata64; + fHandle->nxcompmakedata64=NXXcompmakedata64; fHandle->nxcompress=NXXcompress; fHandle->nxopendata=NXXopendata; fHandle->nxclosedata=NXXclosedata; fHandle->nxputdata=NXXputdata; fHandle->nxputattr=NXXputattr; - fHandle->nxputslab=NXXputslab; + fHandle->nxputslab64=NXXputslab64; fHandle->nxgetdataID=NXXgetdataID; fHandle->nxmakelink=NXXmakelink; fHandle->nxmakenamedlink=NXXmakenamedlink; fHandle->nxgetdata=NXXgetdata; - fHandle->nxgetinfo=NXXgetinfo; + fHandle->nxgetinfo64=NXXgetinfo64; fHandle->nxgetnextentry=NXXgetnextentry; - fHandle->nxgetslab=NXXgetslab; + fHandle->nxgetslab64=NXXgetslab64; fHandle->nxgetnextattr=NXXgetnextattr; fHandle->nxgetattr=NXXgetattr; fHandle->nxgetattrinfo=NXXgetattrinfo; @@ -1546,5 +1984,9 @@ void NXXassignFunctions(pNexusFunction fHandle){ fHandle->nxinitattrdir=NXXinitattrdir; fHandle->nxsetnumberformat=NXXsetnumberformat; fHandle->nxprintlink=NXXprintlink; + fHandle->nxnativeexternallink=NULL; } + + +#endif /*NXXML*/ diff --git a/nxxml.h b/nxxml.h index fc27345d..ee7e9ece 100644 --- a/nxxml.h +++ b/nxxml.h @@ -17,7 +17,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * For further information, see + * For further information, see */ #ifndef NEXUSXML #define NEXUSXML @@ -34,25 +34,25 @@ NXstatus NXXopengroup (NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass); NXstatus NXXclosegroup (NXhandle fid); -NXstatus NXXcompmakedata (NXhandle fid, CONSTCHAR *name, +NXstatus NXXcompmakedata64 (NXhandle fid, CONSTCHAR *name, int datatype, int rank, - int dimensions[], - int compress_type, int chunk_size[]); -NXstatus NXXmakedata (NXhandle fid, + int64_t dimensions[], + int compress_type, int64_t chunk_size[]); +NXstatus NXXmakedata64 (NXhandle fid, CONSTCHAR *name, int datatype, - int rank, int dimensions[]); + int rank, int64_t dimensions[]); NXstatus NXXopendata (NXhandle fid, CONSTCHAR *name); NXstatus NXXclosedata (NXhandle fid); NXstatus NXXputdata (NXhandle fid, void *data); NXstatus NXXgetdata (NXhandle fid, void *data); -NXstatus NXXgetinfo (NXhandle fid, int *rank, - int dimension[], int *iType); -NXstatus NXXputslab (NXhandle fid, void *data, - int iStart[], int iSize[]); -NXstatus NXXgetslab (NXhandle fid, void *data, - int iStart[], int iSize[]); -NXstatus NXXputattr (NXhandle fid, CONSTCHAR *name, void *data, +NXstatus NXXgetinfo64 (NXhandle fid, int *rank, + int64_t dimension[], int *iType); +NXstatus NXXputslab64 (NXhandle fid, void *data, + int64_t iStart[], int64_t iSize[]); +NXstatus NXXgetslab64 (NXhandle fid, void *data, + const int64_t iStart[], const int64_t iSize[]); +NXstatus NXXputattr (NXhandle fid, CONSTCHAR *name, void *data, int datalen, int iType); NXstatus NXXgetattr (NXhandle fid, char *name, void *data, int* datalen, int* iType); diff --git a/o2t.c b/o2t.c index 6359936c..ace981e0 100644 --- a/o2t.c +++ b/o2t.c @@ -49,282 +49,270 @@ #include "fupa.h" #include "o2t.h" - typedef struct __SicsO2T { - pObjectDescriptor pDes; - pIDrivable pDrivInt; - pDummy pOmega; - pDummy pTheta; - } SicsO2T; - -/*---------------------------------------------------------------------------*/ - static void *GetO2TInterface(void *pData, int iID) - { - SicsO2T *self = NULL; - - self = (SicsO2T *)pData; - assert(self); - if(iID == DRIVEID) - { - return self->pDrivInt; - } - return NULL; - } -/*---------------------------------------------------------------------------*/ - static int O2THalt(void *pData) - { - pSicsO2T self = NULL; - pIDrivable pDrivInt = NULL; - - self = (pSicsO2T)pData; - assert(self); - - pDrivInt = self->pOmega->pDescriptor->GetInterface(self->pOmega,DRIVEID); - if(pDrivInt) - { - pDrivInt->Halt(self->pOmega); - } - pDrivInt = self->pTheta->pDescriptor->GetInterface(self->pTheta,DRIVEID); - if(pDrivInt) - { - pDrivInt->Halt(self->pTheta); - } - return 1; - } -/*--------------------------------------------------------------------------*/ - static int O2TCheckLimits(void *pData, float fVal, char *pError, - int iErrLen) - { - pSicsO2T self = NULL; - int iRet; - pIDrivable pDrivInt = NULL; - - self = (pSicsO2T)pData; - assert(self); - - pDrivInt = self->pOmega->pDescriptor->GetInterface(self->pOmega,DRIVEID); - if(pDrivInt) - { - iRet = pDrivInt->CheckLimits(self->pOmega, fVal/2., - pError, iErrLen); - if(!iRet) - { - return iRet; - } - } - pDrivInt = self->pTheta->pDescriptor->GetInterface(self->pTheta,DRIVEID); - if(pDrivInt) - { - return pDrivInt->CheckLimits(self->pTheta, fVal, - pError, iErrLen); - } - return 0; - } -/*-------------------------------------------------------------------------*/ - static long O2TSetValue(void *pData, SConnection *pCon, float fVal) - { - pSicsO2T self = NULL; - pIDrivable pDrivInt = NULL; - int iRet; - - self = (pSicsO2T)pData; - assert(self); - - pDrivInt = self->pOmega->pDescriptor->GetInterface(self->pOmega,DRIVEID); - if(pDrivInt) - { - iRet = pDrivInt->SetValue(self->pOmega,pCon, fVal/2.); - if(iRet != OKOK) - { - return iRet; - } - } - pDrivInt = self->pTheta->pDescriptor->GetInterface(self->pTheta,DRIVEID); - if(pDrivInt) - { - iRet = pDrivInt->SetValue(self->pTheta,pCon, fVal); - return iRet; - } - return 0; - } -/*-------------------------------------------------------------------------*/ - static int O2TCheckStatus(void *pData, SConnection *pCon) - { - pSicsO2T self = NULL; - pIDrivable pDrivInt = NULL; - int iRet; - - self = (pSicsO2T)pData; - assert(self); - - pDrivInt = self->pOmega->pDescriptor->GetInterface(self->pOmega,DRIVEID); - if(pDrivInt) - { - iRet = pDrivInt->CheckStatus(self->pOmega,pCon); - if((iRet != OKOK) && (iRet != HWIdle) ) - { - return iRet; - } - } - pDrivInt = self->pTheta->pDescriptor->GetInterface(self->pTheta,DRIVEID); - if(pDrivInt) - { - iRet = pDrivInt->CheckStatus(self->pTheta,pCon); - return iRet; - } - return 0; - } -/*-------------------------------------------------------------------------*/ - static float O2TGetValue(void *pData, SConnection *pCon) - { - pSicsO2T self = NULL; - pIDrivable pDrivInt = NULL; - - self = (pSicsO2T)pData; - assert(self); - - pDrivInt = self->pTheta->pDescriptor->GetInterface(self->pTheta,DRIVEID); - if(pDrivInt) - { - return pDrivInt->GetValue(self->pTheta,pCon); - } - return -9999.; - } -/*-------------------------------------------------------------------------*/ - pSicsO2T MakeO2T(char *omega, char *theta, SicsInterp *pSics) - { - pSicsO2T self = NULL; - CommandList *pCom = NULL; - pIDrivable pDriv = NULL; - pDummy pDum = NULL; - - /* allocate memory */ - self = (pSicsO2T)malloc(sizeof(SicsO2T)); - if(!self) - { - return NULL; - } - self->pDes = CreateDescriptor("Omega2Theta"); - if(!self->pDes) - { - free(self); - return NULL; - } - - /* get and check drivabels */ - pCom = FindCommand(pSics,omega); - if(pCom != NULL) - { - pDum = pCom->pData; - } else - { - pDum = NULL; - } - if(GetDrivableInterface(pDum) != NULL){ - self->pOmega = pDum; - } - pCom = FindCommand(pSics,theta); - if(pCom != NULL) - { - pDum = pCom->pData; - } - else - { - pDum = NULL; - } - if(GetDrivableInterface(pDum) != NULL){ - self->pTheta = pDum; - } - if( (self->pOmega == NULL) || (self->pTheta == NULL) ) - { - DeleteDescriptor(self->pDes); - free(self); - return NULL; - } - - /* initialize Descriptor */ - self->pDes->GetInterface = GetO2TInterface; - - - /* initialise drivable interface */ - self->pDrivInt = CreateDrivableInterface(); - if(!self->pDrivInt) - { - DeleteDescriptor(self->pDes); - free(self); - return NULL; - } - self->pDrivInt->Halt = O2THalt; - self->pDrivInt->CheckLimits = O2TCheckLimits; - self->pDrivInt->SetValue = O2TSetValue; - self->pDrivInt->CheckStatus = O2TCheckStatus; - self->pDrivInt->GetValue = O2TGetValue; - - return self; - } -/*---------------------------------------------------------------------------*/ - void DeleteO2T(void *pData) - { - pSicsO2T self = NULL; - - self = (pSicsO2T)pData; - assert(self); +typedef struct __SicsO2T { + pObjectDescriptor pDes; + pIDrivable pDrivInt; + pDummy pOmega; + pDummy pTheta; +} SicsO2T; - if(self->pDrivInt) - { - free(self->pDrivInt); - } - if(self->pDes) - { - DeleteDescriptor(self->pDes); - } - free(self); - } -/*-------------------------------------------------------------------------*/ - static int DummyO2T(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - SCWrite(pCon,"WARNING: O2T does not understand any commnds",eWarning); - return 1; +/*---------------------------------------------------------------------------*/ +static void *GetO2TInterface(void *pData, int iID) +{ + SicsO2T *self = NULL; + + self = (SicsO2T *) pData; + assert(self); + if (iID == DRIVEID) { + return self->pDrivInt; } + return NULL; +} + +/*---------------------------------------------------------------------------*/ +static int O2THalt(void *pData) +{ + pSicsO2T self = NULL; + pIDrivable pDrivInt = NULL; + + self = (pSicsO2T) pData; + assert(self); + + pDrivInt = + self->pOmega->pDescriptor->GetInterface(self->pOmega, DRIVEID); + if (pDrivInt) { + pDrivInt->Halt(self->pOmega); + } + pDrivInt = + self->pTheta->pDescriptor->GetInterface(self->pTheta, DRIVEID); + if (pDrivInt) { + pDrivInt->Halt(self->pTheta); + } + return 1; +} + +/*--------------------------------------------------------------------------*/ +static int O2TCheckLimits(void *pData, float fVal, char *pError, + int iErrLen) +{ + pSicsO2T self = NULL; + int iRet; + pIDrivable pDrivInt = NULL; + + self = (pSicsO2T) pData; + assert(self); + + pDrivInt = + self->pOmega->pDescriptor->GetInterface(self->pOmega, DRIVEID); + if (pDrivInt) { + iRet = pDrivInt->CheckLimits(self->pOmega, fVal / 2., pError, iErrLen); + if (!iRet) { + return iRet; + } + } + pDrivInt = + self->pTheta->pDescriptor->GetInterface(self->pTheta, DRIVEID); + if (pDrivInt) { + return pDrivInt->CheckLimits(self->pTheta, fVal, pError, iErrLen); + } + return 0; +} + +/*-------------------------------------------------------------------------*/ +static long O2TSetValue(void *pData, SConnection * pCon, float fVal) +{ + pSicsO2T self = NULL; + pIDrivable pDrivInt = NULL; + int iRet; + + self = (pSicsO2T) pData; + assert(self); + + pDrivInt = + self->pOmega->pDescriptor->GetInterface(self->pOmega, DRIVEID); + if (pDrivInt) { + iRet = pDrivInt->SetValue(self->pOmega, pCon, fVal / 2.); + if (iRet != OKOK) { + return iRet; + } + } + pDrivInt = + self->pTheta->pDescriptor->GetInterface(self->pTheta, DRIVEID); + if (pDrivInt) { + iRet = pDrivInt->SetValue(self->pTheta, pCon, fVal); + return iRet; + } + return 0; +} + +/*-------------------------------------------------------------------------*/ +static int O2TCheckStatus(void *pData, SConnection * pCon) +{ + pSicsO2T self = NULL; + pIDrivable pDrivInt = NULL; + int iRet; + + self = (pSicsO2T) pData; + assert(self); + + pDrivInt = + self->pOmega->pDescriptor->GetInterface(self->pOmega, DRIVEID); + if (pDrivInt) { + iRet = pDrivInt->CheckStatus(self->pOmega, pCon); + if ((iRet != OKOK) && (iRet != HWIdle)) { + return iRet; + } + } + pDrivInt = + self->pTheta->pDescriptor->GetInterface(self->pTheta, DRIVEID); + if (pDrivInt) { + iRet = pDrivInt->CheckStatus(self->pTheta, pCon); + return iRet; + } + return 0; +} + +/*-------------------------------------------------------------------------*/ +static float O2TGetValue(void *pData, SConnection * pCon) +{ + pSicsO2T self = NULL; + pIDrivable pDrivInt = NULL; + + self = (pSicsO2T) pData; + assert(self); + + pDrivInt = + self->pTheta->pDescriptor->GetInterface(self->pTheta, DRIVEID); + if (pDrivInt) { + return pDrivInt->GetValue(self->pTheta, pCon); + } + return -9999.; +} + +/*-------------------------------------------------------------------------*/ +pSicsO2T MakeO2T(char *omega, char *theta, SicsInterp * pSics) +{ + pSicsO2T self = NULL; + CommandList *pCom = NULL; + pIDrivable pDriv = NULL; + pDummy pDum = NULL; + + /* allocate memory */ + self = (pSicsO2T) malloc(sizeof(SicsO2T)); + if (!self) { + return NULL; + } + self->pDes = CreateDescriptor("Omega2Theta"); + if (!self->pDes) { + free(self); + return NULL; + } + + /* get and check drivabels */ + pCom = FindCommand(pSics, omega); + if (pCom != NULL) { + pDum = pCom->pData; + } else { + pDum = NULL; + } + if (GetDrivableInterface(pDum) != NULL) { + self->pOmega = pDum; + } + pCom = FindCommand(pSics, theta); + if (pCom != NULL) { + pDum = pCom->pData; + } else { + pDum = NULL; + } + if (GetDrivableInterface(pDum) != NULL) { + self->pTheta = pDum; + } + if ((self->pOmega == NULL) || (self->pTheta == NULL)) { + DeleteDescriptor(self->pDes); + free(self); + return NULL; + } + + /* initialize Descriptor */ + self->pDes->GetInterface = GetO2TInterface; + + + /* initialise drivable interface */ + self->pDrivInt = CreateDrivableInterface(); + if (!self->pDrivInt) { + DeleteDescriptor(self->pDes); + free(self); + return NULL; + } + self->pDrivInt->Halt = O2THalt; + self->pDrivInt->CheckLimits = O2TCheckLimits; + self->pDrivInt->SetValue = O2TSetValue; + self->pDrivInt->CheckStatus = O2TCheckStatus; + self->pDrivInt->GetValue = O2TGetValue; + + return self; +} + +/*---------------------------------------------------------------------------*/ +void DeleteO2T(void *pData) +{ + pSicsO2T self = NULL; + + self = (pSicsO2T) pData; + assert(self); + + if (self->pDrivInt) { + free(self->pDrivInt); + } + if (self->pDes) { + DeleteDescriptor(self->pDes); + } + free(self); +} + +/*-------------------------------------------------------------------------*/ +static int DummyO2T(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + SCWrite(pCon, "WARNING: O2T does not understand any commnds", eWarning); + return 1; +} + /*--------------------------------------------------------------------------- initialisation command. Syntax: CreateO2T name omegamotor thetamotor -*/ - int CreateO2T(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - pSicsO2T self = NULL; - char pBueffel[256]; - int iRet; - - assert(pCon); - assert(pSics); - - if(argc < 4) - { - SCWrite(pCon,"ERROR: Insufficienet number of argumnets to CreateO2T", - eError); - return 0; - } - - /* make O2T */ - self = MakeO2T(argv[2],argv[3],pSics); - if(!self) - { - sprintf(pBueffel,"ERROR: no Memory or %s %s are no valid motor names", - argv[2], argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* install command */ - iRet = AddCommand(pSics,argv[1],DummyO2T,DeleteO2T,self); - if(!iRet) - { - sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - return 1; - } +*/ +int CreateO2T(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pSicsO2T self = NULL; + char pBueffel[256]; + int iRet; + assert(pCon); + assert(pSics); + + if (argc < 4) { + SCWrite(pCon, "ERROR: Insufficienet number of argumnets to CreateO2T", + eError); + return 0; + } + + /* make O2T */ + self = MakeO2T(argv[2], argv[3], pSics); + if (!self) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: no Memory or %s %s are no valid motor names", + argv[2], argv[3]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* install command */ + iRet = AddCommand(pSics, argv[1], DummyO2T, DeleteO2T, self); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: duplicate command %s not created", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + return 1; +} diff --git a/o2t.h b/o2t.h index 9d695939..1c8b834f 100644 --- a/o2t.h +++ b/o2t.h @@ -10,12 +10,12 @@ #ifndef SICSO2T #define SICSO2T - typedef struct __SicsO2T *pSicsO2T; - - pSicsO2T MakeO2T(char *omega, char *theta, SicsInterp *pSics); - void DeleteO2T(void *pData); - - int CreateO2T(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - +typedef struct __SicsO2T *pSicsO2T; + +pSicsO2T MakeO2T(char *omega, char *theta, SicsInterp * pSics); +void DeleteO2T(void *pData); + +int CreateO2T(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); + #endif diff --git a/obdes.c b/obdes.c index 127e56bc..ce0b9bb6 100644 --- a/obdes.c +++ b/obdes.c @@ -47,160 +47,165 @@ #include "hipadaba.h" /*-------------------------------------------------------------------------*/ - static void *DefaultGetInterface(void *pData,int iID) - { +static void *DefaultGetInterface(void *pData, int iID) +{ + return NULL; +} + +/*-------------------------------------------------------------------------*/ +static int DefaultSave(void *self, char *name, FILE * fd) +{ + return 1; +} + +/*--------------------------------------------------------------------------*/ +pObjectDescriptor CreateDescriptor(char *name) +{ + pObjectDescriptor pRes = NULL; + + pRes = (pObjectDescriptor) malloc(sizeof(ObjectDescriptor)); + if (!pRes) { return NULL; } -/*-------------------------------------------------------------------------*/ - static int DefaultSave(void *self, char *name,FILE *fd) - { - return 1; - } -/*--------------------------------------------------------------------------*/ - pObjectDescriptor CreateDescriptor(char *name) - { - pObjectDescriptor pRes = NULL; - - pRes = (pObjectDescriptor)malloc(sizeof(ObjectDescriptor)); - if(!pRes) - { - return NULL; - } - pRes->name = strdup(name); - pRes->pKeys = NULL; - pRes->parNode = NULL; - pRes->SaveStatus = DefaultSave; - pRes->GetInterface = DefaultGetInterface; - return pRes; - } + pRes->name = strdup(name); + pRes->pKeys = NULL; + pRes->parNode = NULL; + pRes->SaveStatus = DefaultSave; + pRes->GetInterface = DefaultGetInterface; + return pRes; +} + /*---------------------------------------------------------------------------*/ - void DeleteDescriptor(pObjectDescriptor self) - { - assert(self); - if(self->name) free(self->name); - if(self->pKeys) IFDeleteOptions(self->pKeys); - /* - * delate a parameter node only when not linked elsewhere - */ - if(self->parNode != NULL){ - if(self->parNode->mama == NULL){ - DeleteHipadabaNode(self->parNode,NULL); - } +void DeleteDescriptor(pObjectDescriptor self) +{ + assert(self); + if (self->name) + free(self->name); + if (self->pKeys) + IFDeleteOptions(self->pKeys); + /* + * delete a parameter node only when not linked elsewhere + */ + if (self->parNode != NULL) { + if (self->parNode->mama == NULL) { + DeleteHipadabaNode(self->parNode, NULL); } - free(self); - } + free(self); + +} + /*-------------------------------------------------------------------------*/ - pDummy CreateDummy(char *name) - { - pDummy pRes = NULL; - - pRes = (pDummy)malloc(sizeof(Dummy)); - if(!pRes) - { - SICSLogWrite("Out of Memory in CreateDummy",eInternal); - return NULL; - } - - pRes->pDescriptor = CreateDescriptor(name); - if(!pRes->pDescriptor) - { - free(pRes); - SICSLogWrite("Out of Memory in CreateDummy",eInternal); - return NULL; - } - return pRes; +pDummy CreateDummy(char *name) +{ + pDummy pRes = NULL; + + pRes = (pDummy) malloc(sizeof(Dummy)); + if (!pRes) { + SICSLogWrite("Out of Memory in CreateDummy", eInternal); + return NULL; } + + pRes->pDescriptor = CreateDescriptor(name); + if (!pRes->pDescriptor) { + free(pRes); + SICSLogWrite("Out of Memory in CreateDummy", eInternal); + return NULL; + } + return pRes; +} + /*--------------------------------------------------------------------------*/ - void KillDummy(void *pData) - { - pDummy pVictim; - - if(!pData)return; - - pVictim = (pDummy)pData; - if(pVictim->pDescriptor) - { - DeleteDescriptor(pVictim->pDescriptor); - } - free(pData); +void KillDummy(void *pData) +{ + pDummy pVictim; + + if (!pData) + return; + + pVictim = (pDummy) pData; + if (pVictim->pDescriptor) { + DeleteDescriptor(pVictim->pDescriptor); } + free(pData); +} + /*-------------------------------------------------------------------------*/ - int iHasType(void *pData, char *Type) - { - pDummy pTest; - - assert(pData); - pTest = (pDummy)pData; - if(!pTest->pDescriptor) - { - return 0; - } - if(strcmp(pTest->pDescriptor->name,Type) == 0) - { - return 1; - } - return 0; +int iHasType(void *pData, char *Type) +{ + pDummy pTest; + + assert(pData); + pTest = (pDummy) pData; + if (!pTest->pDescriptor) { + return 0; } + if (strcmp(pTest->pDescriptor->name, Type) == 0) { + return 1; + } + return 0; +} + /*------------------------------------------------------------------------*/ - pObjectDescriptor FindDescriptor(void *pData) - { - pDummy pDum = NULL; - - assert(pData); - pDum = (pDummy)pData; - return pDum->pDescriptor; - } +pObjectDescriptor FindDescriptor(void *pData) +{ + pDummy pDum = NULL; + + assert(pData); + pDum = (pDummy) pData; + return pDum->pDescriptor; +} + /*--------------------------------------------------------------------------*/ - void SetDescriptorKey(pObjectDescriptor self, char *keyName, char *eltValue) - { - if(NULL!=self) - { - self->pKeys = IFSetOption(self->pKeys,keyName,eltValue); - } +void SetDescriptorKey(pObjectDescriptor self, char *keyName, + char *eltValue) +{ + if (NULL != self) { + self->pKeys = IFSetOption(self->pKeys, keyName, eltValue); } +} + /*--------------------------------------------------------------------------*/ - void SetDescriptorGroup(pObjectDescriptor self, char *group) - { - if(NULL==self) - { - return; - } - self->pKeys = IFSetOption(self->pKeys,"group",group); +void SetDescriptorGroup(pObjectDescriptor self, char *group) +{ + if (NULL == self) { + return; } + self->pKeys = IFSetOption(self->pKeys, "group", group); +} + /*--------------------------------------------------------------------------*/ - void SetDescriptorDescription(pObjectDescriptor self, char *description) - { - if(NULL==self) - { - return; - } - self->pKeys = IFSetOption(self->pKeys,"description", description); +void SetDescriptorDescription(pObjectDescriptor self, char *description) +{ + if (NULL == self) { + return; } + self->pKeys = IFSetOption(self->pKeys, "description", description); +} + /*--------------------------------------------------------------------------*/ - char * GetDescriptorKey(pObjectDescriptor self, char *keyName) - { - if(NULL==self) - { - return NULL; - } - return IFindOption(self->pKeys,keyName); +char *GetDescriptorKey(pObjectDescriptor self, char *keyName) +{ + if (NULL == self) { + return NULL; } + return IFindOption(self->pKeys, keyName); +} + /*--------------------------------------------------------------------------*/ - char * GetDescriptorGroup(pObjectDescriptor self) - { - if(NULL==self) - { - return NULL; - } - return IFindOption(self->pKeys,"group"); +char *GetDescriptorGroup(pObjectDescriptor self) +{ + if (NULL == self) { + return NULL; } + return IFindOption(self->pKeys, "group"); +} + /*--------------------------------------------------------------------------*/ - char *GetDescriptorDescription(pObjectDescriptor self) - { - if(NULL==self) - { - return NULL; - } - return IFindOption(self->pKeys,"description"); +char *GetDescriptorDescription(pObjectDescriptor self) +{ + if (NULL == self) { + return NULL; } + return IFindOption(self->pKeys, "description"); +} diff --git a/obdes.h b/obdes.h index f842a2e9..d1477dc0 100644 --- a/obdes.h +++ b/obdes.h @@ -1,5 +1,5 @@ -#line 365 "interface.w" +#line 385 "interface.w" #line 29 "interface.w" @@ -25,19 +25,19 @@ #include #include - typedef struct { - char *name; - int (*SaveStatus)(void *self, char *name,FILE *fd); - void *(*GetInterface)(void *self, int iInterfaceID); - IPair *pKeys; - pHdb parNode; - } ObjectDescriptor, *pObjectDescriptor; +typedef struct { + char *name; + int (*SaveStatus) (void *self, char *name, FILE * fd); + void *(*GetInterface) (void *self, int iInterfaceID); + IPair *pKeys; + pHdb parNode; +} ObjectDescriptor, *pObjectDescriptor; /*---------------------------------------------------------------------------*/ - pObjectDescriptor CreateDescriptor(char *name); - void DeleteDescriptor(pObjectDescriptor self); - pObjectDescriptor FindDescriptor(void *pData); - +pObjectDescriptor CreateDescriptor(char *name); +void DeleteDescriptor(pObjectDescriptor self); +pObjectDescriptor FindDescriptor(void *pData); + /*============================================================================ Objects which do not carry data need a dummy descriptor. Otherwise drive or scan will protection fault when trying to drive something @@ -45,26 +45,26 @@ */ typedef struct { - pObjectDescriptor pDescriptor; - }Dummy, *pDummy; - + pObjectDescriptor pDescriptor; +} Dummy, *pDummy; - pDummy CreateDummy(char *name); - void KillDummy(void *pData); - int iHasType(void *pData, char *Type); - -#endif +pDummy CreateDummy(char *name); +void KillDummy(void *pData); -#line 366 "interface.w" +int iHasType(void *pData, char *Type); + +#endif + +#line 386 "interface.w" /*--------------------------------------------------------------------------*/ /* Additional properties used by the ANSTO site to provide more information * about each object instance, especially devices. */ - void SetDescriptorKey(pObjectDescriptor self, char *keyName, char *value); - void SetDescriptorGroup(pObjectDescriptor self, char *group); - void SetDescriptorDescription(pObjectDescriptor self, char *description); - char * GetDescriptorKey(pObjectDescriptor self, char *keyName); - char * GetDescriptorGroup(pObjectDescriptor self); - char * GetDescriptorDescription(pObjectDescriptor self); +void SetDescriptorKey(pObjectDescriptor self, char *keyName, char *value); +void SetDescriptorGroup(pObjectDescriptor self, char *group); +void SetDescriptorDescription(pObjectDescriptor self, char *description); +char *GetDescriptorKey(pObjectDescriptor self, char *keyName); +char *GetDescriptorGroup(pObjectDescriptor self); +char *GetDescriptorDescription(pObjectDescriptor self); diff --git a/object.tcl b/object.tcl index e0e73b14..7aa7e856 100755 --- a/object.tcl +++ b/object.tcl @@ -1,5 +1,5 @@ # -# $Id: object.tcl,v 1.1 2000/02/25 16:21:41 cvs Exp $ +# $Id$ # # This software is copyright (C) 1995 by the Lawrence Berkeley Laboratory. # diff --git a/obpar.c b/obpar.c index 6e20f7b1..c89ef725 100644 --- a/obpar.c +++ b/obpar.c @@ -39,177 +39,169 @@ #include #include #include -#include "Scommon.h" +#include "sics.h" #include "fortify.h" #include "conman.h" #include "status.h" #include "obpar.h" - +#include "devexec.h" /*------------------------------------------------------------------------*/ - int ObParLength(ObPar *self) - { - int i = 0; +int ObParLength(ObPar * self) +{ + int i = 0; - assert(self); - - while(self[i].iCode != -100) - { - i++; - } - return i; + assert(self); + + while (self[i].iCode != -100) { + i++; } + return i; +} + /*-------------------------------------------------------------------------*/ - ObPar *ObParCreate(int iArrayLong) - { - ObPar *pRes = NULL; - int i; - - assert(iArrayLong > 0); - - /* allocate memory */ - pRes = (ObPar *)malloc((iArrayLong + 1)*sizeof(ObPar)); - if(!pRes) - { - return NULL; - } - - /* initialise all to 0 */ - for(i = 0; i < iArrayLong; i++) - { - pRes[i].name = NULL; - pRes[i].fVal = .0; - pRes[i].iCode = usSpy; - } - - /* have a sentinel at the end */ - pRes[iArrayLong].iCode = -100; - - return pRes; +ObPar *ObParCreate(int iArrayLong) +{ + ObPar *pRes = NULL; + int i; + + assert(iArrayLong > 0); + + /* allocate memory */ + pRes = (ObPar *) malloc((iArrayLong + 1) * sizeof(ObPar)); + if (!pRes) { + return NULL; } + + /* initialise all to 0 */ + for (i = 0; i < iArrayLong; i++) { + pRes[i].name = NULL; + pRes[i].fVal = .0; + pRes[i].iCode = usSpy; + } + + /* have a sentinel at the end */ + pRes[iArrayLong].iCode = -100; + + return pRes; +} + /*--------------------------------------------------------------------------*/ - void ObParDelete(ObPar *self) - { - int i; - int iLong; - - assert(self); - - /* free the names */ - iLong = ObParLength(self); - for(i = 0; i < iLong; i++) - { - if(self[i].name) - free(self[i].name); +void ObParDelete(ObPar * self) +{ + int i; + int iLong; + + assert(self); + + /* free the names */ + iLong = ObParLength(self); + for (i = 0; i < iLong; i++) { + if (self[i].name) + free(self[i].name); + } + + free(self); +} + +/*---------------------------------------------------------------------------*/ +ObPar *ObParFind(ObPar * self, char *name) +{ + int i; + + assert(self); + + for (i = 0; self[i].iCode != -100; i++) { + if (strcmp(name, self[i].name) == 0) { + return &self[i]; } - - free(self); } + + return NULL; +} + /*---------------------------------------------------------------------------*/ - ObPar *ObParFind(ObPar *self, char *name) - { - int i; - - assert(self); - - for(i = 0; self[i].iCode != -100; i++) - { - if(strcmp(name,self[i].name) == 0) - { - return &self[i]; - } - } - - return NULL; - } -/*---------------------------------------------------------------------------*/ - int ObParIndex(ObPar *self, char *name) - { - int i; - - assert(self); - - for(i = 0; self[i].iCode != -100; i++) - { - if(strcmp(name,self[i].name) == 0) - { - return i; - } - } - - return -1; - } -/*---------------------------------------------------------------------------*/ - int ObParInit(ObPar *self, int i, char *name, float fVal, int iCode) - { - - assert(self); - - /* check i */ - if( (i < 0) && ( i >= ObParLength(self) )) - { - return 0; - } - - if(self[i].name) - { - free(self[i].name); - } - self[i].name = strdup(name); - self[i].fVal = fVal; - self[i].iCode = iCode; - return 1; +int ObParIndex(ObPar * self, char *name) +{ + int i; + + assert(self); + + for (i = 0; self[i].iCode != -100; i++) { + if (strcmp(name, self[i].name) == 0) { + return i; + } } -/*------------------------------------------------------------------------*/ - int ObParSet(ObPar *self, char *obname, char *name, float fVal, - SConnection *pCon) - { - char pBueffel[512]; - ObPar *pPar = NULL; - Status eStat; - - assert(self); - - /* find the parameter */ - pPar = ObParFind(self,name); - if(pPar == NULL) - { - sprintf(pBueffel,"ERROR: %s.%s parameter not found", - obname,name); - SCWrite(pCon, pBueffel,eError); - return 0; - } - - /* are we running? */ - eStat = GetStatus(); - if(!((eStat == eEager) || (eStat == eBatch)) ) - { - sprintf(pBueffel,"ERROR: Cannot change %s.%s parameter while running", obname, name); - SCWrite(pCon, pBueffel,eError); - return 0; - } - - /* check permission */ - if(!SCMatchRights(pCon,pPar->iCode)) - { - sprintf(pBueffel,"ERROR: Insufficient privilege to change %s.%s", - obname, name); - SCWrite(pCon, pBueffel,eError); - return 0; - } - - /* passed all tests: do It! */ - pPar->fVal = fVal; - return 1; - } + + return -1; +} + +/*---------------------------------------------------------------------------*/ +int ObParInit(ObPar * self, int i, char *name, float fVal, int iCode) +{ + + assert(self); + + /* check i */ + if ((i < 0) && (i >= ObParLength(self))) { + return 0; + } + + if (self[i].name) { + free(self[i].name); + } + self[i].name = strdup(name); + self[i].fVal = fVal; + self[i].iCode = iCode; + return 1; +} + +/*------------------------------------------------------------------------*/ +int ObParSet(ObPar * self, char *obname, char *name, float fVal, + SConnection * pCon) +{ + char pBueffel[512]; + ObPar *pPar = NULL; + Status eStat; + + assert(self); + + /* find the parameter */ + pPar = ObParFind(self, name); + if (pPar == NULL) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s.%s parameter not found", obname, name); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* are we running? */ + if(DevExecLevelRunning(pServ->pExecutor, RUNDRIVE)){ + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Cannot change parameter while running"); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* check permission */ + if (!SCMatchRights(pCon, pPar->iCode)) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Insufficient privilege to change %s.%s", + obname, name); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* passed all tests: do It! */ + pPar->fVal = fVal; + return 1; +} + /*------------------------------------------------------------------------*/ - float ObVal(ObPar *self, int i) - { - assert(self); - assert(i > -1); - assert( i < ObParLength(self)); - - return self[i].fVal; - } +float ObVal(ObPar * self, int i) +{ + assert(self); + assert(i > -1); + assert(i < ObParLength(self)); + + return self[i].fVal; +} diff --git a/obpar.h b/obpar.h index f0a7be55..e8b56950 100644 --- a/obpar.h +++ b/obpar.h @@ -21,53 +21,53 @@ ----------------------------------------------------------------------------*/ #ifndef SICSARPAR #define SICSARPAR - - typedef struct { - char *name; - float fVal; - int iCode; - } ObPar; + +typedef struct { + char *name; + float fVal; + int iCode; +} ObPar; /* quick access internally, self is the ObPar array, i is the parameter number, nice to have defines for some, better than handling ints - */ - float ObVal(ObPar *self, int i); + */ +float ObVal(ObPar * self, int i); - int ObParLength(ObPar *self); +int ObParLength(ObPar * self); /* - finds the length of an ObPar array - */ - - ObPar *ObParFind(ObPar *self, char *name); + finds the length of an ObPar array + */ + +ObPar *ObParFind(ObPar * self, char *name); /* finds a ObPar struct for a name, return NULL if none */ - int ObParIndex(ObPar *self, char *name); +int ObParIndex(ObPar * self, char *name); /* - finds an index for name in self. Returns -1 on failure - */ + finds an index for name in self. Returns -1 on failure + */ - int ObParInit(ObPar *self,int i, char *name, float fVal, int iCode); +int ObParInit(ObPar * self, int i, char *name, float fVal, int iCode); /* - sets a ObPar entry. self is a pointer to the array - */ - int ObParSet(ObPar *self, char *obname,char *name, float fVal, SConnection *pCon); + sets a ObPar entry. self is a pointer to the array + */ +int ObParSet(ObPar * self, char *obname, char *name, float fVal, + SConnection * pCon); /* checks if the connections permissions are alright and changes value if so. Returns 1 on success, 0 on failure. Prints errors directly to pCon. The parameter obmane is the name of the object the parameters belong to. Needed for error printing. name is the parameter name, fVal the new value. - */ - - void ObParDelete(ObPar *self); + */ + +void ObParDelete(ObPar * self); /* Deletes an ObPar array - */ - - ObPar *ObParCreate(int iArrayLong); - /* - creates an array with iArrayLong entries - */ -#endif + */ +ObPar *ObParCreate(int iArrayLong); + /* + creates an array with iArrayLong entries + */ +#endif diff --git a/ofac.c b/ofac.c index d7faebab..760a7695 100644 --- a/ofac.c +++ b/ofac.c @@ -1,498 +1,234 @@ -/*-------------------------------------------------------------------------- +/** + * Startup commands and definitions + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke 1996 - ? + * heavy modifications to separate PSI specific commands into a + * separate library. Mark Koennecke, June 2003 + * + * moved some functions to sicsutil.c + * Markus Zolliker Jan 2010 + */ - The ObjectFactory. - - See .h file what it does. - - - - Mark Koennecke, November 1996 -- ???? - - heavy modifications to separate PSI specific commands into a - separate library. Mark Koennecke, June 2003 - - Copyright: - - Labor fuer Neutronenstreuung - Paul Scherrer Institut - CH-5423 Villigen-PSI - - - The authors hereby grant permission to use, copy, modify, distribute, - and license this software and its documentation for any purpose, provided - that existing copyright notices are retained in all copies and that this - notice is included verbatim in any distributions. No written agreement, - license, or royalty fee is required for any of the authorized uses. - Modifications to this software may be copyrighted by their authors - and need not follow the licensing terms described here, provided that - the new terms are clearly indicated on the first page of each file where - they apply. - - IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY - FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY - DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - - THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, - INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE - IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE - NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR - MODIFICATIONS. ------------------------------------------------------------------------------*/ -#include -#include -#include "fortify.h" -#include "sics.h" -#include "ifile.h" -#include "sicsexit.h" -#include "passwd.h" -#include "macro.h" -#include "splitter.h" -#include "sicsvar.h" -#include "drive.h" -#include "motor.h" -#include "servlog.h" -#include "nserver.h" -#include "status.h" -#include "statusfile.h" -#include "configfu.h" -#include "devexec.h" -#include "mumo.h" -#include "selector.h" -#include "selvar.h" -#include "countdriv.h" -#include "counter.h" -#include "scan.h" -#include "script.h" -#include "o2t.h" -#include "alias.h" -#include "stringdict.h" -#include "HistMem.h" -#include "velo.h" -#include "emon.h" -#include "evcontroller.h" -#include "danu.h" -#include "nserver.h" -#include "scan.h" -#include "fitcenter.h" -#include "token.h" -#include "hkl.h" -#include "optimise.h" -#include "mesure.h" -#include "commandlog.h" -#include "udpquieck.h" -#include "choco.h" -#include "chadapter.h" -#include "hklscan.h" -#include "xytable.h" -#include "maximize.h" -#include "difrac.h" -#include "sicscron.h" -#include "lin2ang.h" -#include "synchronize.h" -#include "definealias.h" -#include "hmcontrol.h" -#include "rs232controller.h" -#include "lomax.h" -#include "anticollider.h" -#include "gpibcontroller.h" -#include "nxscript.h" -#include "tclintimpl.h" -#include "tcldrivable.h" -#include "sicsdata.h" -#include "help.h" -#include "site.h" -#include "nxupdate.h" -#include "confvirtmot.h" +#include "ofac.h" #include "exeman.h" -#include "oscillate.h" -#include "diffscan.h" -#include "hklmot.h" -#include "ubcalc.h" -#include "tasub.h" -#include "tasscanub.h" -#include "mcreader.h" -#include "mccontrol.h" -#include "protocol.h" -#include "sinfox.h" -#include "sicslist.h" -#include "cone.h" +#include "statusfile.h" +#include "site.h" #include "sicshipadaba.h" -#include "multicounter.h" -#include "sicspoll.h" -#include "statemon.h" -#include "asyncqueue.h" -#include "asyncprotocol.h" -#include "sicsobj.h" -#include "hdbqueue.h" -#include "genericcontroller.h" -#include "proxy.h" -/*----------------------- Server options creation -------------------------*/ - static int IFServerOption(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - char pBueffel[512]; - - assert(pSics); - assert(pCon); - /* check authorisation */ - if(!SCMatchRights(pCon,usMugger)) - { - SCWrite(pCon,"Insufficient privilege to set options",eError); - return 0; - } - - /* test if sufficient arguments */ - if(argc < 3) - { - sprintf(pBueffel,"Syntax: %s name value ", argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* just do it */ - pSICSOptions = IFAddOption(pSICSOptions,argv[1],argv[2]); - return 1; - } -/*----------------------- Password database update -------------------------*/ - static int PWSicsUser(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - char pBueffel[512]; - TokenList *pList = NULL; - - assert(pSics); - assert(pCon); - - /* check authorisation */ - if(SCGetRights(pCon) > usMugger) - { - SCWrite(pCon,"Insufficient privilege to set users",eError); - return 0; - } - - /* analyse commandlist */ - pList = SplitArguments(argc-1, &argv[1]); - if( (!pList) || (!pList->pNext) || (!pList->pNext->pNext) ) - { - sprintf(pBueffel,"Invalid Passwd Entry ::\n %s %s %s\n", argv[1], - argv[2], argv[3]); - SCWrite(pCon,pBueffel,eError); - DeleteTokenList(pList); - return 0; - } - else - { - if(pList->pNext->pNext->Type != eInt) - { - SCWrite(pCon,"Need integer rights code",eError); - DeleteTokenList(pList); - return 0; - } - else - { - AddUser(pList->text, pList->pNext->text, - pList->pNext->pNext->iVal); - } - } - DeleteTokenList(pList); - return 1; - } -/*--------------------------------------------------------------------------*/ - static void InitIniCommands(SicsInterp *pInter,pTaskMan pTask) - { - pExeList pExe; - pEnvMon pEnv = NULL; - pSite site = NULL; - assert(pInter); - - pExe = CreateExeList(pTask); - pServ->pExecutor = pExe; - pEnv = CreateEnvMon(); - - assert(pExe); - assert(pEnv); - - /* permanent commands */ - AddCommand(pInter,"Sics_Exitus",SicsExit,NULL,NULL); - AddCommand(pInter,"FileEval",MacroFileEval,NULL,NULL); - - AddCommand(pInter,"InternEval",InternalFileEval,NULL,NULL); - AddCommand(pInter,"ClientPut",ClientPut,NULL,NULL); - AddCommand(pInter,"GumPut",GumPut,NULL,NULL); - AddCommand(pInter,"broadcast",Broadcast,NULL,NULL); - AddCommand(pInter,"transact",TransactAction,NULL,NULL); - AddCommand(pInter,"fulltransact",TransactAction,NULL,NULL); - AddCommand(pInter,"sicsprompt", SicsPrompt,NULL,NULL); - AddCommand(pInter,"Publish",TclPublish,NULL,NULL); - AddCommand(pInter,"GetLog", LogCapture,NULL,NULL); - AddCommand(pInter,"config", ConfigCon,NULL,NULL); - AddCommand(pInter,"wait", UserWait,NULL,NULL); - AddCommand(pInter,"status", UserStatus,NULL,NULL); - AddCommand(pInter,"ResetServer",ResetStatus,NULL,NULL); - AddCommand(pInter,"Dir",ListObjects,NULL,NULL); - AddCommand(pInter,"SetInt", SetSICSInterrupt,NULL,NULL); - AddCommand(pInter,"GetInt",GetSICSInterrupt,NULL,NULL); - AddCommand(pInter,"SICSType",SICSType,NULL,NULL); - AddCommand(pInter,"SICSBounds",SICSBounds,NULL,NULL); - AddCommand(pInter,"SICSStatus",SICSStatus,NULL,NULL); - AddCommand(pInter,"sicstime",SICSTime,NULL,NULL); - AddCommand(pInter,"sicsdescriptor",SICSDescriptor,NULL,NULL); - AddCommand(pInter,"SetStatus",SetSICSStatus,NULL,NULL); - AddCommand(pInter,"db",SICSDebug,NULL,NULL); - AddCommand(pInter,"EVFactory",EVControlFactory,NULL,NULL); - AddCommand(pInter,"emon",EVWrapper,DeleteEnvMon,pEnv); - AddCommand(pInter,"commandlog",CommandLog,CommandLogClose,NULL); - AddCommand(pInter,"udpquieck",QuieckAction,KillQuieck,NULL); - AddCommand(pInter,"alias",MakeAlias,NULL,NULL); - AddCommand(pInter,"findalias",LocateAliasAction,NULL,NULL); - AddCommand(pInter,"sicscron",MakeCron,NULL,NULL); - AddCommand(pInter,"dolater",MakeCron,NULL,NULL); - AddCommand(pInter,"sicsdatafactory",SICSDataFactory,NULL,NULL); - AddCommand(pInter,"scriptcallback",CallbackScript,NULL,NULL); - AddCommand(pInter,"help",SicsHelp,KillHelp,NULL); - AddCommand(pInter,"sicslist",SicsList,NULL,NULL); - AddCommand(pInter,"InstallHdb",InstallSICSHipadaba,NULL,NULL); - MakeProtocol(pInter); - - /* 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(pInter,"StopExe",StopCommand,DeleteExeList, pExe); - AddCommand(pInter,"ListExe",ListExe,NULL,pExe); - AddCommand(pInter,"sicsidle",SicsIdle,NULL,pExe); - AddCommand(pInter,"Success",Success,NULL,pExe); - AddCommand(pInter,"pause",PauseAction,NULL,pExe); - AddCommand(pInter,"continue",ContinueAction,NULL,pExe); - AddCommand(pInter,"devexec",DevexecAction,NULL,pExe); - - /* add additional object creation commands here */ - AddCommand(pInter,"TokenInit",TokenInit,NULL,NULL); - AddCommand(pInter,"ServerOption",IFServerOption,NULL,NULL); - AddCommand(pInter,"SicsUser", PWSicsUser,NULL,NULL); - AddCommand(pInter,"VarMake",VarFactory,NULL,NULL); - AddCommand(pInter,"MakeDrive",MakeDrive,NULL,NULL); - AddCommand(pInter,"Motor",MotorCreate,NULL,NULL); - AddCommand(pInter,"MakeMulti",MakeMulti,NULL,NULL); - AddCommand(pInter,"MakeMono",MonoInit,NULL,NULL); - AddCommand(pInter,"MakeWaveLength",MakeWaveLengthVar,NULL,NULL); - AddCommand(pInter,"MakeEnergy",MakeEnergyVar,NULL,NULL); - AddCommand(pInter,"MakeCounter",MakeCounter,NULL,NULL); - AddCommand(pInter,"MakeO2T",CreateO2T,NULL,NULL); - AddCommand(pInter,"SicsAlias",SicsAlias,NULL,NULL); - AddCommand(pInter,"DefineAlias",DefineAlias,NULL,NULL); /* M.Z. */ - AddCommand(pInter,"MakeHM",MakeHistMemory,NULL,NULL); - AddCommand(pInter,"VelocitySelector",VelSelFactory,NULL,NULL); - AddCommand(pInter,"MakeDataNumber",DNFactory,NULL,NULL); - AddCommand(pInter,"MakeScanCommand",ScanFactory,NULL,NULL); - AddCommand(pInter,"MakePeakCenter",FitFactory,NULL,NULL); - AddCommand(pInter,"MakeHKL",HKLFactory,NULL,NULL); - AddCommand(pInter,"MakeOptimise",MakeOptimiser,NULL,NULL); - AddCommand(pInter,"MakeMesure",MesureFactory,NULL,NULL); - AddCommand(pInter,"kill_command",SICSKill,NULL,NULL); - AddCommand(pInter,"MakeChopper",ChocoFactory,NULL,NULL); - AddCommand(pInter,"ChopperAdapter",CHAdapterFactory,NULL,NULL); - AddCommand(pInter,"MakeHklscan",HklscanFactory,NULL,NULL); - AddCommand(pInter,"MakeXYTable",XYFactory,NULL,NULL); - AddCommand(pInter,"MakeMaximize",MaximizeFactory,NULL,NULL); - AddCommand(pInter,"MakeLin2Ang",MakeLin2Ang,NULL,NULL); - AddCommand(pInter,"MakeSync",MakeSync,NULL,NULL); - AddCommand(pInter,"MakeHMControl",MakeHMControl,NULL,NULL); - AddCommand(pInter,"MakeRS232Controller",RS232Factory,NULL,NULL); - AddCommand(pInter,"MakeMaxDetector",LoMaxFactory,NULL,NULL); - AddCommand(pInter,"AntiCollisionInstall",AntiColliderFactory,NULL,NULL); - AddCommand(pInter,"MakeGPIB",MakeGPIB,NULL,NULL); - AddCommand(pInter,"MakeNXScript",MakeNXScript,NULL,NULL); - AddCommand(pInter,"MakeTclInt",MakeTclInt,NULL,NULL); - AddCommand(pInter,"TclReplaceDrivable",TclReplaceDrivable,NULL,NULL); - AddCommand(pInter,"DrivableInvoke", TclDrivableInvoke,NULL,NULL); - AddCommand(pInter,"UpdateFactory",UpdateFactory,NULL,NULL); - AddCommand(pInter,"allowexec",AllowExec,NULL,NULL); - AddCommand(pInter,"MakeConfigurableMotor", - MakeConfigurableVirtualMotor,NULL,NULL); - AddCommand(pInter,"MakeBatchManager", - MakeExeManager,NULL,NULL); - AddCommand(pInter,"MakeOscillator", - MakeOscillator,NULL,NULL); - AddCommand(pInter,"MakeDiffScan", - MakeDiffScan,NULL,NULL); - AddCommand(pInter,"MakeHKLMot", - HKLMotInstall,NULL,NULL); - AddCommand(pInter,"MakeUBCalc", - MakeUBCalc,NULL,NULL); - AddCommand(pInter,"MakeTasUB", - TasUBFactory,NULL,NULL); - AddCommand(pInter,"MakeTasScan", - TASUBScanFactory,NULL,NULL); - AddCommand(pInter,"MakeMcStasReader", - McStasReaderFactory,NULL,NULL); - AddCommand(pInter,"MakeMcStasController", - McStasControllerFactory,NULL,NULL); - AddCommand(pInter,"InstallSinfox", - InstallSinfox,NULL,NULL); - AddCommand(pInter,"MakeCone", - MakeCone,NULL,NULL); - AddCommand(pInter,"MakeMultiCounter", - MakeMultiCounter,NULL,NULL); - AddCommand(pInter,"MakeSicsPoll", - InstallSICSPoll,NULL,NULL); - AddCommand(pInter,"MakeStateMon", - StateMonFactory,NULL,NULL); - AddCommand(pInter,"MakeAsyncProtocol",AsyncProtocolFactory,NULL,NULL); - AddCommand(pInter,"MakeAsyncQueue",AsyncQueueFactory,NULL,NULL); - AddCommand(pInter,"MakeSicsObj",InstallSICSOBJ,NULL,NULL); - AddCommand(pInter,"DynSicsObj",InstallSICSOBJ,NULL,NULL); -/* AddCommand(pInter,"MakeHdbQueue",MakeHDBQueue,NULL,NULL); */ - AddCommand(pInter,"MakeGenController",GenControllerFactory,NULL,NULL); - AddCommand(pInter,"genconfigure",GenControllerConfigure,NULL,NULL); - AddCommand(pInter,"MakeProxy",ProxyFactory,NULL,NULL); - - /* - install site specific commands - */ - site = getSite(); - if(site != NULL){ - site->AddSiteCommands(pInter); - } - } -/*---------------------------------------------------------------------------*/ - static void KillIniCommands(SicsInterp *pSics) - { - pSite site = NULL; - - /* specify superfluous initialization commands here */ - RemoveCommand(pSics,"TokenInit"); - RemoveCommand(pSics,"ServerOption"); - RemoveCommand(pSics,"SicsUser"); - RemoveCommand(pSics,"VarMake"); - RemoveCommand(pSics,"MakeDrive"); - RemoveCommand(pSics,"Motor"); -/* - RemoveCommand(pSics,"MakeMulti"); -*/ - RemoveCommand(pSics,"MakeMono"); - RemoveCommand(pSics,"MakeWaveLength"); - RemoveCommand(pSics,"MakeEnergy"); - RemoveCommand(pSics,"MakeCounter"); - RemoveCommand(pSics,"MakeRuenBuffer"); - RemoveCommand(pSics,"MakeScan"); - RemoveCommand(pSics,"MakeO2T"); - RemoveCommand(pSics,"SicsAlias"); - RemoveCommand(pSics,"MakeHM"); - RemoveCommand(pSics,"VelocitySelector"); - RemoveCommand(pSics,"MakeDataNumber"); - RemoveCommand(pSics,"MakeScanCommand"); - RemoveCommand(pSics,"MakePeakCenter"); - RemoveCommand(pSics,"MakeHKL"); - RemoveCommand(pSics,"MakeOptimiser"); - RemoveCommand(pSics,"MakeMesure"); - RemoveCommand(pSics,"MakeChopper"); - RemoveCommand(pSics,"ChopperAdapter"); - RemoveCommand(pSics,"MakeHklscan"); - RemoveCommand(pSics,"MakeXYTable"); - RemoveCommand(pSics,"MakeMaximize"); - RemoveCommand(pSics,"MakeLin2Ang"); - RemoveCommand(pSics,"MakeSync"); - RemoveCommand(pSics,"MakeHMControl"); - RemoveCommand(pSics,"MakeRS232Controller"); - RemoveCommand(pSics,"MakeMaxDetector"); - RemoveCommand(pSics,"AntiColliderInstall"); - RemoveCommand(pSics,"MakeGPIB"); - RemoveCommand(pSics,"MakeNXScript"); - RemoveCommand(pSics,"MakeTclInt"); - RemoveCommand(pSics,"UpdateFactory"); - RemoveCommand(pSics,"allowexec"); - RemoveCommand(pSics,"MakeConfigurableMotor"); - RemoveCommand(pSics,"MakeBatchManager"); - RemoveCommand(pSics,"MakeOscillator"); - RemoveCommand(pSics,"MakeDiffScan"); - RemoveCommand(pSics,"MakeHKLMot"); - RemoveCommand(pSics,"MakeUBCalc"); - RemoveCommand(pSics,"MakeTasUB"); - RemoveCommand(pSics,"MakeTasScan"); - RemoveCommand(pSics,"MakemcStasReader"); - RemoveCommand(pSics,"InstallSinfox"); - RemoveCommand(pSics,"MakeCone"); - RemoveCommand(pSics,"MakeMultiCounter"); - RemoveCommand(pSics,"MakeStateMon"); -// RemoveCommand(pSics,"MakeAsyncQueue"); -// RemoveCommand(pSics,"MakeAsyncProtocol"); - RemoveCommand(pSics,"MakeSicsObject"); - RemoveCommand(pSics,"MakeGenController"); - RemoveCommand(pSics,"genconfigure"); - RemoveCommand(pSics,"MakeProxy"); - /* - remove site specific installation commands - */ - site = getSite(); - if(site != NULL){ - site->RemoveSiteCommands(pSics); - } - } +extern void DevExecInit(void); /* devexec.c */ /*--------------------------------------------------------------------------*/ - void InitGeneral(void) - { +static void InitGeneral(void) +{ #define INIT(F) { void F(void); F(); } /* insert here initialization routines ... */ - INIT(StatisticsInit); - INIT(InitializerInit); - INIT(SaveHdbInit); /* must be after InitializerInit */ - INIT(SctInit); - INIT(SctDriveInit); - INIT(LogReaderInit); - INIT(LogSetupInit); - INIT(StatusFileInit); + INIT(StatisticsInit); + INIT(InitializerInit); + INIT(SaveHdbInit); /* must be after InitializerInit */ + INIT(DefineAliasInit); + INIT(SctInit); + INIT(SctDriveAdapterInit); + INIT(SctDriveObjInit); + INIT(SctDriveAdapterInit); + INIT(LogReaderInit); + INIT(LogSetupInit); + INIT(InstallBackground); + INIT(MakeProtocol); + INIT(CommandLogInit); + INIT(UdpInit); + INIT(HelpInit); + INIT(AddTestProt); + INIT(AddGenBinProtocoll); + INIT(AddSyncedProt); + INIT(MakeTrace); + INIT(SiteInit); /* site specific initializations */ +} + +static void InitIniCommands(SicsInterp * pInter) +{ + +/* declare and add permanent command */ +#define PCMD(NAME, FUN) { \ + int FUN(SConnection * pCon, SicsInterp * pSics, void *pData, \ + int argc, char *argv[]); \ + AddCommandWithFlag(pInter, NAME, FUN, NULL, NULL, 0); \ + } + +/* declare and add startup command */ +#define SCMD(NAME, FUN) { \ + int FUN(SConnection * pCon, SicsInterp * pSics, void *pData, \ + int argc, char *argv[]); \ + AddCommandWithFlag(pInter, NAME, FUN, NULL, NULL, 1); \ + } + + /* permanent commands in alphabetic order */ + PCMD("alias", MakeAlias); + PCMD("broadcast", Broadcast); + PCMD("Capture", CaptureAction); + PCMD("ClientPut", ClientPut); + PCMD("ClientLog", ClientLog); + PCMD("config", ConfigCon); + PCMD("db", SICSDebug); + PCMD("Dir", ListObjects); + PCMD("dolater", MakeCron); + PCMD("DrivableInvoke", TclDrivableInvoke); + PCMD("DynSicsObj", InstallSICSOBJ); + PCMD("EVFactory", EVControlFactory); + PCMD("FileEval", MacroFileEval); + PCMD("findalias", LocateAliasAction); + PCMD("fulltransact", TransactAction); + PCMD("GetInt", GetSICSInterrupt); + PCMD("GetLog", LogCapture); + PCMD("GumPut", GumPut); + PCMD("InternEval", InternalFileEval); + PCMD("kill_command", SICSKill); + PCMD("list", SicsList); + PCMD("MakeMcStasController", McStasControllerFactory); + PCMD("MakeMulti", MakeMulti); + PCMD("MakeOptimise", MakeOptimiser); + PCMD("MakeSecMotor", SecMotorFactory); + PCMD("Publish", TclPublish); + PCMD("Remob", RemobCreate); + PCMD("ResetServer", ResetStatus); + PCMD("scriptcallback", CallbackScript); + PCMD("SetInt", SetSICSInterrupt); + PCMD("SetStatus", SetSICSStatus); + PCMD("SICSBounds", SICSBounds); + PCMD("sicscron", MakeCron); + PCMD("sicsdatafactory", SICSDataFactory); + PCMD("sicsdescriptor", SICSDescriptor); + PCMD("sicsprompt", SicsPrompt); + PCMD("SICSStatus", SICSStatus); + PCMD("sicstime", SICSTime); + PCMD("doubletime", SICSDoubleTime); + PCMD("SICSType", SICSType); + PCMD("Sics_Exitus", SicsExit); + PCMD("silent", SICSSilent); + PCMD("status", UserStatus); + PCMD("TclReplaceDrivable", TclReplaceDrivable); + PCMD("transact", TransactAction); + PCMD("wait", UserWait); + PCMD("checksum", CheckSum); + + /* startup commands in alphabetic order */ + SCMD("allowexec", AllowExec); + SCMD("AntiCollisionInstall", AntiColliderFactory); + SCMD("ChopperAdapter", CHAdapterFactory); + SCMD("InstallSinfox", InstallSinfox); + SCMD("MakeAsyncProtocol", AsyncProtocolFactory); + SCMD("MakeAsyncQueue", AsyncQueueFactory); + SCMD("MakeBatchManager", MakeExeManager); + SCMD("MakeChopper", ChocoFactory); + SCMD("MakeCone", MakeCone); + SCMD("MakeConfigurableMotor", MakeConfigurableVirtualMotor); + SCMD("MakeCounter", MakeCounter); + SCMD("MakeDataNumber", DNFactory); + SCMD("MakeDiffScan", MakeDiffScan); + SCMD("MakeDrive", MakeDrive); + SCMD("MakeEnergy", MakeEnergyVar); + SCMD("MakeGPIB", MakeGPIB); + SCMD("MakeHdbTable", HdbTableFactory); + SCMD("MakeHKL", HKLFactory); + SCMD("MakeHKLMot", HKLMotInstall); + SCMD("MakeHM", MakeHistMemory); + SCMD("MakeHMControl", MakeHMControl); + SCMD("MakeLin2Ang", MakeLin2Ang); + SCMD("MakeMaxDetector", LoMaxFactory); + SCMD("MakeMaximize", MaximizeFactory); + SCMD("MakeMcStasReader", McStasReaderFactory); + SCMD("MakeMono", MonoInit); + SCMD("MakeMultiCounter", MakeMultiCounter); + SCMD("MakeNXScript", MakeNXScript); + SCMD("MakeO2T", CreateO2T); + SCMD("MakeOscillator", MakeOscillator); + SCMD("MakePeakCenter", FitFactory); + SCMD("MakeProxy", ProxyFactory); + SCMD("MakeRefList", MakeReflectionList); + SCMD("MakeRS232Controller", RS232Factory); + SCMD("MakeSansBC", SansBCFactory); + SCMD("MakeScanCommand", ScanFactory); + SCMD("MakeSecCounter", MakeSecCter); + SCMD("MakeSecHM", MakeSecHM); + SCMD("MakeSecNVS", MakeSecNVS); + SCMD("MakeSicsObj", InstallSICSOBJ); + SCMD("MakeSicsPoll", InstallSICSPoll); + SCMD("MakeSingleX", MakeSingleX); + SCMD("MakeStateMon", StateMonFactory); + SCMD("MakeSync", MakeSync); + SCMD("MakeTasScan", TASUBScanFactory); + SCMD("MakeTasUB", TasUBFactory); + SCMD("MakeTclInt", MakeTclInt); + SCMD("MakeUBCalc", MakeUBCalc); + SCMD("MakeWaveLength", MakeWaveLengthVar); + SCMD("MakeXYTable", XYFactory); + SCMD("Motor", MotorCreate); + SCMD("ServerOption", IFServerOption); + SCMD("SicsAlias", SicsAlias); + SCMD("SicsUser", PWSicsUser); + SCMD("TokenInit", TokenInit); + SCMD("UpdateFactory", UpdateFactory); + SCMD("VarMake", VarFactory); + SCMD("VelocitySelector", VelSelFactory); + +} - INIT(SiteInit); /* site specific initializations */ - } /*--------------------------------------------------------------------------*/ - int InitObjectCommands(pServer pServ, char *file) - { - SConnection *pCon = NULL; - char pBueffel[1024]; - int iRet; - SicsInterp *pSics; - - pSics = pServ->pSics; - assert(pSics); - - InitGeneral(); - - /* general initialization */ - /* create a connection */ - pCon = SCCreateDummyConnection(pSics); - if(!pCon) - { - return 0; - } - MakeExeManager(pCon,pSics,NULL,1, NULL); - InitIniCommands(pSics,pServ->pTasker); - InstallBckRestore(pCon,pSics); - - pCon->iFiles = 0; - - /* evaluate the file */ - sprintf(pBueffel,"fileeval %s",file); - iRet = InterpExecute(pSics,pCon,pBueffel); - if(!iRet) - { - KillIniCommands(pSics); - RemoveStartupCommands(); - SCDeleteConnection(pCon); - return 0; - } - - /* done */ - pCon->iFiles = 0; - SCDeleteConnection(pCon); - KillIniCommands(pSics); - RemoveStartupCommands(); - return 1; - } +int InitObjectCommands(pServer pServ, char *file) +{ + SConnection *pCon = NULL; + char pBueffel[1024]; + int iRet; + SicsInterp *pSics; + pExeList pExe; + pEnvMon pEnv = NULL; + pSite site = NULL; + pSics = pServ->pSics; + assert(pSics); + + InitGeneral(); + + /* general initialization */ + /* create a connection */ + pCon = SCCreateDummyConnection(pSics); + if (!pCon) { + return 0; + } + MakeExeManager(pCon, pSics, NULL, 1, NULL); + + pExe = CreateExeList(pServ->pTasker); + pServ->pExecutor = pExe; + pEnv = CreateEnvMon(); + DevExecInit(); + + assert(pExe); + assert(pEnv); + + InitIniCommands(pSics); + /* + install site specific commands + */ + site = getSite(); + if (site != NULL) { + site->AddSiteCommands(pServ->pSics); + } + + InstallBckRestore(pCon, pSics); + InstallSICSHipadaba(pCon, pSics,NULL,0,NULL); + + /* evaluate the file */ + snprintf(pBueffel,sizeof(pBueffel)-1, "fileeval %s", file); + iRet = InterpExecute(pSics, pCon, pBueffel); + + /* done */ + SCDeleteConnection(pCon); + if (site != NULL && site->RemoveSiteCommands != NULL) { + site->RemoveSiteCommands(pSics); + } + + RemoveStartupCommands(); + return 1; +} diff --git a/ofac.h b/ofac.h index abd49042..fd13d0f2 100644 --- a/ofac.h +++ b/ofac.h @@ -1,26 +1,25 @@ -/*--------------------------------------------------------------------------- +/** + * Startup commands and definitions + * + * copyright: see file COPYRIGHT + * + * SICS is a highly configurable system. This function implements + * the configurable. Configuration is meant to happen via a Tcl- + * configuration script. This module will initialize commands which + * create SICS-objects. Than an initialization file is evaluated + * via the macro facility. As most of the initialization commands + * will no longer be needed after this, they will be deleted. + * All this will be run with a higly privileged connection which + * prints to stdout/stdin. + * + * Mark Koennecke 1996 - ? + * Markus Zolliker Jan 2010 + */ - ObjectFactory - - - SICS is a highly configurable system. This module implements - the configurable. Configuration is meant to happen via a Tcl- - configuration script. This module will initialize commands which - create SICS-objects. Than an initialization file is evaluated - via the macro facility. As most of the initialization commands - will no longer be needed after this, they will be deleted. - All this will be run with a higly privileged connection which - prints to stdout/stdin. - - Mark Koennecke, November 1996 - - copyright: see implementation file - ------------------------------------------------------------------------------*/ #ifndef OBJECTFACTORY #define OBJECTFACTORY +#include "sics.h" + +int InitObjectCommands(pServer pServ, char *file); - int InitObjectCommands(pServer pServ, char *file); - #endif - diff --git a/optimise.c b/optimise.c index 64afe2cb..c21dbfd2 100644 --- a/optimise.c +++ b/optimise.c @@ -28,1057 +28,955 @@ #define MAXFLOAT 9999999.99 #endif -#define ABS(x) (x < 0 ? -(x) : (x)) +#define ABS(x) (x < 0 ? -(x) : (x)) /*----------------- local variable structure -----------------------------*/ - typedef struct { - char *pName; - float fStep; - int iStep; - float fPrecision; - float fCenter; - float fShift; - pIDrivable pDriv; - void *pData; - int iLost; - } OVarEntry, *pOVarEntry; +typedef struct { + char *pName; + float fStep; + int iStep; + float fPrecision; + float fCenter; + float fShift; + pIDrivable pDriv; + void *pData; + int iLost; +} OVarEntry, *pOVarEntry; /*-------------------------------------------------------------------------*/ - static void FreeOVar(void *pData) - { - pOVarEntry self = NULL; - - self = (pOVarEntry)pData; - if(!self) - return; - - if(self->pName) - { - free(self->pName); - } - free(self); - } - +static void FreeOVar(void *pData) +{ + pOVarEntry self = NULL; + + self = (pOVarEntry) pData; + if (!self) + return; + + if (self->pName) { + free(self->pName); + } + free(self); +} + /*-------------------- the optimise structure -----------------------------*/ - typedef struct __OptimiseStruct { - pObjectDescriptor pDes; - int iMaxCycles; - CounterMode eCount; - float fPreset; - int iChannel; - float fThreshold; - int iVar; - pDynar pVariables; - pScanData pScanner; - pFit pPeakFitter; - } Optimiser; - -/*--- dummy functions to stop scan from writing scan files --------------*/ +typedef struct __OptimiseStruct { + pObjectDescriptor pDes; + int iMaxCycles; + CounterMode eCount; + float fPreset; + int iChannel; + float fThreshold; + int iVar; + pDynar pVariables; + pScanData pScanner; + pFit pPeakFitter; +} Optimiser; + +/*--- dummy functions to stop scan from writing scan files --------------*/ + +static int DummyHeader(pScanData self) +{ + return 1; +} +static int DummyHeader2(pScanData self, int iPoint) +{ + return 1; +} - static int DummyHeader(pScanData self) - { - return 1; - } - static int DummyHeader2(pScanData self,int iPoint) - { - return 1; - } /*------------------------------------------------------------------------*/ - pOptimise CreateOptimiser(pCounter pCount) - { - pOptimise pNew = NULL; - - assert(pCount); - - /* get some memory */ - pNew = (pOptimise)malloc(sizeof(Optimiser)); - if(!pNew) - { - return NULL; - } - memset(pNew,0,sizeof(Optimiser)); - - /* initialise a few defaults */ - pNew->fThreshold = 100; - pNew->iMaxCycles = 7; - pNew->iChannel = 0; - pNew->eCount = eTimer; - pNew->iVar = 0; - pNew->fPreset = 10000.; - - pNew->pDes = CreateDescriptor("PeakOptimiser"); - if(!pNew->pDes) - { - free(pNew); - return NULL; - } - - pNew->pScanner = CreateScanObject(NULL,NULL,pCount,"optiscan"); - if(!pNew->pScanner) - { - DeleteDescriptor(pNew->pDes); - free(pNew); - return NULL; - - } - pNew->pScanner->WriteHeader = DummyHeader; - pNew->pScanner->WriteScanPoints = DummyHeader2; - - pNew->pPeakFitter = CreateFitCenter(pNew->pScanner); - if(!pNew->pPeakFitter) - { - DeleteDescriptor(pNew->pDes); - DeleteScanObject(pNew->pScanner); - free(pNew); - return NULL; - } - - pNew->iVar = 0; - pNew->pVariables = CreateDynar(0,10,10,FreeOVar); - if(!pNew->pVariables) - { - DeleteFitCenter(pNew->pPeakFitter); - DeleteDescriptor(pNew->pDes); - DeleteScanObject(pNew->pScanner); - free(pNew); - return NULL; - } - - return pNew; - } -/*--------------------------------------------------------------------------*/ - void DeleteOptimiser(void *pData) - { - pOptimise self = NULL; - - self = (pOptimise)pData; - if(!self) - return; - - if(self->pVariables) - { - DeleteDynar(self->pVariables); - } - - if(self->pPeakFitter) - { - DeleteFitCenter(self->pPeakFitter); - } - if(self->pDes) - { - DeleteDescriptor(self->pDes); - } - if(self->pScanner) - { - DeleteScanObject(self->pScanner); - } - - free(self); +pOptimise CreateOptimiser(pCounter pCount) +{ + pOptimise pNew = NULL; + + assert(pCount); + + /* get some memory */ + pNew = (pOptimise) malloc(sizeof(Optimiser)); + if (!pNew) { + return NULL; } + memset(pNew, 0, sizeof(Optimiser)); + + /* initialise a few defaults */ + pNew->fThreshold = 100; + pNew->iMaxCycles = 7; + pNew->iChannel = 0; + pNew->eCount = eTimer; + pNew->iVar = 0; + pNew->fPreset = 10000.; + + pNew->pDes = CreateDescriptor("PeakOptimiser"); + if (!pNew->pDes) { + free(pNew); + return NULL; + } + + pNew->pScanner = CreateScanObject(NULL, NULL, pCount, "optiscan"); + if (!pNew->pScanner) { + DeleteDescriptor(pNew->pDes); + free(pNew); + return NULL; + + } + pNew->pScanner->WriteHeader = DummyHeader; + pNew->pScanner->WriteScanPoints = DummyHeader2; + + pNew->pPeakFitter = CreateFitCenter(pNew->pScanner); + if (!pNew->pPeakFitter) { + DeleteDescriptor(pNew->pDes); + DeleteScanObject(pNew->pScanner); + free(pNew); + return NULL; + } + + pNew->iVar = 0; + pNew->pVariables = CreateDynar(0, 10, 10, FreeOVar); + if (!pNew->pVariables) { + DeleteFitCenter(pNew->pPeakFitter); + DeleteDescriptor(pNew->pDes); + DeleteScanObject(pNew->pScanner); + free(pNew); + return NULL; + } + + return pNew; +} + /*--------------------------------------------------------------------------*/ - void OptimiserClear(pOptimise self) - { - assert(self); - self->iVar = 0; - } +void DeleteOptimiser(void *pData) +{ + pOptimise self = NULL; + + self = (pOptimise) pData; + if (!self) + return; + + if (self->pVariables) { + DeleteDynar(self->pVariables); + } + + if (self->pPeakFitter) { + DeleteFitCenter(self->pPeakFitter); + } + if (self->pDes) { + DeleteDescriptor(self->pDes); + } + if (self->pScanner) { + DeleteScanObject(self->pScanner); + } + + free(self); +} + /*--------------------------------------------------------------------------*/ - int OptimiserAdd(pOptimise self, - char *pName, float fStep, int nStep, float fPrecision) - { - OVarEntry sNeu; - CommandList *pCom = NULL; - - /* find and check our object */ - pCom = FindCommand(pServ->pSics,pName); - if(!pCom) - { - return 0; - } - sNeu.pData = pCom->pData; - sNeu.pDriv = GetDrivableInterface(sNeu.pData); - if(!sNeu.pDriv) - { - return 0; - } - sNeu.fStep = fStep; - sNeu.iStep = nStep; - sNeu.fPrecision = fPrecision; - sNeu.pName = strdup(pName); - sNeu.iLost = 0; - - DynarPutCopy(self->pVariables,self->iVar,&sNeu,sizeof(OVarEntry)); - self->iVar++; - - return 1; - } +void OptimiserClear(pOptimise self) +{ + assert(self); + self->iVar = 0; +} + /*--------------------------------------------------------------------------*/ - int OptimiserSetPar(pOptimise self, char *name, float fVal) - { - if(strcmp(name,"maxcycles") == 0) - { - self->iMaxCycles = (int)fVal; - return 1; - } - else if(strcmp(name,"threshold") == 0) - { - self->fThreshold = fVal; - return 1; - } - else if(strcmp(name,"channel") == 0) - { - self->iChannel = (int)fVal; - return 1; - } - else if(strcmp(name,"preset") == 0) - { - self->fPreset = fVal; - return 1; - } - else if(strcmp(name,"countmode") == 0) - { - if(fVal < 0.05) - { - self->eCount = eTimer; - } - else - { - self->eCount = ePreset; - } - return 1; - } - else - { - return 0; - } - } +int OptimiserAdd(pOptimise self, + char *pName, float fStep, int nStep, float fPrecision) +{ + OVarEntry sNeu; + CommandList *pCom = NULL; + + /* find and check our object */ + pCom = FindCommand(pServ->pSics, pName); + if (!pCom) { + return 0; + } + sNeu.pData = pCom->pData; + sNeu.pDriv = GetDrivableInterface(sNeu.pData); + if (!sNeu.pDriv) { + return 0; + } + sNeu.fStep = fStep; + sNeu.iStep = nStep; + sNeu.fPrecision = fPrecision; + sNeu.pName = strdup(pName); + sNeu.iLost = 0; + + DynarPutCopy(self->pVariables, self->iVar, &sNeu, sizeof(OVarEntry)); + self->iVar++; + + return 1; +} + /*--------------------------------------------------------------------------*/ - int OptimiserGetPar(pOptimise self, char *name, float *fVal) - { - if(strcmp(name,"maxcycles") == 0) - { - *fVal = self->iMaxCycles; - return 1; - } - else if(strcmp(name,"threshold") == 0) - { - *fVal = self->fThreshold; - return 1; - } - else if(strcmp(name,"channel") == 0) - { - *fVal = self->iChannel; - return 1; - } - else if(strcmp(name,"preset") == 0) - { - *fVal = self->fPreset; - return 1; - } - else if(strcmp(name,"countmode") == 0) - { - if(self->eCount == eTimer) - { - *fVal = 0.; - } - else - { - *fVal = 1.0; - } - return 1; - } - else - { - return 0; - } - } +int OptimiserSetPar(pOptimise self, char *name, float fVal) +{ + if (strcmp(name, "maxcycles") == 0) { + self->iMaxCycles = (int) fVal; + return 1; + } else if (strcmp(name, "threshold") == 0) { + self->fThreshold = fVal; + return 1; + } else if (strcmp(name, "channel") == 0) { + self->iChannel = (int) fVal; + return 1; + } else if (strcmp(name, "preset") == 0) { + self->fPreset = fVal; + return 1; + } else if (strcmp(name, "countmode") == 0) { + if (fVal < 0.05) { + self->eCount = eTimer; + } else { + self->eCount = ePreset; + } + return 1; + } else { + return 0; + } +} + +/*--------------------------------------------------------------------------*/ +int OptimiserGetPar(pOptimise self, char *name, float *fVal) +{ + if (strcmp(name, "maxcycles") == 0) { + *fVal = self->iMaxCycles; + return 1; + } else if (strcmp(name, "threshold") == 0) { + *fVal = self->fThreshold; + return 1; + } else if (strcmp(name, "channel") == 0) { + *fVal = self->iChannel; + return 1; + } else if (strcmp(name, "preset") == 0) { + *fVal = self->fPreset; + return 1; + } else if (strcmp(name, "countmode") == 0) { + if (self->eCount == eTimer) { + *fVal = 0.; + } else { + *fVal = 1.0; + } + return 1; + } else { + return 0; + } +} + /*---------------------------------------------------------------------------*/ - static int OptimiserInit(pOptimise self,SConnection *pCon) - { - int i, iRet; - void *pData; - pOVarEntry pOVar; - float fVal; - - /* initialise each variable entry with the current position and - set the shift to something senseless. - */ - for(i = 0; i < self->iVar; i++) - { - DynarGet(self->pVariables,i,&pData); - pOVar = (pOVarEntry)pData; - pOVar->fCenter = pOVar->pDriv->GetValue(pOVar->pData,pCon); - if(pOVar->fCenter < -900.) - { - return SCANERROR; - } - pOVar->fShift = MAXFLOAT; - pOVar->iLost = 0; - } - self->pScanner->iChannel = self->iChannel; - return 1; - } -/*-------------------------------------------------------------------------*/ - static int CenterVariable(pOptimise self, SConnection *pCon, int i) - { - pOVarEntry pOvar; - void *pData; - int iRet, iReturn; - float fStart; - float fNewCenter, fStdDev, FWHM, fMax; - char pBueffel[512], cData[80]; - - assert(self); - assert( (i >= 0) && (i < self->iVar)); - assert(pCon); - - /* get variable data */ - DynarGet(self->pVariables,i,&pData); - pOvar = (pOVarEntry)pData; - - /* do a scan first */ - fStart = pOvar->fCenter - (pOvar->iStep/2)*pOvar->fStep; - ClearScanVar(self->pScanner); - iRet = AddScanVar(self->pScanner, pServ->pSics,pCon, - pOvar->pName, fStart, pOvar->fStep); - if(!iRet) - { - return 0; - } - sprintf(pBueffel,"Trying hard to optimise variable %s",pOvar->pName); - SCWrite(pCon,pBueffel,eWarning); - iRet = SilentScan(self->pScanner,pOvar->iStep,self->eCount, - self->fPreset,pServ->pSics,pCon); - if(!iRet) - { - return SCANABORT; - } - - /* try to find a fit for this one */ - iRet = CalculateFit(self->pPeakFitter); - if(iRet == 0) - { - return SYSERROR; - } - GetFitResults(self->pPeakFitter, &fNewCenter,&fStdDev, &FWHM, &fMax); +static int OptimiserInit(pOptimise self, SConnection * pCon) +{ + int i, iRet; + void *pData; + pOVarEntry pOVar; + float fVal; - /* write some diagnostic messages */ - strcpy(pBueffel,"Peak Diagnosis: \n"); - sprintf(cData,"New %s position: %f \n",pOvar->pName,fNewCenter); - switch(iRet) - { - case 1: - strcat(pBueffel,"Peak found in scan range \n"); - strcat(pBueffel,cData); - iReturn = 1; - break; - case -1: - strcat(pBueffel,"Left half of peak missing \n"); - strcat(pBueffel, - "Extending scan range and setting position to maximum \n"); - strcat(pBueffel,cData); - iReturn = VARREDO; - break; - case -2: - strcat(pBueffel,"Right half of peak missing \n"); - strcat(pBueffel, - "Extending scan range and setting position to maximum \n"); - strcat(pBueffel,cData); - iReturn = 2; - break; - case -3: - case -4: - strcat(pBueffel,"No data in scan \n"); - break; - default: - strcat(pBueffel,cData); - sprintf(pData,"Fitting ended with error code %d \n",iRet); - strcat(pBueffel,cData); - break; - } - SCWrite(pCon,pBueffel,eWarning); - - if(fMax < self->fThreshold) - { - SCWrite(pCon,"Peak may be lost, increasing scan range",eWarning); - pOvar->iLost++; - if(pOvar->iLost > 2) - { - return PEAKLOST; - } - } - else - { - pOvar->iLost = 0; - } - - - /* act upon the fits results */ - if(iRet != 1) { - /* not enough scan data for a proper evaluation of the - peak. But the peak fitter has given us the maximum of - the counts. What we do is, we set the center to the - maximum, increase the scan width and mark the variable - for a redo in the next cycle by leaving the fShift - high. But we do this only if the maximum is above a threshold, - otherwise we just increase the scan range and leave the thing - where it is. - */ - if(fMax > self->fThreshold) - { - pOvar->fCenter = fNewCenter; - } - pOvar->iStep += pOvar->iStep; - } - else /* the success case */ - { - pOvar->fShift = ABS(pOvar->fCenter - fNewCenter); - sprintf(pBueffel,"%s shifted by %8.2f ",pOvar->pName,pOvar->fShift); - SCWrite(pCon,pBueffel,eWarning); - pOvar->fPrecision = 3*fStdDev; - sprintf(pBueffel,"%s precision set to 3*StdDev = %8.3f", - pOvar->pName, 3*fStdDev); - SCWrite(pCon,pBueffel,eWarning); - pOvar->fCenter = fNewCenter; - } - /* drive to the new center */ - iRet = Drive(pCon,pServ->pSics,pOvar->pName,pOvar->fCenter); - if(!iRet) - { - return DRIVEERROR; - } - - return iReturn; + /* initialise each variable entry with the current position and + set the shift to something senseless. + */ + for (i = 0; i < self->iVar; i++) { + DynarGet(self->pVariables, i, &pData); + pOVar = (pOVarEntry) pData; + pOVar->fCenter = pOVar->pDriv->GetValue(pOVar->pData, pCon); + if (pOVar->fCenter < -900.) { + return SCANERROR; + } + pOVar->fShift = MAXFLOAT; + pOVar->iLost = 0; } + self->pScanner->iChannel = self->iChannel; + return 1; +} + +/*-------------------------------------------------------------------------*/ +static int CenterVariable(pOptimise self, SConnection * pCon, int i) +{ + pOVarEntry pOvar; + void *pData; + int iRet, iReturn; + float fStart; + float fNewCenter, fStdDev, FWHM, fMax; + char pBueffel[512], cData[80]; + + assert(self); + assert((i >= 0) && (i < self->iVar)); + assert(pCon); + + /* get variable data */ + DynarGet(self->pVariables, i, &pData); + pOvar = (pOVarEntry) pData; + + /* do a scan first */ + fStart = pOvar->fCenter - (pOvar->iStep / 2) * pOvar->fStep; + ClearScanVar(self->pScanner); + iRet = AddScanVar(self->pScanner, pServ->pSics, pCon, + pOvar->pName, fStart, pOvar->fStep); + if (!iRet) { + return 0; + } + snprintf(pBueffel,sizeof(pBueffel)-1, "Trying hard to optimise variable %s", pOvar->pName); + SCWrite(pCon, pBueffel, eLog); + iRet = SilentScan(self->pScanner, pOvar->iStep, self->eCount, + self->fPreset, pServ->pSics, pCon); + if (!iRet) { + return SCANABORT; + } + + /* try to find a fit for this one */ + iRet = CalculateFit(self->pPeakFitter); + if (iRet == 0) { + return SYSERROR; + } + GetFitResults(self->pPeakFitter, &fNewCenter, &fStdDev, &FWHM, &fMax); + + /* write some diagnostic messages */ + strcpy(pBueffel, "Peak Diagnosis: \n"); + snprintf(cData,sizeof(cData)-1, "New %s position: %f \n", pOvar->pName, fNewCenter); + switch (iRet) { + case 1: + strcat(pBueffel, "Peak found in scan range \n"); + strcat(pBueffel, cData); + iReturn = 1; + break; + case -1: + strcat(pBueffel, "Left half of peak missing \n"); + strcat(pBueffel, + "Extending scan range and setting position to maximum \n"); + strcat(pBueffel, cData); + iReturn = VARREDO; + break; + case -2: + strcat(pBueffel, "Right half of peak missing \n"); + strcat(pBueffel, + "Extending scan range and setting position to maximum \n"); + strcat(pBueffel, cData); + iReturn = 2; + break; + case -3: + case -4: + strcat(pBueffel, "No data in scan \n"); + break; + default: + strcat(pBueffel, cData); + snprintf(pData,sizeof(pData)-1, "Fitting ended with error code %d \n", iRet); + strcat(pBueffel, cData); + break; + } + SCWrite(pCon, pBueffel, eLog); + + if (fMax < self->fThreshold) { + SCWrite(pCon, "Peak may be lost, increasing scan range", eLog); + pOvar->iLost++; + if (pOvar->iLost > 2) { + return PEAKLOST; + } + } else { + pOvar->iLost = 0; + } + + + /* act upon the fits results */ + if (iRet != 1) { + /* not enough scan data for a proper evaluation of the + peak. But the peak fitter has given us the maximum of + the counts. What we do is, we set the center to the + maximum, increase the scan width and mark the variable + for a redo in the next cycle by leaving the fShift + high. But we do this only if the maximum is above a threshold, + otherwise we just increase the scan range and leave the thing + where it is. + */ + if (fMax > self->fThreshold) { + pOvar->fCenter = fNewCenter; + } + pOvar->iStep += pOvar->iStep; + } else { /* the success case */ + + pOvar->fShift = ABS(pOvar->fCenter - fNewCenter); + snprintf(pBueffel,sizeof(pBueffel)-1, "%s shifted by %8.2f ", pOvar->pName, pOvar->fShift); + SCWrite(pCon, pBueffel, eLog); + pOvar->fPrecision = 3 * fStdDev; + snprintf(pBueffel,sizeof(pBueffel)-1, "%s precision set to 3*StdDev = %8.3f", + pOvar->pName, 3 * fStdDev); + SCWrite(pCon, pBueffel, eLog); + pOvar->fCenter = fNewCenter; + } + /* drive to the new center */ + iRet = Drive(pCon, pServ->pSics, pOvar->pName, pOvar->fCenter); + if (!iRet) { + return DRIVEERROR; + } + + return iReturn; +} + /*------------------------------------------------------------------------ * We use the scan object here for counting. The reason is that this * handles well in the common case of a single counter but also has * provisions for other counting methods through the scan modules * scripting mechanism * ------------------------------------------------------------------------*/ -static long ClimbCount(pOptimise self, SConnection *pCon) +static long ClimbCount(pOptimise self, SConnection * pCon) { - int status; - long data[1]; - int (*CollectFunc)(pScanData self, int iPoint) = NULL; - - SilentPrepare(self->pScanner); + int status; + long data[1]; + int (*CollectFunc) (pScanData self, int iPoint) = NULL; - status = self->pScanner->ScanCount(self->pScanner,0); - if(status != 1) - { - return status; - } - if(self->pScanner->CollectScanData == CollectScanData) - { - CollectFunc = self->pScanner->CollectScanData; - self->pScanner->CollectScanData = CollectSilent; - } - status = self->pScanner->CollectScanData(self->pScanner,0); - if(CollectFunc != NULL) - { - self->pScanner->CollectScanData = CollectFunc; - } - if(status != 1) - { - return status; - } - GetScanCounts(self->pScanner,data,1); - return data[0]; -} -/*------------------------------------------------------------------------*/ -static int ClimbDrive(SConnection *pCon,char *name, float value) -{ - int status; - - status = Start2Run(pCon,pServ->pSics,name,value); - if(status != 1) - { - return DRIVEERROR; - } - status = Wait4Success(GetExecutor()); - if(status != DEVDONE) - { - return DRIVEERROR; - } - return 1; + SilentPrepare(self->pScanner); + + status = self->pScanner->ScanCount(self->pScanner, 0); + if (status != 1) { + return status; + } + if (self->pScanner->CollectScanData == CollectScanData) { + CollectFunc = self->pScanner->CollectScanData; + self->pScanner->CollectScanData = CollectSilent; + } + status = self->pScanner->CollectScanData(self->pScanner, 0); + if (CollectFunc != NULL) { + self->pScanner->CollectScanData = CollectFunc; + } + if (status != 1) { + return status; + } + GetScanCounts(self->pScanner, data, 1); + return data[0]; } + /*------------------------------------------------------------------------*/ -static int findDirection(pOptimise self, pOVarEntry pOvar, SConnection *pCon) +static int ClimbDrive(SConnection * pCon, char *name, float value) { - int status, direction; - float varValue; - long oneCount, twoCount; - - varValue = pOvar->fCenter + pOvar->fStep; - status = ClimbDrive(pCon,pOvar->pName,varValue); - if(!status) - { - return DRIVEERROR; - } - oneCount = ClimbCount(self,pCon); - if(oneCount < 0) - { - return SCANERROR; - } - if(SCGetInterrupt(pCon) != eContinue) - { - return SCANABORT; - } - varValue = pOvar->fCenter - pOvar->fStep; - status = ClimbDrive(pCon,pOvar->pName,varValue); - if(!status) - { - return DRIVEERROR; - } - twoCount = ClimbCount(self,pCon); - if(SCGetInterrupt(pCon) != eContinue) - { - return SCANABORT; - } - if(twoCount < 0) - { - return SCANERROR; - } - if(oneCount > twoCount) - { - direction = 1; - } - else - { - direction = -1; - } - return direction; + int status; + + status = Start2Run(pCon, pServ->pSics, name, RUNDRIVE, value); + if (status != 1) { + return DRIVEERROR; + } + status = Wait4Success(GetExecutor()); + if (status != DEVDONE) { + return DRIVEERROR; + } + return 1; } + +/*------------------------------------------------------------------------*/ +static int findDirection(pOptimise self, pOVarEntry pOvar, + SConnection * pCon) +{ + int status, direction; + float varValue; + long oneCount, twoCount; + + varValue = pOvar->fCenter + pOvar->fStep; + status = ClimbDrive(pCon, pOvar->pName, varValue); + if (!status) { + return DRIVEERROR; + } + oneCount = ClimbCount(self, pCon); + if (oneCount < 0) { + return SCANERROR; + } + if (SCGetInterrupt(pCon) != eContinue) { + return SCANABORT; + } + varValue = pOvar->fCenter - pOvar->fStep; + status = ClimbDrive(pCon, pOvar->pName, varValue); + if (!status) { + return DRIVEERROR; + } + twoCount = ClimbCount(self, pCon); + if (SCGetInterrupt(pCon) != eContinue) { + return SCANABORT; + } + if (twoCount < 0) { + return SCANERROR; + } + if (oneCount > twoCount) { + direction = 1; + } else { + direction = -1; + } + return direction; +} + /*-------------------------------------------------------------------------*/ - static int ClimbVariable(pOptimise self, SConnection *pCon, int i) - { - pOVarEntry pOvar; - void *pData; - int status, direction = 1; - long oneCount, twoCount, lastCount, currentCount; - float varValue, startValue; - char buffer[256]; - int (*CollectFunc)(pScanData self, int iPoint) = NULL; - - assert(self); - assert( (i >= 0) && (i < self->iVar)); - assert(pCon); - - /* get variable data */ - DynarGet(self->pVariables,i,&pData); - pOvar = (pOVarEntry)pData; - startValue = pOvar->fCenter; +static int ClimbVariable(pOptimise self, SConnection * pCon, int i) +{ + pOVarEntry pOvar; + void *pData; + int status, direction = 1; + long oneCount, twoCount, lastCount, currentCount; + float varValue, startValue; + char buffer[256]; + int (*CollectFunc) (pScanData self, int iPoint) = NULL; - /* - * prepare scan object - */ - self->pScanner->pCon = pCon; - self->pScanner->pSics = pServ->pSics; - self->pScanner->iNP = 1; - self->pScanner->iMode = self->eCount; - self->pScanner->fPreset = self->fPreset; + assert(self); + assert((i >= 0) && (i < self->iVar)); + assert(pCon); - direction = findDirection(self,pOvar, pCon); - if(direction < -1){ - return direction; - } - /* - * drive to the last best position - */ - varValue = pOvar->fCenter + direction*pOvar->fStep; - status = ClimbDrive(pCon,pOvar->pName,varValue); - if(!status) - { - return DRIVEERROR; - } - lastCount = ClimbCount(self,pCon); - if(lastCount < 0) - { - return SCANERROR; - } - currentCount = lastCount; - - /* - * climb upwards as long as possible - */ - while(1) - { - pOvar->fCenter = varValue; - varValue = pOvar->fCenter + direction * pOvar->fStep; - status = ClimbDrive(pCon,pOvar->pName,varValue); - if(!status) - { - return DRIVEERROR; - } - if(SCGetInterrupt(pCon) != eContinue) - { - return SCANABORT; + /* get variable data */ + DynarGet(self->pVariables, i, &pData); + pOvar = (pOVarEntry) pData; + startValue = pOvar->fCenter; + + /* + * prepare scan object + */ + self->pScanner->pCon = pCon; + self->pScanner->pSics = pServ->pSics; + self->pScanner->iNP = 1; + self->pScanner->iMode = self->eCount; + self->pScanner->fPreset = self->fPreset; + + direction = findDirection(self, pOvar, pCon); + if (direction < -1) { + return direction; + } + /* + * drive to the last best position + */ + varValue = pOvar->fCenter + direction * pOvar->fStep; + status = ClimbDrive(pCon, pOvar->pName, varValue); + if (!status) { + return DRIVEERROR; + } + lastCount = ClimbCount(self, pCon); + if (lastCount < 0) { + return SCANERROR; + } + currentCount = lastCount; + + /* + * climb upwards as long as possible + */ + while (1) { + pOvar->fCenter = varValue; + varValue = pOvar->fCenter + direction * pOvar->fStep; + status = ClimbDrive(pCon, pOvar->pName, varValue); + if (!status) { + return DRIVEERROR; + } + if (SCGetInterrupt(pCon) != eContinue) { + return SCANABORT; + } + currentCount = ClimbCount(self, pCon); + if (currentCount < 0) { + return SCANERROR; + } + if (SCGetInterrupt(pCon) != eContinue) { + return SCANABORT; + } + snprintf(buffer, 255, "Climbing %s, value = %f, count = %ld", + pOvar->pName, varValue, currentCount); + SCWrite(pCon, buffer, eLog); + + if (currentCount <= lastCount) { + /* + * we are finished. Drive to previous position and + * break + */ + status = ClimbDrive(pCon, pOvar->pName, pOvar->fCenter); + if (!status) { + return DRIVEERROR; } - currentCount = ClimbCount(self,pCon); - if(currentCount < 0) - { - return SCANERROR; - } - if(SCGetInterrupt(pCon) != eContinue) - { - return SCANABORT; + break; + } else { + /* + * go on, we are not over the top yet + */ + lastCount = currentCount; + } + } + pOvar->fShift = ABS(startValue - pOvar->fCenter); + + return 1; +} + +/*---------------------------------------------------------------------------*/ +static int CheckSuccess(pOptimise self) +{ + int i, iTest; + pOVarEntry pOvar; + void *pData; + + assert(self); + for (i = 0; i < self->iVar; i++) { + DynarGet(self->pVariables, i, &pData); + pOvar = (pOVarEntry) pData; + if (pOvar->fShift > pOvar->fPrecision) { + return 0; + } + } + return 1; +} + +/*---------------------------------------------------------------------------*/ +int OptimiserRun(pOptimise self, SConnection * pCon) +{ + int i, iRet, iCycle, iRedoVar = 0; + char pBueffel[256]; + + assert(self); + + if (self->iVar < 1) { + SCWrite(pCon, "ERROR: Nothing to optimise", eError); + return 0; + } + + iRet = OptimiserInit(self, pCon); + if (!iRet) { + return iRet; + } + for (iCycle = 0; iCycle < self->iMaxCycles; iCycle++) { + snprintf(pBueffel,sizeof(pBueffel)-1, "Optimiser cycle %d of %d started", iCycle, + self->iMaxCycles); + SCWrite(pCon, pBueffel, eLog); + for (i = iRedoVar; i < self->iVar; i++) { + iRet = CenterVariable(self, pCon, i); + if (iRet <= 0) { + return iRet; } - snprintf(buffer,255,"Climbing %s, value = %f, count = %ld", - pOvar->pName, varValue, currentCount); - SCWrite(pCon,buffer,eWarning); - - if(currentCount <= lastCount) - { - /* - * we are finished. Drive to previous position and - * break - */ - status = ClimbDrive(pCon,pOvar->pName,pOvar->fCenter); - if(!status) - { - return DRIVEERROR; - } + if (iRet == VARREDO) { + iRedoVar = i; break; } - else - { - /* - * go on, we are not over the top yet - */ - lastCount = currentCount; - } + iRedoVar = 0; + } + iRet = CheckSuccess(self); + if (iRet) { + return 1; } - pOvar->fShift = ABS(startValue - pOvar->fCenter); - - return 1; } + return MAXCYCLE; +} + /*---------------------------------------------------------------------------*/ - static int CheckSuccess(pOptimise self) - { - int i, iTest; - pOVarEntry pOvar; - void *pData; - - assert(self); - for(i = 0; i < self->iVar; i++) - { - DynarGet(self->pVariables,i,&pData); - pOvar = (pOVarEntry)pData; - if(pOvar->fShift > pOvar->fPrecision) - { - return 0; +int OptimiserClimb(pOptimise self, SConnection * pCon) +{ + int i, iRet, iCycle, iRedoVar = 0; + char pBueffel[256]; + + assert(self); + + if (self->iVar < 1) { + SCWrite(pCon, "ERROR: Nothing to optimise", eError); + return 0; + } + + iRet = OptimiserInit(self, pCon); + if (!iRet) { + return iRet; + } + for (iCycle = 0; iCycle < self->iMaxCycles; iCycle++) { + snprintf(pBueffel,sizeof(pBueffel)-1, "Optimiser cycle %d of %d started", iCycle, + self->iMaxCycles); + SCWrite(pCon, pBueffel, eLog); + for (i = iRedoVar; i < self->iVar; i++) { + iRet = ClimbVariable(self, pCon, i); + if (iRet <= 0) { + return iRet; } } - return 1; - } -/*---------------------------------------------------------------------------*/ - int OptimiserRun(pOptimise self, SConnection *pCon) - { - int i, iRet, iCycle, iRedoVar = 0; - char pBueffel[256]; + iRet = CheckSuccess(self); + if (iRet) { + return 1; + } + } + return MAXCYCLE; +} - assert(self); - - if(self->iVar < 1) - { - SCWrite(pCon,"ERROR: Nothing to optimise",eError); - return 0; - } - - iRet = OptimiserInit(self,pCon); - if(!iRet) - { - return iRet; - } - for(iCycle = 0; iCycle < self->iMaxCycles; iCycle++) - { - sprintf(pBueffel,"Optimiser cycle %d of %d started",iCycle, self->iMaxCycles); - SCWrite(pCon,pBueffel,eStatus); - for(i = iRedoVar; i < self->iVar; i++) - { - iRet = CenterVariable(self,pCon,i); - if(iRet <= 0) - { - return iRet; - } - if(iRet == VARREDO) - { - iRedoVar = i; - break; - } - iRedoVar = 0; - } - iRet = CheckSuccess(self); - if(iRet) - { - return 1; - } - } - return MAXCYCLE; - } -/*---------------------------------------------------------------------------*/ - int OptimiserClimb(pOptimise self, SConnection *pCon) - { - int i, iRet, iCycle, iRedoVar = 0; - char pBueffel[256]; - - assert(self); - - if(self->iVar < 1) - { - SCWrite(pCon,"ERROR: Nothing to optimise",eError); - return 0; - } - - iRet = OptimiserInit(self,pCon); - if(!iRet) - { - return iRet; - } - for(iCycle = 0; iCycle < self->iMaxCycles; iCycle++) - { - sprintf(pBueffel,"Optimiser cycle %d of %d started",iCycle, self->iMaxCycles); - SCWrite(pCon,pBueffel,eStatus); - for(i = iRedoVar; i < self->iVar; i++) - { - iRet = ClimbVariable(self,pCon,i); - if(iRet <= 0) - { - return iRet; - } - } - iRet = CheckSuccess(self); - if(iRet) - { - return 1; - } - } - return MAXCYCLE; - } /*--------------------------------------------------------------------------*/ - int MakeOptimiser(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - CommandList *pCom; - pICountable pCt = NULL; - pCounter pCount; - pOptimise pNew = NULL; - char pBueffel[256]; - int iRet; - - /* check no of args */ - if(argc < 3) - { - SCWrite(pCon,"EEROR: Not enough arguments to create optimiser",eError); - return 0; - } - - /* 2 argument must be counter name */ - pCom = FindCommand(pSics,argv[2]); - if(!pCom) - { - sprintf(pBueffel,"ERROR: Expected counter name, cannot find %s",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - pCt = GetCountableInterface(pCom->pData); - if(!pCt) - { - sprintf(pBueffel,"ERROR: Expected counter name, BUT %s is NO counter",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - pCount = (pCounter)pCom->pData; - - pNew = CreateOptimiser(pCount); - if(!pNew) - { - SCWrite(pCon,"ERROR: cannot create Optimiser",eError); - return 0; - } - - iRet = AddCommand(pSics,argv[1],OptimiserAction, - DeleteOptimiser,pNew); - if(!iRet) - { - sprintf(pBueffel,"ERROR: Duplicate Command %s NOT created", argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - return 1; - } +int MakeOptimiser(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + CommandList *pCom; + pICountable pCt = NULL; + pCounter pCount; + pOptimise pNew = NULL; + char pBueffel[256]; + int iRet; + + /* check no of args */ + if (argc < 3) { + SCWrite(pCon, "EEROR: Not enough arguments to create optimiser", + eError); + return 0; + } + + /* 2 argument must be counter name */ + pCom = FindCommand(pSics, argv[2]); + if (!pCom) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Expected counter name, cannot find %s", + argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + pCt = GetCountableInterface(pCom->pData); + if (!pCt) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Expected counter name, BUT %s is NO counter", + argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + pCount = (pCounter) pCom->pData; + + pNew = CreateOptimiser(pCount); + if (!pNew) { + SCWrite(pCon, "ERROR: cannot create Optimiser", eError); + return 0; + } + + iRet = AddCommand(pSics, argv[1], OptimiserAction, + DeleteOptimiser, pNew); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Duplicate Command %s NOT created", argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + return 1; +} + /*-------------------------------------------------------------------------*/ - int OptimiserAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - pOptimise self = NULL; - char pBueffel[1024]; - int iRet; - double d; - float fStep, fPrec, fVal; - int iStep; - - self = (pOptimise)pData; - assert(self); - assert(pCon); - - - if(argc < 2) - { - sprintf(pBueffel,"ERROR: Insufficient arguments to %s",argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - strtolower(argv[1]); - if(strcmp(argv[1],"addvar") == 0) +int OptimiserAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pOptimise self = NULL; + char pBueffel[1024]; + int iRet; + double d; + float fStep, fPrec, fVal; + int iStep; + + self = (pOptimise) pData; + assert(self); + assert(pCon); + + + if (argc < 2) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Insufficient arguments to %s", argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + strtolower(argv[1]); + if (strcmp(argv[1], "addvar") == 0) /*--------- addvar */ - { - /* check rights */ - if(!SCMatchRights(pCon,usUser)) - { - SCWrite(pCon,"ERROR: You are not authorised to do this!",eError); - return 0; - } - /* check no of args */ - if(argc < 6) - { - sprintf(pBueffel,"ERROR: Insufficient arguments to %s addvar",argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - /* convert arguments to types */ - iRet = Tcl_GetDouble(pSics->pTcl,argv[3],&d); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: expected float value for step but got %s", - argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - fStep = (float)d; - iRet = Tcl_GetInt(pSics->pTcl,argv[4],&iStep); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: expected integer value for iStep but got %s", - argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - iRet = Tcl_GetDouble(pSics->pTcl,argv[5],&d); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: expected float value for precision but got %s", - argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - fPrec = (float)d; - iRet = OptimiserAdd(self,argv[2],fStep,iStep,fPrec); - if(!iRet) - { - sprintf(pBueffel, - "ERROR: cannot optimise variable %s, mistyped?",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - SCSendOK(pCon); - return 1; - } + { + /* check rights */ + if (!SCMatchRights(pCon, usUser)) { + SCWrite(pCon, "ERROR: You are not authorised to do this!", eError); + return 0; + } + /* check no of args */ + if (argc < 6) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Insufficient arguments to %s addvar", + argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + /* convert arguments to types */ + iRet = Tcl_GetDouble(pSics->pTcl, argv[3], &d); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected float value for step but got %s", + argv[3]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + fStep = (float) d; + iRet = Tcl_GetInt(pSics->pTcl, argv[4], &iStep); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: expected integer value for iStep but got %s", + argv[3]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + iRet = Tcl_GetDouble(pSics->pTcl, argv[5], &d); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: expected float value for precision but got %s", + argv[3]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + fPrec = (float) d; + iRet = OptimiserAdd(self, argv[2], fStep, iStep, fPrec); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: cannot optimise variable %s, mistyped?", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + SCSendOK(pCon); + return 1; + } /*----- clear */ - else if(strcmp(argv[1],"clear") == 0) - { - /* check rights */ - if(!SCMatchRights(pCon,usUser)) - { - SCWrite(pCon,"ERROR: You are not aurhorised to do this!",eError); - return 0; - } - OptimiserClear(self); - SCSendOK(pCon); - return 1; - } + else if (strcmp(argv[1], "clear") == 0) { + /* check rights */ + if (!SCMatchRights(pCon, usUser)) { + SCWrite(pCon, "ERROR: You are not aurhorised to do this!", eError); + return 0; + } + OptimiserClear(self); + SCSendOK(pCon); + return 1; + } /*-------- run */ - else if(strcmp(argv[1],"run") == 0) - { - /* check rights */ - if(!SCMatchRights(pCon,usUser)) - { - SCWrite(pCon,"ERROR: You are not aurhorised to do this!",eError); - return 0; - } - iRet = OptimiserRun(self,pCon); - switch(iRet) - { - case PEAKLOST: - SCWrite(pCon,"ERROR: lost the peak, sorry!",eError); - return 0; - break; - case MAXCYCLE: - sprintf(pBueffel,"ERROR: could not optimise peak in %d cycles", - self->iMaxCycles); - SCWrite(pCon,pBueffel,eError); - return 0; - break; - case SCANERROR: - SCWrite(pCon,"ERROR: failed to scan the peak",eError); - return 0; - break; - case SCANABORT: - SCWrite(pCon,"ERROR: Scan was aborted, Optimiser follows",eError); - return 0; - break; - case DRIVEERROR: - SCWrite(pCon,"ERROR: Failure to drive variable to new position",eError); - return 0; - break; - case 1: - SCWrite(pCon,"At long last, I finished optimising the peak",eValue); - return 1; - break; - default: - SCWrite(pCon,"ERROR: Unidentified error krept into Optimiser",eError); - return 0; - break; - } - } + else if (strcmp(argv[1], "run") == 0) { + /* check rights */ + if (!SCMatchRights(pCon, usUser)) { + SCWrite(pCon, "ERROR: You are not aurhorised to do this!", eError); + return 0; + } + iRet = OptimiserRun(self, pCon); + switch (iRet) { + case PEAKLOST: + SCWrite(pCon, "ERROR: lost the peak, sorry!", eError); + return 0; + break; + case MAXCYCLE: + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: could not optimise peak in %d cycles", + self->iMaxCycles); + SCWrite(pCon, pBueffel, eError); + return 0; + break; + case SCANERROR: + SCWrite(pCon, "ERROR: failed to scan the peak", eError); + return 0; + break; + case SCANABORT: + SCWrite(pCon, "ERROR: Scan was aborted, Optimiser follows", eError); + return 0; + break; + case DRIVEERROR: + SCWrite(pCon, "ERROR: Failure to drive variable to new position", + eError); + return 0; + break; + case 1: + SCWrite(pCon, "At long last, I finished optimising the peak", + eValue); + return 1; + break; + default: + SCWrite(pCon, "ERROR: Unidentified error krept into Optimiser", + eError); + return 0; + break; + } + } /*-------- climb */ - else if(strcmp(argv[1],"climb") == 0) - { - /* check rights */ - if(!SCMatchRights(pCon,usUser)) - { - SCWrite(pCon,"ERROR: You are not aurhorised to do this!",eError); - return 0; - } - iRet = OptimiserClimb(self,pCon); - switch(iRet) - { - case PEAKLOST: - SCWrite(pCon,"ERROR: lost the peak, sorry!",eError); - return 0; - break; - case MAXCYCLE: - sprintf(pBueffel,"ERROR: could not optimise peak in %d cycles", - self->iMaxCycles); - SCWrite(pCon,pBueffel,eError); - return 0; - break; - case SCANERROR: - SCWrite(pCon,"ERROR: failed to scan the peak",eError); - return 0; - break; - case SCANABORT: - SCWrite(pCon,"ERROR: Scan was aborted, Optimiser follows",eError); - return 0; - break; - case DRIVEERROR: - SCWrite(pCon,"ERROR: Failure to drive variable to new position",eError); - return 0; - break; - case 1: - SCWrite(pCon,"At long last, I finished optimising the peak",eValue); - return 1; - break; - default: - SCWrite(pCon,"ERROR: Unidentified error krept into Optimiser",eError); - return 0; - break; - } - SCWrite(pCon,"Optimiser climbed successfully",eValue); - return 1; - } + else if (strcmp(argv[1], "climb") == 0) { + /* check rights */ + if (!SCMatchRights(pCon, usUser)) { + SCWrite(pCon, "ERROR: You are not aurhorised to do this!", eError); + return 0; + } + iRet = OptimiserClimb(self, pCon); + switch (iRet) { + case PEAKLOST: + SCWrite(pCon, "ERROR: lost the peak, sorry!", eError); + return 0; + break; + case MAXCYCLE: + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: could not optimise peak in %d cycles", + self->iMaxCycles); + SCWrite(pCon, pBueffel, eError); + return 0; + break; + case SCANERROR: + SCWrite(pCon, "ERROR: failed to scan the peak", eError); + return 0; + break; + case SCANABORT: + SCWrite(pCon, "ERROR: Scan was aborted, Optimiser follows", eError); + return 0; + break; + case DRIVEERROR: + SCWrite(pCon, "ERROR: Failure to drive variable to new position", + eError); + return 0; + break; + case 1: + SCWrite(pCon, "At long last, I finished optimising the peak", + eValue); + return 1; + break; + default: + SCWrite(pCon, "ERROR: Unidentified error krept into Optimiser", + eError); + return 0; + break; + } + SCWrite(pCon, "Optimiser climbed successfully", eValue); + return 1; + } /* ------ count mode */ - if(strcmp(argv[1],"countmode") == 0) - { - if(argc > 2) /* set case */ - { - /* check rights */ - if(!SCMatchRights(pCon,usUser)) - { - SCWrite(pCon,"ERROR: You are not aurhorised to do this!",eError); - return 0; - } - if(strcmp(argv[2],"timer") == 0) - { - fVal = 0.; - } - else if(strcmp(argv[2],"monitor") == 0) - { - fVal = 1.; - } - else - { - SCWrite(pCon,"ERROR: Invalid parameter for countmode",eError); - return 0; - } - OptimiserSetPar(self,"countmode",fVal); - SCSendOK(pCon); - return 1; - } - else /* get case */ - { - OptimiserGetPar(self,"countmode",&fVal); - if(fVal < 0.05) - { - sprintf(pBueffel,"%s.countmode = timer",argv[0]); - } - else - { - sprintf(pBueffel,"%s.countmode = monitor", argv[0]); - } - SCWrite(pCon,pBueffel,eValue); - return 1; - } - } + if (strcmp(argv[1], "countmode") == 0) { + if (argc > 2) { /* set case */ + /* check rights */ + if (!SCMatchRights(pCon, usUser)) { + SCWrite(pCon, "ERROR: You are not aurhorised to do this!", eError); + return 0; + } + if (strcmp(argv[2], "timer") == 0) { + fVal = 0.; + } else if (strcmp(argv[2], "monitor") == 0) { + fVal = 1.; + } else { + SCWrite(pCon, "ERROR: Invalid parameter for countmode", eError); + return 0; + } + OptimiserSetPar(self, "countmode", fVal); + SCSendOK(pCon); + return 1; + } else { /* get case */ + + OptimiserGetPar(self, "countmode", &fVal); + if (fVal < 0.05) { + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.countmode = timer", argv[0]); + } else { + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.countmode = monitor", argv[0]); + } + SCWrite(pCon, pBueffel, eValue); + return 1; + } + } /*------ can be other pars */ - else - { - if(argc > 2) /* set case */ - { - /* check rights */ - if(!SCMatchRights(pCon,usUser)) - { - SCWrite(pCon,"ERROR: You are not aurhorised to do this!",eError); - return 0; - } - iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&d); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: expected numeric value for %s but got %s", - argv[1],argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - fVal = (float)d; - - iRet = OptimiserSetPar(self,argv[1],fVal); - if(iRet) - { - SCSendOK(pCon); - return 1; - } - else - { - sprintf(pBueffel,"ERROR: parameter %s not known",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - } - else /* get case */ - { - iRet = OptimiserGetPar(self,argv[1],&fVal); - if(!iRet) - { - sprintf(pBueffel,"ERROR: parameter %s not known",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - sprintf(pBueffel,"%s.%s = %f",argv[0],argv[1],fVal); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - } - } + else { + if (argc > 2) { /* set case */ + /* check rights */ + if (!SCMatchRights(pCon, usUser)) { + SCWrite(pCon, "ERROR: You are not aurhorised to do this!", eError); + return 0; + } + iRet = Tcl_GetDouble(pSics->pTcl, argv[2], &d); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: expected numeric value for %s but got %s", argv[1], + argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + fVal = (float) d; + + iRet = OptimiserSetPar(self, argv[1], fVal); + if (iRet) { + SCSendOK(pCon); + return 1; + } else { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: parameter %s not known", argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + } else { /* get case */ + + iRet = OptimiserGetPar(self, argv[1], &fVal); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: parameter %s not known", argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.%s = %f", argv[0], argv[1], fVal); + SCWrite(pCon, pBueffel, eValue); + return 1; + } + } +} diff --git a/optimise.h b/optimise.h index 9d73e5ea..40d292e3 100644 --- a/optimise.h +++ b/optimise.h @@ -11,13 +11,13 @@ #ifndef SICSOPTIMISE #define SICSOPTIMISE - typedef struct __OptimiseStruct *pOptimise; +typedef struct __OptimiseStruct *pOptimise; /*------------------- live & death -----------------------------------------*/ - pOptimise CreateOptimiser(pCounter pCount); - void DeleteOptimiser(void *pData); - int MakeOptimiser(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]); +pOptimise CreateOptimiser(pCounter pCount); +void DeleteOptimiser(void *pData); +int MakeOptimiser(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]); /*------------------- operation -------------------------------------------*/ #define PEAKLOST -1 #define MAXCYCLE -2 @@ -28,17 +28,14 @@ #define VARREDO -7 - void OptimiserClear(pOptimise self); - int OptimiserAdd(pOptimise self, - char *pVarName, - float fStep, - int nStep, - float fPrecision); - int OptimiserSetPar(pOptimise self, char *name, float fVal); - int OptimiserGetPar(pOptimise self, char *name, float *fVal); +void OptimiserClear(pOptimise self); +int OptimiserAdd(pOptimise self, + char *pVarName, float fStep, int nStep, float fPrecision); +int OptimiserSetPar(pOptimise self, char *name, float fVal); +int OptimiserGetPar(pOptimise self, char *name, float *fVal); - int OptimiserRun(pOptimise self, SConnection *pCon); +int OptimiserRun(pOptimise self, SConnection * pCon); - int OptimiserAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); +int OptimiserAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); #endif diff --git a/oscillate.c b/oscillate.c index fb45bf56..b65ba11e 100644 --- a/oscillate.c +++ b/oscillate.c @@ -13,32 +13,29 @@ #include "task.h" #include "commandlog.h" #include "oscillate.h" -#include "status.h" -#define ABS(x) (x < 0 ? -(x) : (x)) +#define ABS(x) (x < 0 ? -(x) : (x)) /*================== real work =========================================*/ -static void StopOscillation(pOscillator self){ - int savedStatus; - +static void StopOscillation(pOscillator self) +{ assert(self != NULL); - if(self->taskID > 0){ + if (self->taskID > 0) { self->pMot->pDriver->Halt(self->pMot->pDriver); self->stopFlag = 1; self->taskID = -1; } - savedStatus = GetStatus(); /* fool status check in ObParSet (avoid "Cannot change parameter while running" message */ - SetStatus(eEager); - MotorSetPar(self->pMot,self->pCon,"accesscode",usUser); - SetStatus(savedStatus); - if(self->debug > 0){ - WriteToCommandLog("oscillator>> ","Stopping"); + MotorSetPar(self->pMot, self->pCon, "accesscode", usUser); + if (self->debug > 0) { + WriteToCommandLog("oscillator>> ", "Stopping"); } } + /*-------------------------------------------------------------------*/ -static float getNextPos(pOscillator self){ +static float getNextPos(pOscillator self) +{ float pos; - if(self->nextTargetFlag == 1){ + if (self->nextTargetFlag == 1) { pos = self->upperLimit; self->nextTargetFlag = 0; } else { @@ -47,260 +44,251 @@ static float getNextPos(pOscillator self){ } return pos; } + /*-------------------------------------------------------------------*/ -static float getCurrentTarget(pOscillator self){ +static float getCurrentTarget(pOscillator self) +{ float pos; - if(self->nextTargetFlag == 1){ + if (self->nextTargetFlag == 1) { pos = self->lowerLimit; } else { pos = self->upperLimit; } return pos; } + /*---------------------------------------------------------------------*/ -static int OscillationTask(void *data){ - pOscillator self = (pOscillator)data; +static int OscillationTask(void *data) +{ + pOscillator self = (pOscillator) data; int status, code, errStatus; char error[256], message[132]; float pos, curPos; assert(self); - if(self->stopFlag == 1){ - finishDriving(self->pMot, self->pCon); + if (self->stopFlag == 1) { return 0; } status = self->pMot->pDriver->GetStatus(self->pMot->pDriver); - switch(status){ + switch (status) { case HWFault: case HWPosFault: - self->pMot->pDriver->GetError(self->pMot->pDriver,&code,error,255); - WriteToCommandLog("oscillator>> ",error); + self->pMot->pDriver->GetError(self->pMot->pDriver, &code, error, 255); + WriteToCommandLog("oscillator>> ", error); pos = getCurrentTarget(self); - errStatus = self->pMot->pDriver->TryAndFixIt(self->pMot->pDriver,code,pos); + errStatus = + self->pMot->pDriver->TryAndFixIt(self->pMot->pDriver, code, pos); self->errorCount++; - if(errStatus == MOTFAIL){ + if (errStatus == MOTFAIL) { /* - try driving the other way on a serious error - */ + try driving the other way on a serious error + */ pos = getNextPos(self); - status = MotorRun(self->pMot,self->pCon,pos); - if(self->debug > 0){ - snprintf(message,131,"Started oscillation to %f, ret code = %d", - pos,status); - WriteToCommandLog("oscillator>>",message); + status = MotorRun(self->pMot, self->pCon, pos); + if (self->debug > 0) { + snprintf(message, 131, "Started oscillation to %f, ret code = %d", + pos, status); + WriteToCommandLog("oscillator>>", message); } } break; case HWWarn: - MotorGetSoftPosition(self->pMot,self->pCon,&curPos); + MotorGetSoftPosition(self->pMot, self->pCon, &curPos); pos = getCurrentTarget(self); - if(ABS(curPos - pos) < .5){ - status = MotorRun(self->pMot,self->pCon,getNextPos(self)); - } + if (ABS(curPos - pos) < .5) { + status = MotorRun(self->pMot, self->pCon, getNextPos(self)); + } break; case HWBusy: break; case HWIdle: - if (self->cycles > 0 && self->currcycle == self->cycles) { - StopOscillation(self); - return 1; - } pos = getNextPos(self); - status = MotorRun(self->pMot,self->pCon,pos); - if(status == OKOK){ + status = MotorRun(self->pMot, self->pCon, pos); + if (status == OKOK) { self->pMot->pDrivInt->iErrorCount = 0; - if (self->cycles > 0) - (self->currcycle)++; } - if(self->debug > 0){ - snprintf(message,131,"Started oscillation to %f, ret code = %d", - pos,status); - WriteToCommandLog("oscillator>>",message); + if (self->debug > 0) { + snprintf(message, 131, "Started oscillation to %f, ret code = %d", + pos, status); + WriteToCommandLog("oscillator>>", message); } } return 1; } + /*--------------------------------------------------------------------*/ -static int StartOscillation(pOscillator self, SConnection *pCon){ +static int StartOscillation(pOscillator self, SConnection * pCon) +{ float fval; - int status, savedStatus; - char error[80], pBueffel[255]; + int status; + char error[80], pBueffel[255]; assert(self); - if(self->taskID > 0){ - SCWrite(pCon,"WARNING: oscillation already running",eWarning); - SCWrite(pCon,"WARNING: restarting .. ",eWarning); + if (self->taskID > 0) { + SCWrite(pCon, "WARNING: oscillation already running", eWarning); + SCWrite(pCon, "WARNING: restarting .. ", eWarning); StopOscillation(self); SicsWait(2); - } + } - MotorGetPar(self->pMot,"softlowerlim",&self->lowerLimit); + MotorGetPar(self->pMot, "softlowerlim", &self->lowerLimit); self->lowerLimit += .5; - MotorGetPar(self->pMot,"softupperlim",&self->upperLimit); + MotorGetPar(self->pMot, "softupperlim", &self->upperLimit); self->upperLimit -= .5; - savedStatus = GetStatus(); /* fool status check in ObParSet (avoid "Cannot change parameter while running" message */ - SetStatus(eEager); - MotorSetPar(self->pMot,self->pCon,"accesscode",(float)usInternal); - SetStatus(savedStatus); + MotorSetPar(self->pMot, self->pCon, "accesscode", (float) usInternal); self->nextTargetFlag = 0; self->errorCount = 0; self->stopFlag = 0; /* - check reachability of limits - */ - status = MotorCheckBoundary(self->pMot,self->lowerLimit,&fval,error,79); - if(!status){ - snprintf(pBueffel,255,"ERROR: cannot reach %f: %s reported", - self->lowerLimit,error); - SCWrite(pCon,pBueffel,eError); + check reachability of limits + */ + status = + MotorCheckBoundary(self->pMot, self->lowerLimit, &fval, error, 79); + if (!status) { + snprintf(pBueffel, 255, "ERROR: cannot reach %f: %s reported", + self->lowerLimit, error); + SCWrite(pCon, pBueffel, eError); return 0; } - status = MotorCheckBoundary(self->pMot,self->upperLimit,&fval,error,79); - if(!status){ - snprintf(pBueffel,255,"ERROR: cannot reach %f: %s reported", - self->upperLimit,error); - SCWrite(pCon,pBueffel,eError); + status = + MotorCheckBoundary(self->pMot, self->upperLimit, &fval, error, 79); + if (!status) { + snprintf(pBueffel, 255, "ERROR: cannot reach %f: %s reported", + self->upperLimit, error); + SCWrite(pCon, pBueffel, eError); return 0; } /* - start task - */ + start task + */ self->taskID = TaskRegister(pServ->pTasker, - OscillationTask, - NULL, - NULL, - self, - 10); - if(self->taskID < 0){ - SCWrite(pCon,"ERROR: failed to start oscillation task",eError); + OscillationTask, NULL, NULL, self, 10); + if (self->taskID < 0) { + SCWrite(pCon, "ERROR: failed to start oscillation task", eError); return 0; } return 1; } + /*===================== life and death =================================*/ -static void KillOscillator(void *data){ - pOscillator self = (pOscillator)data; - if(self != NULL){ - if(self->pDes != NULL){ +static void KillOscillator(void *data) +{ + pOscillator self = (pOscillator) data; + if (self != NULL) { + if (self->pDes != NULL) { DeleteDescriptor(self->pDes); } - if(self->pCon != NULL){ + if (self->pCon != NULL) { SCDeleteConnection(self->pCon); } free(self); } } + /*========================================================================*/ -int MakeOscillator(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]){ +int MakeOscillator(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ pOscillator pNew = NULL; pMotor pMot = NULL; char pBueffel[132]; int status; - if(argc < 3){ - SCWrite(pCon,"ERROR: insufficient number of arguments to MakeOscilator", - eError); + if (argc < 3) { + SCWrite(pCon, + "ERROR: insufficient number of arguments to MakeOscilator", + eError); return 0; } - pMot = FindMotor(pSics,argv[2]); - if(pMot == NULL){ - snprintf(pBueffel,131,"ERROR: %s is no motor",argv[2]); - SCWrite(pCon,pBueffel,eError); + pMot = FindMotor(pSics, argv[2]); + if (pMot == NULL) { + snprintf(pBueffel, 131, "ERROR: %s is no motor", argv[2]); + SCWrite(pCon, pBueffel, eError); return 0; } - pNew = (pOscillator)malloc(sizeof(Oscillator)); - if(pNew == NULL){ - SCWrite(pCon,"ERROR: out of memory creating oscillator",eError); + pNew = (pOscillator) malloc(sizeof(Oscillator)); + if (pNew == NULL) { + SCWrite(pCon, "ERROR: out of memory creating oscillator", eError); return 0; } - memset(pNew,0,sizeof(Oscillator)); + memset(pNew, 0, sizeof(Oscillator)); pNew->pDes = CreateDescriptor("Oscillator"); pNew->pMot = pMot; - pNew->cycles = 0; - pNew->currcycle = 0; pNew->pCon = SCCreateDummyConnection(pSics); - if(!pNew->pDes || !pNew->pCon){ - SCWrite(pCon,"ERROR: out of memory creating oscillator",eError); + if (!pNew->pDes || !pNew->pCon) { + SCWrite(pCon, "ERROR: out of memory creating oscillator", eError); return 0; } - SCSetWriteFunc(pNew->pCon,SCFileWrite); - SCSetRights(pNew->pCon,usInternal); - - status = AddCommand(pSics,argv[1], - OscillatorWrapper, - KillOscillator, - pNew); - if(!status){ - snprintf(pBueffel,131,"ERROR: duplicate command %s not created",argv[1]); - SCWrite(pCon,pBueffel,eError); + SCSetWriteFunc(pNew->pCon, SCFileWrite); + SCSetRights(pNew->pCon, usInternal); + + status = AddCommand(pSics, argv[1], + OscillatorWrapper, KillOscillator, pNew); + if (!status) { + snprintf(pBueffel, 131, "ERROR: duplicate command %s not created", + argv[1]); + SCWrite(pCon, pBueffel, eError); return 0; } return 1; } + /*========================================================================*/ -int OscillatorWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]){ - pOscillator self = (pOscillator)pData; +int OscillatorWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pOscillator self = (pOscillator) pData; char pBueffel[256]; assert(self); - if(argc < 2){ - SCWrite(pCon,"ERROR: need start/stop argument for oscillator",eError); + if (argc < 2) { + SCWrite(pCon, "ERROR: need start/stop argument for oscillator", + eError); return 0; } - if(!SCMatchRights(pCon,usUser)){ + if (!SCMatchRights(pCon, usUser)) { return 0; } - + strtolower(argv[1]); - if (argc == 3) { - self->cycles = 2 * atoi(argv[2]); - } else { - self->cycles = 0; - } - self->currcycle=0; - if(strcmp(argv[1],"start") == 0){ - return StartOscillation(self,pCon); - } else if(strcmp(argv[1],"stop") == 0) { + if (strcmp(argv[1], "start") == 0) { + return StartOscillation(self, pCon); + } else if (strcmp(argv[1], "stop") == 0) { StopOscillation(self); - snprintf(pBueffel,255,"Oscillation stopped with %d errors, %s", - self->errorCount, - "see commandlog for details"); - SCWrite(pCon,pBueffel,eValue); + snprintf(pBueffel, 255, "Oscillation stopped with %d errors, %s", + self->errorCount, "see commandlog for details"); + SCWrite(pCon, pBueffel, eValue); return 1; - } else if(strcmp(argv[1],"debug") == 0) { - if(argc >= 3){ + } else if (strcmp(argv[1], "debug") == 0) { + if (argc >= 3) { self->debug = atoi(argv[2]); SCSendOK(pCon); return 1; } - snprintf(pBueffel,255,"%s.debug = %d", argv[0],self->debug); - SCWrite(pCon,pBueffel,eValue); + snprintf(pBueffel, 255, "%s.debug = %d", argv[0], self->debug); + SCWrite(pCon, pBueffel, eValue); return 1; - } else if(strcmp(argv[1],"status") == 0) { - if(self->taskID > 0){ - snprintf(pBueffel,255,"Oscillation running, %d errors so far, %s", - self->errorCount, - " error details in commandlog"); + } else if (strcmp(argv[1], "status") == 0) { + if (self->taskID > 0) { + snprintf(pBueffel, 255, "Oscillation running, %d errors so far, %s", + self->errorCount, " error details in commandlog"); } else { - snprintf(pBueffel,255,"Oscillation stopped"); + snprintf(pBueffel, 255, "Oscillation stopped"); } - SCWrite(pCon,pBueffel,eValue); + SCWrite(pCon, pBueffel, eValue); return 1; } else { - SCWrite(pCon,"ERROR: invalid sub command for oscillator requested", - eError); + SCWrite(pCon, "ERROR: invalid sub command for oscillator requested", + eError); return 0; } return 1; } - diff --git a/oscillate.h b/oscillate.h index 82bd59e0..6ec7eae8 100644 --- a/oscillate.h +++ b/oscillate.h @@ -12,26 +12,23 @@ typedef struct { - pObjectDescriptor pDes; - pMotor pMot; - int oldRights; - float upperLimit; - float lowerLimit; - int nextTargetFlag; - long taskID; - int stopFlag; - SConnection *pCon; - int errorCount; - int debug; - int cycles; - int currcycle; - } Oscillator, *pOscillator; + pObjectDescriptor pDes; + pMotor pMot; + int oldRights; + float upperLimit; + float lowerLimit; + int nextTargetFlag; + long taskID; + int stopFlag; + SConnection *pCon; + int errorCount; + int debug; +} Oscillator, *pOscillator; /*---------------------------------------------------------------------*/ -int MakeOscillator(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); -int OscillatorWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); +int MakeOscillator(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); +int OscillatorWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); #endif - diff --git a/outcode.c b/outcode.c index ad7fa0ee..a55ee959 100644 --- a/outcode.c +++ b/outcode.c @@ -8,20 +8,23 @@ #ifndef POUTCODE #define POUTCODE - static char *pCode[] = { - "internal", - "command", - "hwerror", - "inerror", - "status", - "value", - "start", - "finish", - "event", - "warning", - "error", - "hdbvalue", - "hdbevent", - NULL }; - static int iNoCodes = 13; +static char *pCode[] = { + "internal", + "command", + "hwerror", + "inerror", + "status", + "value", + "start", + "finish", + "event", + "warning", + "error", + "hdbvalue", + "hdbevent", + "log", + "logerror", + NULL +}; +static int iNoCodes = 13; #endif diff --git a/passwd.c b/passwd.c index 46e2f7ea..0f687cf0 100644 --- a/passwd.c +++ b/passwd.c @@ -44,121 +44,148 @@ #include #include "passwd.h" #include "splitter.h" +#include "sics.h" + +typedef struct __PENTRY { + char *name; + char *passwd; + int iCode; + struct __PENTRY *pNext; +} Pentry; -typedef struct __PENTRY - { - char *name; - char *passwd; - int iCode; - struct __PENTRY *pNext; - } Pentry; - /* -------------------------- THE DATABASE --------------------------------*/ - static Pentry *pPasswords = NULL; - +static Pentry *pPasswords = NULL; + /*=========================================================================*/ - void AddUser(char *name, char *passwd, int iCode) - { - Pentry *pNew = NULL; +void AddUser(char *name, char *passwd, int iCode) +{ + Pentry *pNew = NULL; - assert(name); - assert(passwd); - - pNew = (Pentry *)malloc(sizeof(Pentry)); - assert(pNew); + assert(name); + assert(passwd); + + pNew = (Pentry *) malloc(sizeof(Pentry)); + assert(pNew); + + pNew->name = NULL; + pNew->passwd = NULL; + pNew->name = strdup(name); + pNew->passwd = strdup(passwd); + pNew->iCode = iCode; + pNew->pNext = pPasswords; + pPasswords = pNew; +} - pNew->name = NULL; - pNew->passwd = NULL; - pNew->name = strdup(name); - pNew->passwd = strdup(passwd); - pNew->iCode = iCode; - pNew->pNext = pPasswords; - pPasswords = pNew; - } /*--------------------------------------------------------------------------*/ - int IsValidUser(char *name, char *password) - { - int iRes = -10; - Pentry *pCurrent = NULL; - - assert(pPasswords); +int IsValidUser(char *name, char *password) +{ + int iRes = -10; + Pentry *pCurrent = NULL; - if( (name == NULL) || (password == NULL) ) - { - return iRes; - } - pCurrent = pPasswords; - while(pCurrent) - { - if(strcmp(pCurrent->name,name) == 0) - { - if(strcmp(pCurrent->passwd,password) == 0) - { - return pCurrent->iCode; - } - } - pCurrent = pCurrent->pNext; - } - return iRes; - } -/* --------------------------------------------------------------------------*/ - void KillPasswd(void) - { - Pentry *pCurrent, *pTemp; - - pCurrent = pPasswords; - while(pCurrent) - { - pTemp = pCurrent->pNext; - if(pCurrent->name) - free(pCurrent->name); - if(pCurrent->passwd) - free(pCurrent->passwd); - free(pCurrent); - pCurrent = pTemp; - } - pPasswords = NULL; - } -/*-------------------------------------------------------------------------*/ - int InitPasswd(char *filename) - { - FILE *fp = NULL; - char pLine[256]; - TokenList *pList = NULL; - int iRes = 0; - - assert(filename); - fp = fopen(filename,"r"); - if(!fp) - return 0; - - while((int)fgets(pLine,255,fp) != EOF) - { - if(feof(fp)) - break; - - pList = SplitText(pLine); - if( (!pList) || (!pList->pNext) || (!pList->pNext->pNext) ) - { - printf("Invalid Passwd Entry ::\n %s \n",pLine); - continue; - } - else - { - if(pList->pNext->pNext->Type != eInt) - { - continue; - } - else - { - AddUser(pList->text, pList->pNext->text, - pList->pNext->pNext->iVal); - iRes = 1; - } - } - DeleteTokenList(pList); - pList = NULL; - } - fclose(fp); + assert(pPasswords); + + if ((name == NULL) || (password == NULL)) { return iRes; - } + } + pCurrent = pPasswords; + while (pCurrent) { + if (strcmp(pCurrent->name, name) == 0) { + if (strcmp(pCurrent->passwd, password) == 0) { + return pCurrent->iCode; + } + } + pCurrent = pCurrent->pNext; + } + return iRes; +} + +/* --------------------------------------------------------------------------*/ +void KillPasswd(void) +{ + Pentry *pCurrent, *pTemp; + + pCurrent = pPasswords; + while (pCurrent) { + pTemp = pCurrent->pNext; + if (pCurrent->name) + free(pCurrent->name); + if (pCurrent->passwd) + free(pCurrent->passwd); + free(pCurrent); + pCurrent = pTemp; + } + pPasswords = NULL; +} + +/*-------------------------------------------------------------------------*/ +int InitPasswd(char *filename) +{ + FILE *fp = NULL; + char pLine[256]; + TokenList *pList = NULL; + int iRes = 0; + + assert(filename); + fp = fopen(filename, "r"); + if (!fp) + return 0; + + while ((int) fgets(pLine, 255, fp) != EOF) { + if (feof(fp)) + break; + + pList = SplitText(pLine); + if ((!pList) || (!pList->pNext) || (!pList->pNext->pNext)) { + printf("Invalid Passwd Entry ::\n %s \n", pLine); + continue; + } else { + if (pList->pNext->pNext->Type != eInt) { + continue; + } else { + AddUser(pList->text, pList->pNext->text, + pList->pNext->pNext->iVal); + iRes = 1; + } + } + DeleteTokenList(pList); + pList = NULL; + } + fclose(fp); + return iRes; +} +/*----------------------- Password database update -------------------------*/ +int PWSicsUser(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + char pBueffel[512]; + TokenList *pList = NULL; + + assert(pSics); + assert(pCon); + + /* check authorisation */ + if (SCGetRights(pCon) > usMugger) { + SCWrite(pCon, "Insufficient privilege to set users", eError); + return 0; + } + + /* analyse commandlist */ + pList = SplitArguments(argc - 1, &argv[1]); + if ((!pList) || (!pList->pNext) || (!pList->pNext->pNext)) { + snprintf(pBueffel,sizeof(pBueffel)-1, "Invalid Passwd Entry ::\n %s %s %s\n", argv[1], + argv[2], argv[3]); + SCWrite(pCon, pBueffel, eError); + DeleteTokenList(pList); + return 0; + } else { + if (pList->pNext->pNext->Type != eInt) { + SCWrite(pCon, "Need integer rights code", eError); + DeleteTokenList(pList); + return 0; + } else { + AddUser(pList->text, pList->pNext->text, pList->pNext->pNext->iVal); + } + } + DeleteTokenList(pList); + return 1; +} diff --git a/passwd.h b/passwd.h index afc59041..9aad8296 100644 --- a/passwd.h +++ b/passwd.h @@ -10,13 +10,13 @@ #ifndef MKPASSWD #define MKPASSWD - int InitPasswd(char *filename); - void AddUser(char *name, char *passwd, int iCode); - int IsValidUser(char *name, char *passwd); - /* - returns negative number if not found, iCode else - iCode is the integer rights code the user is configured - with. - */ - void KillPasswd(void); +int InitPasswd(char *filename); +void AddUser(char *name, char *passwd, int iCode); +int IsValidUser(char *name, char *passwd); + /* + returns negative number if not found, iCode else + iCode is the integer rights code the user is configured + with. + */ +void KillPasswd(void); #endif diff --git a/perfmon.c b/perfmon.c index 7fd72800..cc5c54c1 100644 --- a/perfmon.c +++ b/perfmon.c @@ -45,125 +45,125 @@ #include "perfmon.h" #include "perfmon.i" /*-------------------------------------------------------------------------*/ - static void *PerfMonInter(void *pData, int iInterface) - { - pPerfMon self = NULL; - - self = (pPerfMon)pData; - assert(self); - - if(iInterface == CALLBACKINTERFACE) - { - return self->pCall; - } +static void *PerfMonInter(void *pData, int iInterface) +{ + pPerfMon self = NULL; + + self = (pPerfMon) pData; + assert(self); + + if (iInterface == CALLBACKINTERFACE) { + return self->pCall; + } + return NULL; +} + +/*--------------------------------------------------------------------------*/ +pPerfMon CreatePerfMon(int iInteg) +{ + + pPerfMon pNew = NULL; + time_t tCurrent; + + pNew = (pPerfMon) malloc(sizeof(PerfMon)); + if (!pNew) { + return NULL; + } + memset(pNew, 0, sizeof(PerfMon)); + + /* initialise Descriptor */ + pNew->pDes = CreateDescriptor("PerfMon"); + if (!pNew->pDes) { + free(pNew); + return NULL; + } + pNew->pDes->GetInterface = PerfMonInter; + + /* initalise callback */ + pNew->pCall = CreateCallBackInterface(); + if (!pNew->pCall) { + DeleteDescriptor(pNew->pDes); + free(pNew); return NULL; } + pNew->tLast = time(&tCurrent); + pNew->tTarget = pNew->tLast + iInteg; + pNew->iInteg = iInteg; + + return pNew; +} + /*--------------------------------------------------------------------------*/ - pPerfMon CreatePerfMon(int iInteg) - { - - pPerfMon pNew = NULL; - time_t tCurrent; - - pNew = (pPerfMon)malloc(sizeof(PerfMon)); - if(!pNew) - { - return NULL; - } - memset(pNew,0,sizeof(PerfMon)); - - /* initialise Descriptor */ - pNew->pDes = CreateDescriptor("PerfMon"); - if(!pNew->pDes) - { - free(pNew); - return NULL; - } - pNew->pDes->GetInterface = PerfMonInter; - - /* initalise callback */ - pNew->pCall = CreateCallBackInterface(); - if(!pNew->pCall) - { - DeleteDescriptor(pNew->pDes); - free(pNew); - return NULL; - } - - pNew->tLast = time(&tCurrent); - pNew->tTarget = pNew->tLast + iInteg; - pNew->iInteg = iInteg; - - return pNew; - } +void DeletePerfMon(void *pData) +{ + pPerfMon self = NULL; + + self = (pPerfMon) pData; + assert(self); + + if (self->pDes) { + DeleteDescriptor(self->pDes); + } + if (self->pCall) { + DeleteCallBackInterface(self->pCall); + } + free(self); +} + /*--------------------------------------------------------------------------*/ - void DeletePerfMon(void *pData) - { - pPerfMon self = NULL; - - self = (pPerfMon)pData; - assert(self); - - if(self->pDes) - { - DeleteDescriptor(self->pDes); - } - if(self->pCall) - { - DeleteCallBackInterface(self->pCall); - } - free(self); - } -/*--------------------------------------------------------------------------*/ - int IncrementPerfMon(pPerfMon self) - { - time_t tCurrent; - char pBueffel[80]; - - self->iCount++; - - time(&tCurrent); - if(tCurrent > self->tTarget) /* recalculation necessary */ - { - self->fCPS = (float)self->iCount / - (float)(tCurrent - self->tLast); - self->iCount = 0; - self->tLast = tCurrent; - self->tTarget = tCurrent + self->iInteg; - if(self->iLog) - { - sprintf(pBueffel,"PerfMon = %f",self->fCPS); - SICSLogWrite(pBueffel,eValue); - } - InvokeCallBack(self->pCall, VALUECHANGE, &self->fCPS); - } - return 1; - } +int IncrementPerfMon(pPerfMon self) +{ + time_t tCurrent; + char pBueffel[80]; + + self->iCount++; + + time(&tCurrent); + if (tCurrent > self->tTarget) { /* recalculation necessary */ + self->fCPS = (float) self->iCount / (float) (tCurrent - self->tLast); + self->iCount = 0; + self->tLast = tCurrent; + self->tTarget = tCurrent + self->iInteg; + if (self->iLog) { + snprintf(pBueffel,sizeof(pBueffel)-1, "PerfMon = %f", self->fCPS); + SICSLogWrite(pBueffel, eValue); + } + InvokeCallBack(self->pCall, VALUECHANGE, &self->fCPS); + traceSys("perfmon","%d:%f", self->iInteg, self->fCPS); + } + return 1; +} + /*---------------------------------------------------------------------------*/ - float GetPerformance(pPerfMon self) - { - assert(self); - return self->fCPS; - } +float GetPerformance(pPerfMon self) +{ + assert(self); + return self->fCPS; +} + /*------------------- The CallBack function for interest ------------------*/ - static int InterestCallback(int iEvent, void *pEvent, void *pUser, - commandContext cc) - { - float *fPos; - SConnection *pCon; - char pBueffel[80]; - - assert(pEvent); - assert(pUser); - - fPos = (float *)pEvent; - pCon = (SConnection *)pUser; - - sprintf(pBueffel,"Performance = %f", *fPos); - SCWriteInContext(pCon,pBueffel,eValue,cc); - return 1; - } +static int InterestCallback(int iEvent, void *pEvent, void *pUser) +{ + float *fPos; + SConnection *pCon; + char pBueffel[80]; + + assert(pEvent); + assert(pUser); + + fPos = (float *) pEvent; + pCon = (SConnection *) pUser; + + if (pCon == NULL || !SCisConnected(pCon)) { + return -1; + } + + snprintf(pBueffel,sizeof(pBueffel)-1, "Performance = %f", *fPos); + SCWrite(pCon, pBueffel, eValue); + return 1; +} + /*---------------------------------------------------------------------------- PerfMon understands this syntax: PerfMon : prints current CPS value @@ -171,85 +171,78 @@ PerfMon off : stops writing performance to ServLog PerfMon interest : makes perfmon writes any change of its value to the connection regsitering this. ------------------------------------------------------------------------------*/ - int PerfMonWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - pPerfMon self = NULL; - char pBueffel[132]; - long lID; - - self = (pPerfMon)pData; - assert(self); - assert(pCon); - - argtolower(argc,argv); - if(argc < 2) /* print value */ - { - sprintf(pBueffel,"Performance = %f",self->fCPS); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - - if(strcmp(argv[1],"on") == 0) - { - self->iLog = 1; - SCSendOK(pCon); - return 1; - } - - if(strcmp(argv[1],"off") == 0) - { - self->iLog = 0; - SCSendOK(pCon); - return 1; - } - - 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; - } - printf(pBueffel,"ERROR: unknown command %s",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } -/*---------------------------------------------------------------------------*/ - int PerfMonTask(void *pData) - { - pPerfMon self = NULL; - - self = (pPerfMon)pData; - assert(self); - - if(self->iEnd) - { - return 0; - } - IncrementPerfMon(self); +-----------------------------------------------------------------------------*/ +int PerfMonWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pPerfMon self = NULL; + char pBueffel[132]; + long lID; + + self = (pPerfMon) pData; + assert(self); + assert(pCon); + + argtolower(argc, argv); + if (argc < 2) { /* print value */ + snprintf(pBueffel,sizeof(pBueffel)-1, "Performance = %f", self->fCPS); + SCWrite(pCon, pBueffel, eValue); return 1; } -/*------------------------------------------------------------------------*/ - void PerfMonSignal(void *pUser, int iSignal, void *pEventData) - { - pPerfMon self = NULL; - int *iInt; - - self = (pPerfMon)pUser; - assert(self); - iInt = (int *)pEventData; - - if(iSignal == SICSINT) - { - iInt = (int *)pEventData; - if(*iInt == eEndServer) - { - self->iEnd = 1; - } - } + + if (strcmp(argv[1], "on") == 0) { + self->iLog = 1; + SCSendOK(pCon); + return 1; } - + + if (strcmp(argv[1], "off") == 0) { + self->iLog = 0; + SCSendOK(pCon); + return 1; + } + + if (strcmp(argv[1], "interest") == 0) { + lID = RegisterCallback(self->pCall, + VALUECHANGE, InterestCallback, + SCCopyConnection(pCon), SCDeleteConnection); + SCSendOK(pCon); + return 1; + } + printf(pBueffel, "ERROR: unknown command %s", argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; +} + +/*---------------------------------------------------------------------------*/ +int PerfMonTask(void *pData) +{ + pPerfMon self = NULL; + + self = (pPerfMon) pData; + assert(self); + + if (self->iEnd) { + return 0; + } + IncrementPerfMon(self); + return 1; +} + +/*------------------------------------------------------------------------*/ +void PerfMonSignal(void *pUser, int iSignal, void *pEventData) +{ + pPerfMon self = NULL; + int *iInt; + + self = (pPerfMon) pUser; + assert(self); + iInt = (int *) pEventData; + + if (iSignal == SICSINT) { + iInt = (int *) pEventData; + if (*iInt == eEndServer) { + self->iEnd = 1; + } + } +} diff --git a/perfmon.h b/perfmon.h index 42cfae52..c4a2f2db 100644 --- a/perfmon.h +++ b/perfmon.h @@ -16,20 +16,20 @@ #line 35 "perfmon.w" - typedef struct __PerfMon *pPerfMon; +typedef struct __PerfMon *pPerfMon; /*---------------------- live and death ----------------------------------*/ - pPerfMon CreatePerfMon(int iInteg); - void DeletePerfMon(void *pData); +pPerfMon CreatePerfMon(int iInteg); +void DeletePerfMon(void *pData); /*---------------------- increment ---------------------------------------*/ - int IncrementPerfMon(pPerfMon self); +int IncrementPerfMon(pPerfMon self); /*------------------------------------------------------------------------*/ - float GetPerformance(pPerfMon self); +float GetPerformance(pPerfMon self); /*------------------------------------------------------------------------*/ - int PerfMonWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); +int PerfMonWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); /*-----------------------------------------------------------------------*/ - int PerfMonTask(void *pPerf); - void PerfMonSignal(void *pPerf, int iSignal, void *pSigData); +int PerfMonTask(void *pPerf); +void PerfMonSignal(void *pPerf, int iSignal, void *pSigData); #line 67 "perfmon.w" diff --git a/polldriv.c b/polldriv.c index da2f5119..de89f650 100644 --- a/polldriv.c +++ b/polldriv.c @@ -16,138 +16,152 @@ #include "macro.h" #include "sicshipadaba.h" /*================ actual driver implementation =========================*/ -static int timeDue(struct __POLLDRIV *self, time_t now, SConnection *pCon){ - if(now > self->nextPoll){ - return 1; - } else { - return 0; - } +static int timeDue(struct __POLLDRIV *self, time_t now, SConnection * pCon) +{ + if (now > self->nextPoll) { + return 1; + } else { + return 0; + } } + /*------------------ HDB Driver -----------------------------------------*/ -static int pollHdb(struct __POLLDRIV *self, SConnection *pCon){ - hdbValue old, newVal; - pHdb node = NULL; - - memset(&old,0,sizeof(hdbValue)); - memset(&newVal,0,sizeof(hdbValue)); - node = (pHdb)self->objPointer; - assert(node != NULL); - old = node->value; - self->nextPoll = time(NULL) + self->pollIntervall; - if(GetHipadabaPar(node, &newVal, pCon) == 1){ - if(!compareHdbValue(old,newVal)){ - UpdateHipadabaPar(node,newVal,pCon); - } - ReleaseHdbValue(&newVal); - return 1; - } else { - return 0; - } +static int pollHdb(struct __POLLDRIV *self, SConnection * pCon) +{ + hdbValue newVal; + pHdb node = NULL; + + memset(&newVal, 0, sizeof(hdbValue)); + node = (pHdb) self->objPointer; + + assert(node != NULL); + + self->nextPoll = time(NULL) + self->pollIntervall; + if (GetHipadabaPar(node, &newVal, pCon) == 1) { + ReleaseHdbValue(&newVal); + return 1; + } else { + return 0; + } } + /*-----------------------------------------------------------------------*/ -static pPollDriv makeHdbDriver(SConnection *pCon, char *objectIdentifier, - int argc, char *argv[]){ - pHdb node = NULL; - pPollDriv pNew = NULL; - - node = FindHdbNode(NULL,objectIdentifier,pCon); - if(node == NULL){ - SCWrite(pCon,"ERROR: object to poll not found",eError); - return 0; - } - pNew = malloc(sizeof(PollDriv)); - if(pNew == NULL){ - return NULL; - } - memset(pNew,0,sizeof(PollDriv)); +static pPollDriv makeHdbDriver(SConnection * pCon, char *objectIdentifier, + int argc, char *argv[]) +{ + pHdb node = NULL; + pPollDriv pNew = NULL; - - pNew->objectIdentifier = strdup(objectIdentifier); - pNew->objPointer = node; - pNew->isDue = timeDue; - pNew->poll = pollHdb; + node = FindHdbNode(NULL, objectIdentifier, pCon); + if (node == NULL) { + SCWrite(pCon, "ERROR: object to poll not found", eError); + return 0; + } + pNew = malloc(sizeof(PollDriv)); + if (pNew == NULL) { + return NULL; + } + memset(pNew, 0, sizeof(PollDriv)); - if(argc > 0){ - pNew->pollIntervall = atoi(argv[0]); - } else { - pNew->pollIntervall = 10; - } - - return pNew; -} -/*==================== script poll driver ========================*/ -static int pollScript(struct __POLLDRIV *self, SConnection *pCon){ - int status; - Tcl_Interp *pTcl = InterpGetTcl(pServ->pSics); - self->nextPoll = time(NULL) + self->pollIntervall; - - MacroPush(pCon); - status = Tcl_Eval(pTcl,(char *)self->objPointer); - MacroPop(); - if(status == 0){ - return 1; - } else { - return 0; - } -} -/*-----------------------------------------------------------------------*/ -static void killScriptObj(void *data){ - if(data != NULL){ - free(data); - } -} -/*-----------------------------------------------------------------------*/ -static pPollDriv makeScriptDriver(SConnection *pCon, char *objectIdentifier, - int argc, char *argv[]){ - pPollDriv pNew = NULL; - char scriptBuffer[512]; - - if(argc < 2){ - SCWrite(pCon, - "ERROR: need intervall and script parameter for script polling driver", eError); - return NULL; - } - - pNew = malloc(sizeof(PollDriv)); - if(pNew == NULL){ - return NULL; - } - memset(pNew,0,sizeof(PollDriv)); + pNew->objectIdentifier = strdup(objectIdentifier); + pNew->objPointer = node; + pNew->isDue = timeDue; + pNew->poll = pollHdb; + if (argc > 0) { pNew->pollIntervall = atoi(argv[0]); - memset(scriptBuffer,0,512); - Arg2Text(argc-1, &argv[1],scriptBuffer,511); - - pNew->objectIdentifier = strdup(objectIdentifier); - pNew->objPointer = strdup(scriptBuffer); - pNew->isDue = timeDue; - pNew->poll = pollScript; - pNew->killObjPointer = killScriptObj; + } else { + pNew->pollIntervall = 10; + } + + return pNew; +} + +/*==================== script poll driver ========================*/ +static int pollScript(struct __POLLDRIV *self, SConnection * pCon) +{ + int status; + Tcl_Interp *pTcl = InterpGetTcl(pServ->pSics); + + self->nextPoll = time(NULL) + self->pollIntervall; + + MacroPush(pCon); + status = Tcl_Eval(pTcl, (char *) self->objPointer); + MacroPop(); + if (status == 0) { + return 1; + } else { + return 0; + } +} + +/*-----------------------------------------------------------------------*/ +static void killScriptObj(void *data) +{ + if (data != NULL) { + free(data); + } +} + +/*-----------------------------------------------------------------------*/ +static pPollDriv makeScriptDriver(SConnection * pCon, + char *objectIdentifier, int argc, + char *argv[]) +{ + pPollDriv pNew = NULL; + char scriptBuffer[512]; + + if (argc < 2) { + SCWrite(pCon, + "ERROR: need intervall and script parameter for script polling driver", + eError); + return NULL; + } + + pNew = malloc(sizeof(PollDriv)); + if (pNew == NULL) { + return NULL; + } + memset(pNew, 0, sizeof(PollDriv)); + + pNew->pollIntervall = atoi(argv[0]); + memset(scriptBuffer, 0, 512); + Arg2Text(argc - 1, &argv[1], scriptBuffer, 511); + + pNew->objectIdentifier = strdup(objectIdentifier); + pNew->objPointer = strdup(scriptBuffer); + pNew->isDue = timeDue; + pNew->poll = pollScript; + pNew->killObjPointer = killScriptObj; + + return pNew; +} - return pNew; -} /*================ external interface ====================================*/ -pPollDriv makePollDriver(SConnection *pCon, char *driver, - char *objectIdentifier, int argc, char *argv[]){ - - strtolower(driver); - if(strcmp(driver,"hdb") == 0) { - return makeHdbDriver(pCon,objectIdentifier, argc, argv); - } else if(strcmp(driver,"script") == 0){ - return makeScriptDriver(pCon,objectIdentifier, argc, argv); - } else { - SCWrite(pCon,"ERROR: polling driver type unknown",eError); - return NULL; - } +pPollDriv makePollDriver(SConnection * pCon, char *driver, + char *objectIdentifier, int argc, char *argv[]) +{ + + strtolower(driver); + if (strcmp(driver, "hdb") == 0) { + return makeHdbDriver(pCon, objectIdentifier, argc, argv); + } else if (strcmp(driver, "script") == 0) { + return makeScriptDriver(pCon, objectIdentifier, argc, argv); + } else { + SCWrite(pCon, "ERROR: polling driver type unknown", eError); + return NULL; + } } + /*------------------------------------------------------------------------*/ -void deletePollDriv(pPollDriv self){ - if(self->objectIdentifier != NULL){ - free(self->objectIdentifier); - } - if(self->objPointer != NULL && self->killObjPointer != NULL){ - self->killObjPointer(self->objPointer); - } - free(self); +void deletePollDriv(pPollDriv self) +{ + if (self->objectIdentifier != NULL) { + free(self->objectIdentifier); + } + if (self->objPointer != NULL && self->killObjPointer != NULL) { + self->killObjPointer(self->objPointer); + } + free(self); } diff --git a/polldriv.h b/polldriv.h index 409afb2d..3100dba0 100644 --- a/polldriv.h +++ b/polldriv.h @@ -11,18 +11,18 @@ #include #include /*==================== a data structure ===================================*/ -typedef struct __POLLDRIV{ - char *objectIdentifier; /* the object identifier */ - void *objPointer; /* a pointer to the object */ - time_t nextPoll; /* next polling time */ - int pollIntervall; /* poll intervall */ - int (*isDue)(struct __POLLDRIV *self, time_t now, SConnection *pCon); - /* function called to determine if this object must be polled */ - int (*poll)(struct __POLLDRIV *self, SConnection *pCon); - /* the actual polling function */ - void (*killObjPointer)(void *data); - /* a function to possibly kill the objPointer. Can be NULL */ -}PollDriv, *pPollDriv; +typedef struct __POLLDRIV { + char *objectIdentifier; /* the object identifier */ + void *objPointer; /* a pointer to the object */ + time_t nextPoll; /* next polling time */ + int pollIntervall; /* poll intervall */ + int (*isDue) (struct __POLLDRIV * self, time_t now, SConnection * pCon); + /* function called to determine if this object must be polled */ + int (*poll) (struct __POLLDRIV * self, SConnection * pCon); + /* the actual polling function */ + void (*killObjPointer) (void *data); + /* a function to possibly kill the objPointer. Can be NULL */ +} PollDriv, *pPollDriv; /*==================== the interface =====================================*/ /* * make a poll driver @@ -33,12 +33,12 @@ typedef struct __POLLDRIV{ * @param *argv[] Additional parameters. * @return NULL on failure or a PollDriv strucure else. */ -pPollDriv makePollDriver(SConnection *pCon, char *driver, - char *objectIdentifier, int argc, char *argv[]); +pPollDriv makePollDriver(SConnection * pCon, char *driver, + char *objectIdentifier, int argc, char *argv[]); /** * free all memory associated with this poll driver * @param self The structure to delete */ -void deletePollDriv(pPollDriv self); - -#endif /*POLLDRIV_H_*/ +void deletePollDriv(pPollDriv self); + +#endif /*POLLDRIV_H_ */ diff --git a/protocol.c b/protocol.c index 23f83873..a6226c17 100644 --- a/protocol.c +++ b/protocol.c @@ -21,803 +21,788 @@ #define MAXMSG 1024 #define INIT_STR_SIZE 256 #define STR_RESIZE_LENGTH 256 -#define NUMPROS 6 -#define PROLISTLEN 7 +#define NUMPROS 7 +#define PROLISTLEN 8 typedef struct __Protocol { - pObjectDescriptor pDes; /* required as first field */ - char *name; /* protocol handler name */ - char *version; /* protocol version string */ - int iNumPros; /* number of valid protocols? */ - writeFunc defaultWriter; /* default write function */ - int isDefaultSet; - char *pProList[PROLISTLEN]; /* list of valid protocols? */ + pObjectDescriptor pDes; /* required as first field */ + char *name; /* protocol handler name */ + char *version; /* protocol version string */ + int iNumPros; /* number of valid protocols? */ + writeFunc defaultWriter; /* default write function */ + int isDefaultSet; + char *pProList[PROLISTLEN]; /* list of valid protocols? */ } Protocol; -char *pEventType[]={ -"VALUECHANGE", /* 0 */ -"MOTDRIVE", /* 1 */ -"MONITOR", /* 2 */ -"ROTSTART", /* 3 */ -"ROTMOVE", /* 4 */ -"SCANEND", /* 5 */ -"SCANSTART", /* 6 */ -"SCANPOINT", /* 7 */ -"WLCHANGE", /* 8 */ -"REFLECTIONDONE", /* 9 */ -"COUNTSTART", /* 10 */ -"COUNTEND", /* 11 */ -"FILELOADED", /* 12 */ -"MOTEND", /* 13 */ -"BATCHSTART", /* 14 */ -"BATCHAREA", /* 15 */ -"BATCHEND", /* 16 */ -"DRIVSTAT", /* 17 */ -"STATUS", /* 18 */ -"POSITION" /* 19 Motor position events, ffr */ +char *pEventType[] = { + "VALUECHANGE", /* 0 */ + "MOTDRIVE", /* 1 */ + "MONITOR", /* 2 */ + "ROTSTART", /* 3 */ + "ROTMOVE", /* 4 */ + "SCANEND", /* 5 */ + "SCANSTART", /* 6 */ + "SCANPOINT", /* 7 */ + "WLCHANGE", /* 8 */ + "REFLECTIONDONE", /* 9 */ + "COUNTSTART", /* 10 */ + "COUNTEND", /* 11 */ + "FILELOADED", /* 12 */ + "MOTEND", /* 13 */ + "BATCHSTART", /* 14 */ + "BATCHAREA", /* 15 */ + "BATCHEND", /* 16 */ + "DRIVSTAT", /* 17 */ + "STATUS", /* 18 */ + "POSITION" /* 19 Motor position events, ffr */ }; -char *pStatus[]={ -"UNSET", -"OKOK", /* 1 */ -"HWIdle", /* 2 */ -"HWBusy", /* 3 */ -"HWFault", /* 4 */ -"HWPosFault", /* 5 */ -"HWCrash", /* 6 */ -"NOMEMORY", /* 7 */ -"HWNoBeam", /* 8 */ -"HWPause", /* 9 */ -"HWWarn", /* 10 */ -"HWRedo", /* 11 */ +char *pStatus[] = { + "UNSET", + "OKOK", /* 1 */ + "HWIdle", /* 2 */ + "HWBusy", /* 3 */ + "HWFault", /* 4 */ + "HWPosFault", /* 5 */ + "HWCrash", /* 6 */ + "NOMEMORY", /* 7 */ + "HWNoBeam", /* 8 */ + "HWPause", /* 9 */ + "HWWarn", /* 10 */ + "HWRedo", /* 11 */ }; typedef struct __Protocol *pProtocol; -/* alternate implementation of protocol list if data hiding in - * Protocol struct via CreateProtocol does not work - * static char *pPros[] = { - * "default", - * "outcodes", - * "sycamore" - * NULL }; - * static int iNumPros = 3 - */ - pProtocol CreateProtocol(void); -static int ProtocolOptions(SConnection* pCon, pProtocol pPro); -static int ProtocolHelp(SConnection* pCon, Protocol* pPro); -static int ProtocolSet(SConnection* pCon, Protocol* pPro, char *pProName); -static int ProtocolList(SConnection* pCon, Protocol* pPro); -int ProtocolAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); +static int ProtocolOptions(SConnection * pCon, pProtocol pPro); +static int ProtocolHelp(SConnection * pCon, Protocol * pPro); +static int ProtocolSet(SConnection * pCon, Protocol * pPro, + char *pProName); +static int ProtocolList(SConnection * pCon, Protocol * pPro); +int ProtocolAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); static int EnumChoice(char *pList[], int iLength, char *pInput); -static int InitDefaultProtocol(SConnection* pCon, Protocol *pPro); +static int InitDefaultProtocol(SConnection * pCon, Protocol * pPro); /* Signatures for protocol writers implemented in this file */ -int SCWriteSycamore(SConnection *pCon, char *pBuffer, int iOut); -int SCWriteJSON_String(SConnection *pCon, char *pBuffer, int iOut); +int SCWriteSycamore(SConnection * pCon, char *pBuffer, int iOut); +int SCWriteJSON_String(SConnection * pCon, char *pBuffer, int iOut); +/* Signatures for protocols from conman.c*/ +extern int SCAllWrite(SConnection * self, char *buffer, int iOut); /*--------------------------------------------------------------------------*/ pProtocol CreateProtocol(void) { - int i, iNumPros = NUMPROS; - char *pPros[] = {"default", - "normal", - "withcode", - "sycamore", - "json", - "act", - NULL - }; - pProtocol pNew = NULL; + int i, iNumPros = NUMPROS; + char *pPros[] = { "default", + "normal", + "withcode", + "sycamore", + "json", + "act", + "all", + NULL + }; + pProtocol pNew = NULL; - pNew = (pProtocol)malloc(sizeof(Protocol)); - if(!pNew) - { - return NULL; - } - pNew->pDes = CreateDescriptor("Protocol"); - if(!pNew->pDes) - { - free(pNew); - return NULL; - } - - pNew->name = strdup("protocol"); - pNew->version = strdup("1.0"); - pNew->iNumPros = iNumPros; + pNew = (pProtocol) malloc(sizeof(Protocol)); + if (!pNew) { + return NULL; + } + pNew->pDes = CreateDescriptor("Protocol"); + if (!pNew->pDes) { + free(pNew); + return NULL; + } + + pNew->name = strdup("protocol"); + pNew->version = strdup("1.0"); + pNew->iNumPros = iNumPros; // pNew->pProList = (char *)malloc(sizeof(pPros)); - for(i=0;ipProList[i] = strdup(pPros[i]); - } - pNew->pProList[i] = NULL; - pNew->isDefaultSet = 0; - - return pNew; + for (i = 0; i < iNumPros; i++) { + pNew->pProList[i] = strdup(pPros[i]); + } + pNew->pProList[i] = NULL; + pNew->isDefaultSet = 0; + + return pNew; } -/*-------------------------------------------------------------------------*/ +/*-------------------------------------------------------------------------*/ void DeleteProtocol(void *self) { - int i; - pProtocol pOld = (pProtocol)self; - - if(NULL==pOld) - { - return; + int i; + pProtocol pOld = (pProtocol) self; + + if (NULL == pOld) { + return; + } + if (pOld->name) { + free(pOld->name); + } + if (pOld->pDes) { + DeleteDescriptor(pOld->pDes); + } + if (pOld->version) { + free(pOld->version); + } + if (pOld->pProList) { + i = 0; + while (NULL != pOld->pProList[i]) { + free(pOld->pProList[i]); + i++; } - if(pOld->name) - { - free(pOld->name); - } - if(pOld->pDes) - { - DeleteDescriptor(pOld->pDes); - } - if(pOld->version) - { - free(pOld->version); - } - if(pOld->pProList) - { - i = 0; - while(NULL!=pOld->pProList[i]) - { - free(pOld->pProList[i]); - i++; - } - } - free(pOld); + } + free(pOld); } + /*------------------------------------------------------------------*/ -static int ContextDo(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]){ - commandContext comCon; - char buffer[1024]; - char *command; - int status; +static int ContextDo(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + SConnection *comCon = NULL; + char buffer[1024]; + char *command; + int status; - if(argc < 3){ - SCWrite(pCon,"ERROR: insufficient arguments to contextdo",eError); - return 0; - } - - status = Tcl_GetInt(pSics->pTcl,argv[1],&comCon.transID); - if(status != TCL_OK){ - snprintf(buffer,1023,"ERROR: failed to convert %s to transaction ID", argv[1]); - SCWrite(pCon,buffer,eError); - return 0; - } - strncpy(comCon.deviceID,argv[2],SCDEVIDLEN); - memset(buffer,0,sizeof(buffer)); - command = Arg2Tcl(argc-2,&argv[2],buffer,sizeof buffer); - if (!command) { - SCWrite(pCon,"ERROR: no more memory",eError); - return 0; - } - SCPushContext2(pCon,comCon); - status = InterpExecute(pSics,pCon,command); - if (command != buffer) free(command); - SCPopContext(pCon); - return status; + if (argc < 3) { + SCWrite(pCon, "ERROR: insufficient arguments to contextdo", eError); + return 0; + } + + comCon = SCCopyConnection(pCon); + if (comCon == NULL) { + SCWrite(pCon, "EROOR: out of memory in contextdo", eError); + return 0; + } + status = Tcl_GetInt(pSics->pTcl, argv[1], &comCon->transID); + if (status != TCL_OK) { + snprintf(buffer, 1023, "ERROR: failed to convert %s to transaction ID", + argv[1]); + SCWrite(pCon, buffer, eError); + return 0; + } + strlcpy(comCon->deviceID, argv[2], SCDEVIDLEN); + memset(buffer, 0, sizeof(buffer)); + command = Arg2Tcl(argc - 2, &argv[2], buffer, sizeof buffer); + if (!command) { + SCWrite(pCon, "ERROR: no more memory", eError); + return 0; + } + status = InterpExecute(pSics, comCon, command); + if (command != buffer) + free(command); + SCDeleteConnection(comCon); + return status; } + /*--------------------------------------------------------------------------*/ -int InstallProtocol(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) +int InstallProtocol(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) { - pProtocol pNew = NULL; - pNew = CreateProtocol(); - if(NULL==pNew) - { - SCWrite(pCon,"No memory to create Protocol",eError); - return 0; - } - AddCommand(pSics,"Protocol",ProtocolAction,DeleteProtocol,pNew); - AddCommand(pSics,"contextdo",ContextDo,NULL,NULL); - SCSendOK(pCon); - return 1; -} -/*------------------------------------------------------------------------*/ -void MakeProtocol(SicsInterp *pSics){ - pProtocol pNew = NULL; - pNew = CreateProtocol(); - if(NULL!= pNew) - { - AddCommand(pSics,"Protocol",ProtocolAction,DeleteProtocol,pNew); - AddCommand(pSics,"contextdo",ContextDo,NULL,NULL); - } -} -/*------------------------------------------------------------------------*/ -static int ProtocolOptions(SConnection* pCon, pProtocol pPro) -{ - int i; - char pBuffer[80]; - for(i=0;iiNumPros;i++) - { - sprintf(pBuffer,"Protocol[%d] = %s",i,pPro->pProList[i]); - SCWrite(pCon,pBuffer,eStatus); - } - return 1; + pProtocol pNew = NULL; + pNew = CreateProtocol(); + if (NULL == pNew) { + SCWrite(pCon, "No memory to create Protocol", eError); + return 0; + } + AddCommand(pSics, "Protocol", ProtocolAction, DeleteProtocol, pNew); + AddCommand(pSics, "contextdo", ContextDo, NULL, NULL); + SCSendOK(pCon); + return 1; } /*------------------------------------------------------------------------*/ -static int ProtocolHelp(SConnection* pCon, Protocol* pPro) +void MakeProtocol(void) { - SCWrite(pCon, - "Usage: protocol {help|list|options|reset} | set protocolName", - eStatus); - return 1; + pProtocol pNew = NULL; + pNew = CreateProtocol(); + if (NULL != pNew) { + AddCommand(pServ->pSics, "Protocol", ProtocolAction, DeleteProtocol, pNew); + AddCommand(pServ->pSics, "contextdo", ContextDo, NULL, NULL); + } } /*------------------------------------------------------------------------*/ -static int ProtocolSet(SConnection* pCon, Protocol* pPro, char *pProName) +static int ProtocolOptions(SConnection * pCon, pProtocol pPro) { - int proID; - if(!SCVerifyConnection(pCon)) - { - return 0; - } - - /* lazy initialisation of defaultWriter since connection is verified */ - InitDefaultProtocol(pCon,pPro); - - /* Do not die if no data */ - if(NULL == pProName) - { - return 0; - } - - /* check list of protocols for valid name and assign functions based */ - /* on match of pProName */ - proID = EnumChoice(pPro->pProList,pPro->iNumPros,pProName); - switch(proID) - { - case -1: /* invalid */ - return 0; - break; - - case 1: /* normal (connection start default) */ - SCSetWriteFunc(pCon,SCNormalWrite); - break; - - case 2: /* outcodes */ - SCSetWriteFunc(pCon,SCWriteWithOutcode); - break; - - case 3: /* sycamore */ - SCSetWriteFunc(pCon,SCWriteSycamore); - break; - case 4: /* json */ - SCSetWriteFunc(pCon,SCWriteJSON_String); - break; - case 5: - SCSetWriteFunc(pCon,SCACTWrite); - break; - case 0: /* default = psi_sics */ - default: - SCSetWriteFunc(pCon,pPro->defaultWriter); - break; - } - pCon->iProtocolID = proID; - SCSendOK(pCon); - return 1; + int i; + char pBuffer[80]; + for (i = 0; i < pPro->iNumPros; i++) { + snprintf(pBuffer,sizeof(pBuffer)-1, "Protocol[%d] = %s", i, pPro->pProList[i]); + SCWrite(pCon, pBuffer, eValue); + } + return 1; } /*------------------------------------------------------------------------*/ -int ProtocolGet(SConnection* pCon, void* pData, char *pProName, int len) +static int ProtocolHelp(SConnection * pCon, Protocol * pPro) +{ + SCWrite(pCon, + "Usage: protocol {help|list|options|reset} | set protocolName", + eValue); + return 1; +} + +/*------------------------------------------------------------------------*/ +static int ProtocolSet(SConnection * pCon, Protocol * pPro, char *pProName) +{ + SConnection *pMaster = NULL; + + int proID; + if (!SCVerifyConnection(pCon)) { + return 0; + } + pMaster = SCfindMaster(pCon); + assert(pMaster != NULL); + + /* lazy initialisation of defaultWriter since connection is verified */ + InitDefaultProtocol(pCon, pPro); + + /* Do not die if no data */ + if (NULL == pProName) { + return 0; + } + + /* check list of protocols for valid name and assign functions based */ + /* on match of pProName */ + proID = EnumChoice(pPro->pProList, pPro->iNumPros, pProName); + switch (proID) { + case -1: /* invalid */ + return 0; + break; + + case 1: /* normal (connection start default) */ + SCSetWriteFunc(pMaster, SCNormalWrite); + SCSetWriteFunc(pCon, SCNormalWrite); + break; + + case 2: /* outcodes */ + SCSetWriteFunc(pMaster, SCWriteWithOutcode); + SCSetWriteFunc(pCon, SCWriteWithOutcode); + break; + + case 3: /* sycamore */ + SCSetWriteFunc(pMaster, SCWriteSycamore); + SCSetWriteFunc(pCon, SCWriteSycamore); + break; + case 4: /* json */ + SCSetWriteFunc(pCon, SCWriteJSON_String); + SCSetWriteFunc(pMaster, SCWriteJSON_String); + break; + case 5: + SCSetWriteFunc(pMaster, SCACTWrite); + SCSetWriteFunc(pCon, SCACTWrite); + break; + case 6: + SCSetWriteFunc(pMaster, SCAllWrite); + SCSetWriteFunc(pCon, SCAllWrite); + break; + case 0: /* default = psi_sics */ + default: + SCSetWriteFunc(pMaster, pPro->defaultWriter); + SCSetWriteFunc(pCon, pPro->defaultWriter); + break; + } + pCon->iProtocolID = proID; + pMaster->iProtocolID = proID; + SCSendOK(pCon); + return 1; +} + +/*------------------------------------------------------------------------*/ +int ProtocolGet(SConnection * pCon, void *pData, char *pProName, int len) { int Index; - Protocol *pPro = (Protocol *)pData; - if(!SCVerifyConnection(pCon)) - { - return 0; - } - - if(pData == NULL) - { - pCon->iProtocolID = 0; - return 1; - } - - /* lazy initialisation of defaultWriter since connection is verified */ - if(0==pPro->isDefaultSet) - { - pPro->defaultWriter = SCGetWriteFunc(pCon); - pPro->isDefaultSet = 1; - pCon->iProtocolID = 0; - } - strncpy(pProName, pPro->pProList[pCon->iProtocolID], len); - return 1; -#if 0 - Index = pCon->iProtocolID; + Protocol *pPro = (Protocol *) pData; + if (!SCVerifyConnection(pCon)) { + return 0; + } - /* check list of protocols for valid name */ - switch(Index) - { - case 0: /* default = psi_sics */ - case 1: /* normal (connection start default) */ - case 2: /* outcodes */ - case 3: /* sycamore */ - case 4: /* json */ - case 5: /* act */ - pProName = pPro->pProList[Index]; - return 1; - break; - default: - return 0; - break; - } + if (pData == NULL) { + pCon->iProtocolID = 0; + return 1; + } + + /* lazy initialisation of defaultWriter since connection is verified */ + if (0 == pPro->isDefaultSet) { + pPro->defaultWriter = SCGetWriteFunc(pCon); + pPro->isDefaultSet = 1; + pCon->iProtocolID = 0; + } + strlcpy(pProName, pPro->pProList[pCon->iProtocolID], len); + return 1; +#if 0 + Index = pCon->iProtocolID; + + /* check list of protocols for valid name */ + switch (Index) { + case 0: /* default = psi_sics */ + case 1: /* normal (connection start default) */ + case 2: /* outcodes */ + case 3: /* sycamore */ + case 4: /* json */ + case 5: /* act */ + pProName = pPro->pProList[Index]; + return 1; + break; + default: + return 0; + break; + } #endif } /*------------------------------------------------------------------------*/ -static int ProtocolList(SConnection* pCon, Protocol* pPro) +static int ProtocolList(SConnection * pCon, Protocol * pPro) { - SCWrite(pCon, - "Usage: protocol {help|list|options|reset} | set protocolName", - eStatus); - return 1; + SCWrite(pCon, + "Usage: protocol {help|list|options|reset} | set protocolName", + eValue); + return 1; } /*-------------------------------------------------------------------------*/ -int ProtocolAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) +int ProtocolAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) { - int iRet; - char **argx; - FuPaResult PaRes; - pProtocol pPro = NULL; - - const int iNumCmds = 5; - FuncTemplate CommandTemplate[] = { - {"help",0,{0,0}}, - {"list",0,{0,0}}, - {"options",0,{0,0}}, - {"set",1,{FUPATEXT}}, - {"reset",0,{0,0}}, - {NULL} - }; + int iRet; + char **argx; + FuPaResult PaRes; + pProtocol pPro = NULL; - assert(pCon != NULL); - assert(pSics != NULL); - pPro = (pProtocol)pData; - assert(pPro != NULL); - - /* You need to have User level access rights to use this facility */ - if(!SCMatchRights(pCon,usSpy)) - { - return 0; - } - - /* parse function args */ - argtolower(argc,argv); - argx = &argv[1]; - iRet = EvaluateFuPa((pFuncTemplate)&CommandTemplate,iNumCmds,argc-1,argx,&PaRes); + const int iNumCmds = 5; + FuncTemplate CommandTemplate[] = { + {"help", 0, {0, 0}}, + {"list", 0, {0, 0}}, + {"options", 0, {0, 0}}, + {"set", 1, {FUPATEXT}}, + {"reset", 0, {0, 0}}, + {NULL} + }; - /* if invalid (iRet < 0) then default to "help" command */ - - switch(iRet) - { - case 1: /* list */ - iRet = ProtocolList(pCon,pPro); - break; - case 2: /* options */ - iRet = ProtocolOptions(pCon,pPro); - break; - case 3: /* set */ - iRet = ProtocolSet(pCon,pPro,PaRes.Arg[0].text); - break; - case 4: /* reset */ - iRet = ProtocolSet(pCon,pPro,"default"); - break; - case 0: /* help */ - default: - iRet = ProtocolHelp(pCon,pPro); - break; - } - return iRet; + assert(pCon != NULL); + assert(pSics != NULL); + pPro = (pProtocol) pData; + assert(pPro != NULL); + + /* You need to have User level access rights to use this facility */ + if (!SCMatchRights(pCon, usSpy)) { + return 0; + } + + /* parse function args */ + argtolower(argc, argv); + argx = &argv[1]; + iRet = + EvaluateFuPa((pFuncTemplate) & CommandTemplate, iNumCmds, argc - 1, + argx, &PaRes); + + /* if invalid (iRet < 0) then default to "help" command */ + + switch (iRet) { + case 1: /* list */ + iRet = ProtocolList(pCon, pPro); + break; + case 2: /* options */ + iRet = ProtocolOptions(pCon, pPro); + break; + case 3: /* set */ + iRet = ProtocolSet(pCon, pPro, PaRes.Arg[0].text); + break; + case 4: /* reset */ + iRet = ProtocolSet(pCon, pPro, "default"); + break; + case 0: /* help */ + default: + iRet = ProtocolHelp(pCon, pPro); + break; + } + return iRet; } /*-------------------------------------------------------------------------*/ static int EnumChoice(char *pList[], int iLength, char *pInput) { - int i; - int iRet = -1; - - for(i=0;iisDefaultSet) - { - pPro->defaultWriter = SCGetWriteFunc(pCon); - pPro->isDefaultSet = 1; - pCon->iProtocolID = 0; - } - return pPro->isDefaultSet; -} + if (NULL == pCon) { + return 0; + } + + /* lazy initialisation of defaultWriter since connection is verified */ + if (0 == pPro->isDefaultSet) { + pPro->defaultWriter = SCGetWriteFunc(pCon); + pPro->isDefaultSet = 1; + pCon->iProtocolID = 0; + } + return pPro->isDefaultSet; +} + /*---------------------------------------------------------------------*/ -void sycformat(char *tag, OutCode msgFlag, pDynString msgString, pDynString msgOut) { - DynStringConcat(msgOut," "); +void sycformat(char *tag, OutCode msgFlag, pDynString msgString, + pDynString msgOut) +{ + DynStringConcat(msgOut, " "); switch (msgFlag) { - eEvent: + eEvent: break; - eFinish: + eFinish: + break; + default: + DynStringConcat(msgOut, tag); + DynStringConcat(msgOut, "={"); + DynStringConcat(msgOut, GetCharArray(msgString)); + DynStringConcat(msgOut, "}"); break; - default: - DynStringConcat(msgOut,tag); - DynStringConcat(msgOut,"={"); - DynStringConcat(msgOut,GetCharArray(msgString)); - DynStringConcat(msgOut,"}"); - break; } } -int SCWriteSycamore(SConnection *pCon, char *pBuffer, int iOut) +int SCWriteSycamore(SConnection * pCon, char *pBuffer, int iOut) { - int iRet; - char pBueffel[MAXMSG], *pBufferFrom, *pBufferTo; - long taskID = 0; + int iRet; + char pBueffel[MAXMSG]; + long taskID = 0; /* char pPrefix[40];*/ - pDynString pMsg = NULL; - pDynString pMsgString = NULL; - commandContext comCon; + pDynString pMsg = NULL; + pDynString pMsgString = NULL; + commandContext comCon; - if (strlen(pBuffer) == 0) { - return 0; - } - /* Strip \r and \n */ - for (pBufferFrom=pBufferTo=pBuffer; ; pBufferFrom++) { - if (*pBufferFrom == '\r' || *pBufferFrom == '\n') - continue; - *pBufferTo = *pBufferFrom; - if (*pBufferTo == '\0') - break; - pBufferTo++; - } + if (strlen(pBuffer) == 0) { + return 0; + } + + if (!SCVerifyConnection(pCon)) { + return 0; + } - if(!SCVerifyConnection(pCon)) - { - return 0; - } + /* log it for any case */ + if (pCon->pSock) { + iRet = pCon->pSock->sockid; + } else { + iRet = 0; + } + snprintf(pBueffel,sizeof(pBueffel)-1, "Next line intended for socket: %d", iRet); + SICSLogWrite(pBueffel, eInternal); + SICSLogWrite(pBuffer, iOut); - /* log it for any case */ - if(pCon->pSock) - { - iRet = pCon->pSock->sockid; - } - else - { - iRet = 0; - } - sprintf(pBueffel,"Next line intended for socket: %d",iRet); - SICSLogWrite(pBueffel,eInternal); - SICSLogWrite(pBuffer,iOut); - - /* write to commandlog if user or manager privilege */ - if(SCGetRights(pCon) <= usUser) - { - WriteToCommandLogId(NULL,iRet,pBuffer); - } - - /* put it into the interpreter if present */ - if(SCinMacro(pCon)) - { - InterpWrite(pServ->pSics,pBuffer); - /* print it to client if error message */ - /* FIXME should report errors via sycamore + /* write to commandlog if user or manager privilege */ + if (SCGetRights(pCon) <= usUser) { + WriteToCommandLogId(NULL, iRet, pBuffer); + } + + /* put it into the interpreter if present */ + if (SCinMacro(pCon)) { + InterpWrite(pServ->pSics, pBuffer); + /* print it to client if error message */ + /* FIXME should report errors via sycamore if((iOut== eError) || (iOut == eWarning) ) - iRet = SCDoSockWrite(pCon,GetCharArray(pMsgOut));*/ - } - else /* not in interpreter, normal logic */ - { - comCon = SCGetContext(pCon); + iRet = SCDoSockWrite(pCon,GetCharArray(pMsgOut)); */ + } else { /* not in interpreter, normal logic */ + + comCon = SCGetContext(pCon); /* Return 0 without dying if no message data */ - if(pBuffer == NULL) - { - return 0; + if (pBuffer == NULL) { + return 0; } taskID = comCon.transID; - + pMsg = CreateDynString(INIT_STR_SIZE, STR_RESIZE_LENGTH); pMsgString = CreateDynString(INIT_STR_SIZE, STR_RESIZE_LENGTH); pBueffel[0] = '\0'; - sprintf(pBueffel,"[con%4.4d:",(int)pCon->ident); /* field 1: connID */ - DynStringConcat(pMsg,pBueffel); - sprintf(pBueffel,"t%6.6d:",(int)taskID); /* field 2: taskID */ - DynStringConcat(pMsg,pBueffel); + snprintf(pBueffel,sizeof(pBueffel)-1, "[con%4.4d:", (int) pCon->ident); /* field 1: connID */ + DynStringConcat(pMsg, pBueffel); + snprintf(pBueffel,sizeof(pBueffel)-1, "t%6.6d:", (int) taskID); /* field 2: taskID */ + DynStringConcat(pMsg, pBueffel); /* deviceID */ - DynStringConcat(pMsg,comCon.deviceID); - DynStringConcatChar(pMsg,':'); + DynStringConcat(pMsg, comCon.deviceID); + DynStringConcatChar(pMsg, ':'); - /* msgFlag */ - switch(iOut) { - case 5: /* eValue */ - DynStringConcat(pMsg,"out"); - break; - default: - DynStringConcat(pMsg,pCode[iOut]); - break; + /* msgFlag */ + switch (iOut) { + case 5: /* eValue */ + DynStringConcat(pMsg, "out"); + break; + default: + DynStringConcat(pMsg, pCode[iOut]); + break; } - DynStringConcatChar(pMsg,']'); - if (iOut == eStart){ + DynStringConcatChar(pMsg, ']'); + if (iOut == eStart) { DynStringConcat(pMsgString, comCon.deviceID); } if (iOut == eEvent) { DynStringConcat(pMsgString, " type="); /* Default type to VALUECHANGE if conEventType not set */ - if (-1 == pCon->conEventType) + if (-1 == pCon->conEventType) DynStringConcat(pMsgString, pEventType[0]); else DynStringConcat(pMsgString, pEventType[pCon->conEventType]); /* DynStringConcat(pMsgString, " status="); DynStringConcat(pMsgString, pStatus[pCon->conStatus]);*/ - DynStringConcat(pMsgString,","); + DynStringConcat(pMsgString, ","); } - DynStringConcat(pMsgString," "); - DynStringConcat(pMsgString,pBuffer); + DynStringConcat(pMsgString, " "); + DynStringConcat(pMsgString, pBuffer); sycformat(comCon.deviceID, iOut, pMsgString, pMsg); - /* is this really to be printed ? */ - if(iOut < pCon->iOutput) - { - if (pMsg != NULL) + /* is this really to be printed ? */ + if (iOut < pCon->iOutput) { + if (pMsg != NULL) DeleteDynString(pMsg); return 0; } - /* first the socket */ - /*strcat(pMsg, pBueffel);*/ - iRet = SCDoSockWrite(pCon,GetCharArray(pMsg)); - SCWriteToLogFiles(pCon,GetCharArray(pMsg)); - } - if (pMsg != NULL) - DeleteDynString(pMsg); - return 1; + /* first the socket */ + /*strcat(pMsg, pBueffel); */ + iRet = SCDoSockWrite(pCon, GetCharArray(pMsg)); + } + if (pMsg != NULL) + DeleteDynString(pMsg); + return 1; } /* Only work for hipadaba commands, hlist, hset, hget, hnotify * A multiline string (ie have crnl) will be converted to an array. * Strings with '=' will be converted to name value pairs */ -struct json_object *mkJSON_Object(SConnection *pCon, char *pBuffer, int iOut) +struct json_object *mkJSON_Object(SConnection * pCon, char *pBuffer, + int iOut) { - int linenum = __LINE__; - char pBueffel[MAXMSG], *pBufferFrom, *pBufferTo; - long taskID = 0; - struct json_object *msg_json=NULL, *tmp_json=NULL; + int linenum = __LINE__; + char pBueffel[MAXMSG], *pBufferFrom, *pBufferTo; + long taskID = 0; + struct json_object *msg_json = NULL, *tmp_json = NULL; - commandContext comCon; - char pError[256]; - pError[0]='\0'; + commandContext comCon; + char pError[256]; + pError[0] = '\0'; - if (strlen(pBuffer) == 0) { - return 0; - } - - if(!SCVerifyConnection(pCon)) - { - return 0; - } - comCon = SCGetContext(pCon); + if (strlen(pBuffer) == 0) { + return 0; + } - /* Return 0 without dying if no message data */ - if(pBuffer == NULL) - { - return 0; - } + if (!SCVerifyConnection(pCon)) { + return 0; + } + comCon = SCGetContext(pCon); - /* - build the Tcl-command to execute for formatting the - data into a sycamore string - */ - taskID = comCon.transID; - - pBueffel[0] = '\0'; - msg_json = json_object_new_object(); - if (is_error(msg_json)) { linenum = __LINE__; goto reporterr; } + /* Return 0 without dying if no message data */ + if (pBuffer == NULL) { + return 0; + } + + /* + build the Tcl-command to execute for formatting the + data into a sycamore string + */ + taskID = comCon.transID; + + pBueffel[0] = '\0'; + msg_json = json_object_new_object(); + if (is_error(msg_json)) { + linenum = __LINE__; + goto reporterr; + } /* field 1: connID */ - json_object_object_add(msg_json, "con", json_object_new_int(pCon->ident)); + json_object_object_add(msg_json, "con", + json_object_new_int(pCon->ident)); /* field 2: taskID */ - json_object_object_add(msg_json, "trans", json_object_new_int(taskID)); - /* deviceID */ - json_object_object_add(msg_json, "object", json_object_new_string(comCon.deviceID)); + json_object_object_add(msg_json, "trans", json_object_new_int(taskID)); + /* deviceID */ + json_object_object_add(msg_json, "object", + json_object_new_string(comCon.deviceID)); /* msgFlag */ - switch(iOut) { - case 5: /* eValue */ - json_object_object_add(msg_json, "flag", json_object_new_string("out")); - break; - default: - json_object_object_add(msg_json, "flag", json_object_new_string(pCode[iOut])); - break; + switch (iOut) { + case 5: /* eValue */ + json_object_object_add(msg_json, "flag", + json_object_new_string("out")); + break; + default: + json_object_object_add(msg_json, "flag", + json_object_new_string(pCode[iOut])); + break; + } + if (iOut == eHdbValue || iOut == eHdbEvent) { + tmp_json = json_tokener_parse(pBuffer); + if (is_error(tmp_json)) { + linenum = __LINE__; + goto reporterr; } - if (iOut == eHdbValue || iOut == eHdbEvent) { - tmp_json = json_tokener_parse(pBuffer); - if (is_error(tmp_json)) { linenum = __LINE__; goto reporterr; } - } else { - /* Strip \r and \n */ - for (pBufferFrom=pBufferTo=pBuffer; ; pBufferFrom++) { - if (*pBufferFrom == '\r' || *pBufferFrom == '\n') - continue; - pBufferTo = pBufferFrom; - if (*pBufferTo == '\0') - break; - pBufferTo++; - } - tmp_json = json_object_new_string(pBuffer); - if (is_error(tmp_json)) { linenum = __LINE__; goto reporterr; } + } else { + /* Strip \r and \n */ + for (pBufferFrom = pBufferTo = pBuffer;; pBufferFrom++) { + if (*pBufferFrom == '\r' || *pBufferFrom == '\n') + continue; + pBufferTo = pBufferFrom; + if (*pBufferTo == '\0') + break; + pBufferTo++; } - json_object_object_add(msg_json, "data", tmp_json); - return msg_json; + tmp_json = json_object_new_string(pBuffer); + if (is_error(tmp_json)) { + linenum = __LINE__; + goto reporterr; + } + } + json_object_object_add(msg_json, "data", tmp_json); + return msg_json; reporterr: - SCSetWriteFunc(pCon,SCNormalWrite); - snprintf(pError, 256,"{\"ERROR\": \"%s:%d Error making json object\"}", __FILE__, linenum); - SCWrite(pCon,pError,eError); - SCSetWriteFunc(pCon,SCWriteJSON_String); + SCSetWriteFunc(pCon, SCNormalWrite); + snprintf(pError, 256, "{\"ERROR\": \"%s:%d Error making json object\"}", + __FILE__, linenum); + SCWrite(pCon, pError, eError); + SCSetWriteFunc(pCon, SCWriteJSON_String); cleanup: - if (tmp_json != NULL && !is_error(tmp_json)) - json_object_put(tmp_json); - if (msg_json != NULL && !is_error(msg_json)) - json_object_put(msg_json); - return NULL; + if (tmp_json != NULL && !is_error(tmp_json)) + json_object_put(tmp_json); + if (msg_json != NULL && !is_error(msg_json)) + json_object_put(msg_json); + return NULL; } -int SCWriteJSON_String(SConnection *pCon, char *pBuffer, int iOut) +int SCWriteJSON_String(SConnection * pCon, char *pBuffer, int iOut) { - struct json_object *my_object=NULL, *tmp_json=NULL; - char pBueffel[MAXMSG], errBuff[MAXMSG]; + struct json_object *my_object = NULL, *tmp_json = NULL; + char pBueffel[MAXMSG], errBuff[MAXMSG]; int iRet, errLen = MAXMSG; if (strlen(pBuffer) == 0) return 1; - /* log it for any case */ - if(pCon->pSock) - { - iRet = pCon->pSock->sockid; - } - else - { - iRet = 0; - } - if(pCon->iMacro != 1) { - sprintf(pBueffel,"Next line intended for socket: %d",iRet); - SICSLogWrite(pBueffel,eInternal); - SICSLogWrite(pBuffer,iOut); - } - - /* write to commandlog if user or manager privilege */ - if(SCGetRights(pCon) <= usUser) - { - if(pCon->iMacro != 1) - { - WriteToCommandLogId(NULL,iRet,pBuffer); - } - else - { - if(iOut == eError || iOut == eWarning) - { - WriteToCommandLogId(NULL,iRet,pBuffer); - } - } - } - - if(SCinMacro(pCon)) - { - InterpWrite(pServ->pSics,pBuffer); - /* print it to client if error message */ - if((iOut== eError) || (iOut == eWarning) ) - { - tmp_json = json_object_new_string(pBuffer); - iRet = SCDoSockWrite(pCon,json_object_to_json_string(tmp_json)); - } + /* log it for any case */ + if (pCon->pSock) { + iRet = pCon->pSock->sockid; + } else { + iRet = 0; + } + snprintf(pBueffel,sizeof(pBueffel)-1, "Next line intended for socket: %d", iRet); + SICSLogWrite(pBueffel, eInternal); + SICSLogWrite(pBuffer, iOut); + + /* write to commandlog if user or manager privilege */ + if (SCGetRights(pCon) <= usUser) { + if (pCon->iMacro != 1) { + WriteToCommandLogId(NULL, iRet, pBuffer); } else { - if ((my_object = mkJSON_Object(pCon, pBuffer, iOut)) == NULL) { - snprintf(errBuff, errLen, "failed to make JSON object from, %s", pBuffer); - tmp_json = json_object_new_string(errBuff); - my_object = json_object_new_object(); - json_object_object_add(my_object, "ERROR", tmp_json); - SCDoSockWrite(pCon,json_object_to_json_string(my_object)); - iRet = 0; - } else { - iRet = SCDoSockWrite(pCon,json_object_to_json_string(my_object)); - SCWriteToLogFiles(pCon,pBuffer); + if (iOut == eError || iOut == eWarning) { + WriteToCommandLogId(NULL, iRet, pBuffer); } } - if (tmp_json != NULL && !is_error(tmp_json)) - json_object_put(tmp_json); - if (my_object != NULL && !is_error(my_object)) - json_object_put(my_object); + } + + if (SCinMacro(pCon)) { + InterpWrite(pServ->pSics, pBuffer); + /* print it to client if error message */ + if ((iOut == eError) || (iOut == eWarning)) { + tmp_json = json_object_new_string(pBuffer); + iRet = SCDoSockWrite(pCon, (char *)json_object_to_json_string(tmp_json)); + } + } else { + if ((my_object = mkJSON_Object(pCon, pBuffer, iOut)) == NULL) { + snprintf(errBuff, errLen, "failed to make JSON object from, %s", + pBuffer); + tmp_json = json_object_new_string(errBuff); + my_object = json_object_new_object(); + json_object_object_add(my_object, "ERROR", tmp_json); + SCDoSockWrite(pCon, (char *)json_object_to_json_string(my_object)); + iRet = 0; + } else { + iRet = SCDoSockWrite(pCon, (char *)json_object_to_json_string(my_object)); + } + } + if (tmp_json != NULL && !is_error(tmp_json)) + json_object_put(tmp_json); + if (my_object != NULL && !is_error(my_object)) + json_object_put(my_object); return iRet; } + /*------------------------------------------------------------------------*/ /* Protocol API */ -char * GetProtocolName(SConnection* pCon) +char *GetProtocolName(SConnection * pCon) { - pProtocol pPro; - pSicsInterp pSics; - - if(!SCVerifyConnection(pCon)) - { - return NULL; - } - - pSics = GetInterpreter(); - if(!pSics) return NULL; - - pPro = FindCommandData(pSics,"protocol","Protocol"); - if(!pPro) return NULL; - - InitDefaultProtocol(pCon,pPro); + pProtocol pPro; + pSicsInterp pSics; - /* check list of protocols for valid name */ - switch(pCon->iProtocolID) - { - case 0: /* default = psi_sics */ - case 1: /* normal (connection start default) */ - case 2: /* outcodes */ - case 3: /* sycamore */ - case 4: /* json */ - return strdup(pPro->pProList[pCon->iProtocolID]); - break; - default: - return strdup("invalid"); - break; - } + if (!SCVerifyConnection(pCon)) { + return NULL; + } + + pSics = GetInterpreter(); + if (!pSics) + return NULL; + + pPro = FindCommandData(pSics, "protocol", "Protocol"); + if (!pPro) + return NULL; + + InitDefaultProtocol(pCon, pPro); + + /* check list of protocols for valid name */ + switch (pCon->iProtocolID) { + case 0: /* default = psi_sics */ + case 1: /* normal (connection start default) */ + case 2: /* outcodes */ + case 3: /* sycamore */ + case 4: /* json */ + return strdup(pPro->pProList[pCon->iProtocolID]); + break; + default: + return strdup("invalid"); + break; + } } /*----------------------------------*/ -int GetProtocolID(SConnection* pCon) +int GetProtocolID(SConnection * pCon) { - if(NULL!=pCon) - { - return pCon->iProtocolID; - } - return -1; + if (NULL != pCon) { + return pCon->iProtocolID; + } + return -1; } + /*---------------------------------------------------------------------------*/ -writeFunc GetProtocolWriteFunc(SConnection *pCon){ - if(pCon != NULL){ - switch(pCon->iProtocolID){ - case 2: /* outcodes */ - return SCWriteWithOutcode; - break; - case 3: /* sycamore */ - return SCWriteSycamore; - break; - case 4: /* json */ - return SCWriteJSON_String; - break; - case 5: - return SCACTWrite; - break; - default: - return SCNormalWrite; - break; - } +writeFunc GetProtocolWriteFunc(SConnection * pCon) +{ + if (pCon != NULL) { + switch (pCon->iProtocolID) { + case 2: /* outcodes */ + return SCWriteWithOutcode; + break; + case 3: /* sycamore */ + return SCWriteSycamore; + break; + case 4: /* json */ + return SCWriteJSON_String; + break; + case 5: + return SCACTWrite; + break; + default: + return SCNormalWrite; + break; } - return SCNormalWrite; + } + return SCNormalWrite; } diff --git a/protocol.h b/protocol.h index 24d51d72..53537abc 100644 --- a/protocol.h +++ b/protocol.h @@ -7,30 +7,30 @@ static const int iNumProTags = 2; static char *pProTags[3] = { - "start", - "finish", - NULL + "start", + "finish", + NULL }; #define esStart -1 #define esFinish -2 - + /*--------------------- lifecycle -------------------------------------- */ -int InstallProtocol(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); +int InstallProtocol(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); void DeleteProtocol(void *pSelf); -void MakeProtocol(SicsInterp *pSics); - +void MakeProtocol(void); + /*--------------------- operations --------------------------------------*/ -int ProtocolAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); +int ProtocolAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); /*--------------------- implement protocol sycamore ---------------------*/ -int SCWriteSycamore(SConnection *pCon, char *pBuffer, int iOut); +int SCWriteSycamore(SConnection * pCon, char *pBuffer, int iOut); /*--------------------- implement protocol API -----------------------*/ -char * GetProtocolName(SConnection *pCon); -int GetProtocolID(SConnection *pCon); -int ProtocolGet(SConnection* pCon, void* pData, char *pProName, int len); -writeFunc GetProtocolWriteFunc(SConnection *pCon); +char *GetProtocolName(SConnection * pCon); +int GetProtocolID(SConnection * pCon); +int ProtocolGet(SConnection * pCon, void *pData, char *pProName, int len); +writeFunc GetProtocolWriteFunc(SConnection * pCon); /*-----------------------------------------------------------------------*/ -#endif +#endif diff --git a/proxy.c b/proxy.c index a30a5dd8..7f8c474f 100644 --- a/proxy.c +++ b/proxy.c @@ -14,463 +14,488 @@ #include /*-----------------------------------------------------------------------*/ typedef struct { - pIDrivable pDriv; - pEVInterface pEnv; - pIDrivable pSlaveDriv; - void *slaveData; - pEVInterface pEnvSlave; + pIDrivable pDriv; + pEVInterface pEnv; + pIDrivable pSlaveDriv; + void *slaveData; + pEVInterface pEnvSlave; } ProxyInt, *pProxyInt; /*------------------------------------------------------------------------*/ -static void KillProxyInt(void *data){ - pProxyInt proxy = (pProxyInt)data; - - if(proxy == NULL){ - return; - } - if(proxy->pDriv != NULL){ - free(proxy->pDriv); - } - if(proxy->pEnv != NULL){ - free(proxy->pEnv); - } - free(proxy); +static void KillProxyInt(void *data) +{ + pProxyInt proxy = (pProxyInt) data; + + if (proxy == NULL) { + return; + } + if (proxy->pDriv != NULL) { + free(proxy->pDriv); + } + if (proxy->pEnv != NULL) { + free(proxy->pEnv); + } + free(proxy); } + /*===================== Drivable Interfaces ================================*/ -static int testDrivProxy(pSICSOBJ self){ - pProxyInt proxy = self->pPrivate; +static int testDrivProxy(pSICSOBJ self) +{ + pProxyInt proxy = self->pPrivate; - if(proxy->pSlaveDriv != NULL && proxy->slaveData != NULL){ - return 1; - } + if (proxy->pSlaveDriv != NULL && proxy->slaveData != NULL) { + return 1; + } + return 0; +} + +/*-----------------------------------------------------------------------*/ +static int ProxyHalt(void *data) +{ + pSICSOBJ self = (pSICSOBJ) data; + pProxyInt proxy = NULL; + + assert(self != NULL); + proxy = self->pPrivate; + assert(self != NULL); + + if (testDrivProxy(self)) { + return proxy->pSlaveDriv->Halt(proxy->slaveData); + } else { return 0; + } } -/*-----------------------------------------------------------------------*/ -static int ProxyHalt(void *data){ - pSICSOBJ self = (pSICSOBJ)data; - pProxyInt proxy = NULL; - - assert(self != NULL); - proxy = self->pPrivate; - assert(self != NULL); - - if(testDrivProxy(self)){ - return proxy->pSlaveDriv->Halt(proxy->slaveData); - } else { - return 0; - } -} + /*------------------------------------------------------------------------*/ -static int ProxyLimits(void *data, float fval, - char *error, int iErrLen){ - pSICSOBJ self = (pSICSOBJ)data; - pProxyInt proxy = NULL; - - assert(self != NULL); - proxy = self->pPrivate; - assert(self != NULL); - - if(testDrivProxy(self)){ - return proxy->pSlaveDriv->CheckLimits(proxy->slaveData, fval, - error, iErrLen); - } else { - strncpy(error,"ERROR: device not configured",iErrLen); - return 0; - } +static int ProxyLimits(void *data, float fval, char *error, int iErrLen) +{ + pSICSOBJ self = (pSICSOBJ) data; + pProxyInt proxy = NULL; + + assert(self != NULL); + proxy = self->pPrivate; + assert(self != NULL); + + if (testDrivProxy(self)) { + return proxy->pSlaveDriv->CheckLimits(proxy->slaveData, fval, + error, iErrLen); + } else { + strlcpy(error, "ERROR: device not configured", iErrLen); + return 0; + } } + /*-----------------------------------------------------------------------*/ -static long ProxySet(void *data, SConnection *pCon, float fVal){ - pSICSOBJ self = (pSICSOBJ)data; - pProxyInt proxy = NULL; - - assert(self != NULL); - proxy = self->pPrivate; - assert(self != NULL); - - if(testDrivProxy(self)){ - return proxy->pSlaveDriv->SetValue(proxy->slaveData, - pCon, fVal); - } else { - SCWrite(pCon,"ERROR: device not configured", eError); - return 0; - } +static long ProxySet(void *data, SConnection * pCon, float fVal) +{ + pSICSOBJ self = (pSICSOBJ) data; + pProxyInt proxy = NULL; + + assert(self != NULL); + proxy = self->pPrivate; + assert(self != NULL); + + if (testDrivProxy(self)) { + return proxy->pSlaveDriv->SetValue(proxy->slaveData, pCon, fVal); + } else { + SCWrite(pCon, "ERROR: device not configured", eError); + return 0; + } } + /*-----------------------------------------------------------------------*/ -static int ProxyStatus(void *data, SConnection *pCon){ - pSICSOBJ self = (pSICSOBJ)data; - pProxyInt proxy = NULL; - - assert(self != NULL); - proxy = self->pPrivate; - assert(self != NULL); - - if(testDrivProxy(self)){ - return proxy->pSlaveDriv->CheckStatus(proxy->slaveData, - pCon); - } else { - SCWrite(pCon,"ERROR: device not configured", eError); - return HWFault; - } +static int ProxyStatus(void *data, SConnection * pCon) +{ + pSICSOBJ self = (pSICSOBJ) data; + pProxyInt proxy = NULL; + + assert(self != NULL); + proxy = self->pPrivate; + assert(self != NULL); + + if (testDrivProxy(self)) { + return proxy->pSlaveDriv->CheckStatus(proxy->slaveData, pCon); + } else { + SCWrite(pCon, "ERROR: device not configured", eError); + return HWFault; + } } + /*-----------------------------------------------------------------------*/ -static float ProxyGet(void *data, SConnection *pCon){ - pSICSOBJ self = (pSICSOBJ)data; - pProxyInt proxy = NULL; - - assert(self != NULL); - proxy = self->pPrivate; - assert(self != NULL); - - if(testDrivProxy(self)){ - return proxy->pSlaveDriv->GetValue(proxy->slaveData, pCon); - } else { - SCWrite(pCon,"ERROR: device not configured", eError); - return HWFault; - } +static float ProxyGet(void *data, SConnection * pCon) +{ + pSICSOBJ self = (pSICSOBJ) data; + pProxyInt proxy = NULL; + + assert(self != NULL); + proxy = self->pPrivate; + assert(self != NULL); + + if (testDrivProxy(self)) { + return proxy->pSlaveDriv->GetValue(proxy->slaveData, pCon); + } else { + SCWrite(pCon, "ERROR: device not configured", eError); + return HWFault; + } } + /*===================== environment interface ==========================*/ -static int testEnvProxy(pSICSOBJ self){ - pProxyInt proxy = self->pPrivate; +static int testEnvProxy(pSICSOBJ self) +{ + pProxyInt proxy = self->pPrivate; - if(proxy->pEnvSlave != NULL && proxy->slaveData != NULL){ - return 1; - } + if (proxy->pEnvSlave != NULL && proxy->slaveData != NULL) { + return 1; + } + return 0; +} + +/*-----------------------------------------------------------------------*/ +static EVMode ProxyMode(void *data) +{ + pSICSOBJ self = (pSICSOBJ) data; + pProxyInt proxy = NULL; + + assert(self != NULL); + proxy = self->pPrivate; + assert(self != NULL); + + if (testEnvProxy(self)) { + return proxy->pEnvSlave->GetMode(proxy->slaveData); + } else { + return EVError; + } +} + +/*------------------------------------------------------------------------*/ +static int ProxyTolerance(void *data) +{ + pSICSOBJ self = (pSICSOBJ) data; + pProxyInt proxy = NULL; + + assert(self != NULL); + proxy = self->pPrivate; + assert(self != NULL); + + if (testEnvProxy(self)) { + return proxy->pEnvSlave->IsInTolerance(proxy->slaveData); + } else { return 0; + } } -/*-----------------------------------------------------------------------*/ -static EVMode ProxyMode(void *data){ - pSICSOBJ self = (pSICSOBJ)data; - pProxyInt proxy = NULL; - - assert(self != NULL); - proxy = self->pPrivate; - assert(self != NULL); - - if(testEnvProxy(self)){ - return proxy->pEnvSlave->GetMode(proxy->slaveData); - } else { - return EVError; - } -} -/*------------------------------------------------------------------------*/ -static int ProxyTolerance(void *data){ - pSICSOBJ self = (pSICSOBJ)data; - pProxyInt proxy = NULL; - - assert(self != NULL); - proxy = self->pPrivate; - assert(self != NULL); - - if(testEnvProxy(self)){ - return proxy->pEnvSlave->IsInTolerance(proxy->slaveData); - } else { - return 0; - } -} -/*-------------------------------------------------------------------------*/ -static int ProxyError(void *data){ - pSICSOBJ self = (pSICSOBJ)data; - pProxyInt proxy = NULL; - - assert(self != NULL); - proxy = self->pPrivate; - assert(self != NULL); - - if(testEnvProxy(self)){ - return proxy->pEnvSlave->HandleError(proxy->slaveData); - } else { - return 0; - } -} -/*-----------------------------------------------------------------------*/ -static void *findRealDev(pHdb node){ - char realDevice[80]; - CommandList *pCom = NULL; - - GetHdbProperty(node,"proxy",realDevice,80); - pCom = FindCommand(pServ->pSics,realDevice); - if(pCom != NULL){ - return pCom->pData; - } else { - return NULL; - } -} -/*-----------------------------------------------------------------------*/ -static void *ProxyGetInterface(void *pData, int iID){ - pSICSOBJ self = (pSICSOBJ)pData; - pDummy other = NULL; - void *inter = NULL; - pProxyInt proxy = NULL; - assert(self != NULL); - proxy = self->pPrivate; - - if(self != NULL){ - other = (pDummy)findRealDev(self->objectNode); - if(other != NULL){ - inter = other->pDescriptor->GetInterface(other, iID); - if(inter == NULL && - (iID == DRIVEID || iID == ENVIRINTERFACE) ){ - proxy->pEnvSlave = NULL; - proxy->pSlaveDriv = NULL; - proxy->slaveData = NULL; - return NULL; - } else { - if(iID == DRIVEID){ - proxy->pSlaveDriv = inter; - proxy->slaveData = other; - return proxy->pDriv; - } else if(iID == ENVIRINTERFACE){ - proxy->pEnvSlave = inter; - proxy->slaveData = other; - return proxy->pEnv; - } - } - return inter; - } - } +/*-------------------------------------------------------------------------*/ +static int ProxyError(void *data) +{ + pSICSOBJ self = (pSICSOBJ) data; + pProxyInt proxy = NULL; + + assert(self != NULL); + proxy = self->pPrivate; + assert(self != NULL); + + if (testEnvProxy(self)) { + return proxy->pEnvSlave->HandleError(proxy->slaveData); + } else { + return 0; + } +} + +/*-----------------------------------------------------------------------*/ +static void *findRealDev(pHdb node) +{ + char realDevice[80]; + CommandList *pCom = NULL; + + GetHdbProperty(node, "proxy", realDevice, 80); + pCom = FindCommand(pServ->pSics, realDevice); + if (pCom != NULL) { + return pCom->pData; + } else { return NULL; + } } + +/*-----------------------------------------------------------------------*/ +static void *ProxyGetInterface(void *pData, int iID) +{ + pSICSOBJ self = (pSICSOBJ) pData; + pDummy other = NULL; + void *inter = NULL; + pProxyInt proxy = NULL; + + assert(self != NULL); + proxy = self->pPrivate; + + if (self != NULL) { + other = (pDummy) findRealDev(self->objectNode); + if (other != NULL) { + inter = other->pDescriptor->GetInterface(other, iID); + if (inter == NULL && (iID == DRIVEID || iID == ENVIRINTERFACE)) { + proxy->pEnvSlave = NULL; + proxy->pSlaveDriv = NULL; + proxy->slaveData = NULL; + return NULL; + } else { + if (iID == DRIVEID) { + proxy->pSlaveDriv = inter; + proxy->slaveData = other; + return proxy->pDriv; + } else if (iID == ENVIRINTERFACE) { + proxy->pEnvSlave = inter; + proxy->slaveData = other; + return proxy->pEnv; + } + } + return inter; + } + } + return NULL; +} + /*------------------------------------------------------------------------*/ -static hdbCallbackReturn ProxyCallback(pHdb node, void *userData, - pHdbMessage message){ - pHdbDataMessage get = NULL, set = NULL; - pDummy other = NULL; - pIDrivable pDriv = NULL; - float fval; - int status; - SConnection *pCon = NULL; - pSICSOBJ self = (pSICSOBJ)userData; - char proxyDev[80]; - - get = GetHdbGetMessage(message); - if(get != NULL){ - pCon = (SConnection *)get->callData; - other = (pDummy)findRealDev(node); - if(other != NULL){ - pDriv = other->pDescriptor->GetInterface(other,DRIVEID); - if(pDriv != NULL && pCon != NULL){ - fval = pDriv->GetValue(other, pCon); - get->v->v.doubleValue = (double)fval; - node->value.v.doubleValue = (double)fval; - return hdbContinue; - } - } - get->v->v.doubleValue = .0; - } +static hdbCallbackReturn ProxyCallback(pHdb node, void *userData, + pHdbMessage message) +{ + pHdbDataMessage get = NULL, set = NULL; + pDummy other = NULL; + pIDrivable pDriv = NULL; + float fval; + int status; + SConnection *pCon = NULL; + pSICSOBJ self = (pSICSOBJ) userData; + char proxyDev[80]; - set = GetHdbSetMessage(message); - if(set != NULL){ - pCon = (SConnection *)set->callData; - other = (pDummy)findRealDev(node); - if(other == NULL){ - if(pCon != NULL){ - SCWrite(pCon,"ERROR: device not configured", eError); - return hdbAbort; - } - } - GetHdbProperty(node,"proxy", proxyDev,80); - status = StartDevice(pServ->pExecutor, proxyDev, - self->pDes, self, pCon, (float)set->v->v.doubleValue); - if(status == 1){ - return hdbContinue; - } else { - return hdbAbort; - } - } - - return hdbContinue; + get = GetHdbGetMessage(message); + if (get != NULL) { + pCon = (SConnection *) get->callData; + other = (pDummy) findRealDev(node); + if (other != NULL) { + pDriv = other->pDescriptor->GetInterface(other, DRIVEID); + if (pDriv != NULL && pCon != NULL) { + fval = pDriv->GetValue(other, pCon); + get->v->v.doubleValue = (double) fval; + node->value.v.doubleValue = (double) fval; + return hdbContinue; + } + } + get->v->v.doubleValue = .0; + } + + set = GetHdbSetMessage(message); + if (set != NULL) { + pCon = (SConnection *) set->callData; + other = (pDummy) findRealDev(node); + if (other == NULL) { + if (pCon != NULL) { + SCWrite(pCon, "ERROR: device not configured", eError); + return hdbAbort; + } + } + GetHdbProperty(node, "proxy", proxyDev, 80); + status = StartDevice(pServ->pExecutor, proxyDev, + self->pDes, self, pCon, + pCon->runLevel, (float) set->v->v.doubleValue); + if (status == 1) { + return hdbContinue; + } else { + return hdbAbort; + } + } + + return hdbContinue; } + /*----------------------------------------------------------------------------*/ -static hdbCallbackReturn MapParCallback(pHdb node, void *userData, - pHdbMessage message){ - pHdbDataMessage get = NULL, set = NULL; - CommandList *pCom = NULL; - SConnection *pCon = NULL; - char mapPar[80], proxyDev[80], *pData = NULL; - char command[1024]; - pDynString data = NULL; - - if(GetHdbKillNodeMessage(message) != NULL ){ - return hdbContinue; - } - - GetHdbProperty(node->mama, "proxy", proxyDev,80); - pCom = FindCommand(pServ->pSics, proxyDev); - if(pCom == NULL){ - if(pCon != NULL){ - SCWrite(pCon,"ERROR: device not configured", eError); - } - return hdbContinue; - } - GetHdbProperty(node,"mappar", mapPar, 80); - - get = GetHdbGetMessage(message); - if(get != NULL){ - pCon = (SConnection *)get->callData; snprintf(command,1024,"%s %s", proxyDev, mapPar); - if(pCon != NULL){ - SCStartBuffering(pCon); - InterpExecute(pServ->pSics, pCon,command); - data = SCEndBuffering(pCon); - if(data != NULL){ - pData = GetCharArray(data); - if(strstr(pData,"ERROR") != NULL){ - SCWrite(pCon,pData,eError); - } else { - pData = strchr(pData,(int)'='); - if(pData != NULL){ - pData++; - if(!readHdbValue(get->v, pData, command, 1024)){ - SCWrite(pCon, command, eError); - } - copyHdbValue(get->v, &node->value); - return hdbContinue; - } - } - } - } - } +static hdbCallbackReturn MapParCallback(pHdb node, void *userData, + pHdbMessage message) +{ + pHdbDataMessage get = NULL, set = NULL; + CommandList *pCom = NULL; + SConnection *pCon = NULL; + char mapPar[80], proxyDev[80], *pData = NULL; + char command[1024]; + pDynString data = NULL; - set = GetHdbSetMessage(message); - if(set != NULL){ - pCon = (SConnection *)set->callData; - data = formatValue(*(set->v), node); - if(data != NULL){ - snprintf(command,1024,"%s %s %s", proxyDev, mapPar, - GetCharArray(data)); - DeleteDynString(data); - InterpExecute(pServ->pSics, pCon, command); - } - } - - return hdbContinue; + if (GetHdbKillNodeMessage(message) != NULL) { + return hdbContinue; + } + + GetHdbProperty(node->mama, "proxy", proxyDev, 80); + pCom = FindCommand(pServ->pSics, proxyDev); + if (pCom == NULL) { + if (pCon != NULL) { + SCWrite(pCon, "ERROR: device not configured", eError); + } + return hdbContinue; + } + GetHdbProperty(node, "mappar", mapPar, 80); + + get = GetHdbGetMessage(message); + if (get != NULL) { + pCon = (SConnection *) get->callData; + snprintf(command, 1024, "%s %s", proxyDev, mapPar); + if (pCon != NULL) { + SCStartBuffering(pCon); + InterpExecute(pServ->pSics, pCon, command); + data = SCEndBuffering(pCon); + if (data != NULL) { + pData = GetCharArray(data); + if (strstr(pData, "ERROR") != NULL) { + SCWrite(pCon, pData, eError); + } else { + pData = strchr(pData, (int) '='); + if (pData != NULL) { + pData++; + if (!readHdbValue(get->v, pData, command, 1024)) { + SCWrite(pCon, command, eError); + } + copyHdbValue(get->v, &node->value); + return hdbContinue; + } + } + } + } + } + + set = GetHdbSetMessage(message); + if (set != NULL) { + pCon = (SConnection *) set->callData; + data = formatValue(*(set->v), node); + if (data != NULL) { + snprintf(command, 1024, "%s %s %s", proxyDev, mapPar, + GetCharArray(data)); + DeleteDynString(data); + InterpExecute(pServ->pSics, pCon, command); + } + } + + return hdbContinue; } + /*-------------------------------------------------------------------------*/ -static int MapFunc(pSICSOBJ self, SConnection *pCon, pHdb commandNode, - pHdb par[], int nPar){ - pHdb node = NULL; - int type; - - if(nPar < 4){ - SCWrite(pCon,"ERROR: not enough arguments to MapFunc", eError); - return 0; - } - - type = convertHdbType(par[2]->value.v.text); - node = MakeHipadabaNode(par[0]->value.v.text, type, 1); - if(node == NULL){ - SCWrite(pCon,"ERROR: out of memory in MapFunc", eError); - return 0; - } - SetHdbProperty(node,"mappar", par[1]->value.v.text); - SetHdbProperty(node,"priv", par[3]->value.v.text); - AppendHipadabaCallback(node, - MakeHipadabaCallback(MapParCallback, NULL, NULL)); - AddHipadabaChild(self->objectNode, node, pCon); - - return 1; +static int MapFunc(pSICSOBJ self, SConnection * pCon, pHdb commandNode, + pHdb par[], int nPar) +{ + pHdb node = NULL; + int type; + + if (nPar < 4) { + SCWrite(pCon, "ERROR: not enough arguments to MapFunc", eError); + return 0; + } + + type = convertHdbType(par[2]->value.v.text); + node = MakeHipadabaNode(par[0]->value.v.text, type, 1); + if (node == NULL) { + SCWrite(pCon, "ERROR: out of memory in MapFunc", eError); + return 0; + } + SetHdbProperty(node, "mappar", par[1]->value.v.text); + SetHdbProperty(node, "priv", par[3]->value.v.text); + AppendHipadabaCallback(node, + MakeHipadabaCallback(MapParCallback, NULL, NULL)); + AddHipadabaChild(self->objectNode, node, pCon); + + return 1; } + /*--------------------------------------------------------------------------*/ -static int ProxyAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]){ - int status; - pSICSOBJ self = (pSICSOBJ)pData; - CommandList *pCom = NULL; - char proxyObj[80]; - - assert(self != NULL); - - /* - * do parameters and object functions - */ - if(argc > 1){ - status = InvokeSICSOBJ(pCon, pSics, pData, argc, argv); - if(status != -1 ){ - return status; - } - } - - /* - * try the interpreter function of the proxy object - */ - GetHdbProperty(self->objectNode,"proxy", proxyObj, 80); - pCom = FindCommand(pSics, proxyObj); - if(pCom != NULL){ - return pCom->OFunc(pCon,pSics,pCom->pData, argc, argv); - } else { - SCWrite(pCon,"ERROR: device not configured", eError); - return 0; - } +static int ProxyAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + int status; + pSICSOBJ self = (pSICSOBJ) pData; + CommandList *pCom = NULL; + char proxyObj[80]; + + assert(self != NULL); + + /* + * do parameters and object functions + */ + if (argc > 1) { + status = InvokeSICSOBJ(pCon, pSics, pData, argc, argv); + if (status != -1) { + return status; + } + } + + /* + * try the interpreter function of the proxy object + */ + GetHdbProperty(self->objectNode, "proxy", proxyObj, 80); + pCom = FindCommand(pSics, proxyObj); + if (pCom != NULL) { + return pCom->OFunc(pCon, pSics, pCom->pData, argc, argv); + } else { + SCWrite(pCon, "ERROR: device not configured", eError); + return 0; + } } + /*--------------------------------------------------------------------------*/ -int ProxyFactory(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]){ - int type; - pSICSOBJ pNew = NULL; - pHdb mapFunc = NULL; - hdbValue v; - pProxyInt proxy = NULL; - - if(argc < 4){ - SCWrite(pCon,"ERROR: not enough arguments for ProxyFactory", - eError); - return 0; - } - - type = convertHdbType(argv[3]); - pNew = MakeSICSOBJv(argv[1], "ProxyObject", type, usSpy); - if(pNew == NULL){ - SCWrite(pCon,"ERROR: out of memory in ProxyFactory", - eError); - return 0; - } +int ProxyFactory(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + int type; + pSICSOBJ pNew = NULL; + pHdb mapFunc = NULL; + hdbValue v; + pProxyInt proxy = NULL; - proxy = malloc(sizeof(ProxyInt)); - if(proxy == NULL){ - SCWrite(pCon,"ERROR: out of memory in ProxyFactory", - eError); - return 0; - } - memset(proxy,0,sizeof(ProxyInt)); - proxy->pDriv = CreateDrivableInterface(); - proxy->pEnv = CreateEVInterface(); - if(proxy->pDriv == NULL && proxy->pEnv == NULL){ - SCWrite(pCon,"ERROR: out of memory in ProxyFactory", - eError); - return 0; - } - proxy->pDriv->CheckLimits = ProxyLimits; - proxy->pDriv->CheckStatus = ProxyStatus; - proxy->pDriv->GetValue = ProxyGet; - proxy->pDriv->Halt = ProxyHalt; - proxy->pDriv->SetValue = ProxySet; + if (argc < 4) { + SCWrite(pCon, "ERROR: not enough arguments for ProxyFactory", eError); + return 0; + } - proxy->pEnv->GetMode = ProxyMode; - proxy->pEnv->HandleError = ProxyError; - proxy->pEnv->IsInTolerance = ProxyTolerance; - - pNew->KillPrivate = KillProxyInt; - pNew->pPrivate = proxy; - - pNew->pDes->GetInterface = ProxyGetInterface; - SetHdbProperty(pNew->objectNode, "proxy", argv[2]); - AppendHipadabaCallback(pNew->objectNode, - MakeHipadabaCallback(ProxyCallback, pNew,NULL)); - - v = MakeSICSFunc(MapFunc); - mapFunc = MakeSICSHdbPar("map", usMugger, v); - SetHdbProperty(mapFunc,"visible","false"); - v = MakeHdbText("Undefined"); - AddSICSHdbPar(mapFunc,"name",usMugger,v); - AddSICSHdbPar(mapFunc,"target",usMugger,v); - AddSICSHdbPar(mapFunc,"type",usMugger,v); - AddSICSHdbPar(mapFunc,"priv",usMugger,v); - AddHipadabaChild(pNew->objectNode, mapFunc, pCon); - - AddCommand(pSics,argv[1], - ProxyAction, - KillSICSOBJ, - pNew); - - return 1; + type = convertHdbType(argv[3]); + pNew = MakeSICSOBJv(argv[1], "ProxyObject", type, usSpy); + if (pNew == NULL) { + SCWrite(pCon, "ERROR: out of memory in ProxyFactory", eError); + return 0; + } + + proxy = malloc(sizeof(ProxyInt)); + if (proxy == NULL) { + SCWrite(pCon, "ERROR: out of memory in ProxyFactory", eError); + return 0; + } + memset(proxy, 0, sizeof(ProxyInt)); + proxy->pDriv = CreateDrivableInterface(); + proxy->pEnv = CreateEVInterface(); + if (proxy->pDriv == NULL && proxy->pEnv == NULL) { + SCWrite(pCon, "ERROR: out of memory in ProxyFactory", eError); + return 0; + } + proxy->pDriv->CheckLimits = ProxyLimits; + proxy->pDriv->CheckStatus = ProxyStatus; + proxy->pDriv->GetValue = ProxyGet; + proxy->pDriv->Halt = ProxyHalt; + proxy->pDriv->SetValue = ProxySet; + + proxy->pEnv->GetMode = ProxyMode; + proxy->pEnv->HandleError = ProxyError; + proxy->pEnv->IsInTolerance = ProxyTolerance; + + pNew->KillPrivate = KillProxyInt; + pNew->pPrivate = proxy; + + pNew->pDes->GetInterface = ProxyGetInterface; + SetHdbProperty(pNew->objectNode, "proxy", argv[2]); + AppendHipadabaCallback(pNew->objectNode, + MakeHipadabaCallback(ProxyCallback, pNew, NULL)); + + v = MakeSICSFunc(MapFunc); + mapFunc = MakeSICSHdbPar("map", usMugger, v); + SetHdbProperty(mapFunc, "visible", "false"); + v = MakeHdbText("Undefined"); + AddSICSHdbPar(mapFunc, "name", usMugger, v); + AddSICSHdbPar(mapFunc, "target", usMugger, v); + AddSICSHdbPar(mapFunc, "type", usMugger, v); + AddSICSHdbPar(mapFunc, "priv", usMugger, v); + AddHipadabaChild(pNew->objectNode, mapFunc, pCon); + + AddCommand(pSics, argv[1], ProxyAction, KillSICSOBJ, pNew); + + return 1; } - diff --git a/proxy.h b/proxy.h index 4afc22cc..70df5bd4 100644 --- a/proxy.h +++ b/proxy.h @@ -11,7 +11,7 @@ */ #ifndef PROXY_H_ #define PROXY_H_ -int ProxyFactory(SConnection *pCon, SicsInterp *pSics, void *pData, +int ProxyFactory(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]); -#endif /*PROXY_H_*/ +#endif /*PROXY_H_ */ diff --git a/reflist.c b/reflist.c new file mode 100644 index 00000000..dd2e81bd --- /dev/null +++ b/reflist.c @@ -0,0 +1,746 @@ +/** + * Reflection list: a configurable list of reflections and + * their setting angles. To be used for four circle and possibly + * TAS diffraction. + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, July 2008 + * + * Fixed saving of anglesheader status + * + * Mark Koennecke, September 2009 + */ +#include +#include +#include "reflist.h" +#include "sicshipadaba.h" +#include "stptok.h" +#include "hdbtable.h" + +#define INAME "index" +#define ANAME "angles" +#define FLAG "flag" +static char undef[] = "Undefined"; +#define IDXFMT " %8.4f" +#define ANGFMT " %8.2f" +/*----------------------------------------------------------------------*/ +typedef struct { + int idxCount; + int angCount; + int count; +} RLPriv, *pRLPriv; +/*-----------------------------------------------------------------------*/ +int SaveRefList(void *data, char *name, FILE * fd) +{ + pHdb node = NULL; + pSICSOBJ self = (pSICSOBJ)data; + + node = GetHipadabaNode(self->objectNode,"anglesheader"); + fprintf(fd,"%s anglesheader %s\n", name, node->value.v.text); + SaveHdbTable(data,name,fd); + + return 1; +} +/*---------------------------------------------------------------------- + * The point of the code below and the callback is to update the + * configuration counts whenever the corresponding parameters + * are changed. + * ---------------------------------------------------------------------*/ +static void UpdateConfiguration(pSICSOBJ refl) +{ + pRLPriv priv = refl->pPrivate; + hdbValue v; + char *pPtr = NULL, token[50]; + pHdb template, node; + + template = GetHipadabaNode(refl->objectNode,"template"); + if(template != NULL){ + DeleteHipadabaNode(template,NULL); + } + template = MakeHipadabaNode("template",HIPNONE, 1); + AddHipadabaChild(refl->objectNode, template, NULL); + + SICSHdbGetPar(refl, NULL, "indexheader", &v); + pPtr = v.v.text; + priv->idxCount = 0; + while ((pPtr = stptok(pPtr, token, 50, ",")) != NULL) { + node = MakeHipadabaNode(token,HIPFLOAT,1); + AddHipadabaChild(template,node,NULL); + priv->idxCount++; + } + + SICSHdbGetPar(refl, NULL, "anglesheader", &v); + pPtr = v.v.text; + priv->angCount = 0; + while ((pPtr = stptok(pPtr, token, 50, ",")) != NULL) { + node = MakeHipadabaNode(token,HIPFLOAT,1); + AddHipadabaChild(template,node,NULL); + priv->angCount++; + } + node = GetHipadabaNode(refl->objectNode,"clear"); + assert(node != NULL); + runObjFunction(refl,pServ->dummyCon,node); + + node = GetHipadabaNode(refl->objectNode,"readtemplate"); + assert(node != NULL); + runObjFunction(refl,pServ->dummyCon,node); + +} + +/*-----------------------------------------------------------------------*/ +static hdbCallbackReturn CalcConfiguration(pHdb node, void *userData, + pHdbMessage mm) +{ + + if (GetHdbSetMessage(mm) != NULL) { + /* + * This is after the normal SICS parameter SetUpdateCallback + * which already updated the node + */ + UpdateConfiguration((pSICSOBJ) userData); + } + return hdbContinue; +} +/*-----------------------------------------------------------------------*/ +pSICSOBJ MakeReflectionListInt(char *name) +{ + pSICSOBJ pNew = NULL; + pHdb node = NULL; + hdbValue v; + pRLPriv priv = NULL; + + pNew = MakeHdbTable(name, "ReflectionList"); + priv = malloc(sizeof(RLPriv)); + if (pNew == NULL || priv == NULL) { + return NULL; + } + + pNew->pPrivate = priv; + pNew->KillPrivate = DefaultKill; + + v = MakeHdbText("h,k,l"); + node = MakeSICSHdbPar("indexheader", usMugger, v); + AppendHipadabaCallback(node, MakeHipadabaCallback(CalcConfiguration, + pNew, NULL)); + AddHipadabaChild(pNew->objectNode, node, NULL); + priv->idxCount = 3; + + v = MakeHdbText("stt,om,chi,phi"); + node = MakeSICSHdbPar("anglesheader", usUser, v); + AppendHipadabaCallback(node, MakeHipadabaCallback(CalcConfiguration, + pNew, NULL)); + AddHipadabaChild(pNew->objectNode, node, NULL); + UpdateConfiguration(pNew); + priv->angCount = 4; + priv->count = 0; + + return pNew; +} +/*----------------------------------------------------------------------*/ +static int AddIndexCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, + pHdb par[], int nPar) +{ + char path[80]; + int status, i; + pHdb node = NULL, addrowNode = NULL; + hdbValue v; + + if (nPar < 3) { + SCWrite(pCon, "ERROR: need indexes as arguments", eError); + return 0; + } + + addrowNode = GetHipadabaNode(self->objectNode,"addrow"); + assert(addrowNode != NULL); + /* copy HKL */ + node = addrowNode->child; + UpdateHipadabaPar(node, par[0]->value, pCon); + node = node->next; + UpdateHipadabaPar(node, par[1]->value, pCon); + node = node->next; + UpdateHipadabaPar(node, par[2]->value, pCon); + + /* set angles to zero */ + node = node->next; + v = MakeHdbFloat(.0); + while(node != NULL){ + UpdateHipadabaPar(node,v,pCon); + node = node->next; + } + + return runObjFunction(self, pCon, addrowNode); +} + +/*----------------------------------------------------------------------*/ +void AddRefIdx(pSICSOBJ refl, double hkl[]) +{ + int status; + hdbValue v; + pHdb node, child; + + node = GetHipadabaNode(refl->objectNode,"addrow"); + assert(node != NULL); + child = node->child; + UpdateHipadabaPar(child, MakeHdbFloat(hkl[0]),NULL); + child = child->next; + UpdateHipadabaPar(child, MakeHdbFloat(hkl[1]),NULL); + child = child->next; + UpdateHipadabaPar(child, MakeHdbFloat(hkl[2]),NULL); + + v = MakeHdbFloat(.0); + child = child->next; + if(child != NULL){ + UpdateHipadabaPar(child, v,NULL); + } + child = child->next; + if(child != NULL){ + UpdateHipadabaPar(child, v,NULL); + } + child = child->next; + if(child != NULL){ + UpdateHipadabaPar(child, v,NULL); + } + child = child->next; + if(child != NULL){ + UpdateHipadabaPar(child, v,NULL); + } + runObjFunction(refl, pServ->dummyCon, node); +} +/*----------------------------------------------------------------------*/ +static void AddRowIntern(pSICSOBJ refl, double hkl[], double ang[], + SConnection *pCon) +{ + int status; + hdbValue v; + pHdb node, child; + + node = GetHipadabaNode(refl->objectNode,"addrow"); + assert(node != NULL); + child = node->child; + UpdateHipadabaPar(child, MakeHdbFloat(hkl[0]),NULL); + child = child->next; + UpdateHipadabaPar(child, MakeHdbFloat(hkl[1]),NULL); + child = child->next; + UpdateHipadabaPar(child, MakeHdbFloat(hkl[2]),NULL); + + child = child->next; + if(child != NULL){ + UpdateHipadabaPar(child, MakeHdbFloat(ang[0]),NULL); + } + child = child->next; + if(child != NULL){ + UpdateHipadabaPar(child, MakeHdbFloat(ang[1]),NULL); + } + child = child->next; + if(child != NULL){ + UpdateHipadabaPar(child, MakeHdbFloat(ang[2]),NULL); + } + child = child->next; + if(child != NULL){ + UpdateHipadabaPar(child, MakeHdbFloat(ang[3]),NULL); + } + if(child != NULL){ + child = child->next; + if(child != NULL){ + UpdateHipadabaPar(child, MakeHdbFloat(ang[4]),NULL); + } + } + runObjFunction(refl, pCon, node); +} +/*----------------------------------------------------------------------*/ +void AddRefIdxAng(pSICSOBJ refl, double hkl[], double ang[]) +{ + AddRowIntern(refl,hkl,ang,pServ->dummyCon); +} + +/*----------------------------------------------------------------------*/ +static int AddAnglesCmd(pSICSOBJ self, SConnection * pCon, + pHdb commandNode, pHdb par[], int nPar) +{ + int i; + double hkl[3], ang[5]; + + memset(hkl,0,3*sizeof(double)); + memset(ang,0,4*sizeof(double)); + for(i = 0; i < nPar; i++){ + ang[i] = par[i]->value.v.doubleValue; + } + + AddRowIntern(self,hkl,ang,pCon); + return 1; +} +/*----------------------------------------------------------------------*/ +static int AddIndexesAnglesCmd(pSICSOBJ self, SConnection * pCon, + pHdb commandNode, pHdb par[], int nPar) +{ + pHdb node = NULL, addrowNode; + hdbValue v; + pRLPriv priv = self->pPrivate; + + + if (nPar < 6) { + SCWrite(pCon, "ERROR: need indexes/angles as arguments", eError); + return 0; + } + + addrowNode = GetHipadabaNode(self->objectNode,"addrow"); + assert(addrowNode != NULL); + /* copy HKL */ + node = addrowNode->child; + UpdateHipadabaPar(node, par[0]->value, pCon); + node = node->next; + UpdateHipadabaPar(node, par[1]->value, pCon); + node = node->next; + UpdateHipadabaPar(node, par[2]->value, pCon); + + /* copy angles */ + v = MakeHdbFloat(.0); + node = node->next; + if(node != NULL && nPar > 3){ + UpdateHipadabaPar(node, par[3]->value, pCon); + } else if(node != NULL) { + UpdateHipadabaPar(node, v, pCon); + } + node = node->next; + if(node != NULL && nPar > 4){ + UpdateHipadabaPar(node, par[4]->value, pCon); + } else if(node!= NULL) { + UpdateHipadabaPar(node, v, pCon); + } + node = node->next; + if(node != NULL && nPar > 5){ + UpdateHipadabaPar(node, par[5]->value, pCon); + } else if (node != NULL) { + UpdateHipadabaPar(node, v, pCon); + } + node = node->next; + if(node != NULL && nPar > 6){ + UpdateHipadabaPar(node, par[6]->value, pCon); + } else if(node!= NULL) { + UpdateHipadabaPar(node, v, pCon); + } + if(node != NULL){ + node = node->next; + if(node != NULL && nPar > 7){ + UpdateHipadabaPar(node, par[7]->value, pCon); + } else if(node!= NULL) { + UpdateHipadabaPar(node, v, pCon); + } + } + + return runObjFunction(self, pCon, addrowNode); +} +/*-----------------------------------------------------------------------*/ +static int ShowCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, + pHdb par[], int nPar) +{ + pHdb row = NULL, child = NULL; + char path[132], num[20]; + char data[1024]; + hdbValue v; + int i; + + if (nPar < 1) { + SCWrite(pCon, "ERROR: need id for reflection to show", eError); + return 0; + } + snprintf(path, 132, "data/%s", par[0]->value.v.text); + row = GetHipadabaNode(self->objectNode, path); + if (row == NULL) { + SCPrintf(pCon, eError, "ERROR: bad ID %s", par[0]->value.v.text); + return 0; + } + + child = row->child; + strlcpy(data,par[0]->value.v.text,1023); + strcat(data," 1"); + while(child != NULL){ + snprintf(num,20," %f",child->value.v.doubleValue); + strcat(data,num); + child = child->next; + } + + SCWrite(pCon, data, eValue); + return 1; +} +/*-----------------------------------------------------------------------*/ +static int NamesCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, + pHdb par[], int nPar) +{ + char buffer[132]; + pHdb node = NULL; + pDynString txt; + + txt = CreateDynString(256,256); + if(txt == NULL){ + SCWrite(pCon,"ERROR: out of memory listing names", eError); + return 0; + } + node = GetHipadabaNode(self->objectNode, "data"); + node = node->child; + while (node != NULL) { + snprintf(buffer, 132, "%s", node->name); + DynStringConcatLine(txt,buffer); + node = node->next; + } + + SCWrite(pCon, GetCharArray(txt), eValue); + DeleteDynString(txt); + return 1; +} +/*----------------------------------------------------------------------*/ +static int SetIndexCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, + pHdb par[], int nPar) +{ + char path[80]; + int i; + pHdb row = NULL, child; + + if (nPar < 4) { + SCWrite(pCon, "ERROR: need id and indexes as arguments", eError); + return 0; + } + + snprintf(path,80,"data/%s", par[0]->value.v.text); + row = GetHipadabaNode(self->objectNode, path); + if(row == NULL){ + SCPrintf(pCon,eError, "ERROR: reflection with ID %s not found", par[0]->value.v.text); + return 0; + } + + child = row->child; + for(i = 0; i < 3; i++, child = child->next){ + if(child != NULL){ + UpdateHipadabaPar(child, par[i+1]->value, pCon); + } + } + SCSendOK(pCon); + return 1; +} +/*----------------------------------------------------------------------*/ +static int SetAnglesCmd(pSICSOBJ self, SConnection * pCon, + pHdb commandNode, pHdb par[], int nPar) +{ + char path[80]; + int i; + pHdb row = NULL, child; + hdbValue v; + + if (nPar < 4) { + SCWrite(pCon, "ERROR: need id and angles as arguments", eError); + return 0; + } + snprintf(path,80,"data/%s", par[0]->value.v.text); + row = GetHipadabaNode(self->objectNode, path); + if(row == NULL){ + SCPrintf(pCon,eError, "ERROR: reflection with ID %s not found", par[0]->value.v.text); + return 0; + } + + child = row->child; + /* skip over hkl */ + for(i = 0; i < 3; i++, child = child->next) {} + + /* do angles */ + v = MakeHdbFloat(.0); + for(i = 0; i < 5 && child != NULL; i++, child = child->next){ + if(child != NULL){ + UpdateHipadabaPar(child, par[i+1]->value, pCon); + } + } + SCSendOK(pCon); + return 1; +} +/*-----------------------------------------------------------------------*/ +int MakeReflectionList(SConnection * pCon, SicsInterp * pSics, + void *data, int argc, char *argv[]) +{ + pSICSOBJ pNew = NULL; + pHdb cmd; + + if (argc < 2) { + SCWrite(pCon, "ERROR: need name of reflection list", eError); + return 0; + } + pNew = CreateReflectionList(pCon, pSics, argv[1]); + if (pNew == NULL) { + return 0; + } + return 1; +} + +/*------------------------------------------------------------------------*/ +pSICSOBJ CreateReflectionList(SConnection * pCon, SicsInterp * pSics, + char *name) +{ + pSICSOBJ pNew = NULL; + pHdb cmd; + + pNew = MakeReflectionListInt(name); + if (pNew == NULL) { + SCWrite(pCon, "ERROR: failed to create reflection list", eError); + return 0; + } + pNew->pDes->SaveStatus = SaveRefList; + + AddSICSHdbPar(pNew->objectNode, "names", usUser, MakeSICSFunc(NamesCmd)); + + cmd = + AddSICSHdbPar(pNew->objectNode, "addx", usUser, + MakeSICSFunc(AddIndexCmd)); + SetHdbProperty(cmd,"type","command"); + SetHdbProperty(cmd,"priv","user"); + AddSICSHdbPar(cmd, "h", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "k", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "l", usUser, MakeHdbFloat(.0)); + + cmd = + AddSICSHdbPar(pNew->objectNode, "setx", usUser, + MakeSICSFunc(SetIndexCmd)); + SetHdbProperty(cmd,"type","command"); + SetHdbProperty(cmd,"priv","user"); + AddSICSHdbPar(cmd, "id", usUser, MakeHdbText("")); + AddSICSHdbPar(cmd, "h", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "k", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "l", usUser, MakeHdbFloat(.0)); + + cmd = + AddSICSHdbPar(pNew->objectNode, "adda", usUser, + MakeSICSFunc(AddAnglesCmd)); + SetHdbProperty(cmd,"type","command"); + SetHdbProperty(cmd,"priv","user"); + AddSICSHdbPar(cmd, "stt", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "om", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "chi", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "phi", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "nu", usUser, MakeHdbFloat(.0)); + + cmd = + AddSICSHdbPar(pNew->objectNode, "seta", usUser, + MakeSICSFunc(SetAnglesCmd)); + SetHdbProperty(cmd,"type","command"); + SetHdbProperty(cmd,"priv","user"); + AddSICSHdbPar(cmd, "id", usUser, MakeHdbText("")); + AddSICSHdbPar(cmd, "stt", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "om", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "chi", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "phi", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "nu", usUser, MakeHdbFloat(.0)); + + + cmd = AddSICSHdbPar(pNew->objectNode, "addax", usUser, + MakeSICSFunc(AddIndexesAnglesCmd)); + SetHdbProperty(cmd,"type","command"); + SetHdbProperty(cmd,"priv","user"); + AddSICSHdbPar(cmd, "h", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "k", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "l", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "stt", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "om", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "chi", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "phi", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "nu", usUser, MakeHdbFloat(.0)); + + + cmd = AddSICSHdbPar(pNew->objectNode, "show", usUser, + MakeSICSFunc(ShowCmd)); + SetHdbProperty(cmd,"type","command"); + SetHdbProperty(cmd,"priv","user"); + AddSICSHdbPar(cmd, "id", usUser, MakeHdbText("")); + + AddCommand(pSics, name, InterInvokeSICSOBJ, KillSICSOBJ, pNew); + return pNew; +} +/*------------------------------------------------------------------------*/ +void ClearReflectionList(pSICSOBJ refl) +{ + pHdb node = NULL; + hdbValue v; + pRLPriv priv = refl->pPrivate; + + node = GetHipadabaNode(refl->objectNode, "clear"); + assert(node != NULL); + runObjFunction(refl,pServ->dummyCon,node); + priv->count = 0; +} + +/*-------------------------------------------------------------------------*/ +int ReflectionListCount(pSICSOBJ refl) +{ + pHdb node = NULL; + + node = GetHipadabaNode(refl->objectNode, "data"); + assert(node); + return CountHdbChildren(node); +} +/*--------------------------------------------------------------------------*/ +static pHdb findReflection(pSICSOBJ refl, int idx) +{ + pHdb node = NULL; + int count = 0; + + if (idx < 0) { + return node; + } + + node = GetHipadabaNode(refl->objectNode, "data"); + assert(node); + + node = node->child; + while (node != NULL && count != idx) { + count++; + node = node->next; + } + return node; +} +/*---------------------------------------------------------------------------*/ +void DelListReflection(pSICSOBJ refl, int idx) +{ + pHdb node = NULL; + + node = findReflection(refl, idx); + if (node != NULL) { + DeleteHipadabaNode(node, NULL); + } +} +/*-----------------------------------------------------------------------------*/ +int SetRefIndex(pSICSOBJ refl, int idx, double hkl[]) +{ + pHdb node = NULL, child; + int i; + pRLPriv priv = refl->pPrivate; + + + node = findReflection(refl, idx); + if (node != NULL) { + child = node->child; + for(i = 0; i < 3; i++, child = child->next){ + if(child != NULL){ + UpdateHipadabaPar(child, MakeHdbFloat(hkl[i]), NULL); + } + } + return 1; + } else { + return 0; + } +} +/*-----------------------------------------------------------------------------*/ +int SetRefAngles(pSICSOBJ refl, int idx, double ang[]) +{ + pHdb node = NULL, child = NULL; + hdbValue v; + int i; + pRLPriv priv = refl->pPrivate; + + + node = findReflection(refl, idx); + if (node != NULL) { + child = node->child; + /* skip over hkl */ + for(i = 0; i < 3; i++, child = child->next){} + /* set angles */ + for(i = 0; i < 5; i++, child = child->next){ + if(child != NULL){ + UpdateHipadabaPar(child, MakeHdbFloat(ang[i]), NULL); + } + } + return 1; + } else { + return 0; + } +} +/*-------------------------------------------------------------------------------*/ +int GetRefIndex(pSICSOBJ refl, int idx, double hkl[]) +{ + pHdb node = NULL, child; + int i; + pRLPriv priv = refl->pPrivate; + + node = findReflection(refl, idx); + if (node != NULL) { + child = node->child; + for(i = 0; i < 3; i++, child = child->next){ + hkl[i] = child->value.v.doubleValue; + } + return 1; + } else { + return 0; + } +} +/*-------------------------------------------------------------------------------*/ +int GetRefIndexID(pSICSOBJ refl, char *id, double hkl[]) +{ + pHdb node = NULL, child; + pRLPriv priv = refl->pPrivate; + char path[132]; + int i; + + snprintf(path, 132, "data/%s", id); + node = GetHipadabaNode(refl->objectNode, path); + if (node != NULL) { + child = node->child; + for(i = 0; i < 3; i++, child = child->next){ + hkl[i] = child->value.v.doubleValue; + } + return 1; + } else { + return 0; + } +} +/*-------------------------------------------------------------------------------*/ +int GetRefAngles(pSICSOBJ refl, int idx, double ang[]) +{ + pHdb node = NULL, child; + pRLPriv priv = refl->pPrivate; + int i; + + node = findReflection(refl, idx); + if (node != NULL) { + child = node->child; + /* skip hkl */ + for(i = 0; i < 3; i++, child = child->next){} + /* do angles */ + for(i = 0; i < 5 && child != NULL; i++, child = child->next){ + ang[i] = child->value.v.doubleValue; + } + return 1; + } else { + return 0; + } +} +/*-------------------------------------------------------------------------------*/ +int GetRefAnglesID(pSICSOBJ refl, char *id, double ang[]) +{ + pHdb node = NULL, child; + pRLPriv priv = refl->pPrivate; + char path[132]; + int i; + + snprintf(path, 132, "data/%s", id); + node = GetHipadabaNode(refl->objectNode, path); + if (node != NULL) { + child = node->child; + /* skip hkl */ + for(i = 0; i < 3; i++, child = child->next){} + /* do angles */ + for(i = 0; i < 5 && child != NULL; i++, child = child->next){ + ang[i] = child->value.v.doubleValue; + } + return 1; + } else { + return 0; + } +} +/*--------------------------------------------------------------------------------*/ +char *GetRefName(pSICSOBJ refl, int idx) +{ + pHdb node = NULL; + + node = findReflection(refl, idx); + if (node != NULL) { + return node->name; + } else { + return undef; + } +} diff --git a/reflist.h b/reflist.h new file mode 100644 index 00000000..ea591e7c --- /dev/null +++ b/reflist.h @@ -0,0 +1,60 @@ +/** + * Reflection list: a configurable list of reflections and + * their setting angles. To be used for four circle and possibly + * TAS diffraction. + * + * copyright: see File COPYRIGHT + * + * Mark Koennecke, July 2008 + */ +#ifndef REFLIST_H_ +#define REFLIST_H_ +#include +#include +/** + * This is an internal creation command: it only creates the data + * structure but does not add the commands + * \param name The name of the reflection list + * \return A SICSOBJ representing a new reflection list + */ +pSICSOBJ MakeReflectionListInt(char *name); +/** + * This is the standard SICS creation function for reflection lists + */ +int MakeReflectionList(SConnection * pCon, SicsInterp * pSics, + void *data, int argc, char *argv[]); +/** + * This creates a full reflection list with commands and adds it to the + * interpreter. + * \param pCon for error messages + * \param pSics the interpreter to add the command to + * \param The name of the reflection list + * \return A SICSOBJ representing the reflection list + */ +pSICSOBJ CreateReflectionList(SConnection * pCon, SicsInterp * pSics, + char *name); + +void ConfigureReflectionListIndex(pSICSOBJ refl, char *header); +void ConfigureReflectionListSettings(pSICSOBJ refl, char *header); + +void ClearReflectionList(pSICSOBJ refl); +int NewListReflection(pSICSOBJ refl); +void DelListReflection(pSICSOBJ refl, int idx); +int ReflectionListCount(pSICSOBJ refl); + +void AddRefIdx(pSICSOBJ refl, double hkl[]); +void AddRefIdxAng(pSICSOBJ refl, double hkl[], double ang[]); + +int SetRefIndex(pSICSOBJ refl, int idx, double hkl[]); +int SetRefAngles(pSICSOBJ refl, int idx, double ang[]); +int SetRefFlag(pSICSOBJ refl, int idx, int val); + +int GetRefIndex(pSICSOBJ refl, int idx, double hkl[]); +int GetRefIndexID(pSICSOBJ refl, char *id, double hkl[]); +int GetRefAngles(pSICSOBJ refl, int idx, double ang[]); +int GetRefAnglesID(pSICSOBJ refl, char *id, double ang[]); +int GetRefFlag(pSICSOBJ refl, int idx); + +char *GetRefName(pSICSOBJ refl, int idx); + +#endif /*REFLIST_H_ */ diff --git a/regresscter.c b/regresscter.c index a0701b50..2e6a41b3 100644 --- a/regresscter.c +++ b/regresscter.c @@ -26,237 +26,260 @@ #define STATEPAU 2 /*--------------------------------------------------------------------------*/ typedef struct { - int errType; - int recover; - int state; - time_t endTime; + int errType; + int recover; + int state; + time_t endTime; } RegressSt; /*---------------------------------------------------------------------------*/ -static int RegressGetStatus(struct __COUNTER *self, float *fControl){ - RegressSt *pSim = NULL; - time_t tD, tDe; - int iRun; +static int RegressGetStatus(struct __COUNTER *self, float *fControl) +{ + RegressSt *pSim = NULL; + time_t tD, tDe; + int iRun; - assert(self); - pSim = (RegressSt *) self->pData; - assert(pSim); + assert(self); + pSim = (RegressSt *) self->pData; + assert(pSim); - if(pSim->errType == STATUSFAIL){ - return HWFault; - } - if(time(NULL) > pSim->endTime){ - pSim->state = STATEIDLE; - } - switch(pSim->state){ - case STATEIDLE: - return HWIdle; - break; - case STATERUN: - return HWBusy; - break; - case STATEPAU: - return HWPause; - break; - } - assert(0); + if (pSim->errType == STATUSFAIL) { return HWFault; -} -/*---------------------------------------------------------------------------*/ -static int RegressStart(struct __COUNTER *self){ - RegressSt *pSim = NULL; - time_t tD; - int iRun; - - assert(self); - pSim = (RegressSt *) self->pData; - assert(pSim); - - if(pSim->errType == STARTFAIL){ - return HWFault; - } - pSim->state = STATERUN; - if(self->eMode == eTimer){ - pSim->endTime = time(NULL) + (int)self->fPreset; - } else { - pSim->endTime = time(NULL) + 7; - } - - return OKOK; -} -/*---------------------------------------------------------------------------*/ -static int RegressPause(struct __COUNTER *self){ - RegressSt *pSim = NULL; - time_t tD; - int iRun; - - assert(self); - pSim = (RegressSt *) self->pData; - assert(pSim); - - if(pSim->errType == PAUSEFAIL){ - return HWFault; - } - - pSim->state = STATEPAU; - - return OKOK; -} -/*---------------------------------------------------------------------------*/ -static int RegressContinue(struct __COUNTER *self){ - RegressSt *pSim = NULL; - - assert(self); - pSim = (RegressSt *) self->pData; - assert(pSim); - - if(pSim->errType == CONTFAIL){ - return HWFault; - } - - pSim->state = STATERUN; - - return OKOK; -} -/*--------------------------------------------------------------------------*/ -static int RegressHalt(struct __COUNTER *self){ - RegressSt *pSim = NULL; - - assert(self); - pSim = (RegressSt *) self->pData; - assert(pSim); - + } + if (time(NULL) > pSim->endTime) { pSim->state = STATEIDLE; + } + switch (pSim->state) { + case STATEIDLE: + return HWIdle; + break; + case STATERUN: + return HWBusy; + break; + case STATEPAU: + return HWPause; + break; + } + assert(0); + return HWFault; +} - return OKOK; +/*---------------------------------------------------------------------------*/ +static int RegressStart(struct __COUNTER *self) +{ + RegressSt *pSim = NULL; + time_t tD; + int iRun; + + assert(self); + pSim = (RegressSt *) self->pData; + assert(pSim); + + if (pSim->errType == STARTFAIL) { + return HWFault; + } + pSim->state = STATERUN; + if (self->eMode == eTimer) { + pSim->endTime = time(NULL) + (int) self->fPreset; + } else { + pSim->endTime = time(NULL) + 7; + } + + return OKOK; +} + +/*---------------------------------------------------------------------------*/ +static int RegressPause(struct __COUNTER *self) +{ + RegressSt *pSim = NULL; + time_t tD; + int iRun; + + assert(self); + pSim = (RegressSt *) self->pData; + assert(pSim); + + if (pSim->errType == PAUSEFAIL) { + return HWFault; + } + + pSim->state = STATEPAU; + + return OKOK; +} + +/*---------------------------------------------------------------------------*/ +static int RegressContinue(struct __COUNTER *self) +{ + RegressSt *pSim = NULL; + + assert(self); + pSim = (RegressSt *) self->pData; + assert(pSim); + + if (pSim->errType == CONTFAIL) { + return HWFault; + } + + pSim->state = STATERUN; + + return OKOK; +} + +/*--------------------------------------------------------------------------*/ +static int RegressHalt(struct __COUNTER *self) +{ + RegressSt *pSim = NULL; + + assert(self); + pSim = (RegressSt *) self->pData; + assert(pSim); + + pSim->state = STATEIDLE; + + return OKOK; } /*-------------------------------------------------------------------------*/ -static int RegressReadValues(struct __COUNTER *self){ - RegressSt *pSim = NULL; - int i; +static int RegressReadValues(struct __COUNTER *self) +{ + RegressSt *pSim = NULL; + int i; - assert(self); - pSim = (RegressSt *) self->pData; - assert(pSim); + assert(self); + pSim = (RegressSt *) self->pData; + assert(pSim); - if(pSim->errType == READFAIL){ - return HWFault; - } - - for (i = 0; i < MAXCOUNT; i++) { - self->lCounts[i] = i*10+5; - } - self->lCounts[1] = self->fPreset; - self->fTime = self->fPreset; - return OKOK; + if (pSim->errType == READFAIL) { + return HWFault; + } + + for (i = 0; i < MAXCOUNT; i++) { + self->lCounts[i] = i * 10 + 5; + } + self->lCounts[1] = self->fPreset; + self->fTime = self->fPreset; + return OKOK; } + /*-------------------------------------------------------------------------*/ static int RegressGetError(struct __COUNTER *self, int *iCode, char *error, - int iErrLen){ - strncpy(error, "Regression counter error", iErrLen); - *iCode = 1; + int iErrLen) +{ + strlcpy(error, "Regression counter error", iErrLen); + *iCode = 1; + return 1; +} + +/*--------------------------------------------------------------------------*/ +static int RegressTryAndFixIt(struct __COUNTER *self, int iCode) +{ + RegressSt *pSim = NULL; + + assert(self); + pSim = (RegressSt *) self->pData; + assert(pSim); + + if (pSim->recover == 1) { + pSim->errType = NONE; + return COREDO; + } else { + return COTERM; + } +} + +/*--------------------------------------------------------------------------*/ +static int RegressSet(struct __COUNTER *self, char *name, int iCter, + float FVal) +{ + RegressSt *pSim = NULL; + + assert(self); + pSim = (RegressSt *) self->pData; + assert(pSim); + + if (strcmp(name, "errortype") == 0) { + pSim->errType = (int) FVal; return 1; + } + if (strcmp(name, "recover") == 0) { + pSim->recover = (int) FVal; + return 1; + } + if (strcmp(name, "finish") == 0) { + pSim->state = STATEIDLE; + return 1; + } + return 0; } + /*--------------------------------------------------------------------------*/ -static int RegressTryAndFixIt(struct __COUNTER *self, int iCode){ - RegressSt *pSim = NULL; +static int RegressGet(struct __COUNTER *self, char *name, + int iCter, float *fVal) +{ + RegressSt *pSim = NULL; - assert(self); - pSim = (RegressSt *) self->pData; - assert(pSim); - - if(pSim->recover == 1){ - pSim->errType = NONE; - return COREDO; - } else { - return COTERM; - } + assert(self); + pSim = (RegressSt *) self->pData; + assert(pSim); + + if (strcmp(name, "errortype") == 0) { + *fVal = pSim->errType; + return 1; + } + if (strcmp(name, "recover") == 0) { + *fVal = pSim->recover; + return 1; + } + return 0; } -/*--------------------------------------------------------------------------*/ -static int RegressSet(struct __COUNTER *self, char *name, int iCter, float FVal){ - RegressSt *pSim = NULL; - assert(self); - pSim = (RegressSt *) self->pData; - assert(pSim); - - if(strcmp(name,"errortype") == 0){ - pSim->errType = (int)FVal; - return 1; - } - if(strcmp(name,"recover") == 0){ - pSim->recover = (int)FVal; - return 1; - } - if(strcmp(name,"finish") == 0){ - pSim->state = STATEIDLE; - return 1; - } - return 0; -} -/*--------------------------------------------------------------------------*/ -static int RegressGet(struct __COUNTER *self, char *name, - int iCter, float *fVal){ - RegressSt *pSim = NULL; - - assert(self); - pSim = (RegressSt *) self->pData; - assert(pSim); - - if(strcmp(name,"errortype") == 0){ - *fVal = pSim->errType; - return 1; - } - if(strcmp(name,"recover") == 0){ - *fVal = pSim->recover; - return 1; - } - return 0; -} /*---------------------------------------------------------------------------*/ static int RegressSend(struct __COUNTER *self, char *pText, - char *pReply, int iReplyLen){ - strncpy(pReply, "Simulated response", iReplyLen); - return 1; + char *pReply, int iReplyLen) +{ + strlcpy(pReply, "Simulated response", iReplyLen); + return 1; } + /*---------------------------------------------------------------------------*/ -pCounterDriver NewRegressCounter(char *name){ - pCounterDriver pRes = NULL; - RegressSt *pData = NULL; - int iRet; - int iC1, iC2, iC3; - char *pErr; - char pBueffel[132]; +pCounterDriver NewRegressCounter(char *name) +{ + pCounterDriver pRes = NULL; + RegressSt *pData = NULL; + int iRet; + int iC1, iC2, iC3; + char *pErr; + char pBueffel[132]; - pRes = CreateCounterDriver(name, "Regress"); - if (!pRes) { - return NULL; - } + pRes = CreateCounterDriver(name, "Regress"); + if (!pRes) { + return NULL; + } - pData = (RegressSt *) malloc(sizeof(RegressSt)); - if (!pData) { - DeleteCounterDriver(pRes); - return NULL; - } - memset(pData,0,sizeof(RegressSt)); - pRes->pData = pData; + pData = (RegressSt *) malloc(sizeof(RegressSt)); + if (!pData) { + DeleteCounterDriver(pRes); + return NULL; + } + memset(pData, 0, sizeof(RegressSt)); + pRes->pData = pData; - /* - * assign functions - */ - pRes->GetStatus = RegressGetStatus; - pRes->Start = RegressStart; - pRes->Halt = RegressHalt; - pRes->ReadValues = RegressReadValues; - pRes->GetError = RegressGetError; - pRes->TryAndFixIt = RegressTryAndFixIt; - pRes->Pause = RegressPause; - pRes->Continue = RegressContinue; - pRes->Set = RegressSet; - pRes->Get = RegressGet; - pRes->Send = RegressSend; - pRes->KillPrivate = NULL; - pRes->iNoOfMonitors = 8; + /* + * assign functions + */ + pRes->GetStatus = RegressGetStatus; + pRes->Start = RegressStart; + pRes->Halt = RegressHalt; + pRes->ReadValues = RegressReadValues; + pRes->GetError = RegressGetError; + pRes->TryAndFixIt = RegressTryAndFixIt; + pRes->Pause = RegressPause; + pRes->Continue = RegressContinue; + pRes->Set = RegressSet; + pRes->Get = RegressGet; + pRes->Send = RegressSend; + pRes->KillPrivate = NULL; + pRes->iNoOfMonitors = 8; - return pRes; + return pRes; } diff --git a/remob.c b/remob.c index e0308028..a1e649df 100644 --- a/remob.c +++ b/remob.c @@ -35,7 +35,7 @@ typedef struct RemChannel { } RemChannel; typedef struct RemServer { - pObjectDescriptor desc; + pObjectDescriptor desc; char *name; char *host; int port; @@ -45,11 +45,11 @@ typedef struct RemServer { int taskActive; int interestActive; int forwardMessages; - SCStore *conn; + SConnection *conn; } RemServer; struct Remob { - pObjectDescriptor desc; + pObjectDescriptor desc; char *name; pIDrivable pDrivInt; pICallBack pCall; @@ -70,70 +70,81 @@ typedef struct { } RemobInfo; /*-------------------------------------------------------------------------*/ -static char *StartsWith(char *line, char *name) { +static char *StartsWith(char *line, char *name) +{ /* if line does not start with name, return NULL else return a pointer to the next non-white space character - */ + */ char *str; int l; - + l = strlen(name); - if (0 != strncmp(line, name, l)) return NULL; + if (0 != strncmp(line, name, l)) + return NULL; str = line + l; while (*str == ' ') { str++; } return str; } + /*-------------------------------------------------------------------------*/ -static int RemWrite(RemChannel *rc, char *line) { +static int RemWrite(RemChannel * rc, char *line) +{ int iret; - + if (rc->chan) { /* printf("> %s\n", line); */ iret = NETWrite(rc->chan, line, strlen(line)); - if (iret == 0) iret = -1; + if (iret == 0) + iret = -1; return iret; } else { return -1; - } + } } + /*-------------------------------------------------------------------------*/ -static int RemRead(RemChannel *rc, long tmo) { +static int RemRead(RemChannel * rc, long tmo) +{ int iRet; - - if (rc->chan == NULL) return 0; /* no data */ + + if (rc->chan == NULL) + return 0; /* no data */ iRet = NETReadTillTerm(rc->chan, tmo, "\n", rc->line + rc->incomplete, - sizeof(rc->line) - rc->incomplete); + sizeof(rc->line) - rc->incomplete); if (iRet == 0) { - rc->incomplete = strlen(rc->line); /* number of chars already received */ - return 0; /* timeout */ + rc->incomplete = strlen(rc->line); /* number of chars already received */ + return 0; /* timeout */ } else { - rc->incomplete=0; + rc->incomplete = 0; } return iRet; } + /*-------------------------------------------------------------------------*/ -static int RemHandle(RemServer *remserver) { +static int RemHandle(RemServer * remserver) +{ char *line, *par, *str; Remob *remob; RemChannel *rc; - - rc = &remserver->rc[0]; /* drivstat messages appear only on the spy channel */ - + + rc = &remserver->rc[0]; /* drivstat messages appear only on the spy channel */ + /* skip whitespace at the beginning */ - line=rc->line; - if (line[0] == '\0') return 0; /* return when line is empty */ + line = rc->line; + if (line[0] == '\0') + return 0; /* return when line is empty */ while (*line < ' ' && *line != '\0') { line++; } memmove(rc->line, line, strlen(line)); - + /* handle drivstat messages */ line = rc->line; - + for (remob = remserver->objList; remob != NULL; remob = remob->next) { - par=StartsWith(line, remob->name); + par = StartsWith(line, remob->name); if (par != NULL) { if ((str = StartsWith(par, "finished"))) { if (*str == '\0') { @@ -141,30 +152,34 @@ static int RemHandle(RemServer *remserver) { } else { remob->status = HWFault; } - line[0]='\0'; + line[0] = '\0'; return 1; } if ((str = StartsWith(par, "started"))) { remob->status = HWBusy; - line[0]='\0'; + line[0] = '\0'; return 1; } } } return 0; } + /*-------------------------------------------------------------------------*/ -static void RemCopy(RemChannel *rc, SConnection *pCon) { +static void RemCopy(RemChannel * rc, SConnection * pCon) +{ if (pCon != NULL && rc->line[0] != '\0') { - SCPrintf(pCon, eStatus, " %s", rc->line); + SCPrintf(pCon, eValue, " %s", rc->line); } } + /*-------------------------------------------------------------------------*/ -static void RemDisconnect(RemServer *remserver) { +static void RemDisconnect(RemServer * remserver) +{ int isUser; RemChannel *rc; - - for (isUser=0; isUser<=1; isUser++) { + + for (isUser = 0; isUser <= 1; isUser++) { rc = &remserver->rc[isUser]; if (rc->chan != NULL) { NETClosePort(rc->chan); @@ -174,15 +189,17 @@ static void RemDisconnect(RemServer *remserver) { } } } + /*-------------------------------------------------------------------------*/ -static int RemSetInterest(RemChannel *rc) { +static int RemSetInterest(RemChannel * rc) +{ int iRet; - - if (rc->chan != NULL) { /* already connected */ + + if (rc->chan != NULL) { /* already connected */ iRet = RemWrite(rc, "transact listexe interest\n"); if (iRet >= 0) { iRet = RemRead(rc, 1000); - while (iRet > 0) { /* eat response */ + while (iRet > 0) { /* eat response */ if (StartsWith(rc->line, "TRANSACTIONFINISHED")) { return 1; } @@ -192,15 +209,16 @@ static int RemSetInterest(RemChannel *rc) { } return 0; } + /*-------------------------------------------------------------------------*/ -static void RemConnect(RemServer *remserver, int both) { +static void RemConnect(RemServer * remserver, int both) +{ /* open channel 0 or both channels, if not yet opened */ int iRet; - char buf[256]; mkChannel *chan; int i; RemChannel *rc; - + for (i = 0; i <= both; i++) { rc = &remserver->rc[i]; if (!rc->chan) { @@ -210,24 +228,27 @@ static void RemConnect(RemServer *remserver, int both) { return; } rc->chan = chan; - if (i != 0) { /* open the user channel */ + if (i != 0) { /* open the user channel */ iRet = RemWrite(rc, "remuser sesam\n"); - } else { /* open spy channel */ + } else { /* open spy channel */ iRet = RemWrite(rc, "Spy 007\n"); } - if (iRet < 0) goto close; + if (iRet < 0) + goto close; iRet = RemRead(rc, 1000); - while (iRet > 0) { /* eat login response */ + while (iRet > 0) { /* eat login response */ if (StartsWith(rc->line, "Login OK")) { /* printf("connected\n"); */ - if (remserver->interestActive && rc == &remserver->rc[0]) { /* open the user channel */ - if (!RemSetInterest(rc)) goto close; + if (remserver->interestActive && rc == &remserver->rc[0]) { /* open the user channel */ + if (!RemSetInterest(rc)) + goto close; } break; } iRet = RemRead(rc, 1000); } - if (iRet <= 0) goto close; + if (iRet <= 0) + goto close; } } return; @@ -235,53 +256,57 @@ close: RemDisconnect(remserver); return; } + /*-------------------------------------------------------------------------*/ -static int RemServerTask(void *data) { - RemServer *remserver=data; +static int RemServerTask(void *data) +{ + RemServer *remserver = data; int iRet; SConnection *pCon; int isUser; RemChannel *rc; - - if (!remserver->taskActive) return 0; /* remove task */ - + + if (!remserver->taskActive) + return 0; /* remove task */ + for (isUser = 0; isUser <= 1; isUser++) { rc = &remserver->rc[isUser]; - if (RemRead(rc, 0) <= 0) continue; + if (RemRead(rc, 0) <= 0) + continue; if (strstr(rc->line, " ") == rc->line) { WriteToCommandLog("REMOB>", "infinite echo loop detected"); continue; } if (isUser == 0) { - if (RemHandle(remserver)) { /* handle drivstat messages */ + if (RemHandle(remserver)) { /* handle drivstat messages */ continue; } } if (remserver->forwardMessages) { /* forward all other messages */ - if (SCStoreConnected(remserver->conn)) { - pCon = SCStorePush(remserver->conn); - RemCopy(rc, pCon); - SCStorePop(remserver->conn); + if (SCisConnected(remserver->conn)) { + RemCopy(rc, remserver->conn); } } } return 1; } + /*-------------------------------------------------------------------------*/ -static int RemTransact(RemServer *remserver, int nChan, SConnection *pCon, - char *cmd, ...) { +static int RemTransact(RemServer * remserver, int nChan, + SConnection * pCon, char *cmd, ...) +{ /* the variable arguments are for filtering: - + "" write untreated lines to pCon - */ - char buf[256]; + */ + char *buffer; + int bufferLen; int iRet; - int i, typ; char *arg, *val, *endp; float *f; va_list ap; @@ -289,43 +314,53 @@ static int RemTransact(RemServer *remserver, int nChan, SConnection *pCon, int argMask; RemChannel *rc = &remserver->rc[nChan]; - try=2; - if (rc->timeout) { /* eat old responses */ + try = 3; + if (rc->timeout) { /* eat old responses */ while (RemRead(rc, 0) > 0) { RemHandle(remserver); } } tryagain: - snprintf(buf, sizeof buf, "transact %s\n", cmd); + bufferLen = strlen(cmd) + 16; + buffer = malloc(bufferLen); + if (buffer == NULL) { + SCPrintf(pCon, eError, "ERROR: can not get another %d bytes", + bufferLen); + return 0; + } + snprintf(buffer, bufferLen, "transact %s\n", cmd); RemConnect(remserver, nChan); - iRet = RemWrite(rc, buf); - if (iRet < 0) goto close; - + iRet = RemWrite(rc, buffer); + free(buffer); + if (iRet < 0) + goto close; + iRet = RemRead(rc, 2000); - if (iRet <= 0) goto close; + if (iRet <= 0) + goto close; while (!StartsWith(rc->line, "TRANSACTIONFINISHED")) { RemHandle(remserver); va_start(ap, cmd); arg = va_arg(ap, char *); - argMask=1; + argMask = 1; remserver->matchMap = 0; while (arg != NULL) { if (*arg == '>') { RemCopy(rc, pCon); } else if (*arg == '<') { f = va_arg(ap, float *); - val = StartsWith(rc->line, arg+1); + val = StartsWith(rc->line, arg + 1); if (val != NULL) { val = StartsWith(val, "="); if (val != NULL) { *f = strtod(val, &endp); break; - } + } } } else if (*arg == '!') { - if (StartsWith(rc->line, arg+1)) { + if (StartsWith(rc->line, arg + 1)) { remserver->matchMap |= argMask; - argMask = argMask*2; + argMask = argMask * 2; break; } } else { @@ -336,42 +371,50 @@ tryagain: } va_end(ap); iRet = RemRead(rc, 2000); - if (iRet <= 0) goto close; + if (iRet <= 0) + goto close; } return 1; close: if (iRet == 0) { - snprintf(buf, sizeof(buf), "ERROR: timeout on %s", remserver->name); - SCWrite(pCon,buf,eError); - rc->timeout = 1; - return iRet; + if (try == 1) { + SCPrintf(pCon, eError, "ERROR: timeout on %s", remserver->name); + rc->timeout = 1; + return iRet; + } else { + SCPrintf(pCon, eError, "WARNING: timeout on %s", remserver->name); + } } RemDisconnect(remserver); try--; - if (try>0) goto tryagain; - snprintf(buf, sizeof(buf), "ERROR: no connection to %s", remserver->name); - SCWrite(pCon,buf,eError); + if (try > 0) + goto tryagain; + SCPrintf(pCon, eError, "ERROR: no connection to %s", remserver->name); return iRet; } + /*-------------------------------------------------------------------------*/ -static void *RemobGetInterface(void *pData, int iID) { +static void *RemobGetInterface(void *pData, int iID) +{ Remob *self = pData; - + assert(self); - if(iID == DRIVEID) { + if (iID == DRIVEID) { return self->pDrivInt; - } else if(iID == CALLBACKINTERFACE) { + } else if (iID == CALLBACKINTERFACE) { return self->pCall; } return NULL; } + /*------------------------------------------------------------------------*/ -static int RemobHalt(void *self) { - Remob *remob=self; +static int RemobHalt(void *self) +{ + Remob *remob = self; RemServer *remserver = remob->server; - RemChannel *rc = &remserver->rc[1]; /* Halt is only called with at least user priv. */ + RemChannel *rc = &remserver->rc[1]; /* Halt is only called with at least user priv. */ char buf[64]; - + assert(remob); RemConnect(remserver, 1); snprintf(buf, sizeof(buf), "stopexe %s\n", remob->name); @@ -380,30 +423,37 @@ static int RemobHalt(void *self) { } /*--------------------------------------------------------------------------*/ -static int RemobLimits(void *self, float fVal, char *error, int iErrLen) { +static int RemobLimits(void *self, float fVal, char *error, int iErrLen) +{ float fHard; - Remob *remob=self; - + Remob *remob = self; + assert(remob); /* check is done on remote server */ return 1; } + /*---------------------------------------------------------------------------*/ -static float RemobGetValue(void *pData, SConnection *pCon) { - Remob *remob=pData; +static float RemobGetValue(void *pData, SConnection * pCon) +{ + Remob *remob = pData; RemServer *remserver = remob->server; char buf[80]; float none, value; int iRet; - + assert(remob); - - remserver->conn = SCSave(pCon, remserver->conn); + + if (remserver->conn != NULL) { + SCDeleteConnection(remserver->conn); + } + remserver->conn = SCCopyConnection(pCon); none = -1.25e6; - value= none; + value = none; snprintf(buf, sizeof(buf), "<%s", remob->name); /* get value needs only spy priviledge */ - iRet = RemTransact(remserver, 0, pCon, remob->name, buf, &value, ">", NULL); + iRet = + RemTransact(remserver, 0, pCon, remob->name, buf, &value, ">", NULL); if (iRet <= 0) { return 0.0; } @@ -413,48 +463,61 @@ static float RemobGetValue(void *pData, SConnection *pCon) { snprintf(buf, sizeof(buf), "can not get %s", remob->name); SCWrite(pCon, buf, eWarning); return 0.0; -} +} + /*------------------------------------------------------------------------*/ -static int RemobSaveStatus(void *pData, char *name, FILE *fil) { +static int RemobSaveStatus(void *pData, char *name, FILE * fil) +{ Remob *self = pData; - + assert(self); assert(fil); - + /* - data is stored on remote server - */ + data is stored on remote server + */ return 1; } + /*------------------------------------------------------------------------*/ -static int RemServerSaveStatus(void *pData, char *name, FILE *fil) { +static int RemServerSaveStatus(void *pData, char *name, FILE * fil) +{ RemServer *remserver = pData; Remob *remob; - + assert(remserver); assert(fil); for (remob = remserver->objList; remob != NULL; remob = remob->next) { if (remob->pDrivInt) { - fprintf(fil, "catch { remob drv %s %s }\n", remob->name, remserver->name); + fprintf(fil, "catch { remob drv %s %s }\n", remob->name, + remserver->name); } else { - fprintf(fil, "catch { remob obj %s %s }\n", remob->name, remserver->name); + fprintf(fil, "catch { remob obj %s %s }\n", remob->name, + remserver->name); } } return 1; } + /*------------------------------------------------------------------------*/ -static int RemobStatus(void *pData, SConnection *pCon) { - Remob *remob=pData; - +static int RemobStatus(void *pData, SConnection * pCon) +{ + Remob *remob = pData; + assert(remob); - - remob->server->conn = SCSave(pCon, remob->server->conn); + + if (remob->server->conn != NULL) { + SCDeleteConnection(remob->server->conn); + } + remob->server->conn = SCCopyConnection(pCon); return remob->status; } + /*---------------------------------------------------------------------------*/ -static long RemobRun(void *self, SConnection *pCon, float fNew) { - Remob *remob=self; +static long RemobRun(void *self, SConnection * pCon, float fNew) +{ + Remob *remob = self; float fHard; int i, iRet, iCode; char buf[512], sBuf[64]; @@ -467,41 +530,52 @@ static long RemobRun(void *self, SConnection *pCon, float fNew) { RemChannel *rc; int nChan; - remserver = remob->server; - remserver->conn = SCSave(pCon, remserver->conn); assert(remob); assert(pCon); - + + remserver = remob->server; + if (remserver->conn != NULL) { + SCDeleteConnection(remserver->conn); + } + remserver->conn = SCCopyConnection(pCon); + rights = SCGetRights(pCon); nChan = rights <= usUser; rc = &remserver->rc[nChan]; - RemConnect(remserver, 0); /* connect spy for listexe interest */ + RemConnect(remserver, 0); /* connect spy for listexe interest */ remob->status = HWIdle; - snprintf(buf, sizeof(buf), "run %s %f", remob->name, fNew); - iRet = RemTransact(remserver, nChan, pCon, buf, "!ERROR: somebody else", "!ERROR: cannot", ">", NULL); - if (iRet <= 0) return 0; + snprintf(buf, sizeof(buf), "run %s %g", remob->name, fNew); + iRet = + RemTransact(remserver, nChan, pCon, buf, "!ERROR: somebody else", + "!ERROR: cannot", ">", NULL); + if (iRet <= 0) + return 0; - if (remserver->matchMap & 1) { /* already running, stop first */ + if (remserver->matchMap & 1) { /* already running, stop first */ remob->status = HWBusy; snprintf(sBuf, sizeof(sBuf), "stopexe %s", remob->name); iRet = RemTransact(remserver, nChan, pCon, sBuf, ">", NULL); - if (iRet <= 0) return 0; + if (iRet <= 0) + return 0; while (remob->status == HWBusy) { iRet = RemRead(rc, 1000); - if (iRet <= 0) break; - if (! RemHandle(remserver)) { + if (iRet <= 0) + break; + if (!RemHandle(remserver)) { RemCopy(rc, pCon); } } iRet = RemTransact(remserver, nChan, pCon, buf, ">", NULL); - if (iRet <= 0) return 0; + if (iRet <= 0) + return 0; } /* wait for "started" message */ while (remob->status != HWBusy) { iRet = RemRead(&remserver->rc[0], 1000); - if (iRet <= 0) break; - if (! RemHandle(remserver)) { + if (iRet <= 0) + break; + if (!RemHandle(remserver)) { RemCopy(&remserver->rc[0], pCon); } } @@ -510,38 +584,48 @@ static long RemobRun(void *self, SConnection *pCon, float fNew) { } return OKOK; } + /*-----------------------------------------------------------------------*/ -static void KillInfo(void *pData) { +static void KillInfo(void *pData) +{ RemobInfo *self = pData; - + assert(self); if (self->pName) { free(self->pName); } + if (self->pCon) { + SCDeleteConnection(self->pCon); + } free(self); } + /*------------------- The CallBack function for interest ------------------*/ -static int InterestCallback(int iEvent, void *pEvent, void *pUser) { +static int InterestCallback(int iEvent, void *pEvent, void *pUser) +{ RemobCallback *psCall = pEvent; RemobInfo *pInfo = pUser; char buf[80]; - + assert(psCall); assert(pInfo); - - snprintf(buf, sizeof(buf),"%s.position = %f ", pInfo->pName, psCall->fVal); - SCWrite(pInfo->pCon,buf,eValue); + + snprintf(buf, sizeof(buf), "%s.position = %g ", pInfo->pName, + psCall->fVal); + SCWrite(pInfo->pCon, buf, eValue); return 1; -} +} + /*---------------------------------------------------------------------------*/ -int RemobAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) { +int RemobAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ Remob *remob = pData; RemServer *remserver = remob->server; char buf[512]; TokenList *pList = NULL; TokenList *pCurrent; - TokenList *pName; + TokenList *pName; int iRet; int i; int pos; @@ -550,60 +634,66 @@ int RemobAction(SConnection *pCon, SicsInterp *pSics, void *pData, char *endp; char *cmd; /* - char acce[128], inte[128]; - */ + char acce[128], inte[128]; + */ int rights; int nChan; RemChannel *rc; - + assert(pCon); assert(pSics); assert(remob); - + rights = SCGetRights(pCon); nChan = (rights <= usUser); rc = &remserver->rc[nChan]; if (rights >= usUser) { - remserver->conn = SCSave(pCon, remserver->conn); + if (remserver->conn != NULL) { + SCDeleteConnection(remserver->conn); + } + remserver->conn = SCCopyConnection(pCon); } if (argc == 1) { iRet = RemTransact(remserver, nChan, pCon, remob->name, ">", NULL); - } else if (strcasecmp(argv[1],"interest") == 0) { + } else if (strcasecmp(argv[1], "interest") == 0) { /* ignore interest commands, as they would not work properly */ - iRet=1; - } else if (strcasecmp(argv[1],"list") == 0) { + iRet = 1; + } else if (strcasecmp(argv[1], "list") == 0) { /* - snprintf(acce, sizeof(acce), "!%s.accesscode", remob->name); - snprintf(inte, sizeof(inte), "!%s.interruptmode", remob->name); - */ - - cmd = Arg2Tcl0(argc-1, argv+1, buf, sizeof buf, remob->name); + snprintf(acce, sizeof(acce), "!%s.accesscode", remob->name); + snprintf(inte, sizeof(inte), "!%s.interruptmode", remob->name); + */ + + cmd = Arg2Tcl0(argc - 1, argv + 1, buf, sizeof buf, remob->name); if (cmd) { RemTransact(remserver, nChan, pCon, cmd, ">", NULL); - if (cmd != buf) free(cmd); + if (cmd != buf) + free(cmd); } - iRet=1; + iRet = 1; } else { - pos=snprintf(buf, sizeof(buf), "%s ", remob->name); - for (i=1; iname); + for (i = 1; i < argc; i++) { + pos += snprintf(buf + pos, sizeof(buf) - pos, "%s ", argv[i]); } iRet = RemTransact(remserver, nChan, pCon, buf, ">", NULL); } return iRet; } + /*--------------------------------------------------------------------------*/ -static void RemobKill(void *self) { +static void RemobKill(void *self) +{ Remob *remob = self; Remob *p, **last; - + assert(remob); - + /* remove from object list */ if (remob->server) { last = &remob->server->objList; p = *last; - while (p != remob && p !=NULL) { + while (p != remob && p != NULL) { last = &p->next; p = p->next; } @@ -614,28 +704,29 @@ static void RemobKill(void *self) { } if (remob->name) { free(remob->name); - } + } if (remob->pDrivInt) { free(remob->pDrivInt); - } + } if (remob->pCall) { DeleteCallBackInterface(remob->pCall); } - + /* kill Descriptor */ if (remob->desc) { DeleteDescriptor(remob->desc); } free(remob); -} +} + /*---------------------------------------------------------------------------*/ -int RemServerAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) { +int RemServerAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ RemServer *remserver = pData; - char buf[512]; TokenList *pList = NULL; TokenList *pCurrent; - TokenList *pName; + TokenList *pName; int iRet; socklen_t i; int pos; @@ -647,55 +738,59 @@ int RemServerAction(SConnection *pCon, SicsInterp *pSics, void *pData, Remob *p, *next; int rights, nChan; RemChannel *rc; - + char *args; + assert(pCon); assert(pSics); assert(remserver); - + rights = SCGetRights(pCon); nChan = (rights <= usUser); rc = &remserver->rc[nChan]; if (nChan) { - remserver->conn = SCSave(pCon, remserver->conn); + if (remserver->conn != NULL) { + SCDeleteConnection(remserver->conn); + } + remserver->conn = SCCopyConnection(pCon); } if (argc == 1) { - serverport = IFindOption(pSICSOptions,"ServerPort"); + serverport = IFindOption(pSICSOptions, "ServerPort"); i = sizeof adr; thishostname = NULL; if (rc->chan) { - if (getsockname(rc->chan->sockid, (void *)&adr, &i) >= 0) { - thishost = gethostbyaddr((char *)&adr.sin_addr, - sizeof adr.sin_addr, AF_INET); + if (getsockname(rc->chan->sockid, (void *) &adr, &i) >= 0) { + thishost = gethostbyaddr((char *) &adr.sin_addr, + sizeof adr.sin_addr, AF_INET); if (thishost) { thishostname = thishost->h_name; } } } - if (thishostname == NULL) thishostname = "undef"; - SCPrintf(pCon, eStatus, "%s = %s:%d %s:%s", - argv[0], remserver->host, remserver->port, thishostname, serverport); - } else if (argc>2 && strcasecmp(argv[1],"nowait") == 0) { + if (thishostname == NULL) + thishostname = "undef"; + SCPrintf(pCon, eValue, "%s = %s:%d %s:%s", + argv[0], remserver->host, remserver->port, thishostname, + serverport); + } else if (argc > 2 && strcasecmp(argv[1], "nowait") == 0) { RemConnect(remserver, nChan); - for (i=2; i2) { - RemWrite(rc, " "); - } - RemWrite(rc, argv[i]); - } + args = Arg2Tcl(argc - 2, argv + 2, NULL, 0); + RemWrite(rc, args); RemWrite(rc, "\n"); - } else if (argc==2 && strcasecmp(argv[1],"markForDel") == 0) { + free(args); + } else if (argc == 2 && strcasecmp(argv[1], "markForDel") == 0) { p = remserver->objList; while (p) { p->markForDel = 1; p = p->next; } - } else if (argc==2 && strcasecmp(argv[1],"delMarked") == 0) { + } else if (argc == 2 && strcasecmp(argv[1], "delMarked") == 0) { p = remserver->objList; while (p) { next = p->next; if (p->markForDel) { - if (p->pDrivInt && pServ->pExecutor && isInRunMode(pServ->pExecutor)) { - SCWrite(pCon,"ERROR: cannot delete while running",eError); + if (p->pDrivInt && pServ->pExecutor + && isInRunMode(pServ->pExecutor)) { + SCWrite(pCon, "ERROR: cannot delete while running", eError); return 0; } RemoveCommand(pSics, p->name); @@ -703,24 +798,24 @@ int RemServerAction(SConnection *pCon, SicsInterp *pSics, void *pData, p = next; } } else { - pos=0; - for (i=1; i", NULL); + args = Arg2Tcl(argc - 1, argv + 1, NULL, 0); + iRet = RemTransact(remserver, nChan, pCon, args, ">", NULL); + free(args); return iRet; } return 1; } + /*--------------------------------------------------------------------------*/ -static void RemServerKill(void *self) { +static void RemServerKill(void *self) +{ RemServer *remserver = self; Remob *remob, *next; - + assert(remserver); - + if (remserver->taskActive) { - remserver->taskActive=0; + remserver->taskActive = 0; /* let the tasker kill me */ return; } @@ -732,19 +827,26 @@ static void RemServerKill(void *self) { } RemDisconnect(remserver); DeleteDescriptor(remserver->desc); - if (remserver->name) free(remserver->name); - if (remserver->host) free(remserver->host); - SCStoreFree(remserver->conn); + if (remserver->name) + free(remserver->name); + if (remserver->host) + free(remserver->host); + if (remserver->conn != NULL) { + SCDeleteConnection(remserver->conn); + } free(remserver); } + /*-----------------------------------------------------------------------*/ -static int RemobSetDriveable(Remob *remob, int driveable) { +static int RemobSetDriveable(Remob * remob, int driveable) +{ RemChannel *rc; - + if (driveable) { /* initialise Drivable interface */ remob->pDrivInt = CreateDrivableInterface(); - if (!remob->pDrivInt) return 0; + if (!remob->pDrivInt) + return 0; remob->pDrivInt->SetValue = RemobRun; remob->pDrivInt->CheckLimits = RemobLimits; remob->pDrivInt->CheckStatus = RemobStatus; @@ -753,8 +855,8 @@ static int RemobSetDriveable(Remob *remob, int driveable) { if (remob->server->interestActive == 0) { rc = &remob->server->rc[0]; remob->server->interestActive = 1; - if (! RemSetInterest(rc)) { - RemDisconnect(remob->server); /* disconnect on error, RemSetInterest will be called again on connect */ + if (!RemSetInterest(rc)) { + RemDisconnect(remob->server); /* disconnect on error, RemSetInterest will be called again on connect */ } } } else if (remob->pDrivInt) { @@ -763,35 +865,40 @@ static int RemobSetDriveable(Remob *remob, int driveable) { } return 1; } + /*-----------------------------------------------------------------------*/ -static Remob *RemobInit(char *name, RemServer *remserver) { +static Remob *RemobInit(char *name, RemServer * remserver) +{ Remob *remob, *p; assert(name); - + /* get memory */ - remob = (Remob *)calloc(1,sizeof(Remob)); - if(!remob) { + remob = (Remob *) calloc(1, sizeof(Remob)); + if (!remob) { return NULL; } - + /* copy arguments */ remob->server = remserver; remob->name = strdup(name); - - /* initialise object descriptor */ + + /* initialise object descriptor */ remob->desc = CreateDescriptor("RemObject"); - if (!remob->desc) goto killit; + if (!remob->desc) + goto killit; remob->desc->GetInterface = RemobGetInterface; remob->desc->SaveStatus = RemobSaveStatus; - + /* initialise callback interface */ remob->pCall = CreateCallBackInterface(); - if(!remob->pCall) goto killit; - + if (!remob->pCall) + goto killit; + /* check if not yet in object list */ - for (p = remserver->objList; p != NULL; p=p->next) { - if (p == remob) break; + for (p = remserver->objList; p != NULL; p = p->next) { + if (p == remob) + break; } if (p == NULL) { remob->next = remserver->objList; @@ -805,20 +912,22 @@ killit: RemobKill(remob); return NULL; } + /*-----------------------------------------------------------------------*/ -static RemServer *RemServerInit(char *name, char *host, int port) { +static RemServer *RemServerInit(char *name, char *host, int port) +{ RemServer *remserver = NULL; RemChannel *rc; int isUser; - + assert(name); - + remserver = calloc(1, sizeof(RemServer)); if (!remserver) { return 0; } - - /* initialise object descriptor */ + + /* initialise object descriptor */ remserver->desc = CreateDescriptor("RemServer"); if (!remserver->desc) { free(remserver); @@ -828,7 +937,7 @@ static RemServer *RemServerInit(char *name, char *host, int port) { remserver->name = strdup(name); remserver->host = strdup(host); remserver->port = port; - for (isUser=0; isUser <= 1; isUser++) { + for (isUser = 0; isUser <= 1; isUser++) { rc = &remserver->rc[isUser]; rc->incomplete = 0; rc->chan = NULL; @@ -836,9 +945,7 @@ static RemServer *RemServerInit(char *name, char *host, int port) { } remserver->objList = NULL; remserver->conn = NULL; - if (!remserver->name || - !remserver->host || - !remserver->port) { + if (!remserver->name || !remserver->host || !remserver->port) { /* no success, clean up */ RemServerKill(remserver); return NULL; @@ -846,9 +953,11 @@ static RemServer *RemServerInit(char *name, char *host, int port) { remserver->taskActive = 1; remserver->interestActive = 0; remserver->forwardMessages = 1; - TaskRegister(pServ->pTasker, RemServerTask, NULL, RemServerKill, remserver, 1); + TaskRegister(pServ->pTasker, RemServerTask, NULL, RemServerKill, + remserver, 1); return remserver; } + /*-------------------------------------------------------------------------- The Factory function for creating a remote driveable object. @@ -860,19 +969,20 @@ static RemServer *RemServerInit(char *name, char *host, int port) { Remob del serverName */ -int RemobCreate(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) { +int RemobCreate(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ RemServer *remserver = NULL; Remob *remob = NULL; char host[128]; char *p; int iD, iRet; char *obj; - + assert(pCon); assert(pSics); - - argtolower(argc,argv); + + argtolower(argc, argv); if (argc >= 4 && strcmp(argv[1], "server") == 0) { if (argc >= 5) { remserver = RemServerInit(argv[2], argv[3], atoi(argv[4])); @@ -885,23 +995,30 @@ int RemobCreate(SConnection *pCon, SicsInterp *pSics, void *pData, SCPrintf(pCon, eError, "ERROR: illegal host:port"); return 0; } - snprintf(host, sizeof host, "%.*s", p-argv[3], argv[3]); - remserver = RemServerInit(argv[2], host, atoi(p+1)); + snprintf(host, sizeof host, "%.*s", p - argv[3], argv[3]); + remserver = RemServerInit(argv[2], host, atoi(p + 1)); } if (!remserver) { - SCPrintf(pCon, eError, "ERROR: Failure to create remote server connection %s", argv[2]); + SCPrintf(pCon, eError, + "ERROR: Failure to create remote server connection %s", + argv[2]); return 0; } /* create the interpreter command */ - iRet = AddCommand(pSics,argv[2],RemServerAction,RemServerKill,remserver); + iRet = + AddCommand(pSics, argv[2], RemServerAction, RemServerKill, + remserver); if (!iRet) { - SCPrintf(pCon, eError, "ERROR: duplicate command %s not created",argv[2]); + SCPrintf(pCon, eError, "ERROR: duplicate command %s not created", + argv[2]); RemServerKill(remserver); return 0; } - + return 1; - } else if (argc == 4 && (strcmp(argv[1], "obj") == 0 || strcmp(argv[1], "drv") == 0)) { + } else if (argc == 4 + && (strcmp(argv[1], "obj") == 0 + || strcmp(argv[1], "drv") == 0)) { remserver = FindCommandData(pServ->pSics, argv[3], "RemServer"); if (!remserver) { SCPrintf(pCon, eError, "ERROR: remote server %s not found", argv[3]); @@ -912,47 +1029,49 @@ int RemobCreate(SConnection *pCon, SicsInterp *pSics, void *pData, if (remob->server == remserver) { RemobSetDriveable(remob, strcmp(argv[1], "drv") == 0); remob->markForDel = 0; - return 1; /* object exists already, silent return */ + return 1; /* object exists already, silent return */ } } remob = RemobInit(argv[2], remserver); if (!remob) { - SCPrintf(pCon, eError, "ERROR: Failure to create remote object %s", argv[1]); + SCPrintf(pCon, eError, "ERROR: Failure to create remote object %s", + argv[1]); return 0; } RemobSetDriveable(remob, strcmp(argv[1], "drv") == 0); /* create the interpreter command */ - iRet = AddCommand(pSics,argv[2],RemobAction,RemobKill,remob); + iRet = AddCommand(pSics, argv[2], RemobAction, RemobKill, remob); SCparChange(pCon); if (!iRet) { - SCPrintf(pCon, eError, "ERROR: duplicate command %s not created",argv[2]); + SCPrintf(pCon, eError, "ERROR: duplicate command %s not created", + argv[2]); RemobKill(remob); return 0; } return 1; } else if (argc == 3 && strcmp(argv[1], "del") == 0) { remob = FindCommandData(pSics, argv[2], "RemObject"); - if (remob) { /* its a remob */ - if (remob->pDrivInt && pServ->pExecutor && isInRunMode(pServ->pExecutor)) { - SCPrintf(pCon,eError,"ERROR: cannot delete %s while running", argv[2]); + if (remob) { /* its a remob */ + if (remob->pDrivInt && pServ->pExecutor + && isInRunMode(pServ->pExecutor)) { + SCPrintf(pCon, eError, "ERROR: cannot delete %s while running", + argv[2]); return 0; } return RemoveCommand(pSics, argv[2]); } if (pServ->pExecutor && isInRunMode(pServ->pExecutor)) { - SCPrintf(pCon,eError,"ERROR: cannot delete %s while running", argv[2]); + SCPrintf(pCon, eError, "ERROR: cannot delete %s while running", + argv[2]); return 0; } remserver = FindCommandData(pSics, argv[2], "RemServer"); - if (remserver) { /* its a remserver */ + if (remserver) { /* its a remserver */ return RemoveCommand(pSics, argv[2]); } - SCWrite(pCon,"ERROR: remob object not found",eError); + SCWrite(pCon, "ERROR: remob object not found", eError); return 0; } SCPrintf(pCon, eError, "ERROR: illegal arguments for command remob"); return 0; } - - - diff --git a/remob.h b/remob.h index fed42c5f..4e6087f0 100644 --- a/remob.h +++ b/remob.h @@ -10,10 +10,9 @@ copyright: see implementation file #define SICSREM #include "Scommon.h" -/*-------------------------------------------------------------------------*/ +/*-------------------------------------------------------------------------*/ -int RemobCreate(SConnection *pCon, SicsInterp *pSics, void *pData, +int RemobCreate(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]); - -#endif +#endif diff --git a/rmlead.c b/rmlead.c index e3e3c18a..75bceb11 100644 --- a/rmlead.c +++ b/rmlead.c @@ -7,20 +7,20 @@ ** Subset version released to the public domain, 1991 ** ** remove leading whitespace from a string -*/ - +*/ + #include #include - + #define NUL '\0' + char *rmlead(char *str) +{ + char *obuf; + for (obuf = str; obuf && *obuf && isspace(*obuf); ++obuf) + ; + if (str != obuf) + strcpy(str, obuf); + return str; + } + -char *rmlead(char *str) -{ - char *obuf; - - for (obuf = str; obuf && *obuf && isspace(*obuf); ++obuf) - ; - if (str != obuf) - strcpy(str, obuf); - return str; -} diff --git a/rmtrail.c b/rmtrail.c index 154168c3..e16b9898 100644 --- a/rmtrail.c +++ b/rmtrail.c @@ -16,16 +16,14 @@ char *rmtrail(char *str) { - int i; + int i; - if (0 != (i = strlen(str))) - { - while (--i >= 0) - { - if (!isspace(str[i])) - break; - } - str[++i] = NUL; - } - return str; + if (0 != (i = strlen(str))) { + while (--i >= 0) { + if (!isspace(str[i])) + break; + } + str[++i] = NUL; + } + return str; } diff --git a/rs232controller.c b/rs232controller.c index 544a54f9..eaa3b098 100644 --- a/rs232controller.c +++ b/rs232controller.c @@ -20,57 +20,58 @@ #include "nread.h" #include "rs232controller.h" - +/*--------------------------------------------------------------------*/ +static char *MakeID(prs232 self){ + static char id[132]; + snprintf(id,sizeof(id),"%s:%d",self->pHost, self->iPort); + return id; +} /*--------------------------------------------------------------------*/ void setRS232SendTerminator(prs232 self, char *term) { assert(self); - - if(self->sendTerminator != NULL) - { + + if (self->sendTerminator != NULL) { free(self->sendTerminator); } - if(term != NULL) - { + if (term != NULL) { self->sendTerminator = strdup(term); - } - else - { + } else { self->sendTerminator = NULL; } } + /*--------------------------------------------------------------------*/ void setRS232ReplyTerminator(prs232 self, char *term) { assert(self); - if(self->replyTerminator != NULL) - { + if (self->replyTerminator != NULL) { free(self->replyTerminator); } - if(term != NULL) - { + if (term != NULL) { self->replyTerminator = strdup(term); - } - else - { + } else { self->replyTerminator = NULL; } - + } + /*---------------------------------------------------------------------*/ void setRS232Timeout(prs232 self, int timeout) { assert(self); self->timeout = timeout; } + /*---------------------------------------------------------------------*/ void setRS232Debug(prs232 self, int deb) { assert(self); self->debug = deb; } + /*--------------------------------------------------------------------*/ int writeRS232(prs232 self, void *data, int dataLen) { @@ -81,217 +82,208 @@ int writeRS232(prs232 self, void *data, int dataLen) assert(self); /* - catch an unconnected socket - */ - if(!self->pSock) - { + catch an unconnected socket + */ + if (!self->pSock) { return NOTCONNECTED; } - + /* do the terminator processing, if required. If new data had to be allocated in order to add the terminator, pPtr is not NULL. I any other case it is. - */ - if(self->sendTerminator != NULL) - { - pPtr = (char *)data; - if(strstr(pPtr,self->sendTerminator) == NULL) - { + */ + if (self->sendTerminator != NULL) { + pPtr = (char *) data; + if (strstr(pPtr, self->sendTerminator) == NULL) { /* - the terminator is missing. add it. - */ - pPtr = (char *)malloc((dataLen + strlen(self->sendTerminator) +2) - *sizeof(char)); - if(!pPtr) - { - return BADMEMORY; + the terminator is missing. add it. + */ + pPtr = (char *) malloc((dataLen + strlen(self->sendTerminator) + 2) + * sizeof(char)); + if (!pPtr) { + return BADMEMORY; } - strcpy(pPtr,(char *) data); - strcat(pPtr,self->sendTerminator); + strcpy(pPtr, (char *) data); + strcat(pPtr, self->sendTerminator); dataLen += strlen(self->sendTerminator); data = pPtr; - } - else - { + } else { pPtr = NULL; } } /* - send - */ - iRet = NETWrite(self->pSock,data,dataLen); - if(self->debug > 0) - { - printf("RS232 OUT : %s",(char *)data); - if(strchr((char *)data,'\n') == NULL) - { + send + */ + iRet = NETWrite(self->pSock, data, dataLen); + if (self->debug > 0) { + printf("RS232 OUT : %s", (char *) data); + if (strchr((char *) data, '\n') == NULL) { puts(""); } fflush(stdout); } + if(strlen((char *)data) <= dataLen){ + traceIO(MakeID(self),"out:%s",(char *)data); + } else { + traceIO(MakeID(self),"out:%s","Binary output"); + } - if(pPtr != NULL) + if (pPtr != NULL) free(pPtr); - if(iRet != 1){ + if (iRet != 1) { return BADSEND; } return iRet; } + /*----------------------------------------------------------------------*/ int readRS232(prs232 self, void *data, int *dataLen) { long lRead; int iRet; size_t rLength; - + assert(self); /* - catch an unconnected socket - */ - if(!self->pSock) - { + catch an unconnected socket + */ + if (!self->pSock) { return NOTCONNECTED; } /* - clean our space in order to prevent corrupted stuff - */ - memset(data,0,*dataLen); + clean our space in order to prevent corrupted stuff + */ + memset(data, 0, *dataLen); - iRet = NETAvailable(self->pSock,self->timeout); - if(iRet < 0) - { + iRet = NETAvailable(self->pSock, self->timeout); + if (iRet < 0) { return iRet; - } - else if(iRet == 0) - { + } else if (iRet == 0) { *dataLen = 0; return TIMEOUT; - } - else - { - rLength = *dataLen; - lRead = recv(self->pSock->sockid, data,rLength,0); - if(lRead >= 0) - { - if(self->debug > 0) - { - printf("RS232 IN : %s",(char *)data); - if(strchr((char *)data,'\n') == NULL) - { - puts(""); - } - fflush(stdout); + } else { + rLength = *dataLen; + lRead = recv(self->pSock->sockid, data, rLength, 0); + if (lRead >= 0) { + if (self->debug > 0) { + printf("RS232 IN : %s", (char *) data); + if (strchr((char *) data, '\n') == NULL) { + puts(""); + } + fflush(stdout); + } + if(strlen((char *)data) <= *dataLen){ + traceIO(MakeID(self),"in:%s",(char *)data); + } else { + traceIO(MakeID(self),"in:%s","Binary Input"); } *dataLen = lRead; return 1; - } - else - { - return (int)lRead; + } else { + return (int) lRead; } } /* - not reached - */ + not reached + */ return 0; } + /*--------------------------------------------------------------------*/ -int readRS232TillTerm(prs232 self, void *data, int *datalen){ +int readRS232TillTerm(prs232 self, void *data, int *datalen) +{ int iRet, replylen; assert(self); /* - catch an unconnected socket - */ - if(!self->pSock) - { + catch an unconnected socket + */ + if (!self->pSock) { return NOTCONNECTED; } - memset(data,0,*datalen); + memset(data, 0, *datalen); replylen = *datalen; - iRet = NETReadTillTerm(self->pSock,self->timeout,self->replyTerminator, - (char *)data, replylen); - if(self->debug > 0 && iRet > 0) - { - printf("RS232 IN/TERM : %s",(char *)data); - if(strchr((char *)data,'\n') == NULL) - { - puts(""); + iRet = NETReadTillTerm(self->pSock, self->timeout, self->replyTerminator, + (char *) data, replylen); + if (self->debug > 0 && iRet > 0) { + printf("RS232 IN/TERM : %s", (char *) data); + if (strchr((char *) data, '\n') == NULL) { + puts(""); } fflush(stdout); } - if(iRet == 0) - { - if(self->debug > 0) - { - printf("RS232 IN/TERM : TIMEOUT:%s\n",(char *)data); + if (iRet == 0) { + if (self->debug > 0) { + printf("RS232 IN/TERM : TIMEOUT:%s\n", (char *) data); } + traceIO(MakeID(self),"in:%s","TIMEOUT"); return TIMEOUT; - } - else if(iRet == -1) - { - printf("Incomplete read: %s\n", (char *)data); + } else if (iRet == -1) { + traceIO(MakeID(self),"in:%s %s","Incomplete read", (char *)data); + printf("Incomplete read: %s, errno = %d\n", (char *) data, errno); return INCOMPLETE; - } - else if (iRet < 0) - { + } else if (iRet < 0) { + traceIO(MakeID(self),"in:Error %d",errno); return iRet; } if (*self->replyTerminator != 0) { - *datalen = strlen((char *)data); + *datalen = strlen((char *) data); } else { *datalen = iRet; } + traceIO(MakeID(self),"in:%s",(char *)data); return 1; } + /*----------------------------------------------------------------------*/ -int readRS232UntilWord(prs232 self, - char *buffer, int buflen, char *word){ - time_t endTime; - int status; - int bytesRead = 0; +int readRS232UntilWord(prs232 self, char *buffer, int buflen, char *word) +{ + time_t endTime; + int status; + int bytesRead = 0; - endTime = time(NULL) + self->timeout; - memset(buffer,0,buflen); - while(time(NULL) < endTime){ - if(availableRS232(self)){ - bytesRead = recv(self->pSock->sockid,buffer + bytesRead, - buflen - bytesRead - 1,0); - if(bytesRead < 0){ - return BADREAD; - } - if(strstr(buffer,word) != NULL) { - return 1; - } - } else { - SicsWait(1); - } + endTime = time(NULL) + self->timeout; + memset(buffer, 0, buflen); + while (time(NULL) < endTime) { + if (availableRS232(self)) { + bytesRead = recv(self->pSock->sockid, buffer + bytesRead, + buflen - bytesRead - 1, 0); + if (bytesRead < 0) { + return BADREAD; + } + if (strstr(buffer, word) != NULL) { + return 1; + } + } else { + SicsWait(1); } + } - return 0; + return 0; } + /*-----------------------------------------------------------------------*/ int availableRS232(prs232 self) { assert(self); /* - catch an unconnected socket - */ - if(!self->pSock) - { + catch an unconnected socket + */ + if (!self->pSock) { return NOTCONNECTED; } - return NETAvailable(self->pSock,0); + return NETAvailable(self->pSock, 0); } + /*-----------------------------------------------------------------------*/ int availableNetRS232(prs232 self) { @@ -299,180 +291,169 @@ int availableNetRS232(prs232 self) assert(self); /* - catch an unconnected socket - */ - if(!self->pSock) - { + catch an unconnected socket + */ + if (!self->pSock) { return NOTCONNECTED; } - if(!self->registered){ - if(pServ->pReader != NULL){ - NetReadRegisterUserSocket(pServ->pReader,self->pSock->sockid); + if (!self->registered) { + if (pServ->pReader != NULL) { + NetReadRegisterUserSocket(pServ->pReader, self->pSock->sockid); self->registered = 1; return 0; } } - status = NetReadReadable(pServ->pReader,self->pSock->sockid); + status = NetReadReadable(pServ->pReader, self->pSock->sockid); NetReadResetUser(pServ->pReader, self->pSock->sockid); return status; } + /*------------------------------------------------------------------------*/ int transactRS232(prs232 self, void *send, int sendLen, - void *reply, int replyLen) + void *reply, int replyLen) { int iRet, len; assert(self); /* - catch an unconnected socket - */ - if(!self->pSock) - { + catch an unconnected socket + */ + if (!self->pSock) { return NOTCONNECTED; } /* - if there is still data on the socket: clear it - while(availableRS232(self)){ + if there is still data on the socket: clear it + while(availableRS232(self)){ len = replyLen; readRS232(self,reply,&len); - } + } */ - - + + /* - write data - */ - iRet = writeRS232(self,send,sendLen); - if(iRet <= 0) - { + write data + */ + iRet = writeRS232(self, send, sendLen); + if (iRet <= 0) { return BADSEND; } /* - read - */ - memset(reply,0,replyLen); - iRet = NETReadTillTerm(self->pSock,self->timeout,self->replyTerminator, - reply, replyLen); - if(self->debug > 0) - { - if(iRet > 0) - { - printf("RS232 IN/TRANS: %s",(char *)reply); - if(strchr((char *)reply,'\n') == NULL) - { - puts(""); + read + */ + memset(reply, 0, replyLen); + iRet = NETReadTillTerm(self->pSock, self->timeout, self->replyTerminator, + reply, replyLen); + if (self->debug > 0) { + if (iRet > 0) { + printf("RS232 IN/TRANS: %s", (char *) reply); + if (strchr((char *) reply, '\n') == NULL) { + puts(""); } fflush(stdout); - } - else if(iRet == 0) - { + } else if (iRet == 0) { printf("RS232 IN/TRANS: TIMEOUT\n"); - } - else - { - printf("RS232 IN/TRANS/INCOMPLETE: %s",(char *)reply); + } else { + printf("RS232 IN/TRANS/INCOMPLETE: %s, errno = %d", (char *) reply, + errno); } } - if(iRet == 0) - { + if (iRet == 0) { + traceIO(MakeID(self),"in:%s", "TIMEOUT"); return TIMEOUT; - } - else if(iRet == -1) - { + } else if (iRet == -1) { + traceIO(MakeID(self),"in:%s:%d", "Incomplete read", errno); return INCOMPLETE; - } - else - { - return iRet; + } else { + traceIO(MakeID(self),"in:%s", (char *)reply); + return iRet; } } + /*------------------------------------------------------------------------*/ -void getRS232Error(int iCode, char *errorBuffer, - int errorBufferLen) +void getRS232Error(int iCode, char *errorBuffer, int errorBufferLen) { /* - the error code is either one of our errors, or an errno code from - the system - */ - switch(iCode) - { - case BADMEMORY: - strncpy(errorBuffer, - "Out of memory for appending terminators", - errorBufferLen); - break; - case NOTCONNECTED: - strncpy(errorBuffer, - "Not connected!", - errorBufferLen); - break; - case TIMEOUT: - strncpy(errorBuffer, - "Timeout or network error when reading data", - errorBufferLen); - break; - case FAILEDCONNECT: - strncpy(errorBuffer, - "Failed to connect to terminal server", - errorBufferLen); - break; + the error code is either one of our errors, or an errno code from + the system + */ + switch (iCode) { + case BADMEMORY: + strlcpy(errorBuffer, + "Out of memory for appending terminators", errorBufferLen); + break; + case NOTCONNECTED: + strlcpy(errorBuffer, "Not connected!", errorBufferLen); + break; + case TIMEOUT: + strlcpy(errorBuffer, + "Timeout or network error when reading data", errorBufferLen); + break; + case FAILEDCONNECT: + strlcpy(errorBuffer, + "Failed to connect to terminal server", errorBufferLen); + break; case INCOMPLETE: - strncpy(errorBuffer,"Did not find terminator in read buffer", - errorBufferLen); - break; + strlcpy(errorBuffer, "Did not find terminator in read buffer", + errorBufferLen); + break; case BADSEND: - strncpy(errorBuffer,"Network problem: failed to send",errorBufferLen); - break; - default: - strncpy(errorBuffer,strerror(errno), - errorBufferLen); - break; + strlcpy(errorBuffer, "Network problem: failed to send", + errorBufferLen); + break; + default: + strlcpy(errorBuffer, strerror(errno), errorBufferLen); + break; } } + /*--------------------------------------------------------------------*/ -int fixRS232Error(prs232 self, int iCode){ - int i, status, read; - char buffer[8192]; - - switch(iCode){ - case BADMEMORY: - case FAILEDCONNECT: - return 0; - break; - case INCOMPLETE: - case TIMEOUT: - /* - * try to clear possibly pending stuff - */ - for(i = 0; i < 3; i++){ - if(availableRS232(self)){ - read = 8192; - readRS232(self,buffer,&read); - } - } - return 1; - break; - case NOTCONNECTED: - case BADSEND: - closeRS232(self); - status = initRS232(self); - if(status > 0){ - return 1; - } else { - return 0; - } - break; - } +int fixRS232Error(prs232 self, int iCode) +{ + int i, status, read; + char buffer[8192]; + + switch (iCode) { + case BADMEMORY: + case FAILEDCONNECT: return 0; + break; + case INCOMPLETE: + case TIMEOUT: + /* + * try to clear possibly pending stuff + */ + for (i = 0; i < 3; i++) { + if (availableRS232(self)) { + read = 8192; + readRS232(self, buffer, &read); + } + } + return 1; + break; + case NOTCONNECTED: + case BADSEND: + closeRS232(self); + status = initRS232(self); + if (status > 0) { + return 1; + } else { + return 0; + } + break; + } + return 0; } + /*--------------------------------------------------------------------*/ -int getRS232Timeout(prs232 self){ +int getRS232Timeout(prs232 self) +{ return self->timeout; } + /*--------------------------------------------------------------------*/ int initRS232WithFlags(prs232 self, int flags) { @@ -480,71 +461,74 @@ int initRS232WithFlags(prs232 self, int flags) assert(self); - if(self->pSock != NULL) - { - if(pServ->pReader != NULL){ - NetReadRemoveUserSocket(pServ->pReader,self->pSock->sockid); + traceIO(MakeID(self),"connect"); + + if (self->pSock != NULL) { + if (pServ->pReader != NULL) { + NetReadRemoveUserSocket(pServ->pReader, self->pSock->sockid); } NETClosePort(self->pSock); free(self->pSock); self->pSock = NULL; } self->pSock = NETConnectWithFlags(self->pHost, self->iPort, flags); - if(!self->pSock){ + if (!self->pSock) { return FAILEDCONNECT; - } else{ - if(pServ->pReader != NULL){ - NetReadRegisterUserSocket(pServ->pReader,self->pSock->sockid); + } else { + if (pServ->pReader != NULL) { + NetReadRegisterUserSocket(pServ->pReader, self->pSock->sockid); self->registered = 1; } return 1; } } + /*--------------------------------------------------------------------*/ int initRS232(prs232 self) { return initRS232WithFlags(self, 0); } + /*--------------------------------------------------------------------*/ int initRS232Finished(prs232 self) { - int iret; - - iret = NETConnectFinished(self->pSock); - if (iret < 0) { - return FAILEDCONNECT; - } else { - return iret; - } + int iret; + + iret = NETConnectFinished(self->pSock); + if (iret < 0) { + return FAILEDCONNECT; + } else { + return iret; + } } + /*--------------------------------------------------------------------*/ void closeRS232(prs232 self) { assert(self); - if(self->pSock != NULL) - { - if(pServ->pReader != NULL){ - NetReadRemoveUserSocket(pServ->pReader,self->pSock->sockid); + if (self->pSock != NULL) { + if (pServ->pReader != NULL) { + NetReadRemoveUserSocket(pServ->pReader, self->pSock->sockid); } NETClosePort(self->pSock); free(self->pSock); self->pSock = NULL; } } + /*------------------------------------------------------------------*/ prs232 createRS232(char *host, int iPort) { prs232 pNew = NULL; assert(iPort > 0); - + /* - create data structure - */ - pNew = (prs232)malloc(sizeof(rs232)); - if(!pNew) - { + create data structure + */ + pNew = (prs232) malloc(sizeof(rs232)); + if (!pNew) { return NULL; } memset(pNew, 0, sizeof(rs232)); @@ -556,93 +540,82 @@ prs232 createRS232(char *host, int iPort) pNew->timeout = 1000; pNew->debug = 0; pNew->pDes = CreateDescriptor("RS232 Controller"); - if(!pNew->pDes || !pNew->pHost || - !pNew->replyTerminator || !pNew->sendTerminator) - { + if (!pNew->pDes || !pNew->pHost || + !pNew->replyTerminator || !pNew->sendTerminator) { return NULL; } return pNew; } + /*-------------------------------------------------------------------*/ - void KillRS232(void *pData) +void KillRS232(void *pData) { - prs232 self = (prs232)pData; - if(!self) - { - return; + prs232 self = (prs232) pData; + if (!self) { + return; } - if(self->pDes) - { + if (self->pDes) { DeleteDescriptor(self->pDes); } - if(self->sendTerminator != NULL) - { + if (self->sendTerminator != NULL) { free(self->sendTerminator); } - if(self->replyTerminator != NULL) - { + if (self->replyTerminator != NULL) { free(self->replyTerminator); } - if(self->pSock) - { - if(pServ->pReader != NULL){ - NetReadRemoveUserSocket(pServ->pReader,self->pSock->sockid); + if (self->pSock) { + if (pServ->pReader != NULL) { + NetReadRemoveUserSocket(pServ->pReader, self->pSock->sockid); } NETClosePort(self->pSock); free(self->pSock); } - if(self->pHost) - { + if (self->pHost) { free(self->pHost); } } + /*-------------------------------------------------------------------*/ -static void KillAndFreeRS232(void *pData) { +static void KillAndFreeRS232(void *pData) +{ KillRS232(pData); free(pData); } + /*-------------------------------------------------------------------*/ -static int checkSet(SConnection *pCon, int argc, int rights) +static int checkSet(SConnection * pCon, int argc, int rights) { - if(argc < 3) - { - return 0; - } - else - { - if(SCMatchRights(pCon,rights)) - { + if (argc < 3) { + return 0; + } else { + if (SCMatchRights(pCon, rights)) { return 1; - } - else - { + } else { return 0; } - } + } /* - not reached - */ + not reached + */ return 0; } + /*--------------------------------------------------------------------*/ static void encodeTerminator(char *result, char *terminator) { int i, len; char pBuffer[10]; - - if(terminator == NULL) - { + + if (terminator == NULL) { result[0] = '\0'; - return; } len = strlen(terminator); - sprintf(pBuffer,"0x%x",(int)terminator[0]); - strcpy(result,pBuffer); - for(i = 1; i < len; i++) - { - sprintf(pBuffer,"0x%x",(int)terminator[i]); - strcat(result,pBuffer); + snprintf(pBuffer,sizeof(pBuffer)-1, "0x%x", (int) terminator[0]); + strcpy(result, pBuffer); + for (i = 1; i < len; i++) { + snprintf(pBuffer,sizeof(pBuffer)-1, "0x%x", (int) terminator[i]); + strcat(result, pBuffer); } } extern char *stptok(char *pPtr, char *pToken, int tokenLen, char *term); @@ -654,34 +627,33 @@ char *decodeTerminator(char *code) char *pPtr, pToken[10]; /* - max 10 terminators! - */ - pResult = (char *)malloc(10*sizeof(char)); - if(!pResult) - { + max 10 terminators! + */ + pResult = (char *) malloc(10 * sizeof(char)); + if (!pResult) { return NULL; } - memset(pResult,0,10); + memset(pResult, 0, 10); pToken[0] = '0'; /* - I seem to get an empty token on the first call to stptok, this is why - I do 2 stptoks. Strange and wonderful. - */ - pPtr = stptok(code,pToken+1,9,"0"); - pPtr = stptok(pPtr,pToken+1,9,"0"); - while(pPtr != NULL) - { - sscanf(pToken,"%x",&icode); - pResult[count] = (char)icode; + I seem to get an empty token on the first call to stptok, this is why + I do 2 stptoks. Strange and wonderful. + */ + pPtr = stptok(code, pToken + 1, 9, "0"); + pPtr = stptok(pPtr, pToken + 1, 9, "0"); + while (pPtr != NULL) { + sscanf(pToken, "%x", &icode); + pResult[count] = (char) icode; count++; - pPtr = stptok(pPtr,pToken+1,9,"0"); + pPtr = stptok(pPtr, pToken + 1, 9, "0"); } return pResult; } + /*--------------------------------------------------------------------*/ -int RS232Action(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]) +int RS232Action(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]) { prs232 self = NULL; char pError[256]; @@ -690,270 +662,212 @@ int RS232Action(SConnection *pCon, SicsInterp *pSics, char *pPtr = NULL; int iRet, iRead = 8191, count, i; - self = (prs232)pData; + self = (prs232) pData; assert(self); assert(pCon); /* - check for arguments - */ - if(argc < 2) - { - sprintf(pError,"ERROR: insufficient no of arguments to %s",argv[0]); - SCWrite(pCon,pError,eError); + check for arguments + */ + if (argc < 2) { + snprintf(pError,sizeof(pError)-1, "ERROR: insufficient no of arguments to %s", argv[0]); + SCWrite(pCon, pError, eError); return 0; } strtolower(argv[1]); - if(strcmp(argv[1],"sendterminator") == 0) - { - if(checkSet(pCon,argc,usMugger)) - { + if (strcmp(argv[1], "sendterminator") == 0) { + if (checkSet(pCon, argc, usMugger)) { pPtr = decodeTerminator(argv[2]); - setRS232SendTerminator(self,pPtr); - if(pPtr) - free(pPtr); + setRS232SendTerminator(self, pPtr); + if (pPtr) + free(pPtr); SCSendOK(pCon); return 1; + } else { + encodeTerminator(pBuffer, self->sendTerminator); + snprintf(pError,sizeof(pError)-1, "%s.sendTerminator = \"%s\"", argv[0], pBuffer); + SCWrite(pCon, pError, eValue); + return 1; } - else - { - encodeTerminator(pBuffer,self->sendTerminator); - sprintf(pError,"%s.sendTerminator = \"%s\"",argv[0], - pBuffer); - SCWrite(pCon,pError,eValue); - return 1; - } - } - else if(strcmp(argv[1],"debug") == 0) - { + } else if (strcmp(argv[1], "debug") == 0) { self->debug = atoi(argv[2]); SCSendOK(pCon); return 1; - } - else if(strcmp(argv[1],"timeout") == 0) - { - if(checkSet(pCon,argc,usUser)) - { - setRS232Timeout(self,atoi(argv[2])); + } else if (strcmp(argv[1], "timeout") == 0) { + if (checkSet(pCon, argc, usUser)) { + setRS232Timeout(self, atoi(argv[2])); SCSendOK(pCon); return 1; + } else { + snprintf(pError,sizeof(pError)-1, "%s.Timeout = %d", argv[0], self->timeout); + SCWrite(pCon, pError, eValue); + return 1; } - else - { - sprintf(pError,"%s.Timeout = %d",argv[0],self->timeout); - SCWrite(pCon,pError,eValue); - return 1; - } - } - else if(strcmp(argv[1],"replyterminator") == 0) - { - if(checkSet(pCon,argc,usMugger)) - { - memset(pTerm,0,10); - for(i = 2; i < argc;i++){ + } else if (strcmp(argv[1], "replyterminator") == 0) { + if (checkSet(pCon, argc, usMugger)) { + memset(pTerm, 0, 10); + for (i = 2; i < argc; i++) { pPtr = decodeTerminator(argv[i]); - pTerm[i-2] = pPtr[0]; - if(pPtr) - free(pPtr); + pTerm[i - 2] = pPtr[0]; + if (pPtr) + free(pPtr); } - setRS232ReplyTerminator(self,pTerm); + setRS232ReplyTerminator(self, pTerm); SCSendOK(pCon); return 1; + } else { + encodeTerminator(pBuffer, self->replyTerminator); + snprintf(pError,sizeof(pError)-1, "%s.replyTerminator = \"%s\"", argv[0], pBuffer); + SCWrite(pCon, pError, eValue); + return 1; } - else - { - encodeTerminator(pBuffer,self->replyTerminator); - sprintf(pError,"%s.replyTerminator = \"%s\"",argv[0], - pBuffer); - SCWrite(pCon,pError,eValue); - return 1; - } - } - else if(strcmp(argv[1],"write") == 0) - { - Arg2Text(argc-2,argv+2,pBuffer,8191); - iRet = writeRS232(self,pBuffer,strlen(pBuffer)); - if(iRet < 0) - { - getRS232Error(iRet,pError,255); - SCWrite(pCon,pError,eError); + } else if (strcmp(argv[1], "write") == 0) { + Arg2Text(argc - 2, argv + 2, pBuffer, 8191); + iRet = writeRS232(self, pBuffer, strlen(pBuffer)); + if (iRet < 0) { + getRS232Error(iRet, pError, 255); + SCWrite(pCon, pError, eError); return 0; } SCSendOK(pCon); return 1; - } - else if(strcmp(argv[1],"read") == 0) - { - if(!availableRS232(self)) - { - SCWrite(pCon,"Nothing to read!",eError); + } else if (strcmp(argv[1], "read") == 0) { + if (!availableRS232(self)) { + SCWrite(pCon, "Nothing to read!", eError); return 1; } - iRet = readRS232(self,pBuffer,&iRead); - if(iRet < 0) - { - getRS232Error(iRet,pError,255); - SCWrite(pCon,pError,eError); + iRet = readRS232(self, pBuffer, &iRead); + if (iRet < 0) { + getRS232Error(iRet, pError, 255); + SCWrite(pCon, pError, eError); return 0; } - SCWrite(pCon,pBuffer,eValue); + SCWrite(pCon, pBuffer, eValue); return 1; - } - else if(strcmp(argv[1],"readchar") == 0){ - if(argc < 3){ - SCWrite(pCon,"ERROR: need number of chars to read",eError); - return 0; - } - iRet = Tcl_GetInt(pSics->pTcl,argv[2],&iRead); - if(iRet != TCL_OK){ - SCWrite(pCon,"ERROR: failed to convert argument to number",eError); - return 0; - } - if(!availableRS232(self)) - { - SCWrite(pCon,"Nothing to read!",eError); + } else if (strcmp(argv[1], "readchar") == 0) { + if (argc < 3) { + SCWrite(pCon, "ERROR: need number of chars to read", eError); + return 0; + } + iRet = Tcl_GetInt(pSics->pTcl, argv[2], &iRead); + if (iRet != TCL_OK) { + SCWrite(pCon, "ERROR: failed to convert argument to number", eError); + return 0; + } + if (!availableRS232(self)) { + SCWrite(pCon, "Nothing to read!", eError); return 1; } - iRet = readRS232(self,pBuffer,&iRead); - if(iRet < 0) - { - getRS232Error(iRet,pError,255); - SCWrite(pCon,pError,eError); + iRet = readRS232(self, pBuffer, &iRead); + if (iRet < 0) { + getRS232Error(iRet, pError, 255); + SCWrite(pCon, pError, eError); return 0; } - SCWrite(pCon,pBuffer,eValue); + SCWrite(pCon, pBuffer, eValue); return 1; - } - else if(strcmp(argv[1],"available") == 0) - { + } else if (strcmp(argv[1], "available") == 0) { iRet = availableRS232(self); - if(iRet < 0) - { - getRS232Error(iRet,pError,255); - SCWrite(pCon,pError,eError); + if (iRet < 0) { + getRS232Error(iRet, pError, 255); + SCWrite(pCon, pError, eError); return 0; - } - else if(iRet == 0) - { - SCWrite(pCon,"No data pending",eValue); + } else if (iRet == 0) { + SCWrite(pCon, "No data pending", eValue); + return 1; + } else { + SCWrite(pCon, "Data available", eValue); return 1; } - else - { - SCWrite(pCon,"Data available",eValue); - return 1; - } - } - else if(strcmp(argv[1],"send") == 0) - { - Arg2Text(argc-2,argv+2,pBuffer,8191); - iRet = transactRS232(self,pBuffer,strlen(pBuffer), - pReply,iRead); - if(iRet < 0) - { - getRS232Error(iRet,pError,255); - SCWrite(pCon,pError,eError); + } else if (strcmp(argv[1], "send") == 0) { + Arg2Text(argc - 2, argv + 2, pBuffer, 8191); + iRet = transactRS232(self, pBuffer, strlen(pBuffer), pReply, iRead); + if (iRet < 0) { + getRS232Error(iRet, pError, 255); + SCWrite(pCon, pError, eError); return 0; } - SCWrite(pCon,pReply,eValue); + SCWrite(pCon, pReply, eValue); return 1; - } - else if(strcmp(argv[1],"binwrite") == 0) - { + } else if (strcmp(argv[1], "binwrite") == 0) { count = argc - 2; - for(i = 0; i < count; i++) - { - pBuffer[i] = (char)atoi(argv[i+2]); + for (i = 0; i < count; i++) { + pBuffer[i] = (char) atoi(argv[i + 2]); } - if(self->pSock) - { - iRet = NETWrite(self->pSock,pBuffer,count); - } - else - { + if (self->pSock) { + iRet = NETWrite(self->pSock, pBuffer, count); + } else { iRet = NOTCONNECTED; } - if(iRet < 0) - { - getRS232Error(iRet,pError,255); - SCWrite(pCon,pError,eError); + if (iRet < 0) { + getRS232Error(iRet, pError, 255); + SCWrite(pCon, pError, eError); return 0; } SCSendOK(pCon); return 1; - } - else if(strcmp(argv[1],"init") == 0) - { + } else if (strcmp(argv[1], "init") == 0) { iRet = initRS232(self); - if(iRet != 1) - { - sprintf(pError,"ERROR: reinitializing connection to %s at %d failed", - self->pHost, self->iPort); - SCWrite(pCon,pError,eError); + if (iRet != 1) { + snprintf(pError,sizeof(pError)-1, + "ERROR: reinitializing connection to %s at %d failed", + self->pHost, self->iPort); + SCWrite(pCon, pError, eError); return 0; - } - else - { + } else { SCSendOK(pCon); return 1; } - } - else - { - sprintf(pError,"ERROR: %s does not understand %s",argv[0], argv[1]); - SCWrite(pCon,pError,eError); + } else { + snprintf(pError,sizeof(pError)-1, "ERROR: %s does not understand %s", argv[0], argv[1]); + SCWrite(pCon, pError, eError); return 0; } return 1; } + /*-------------------------------------------------------------------*/ -int RS232Factory(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]) +int RS232Factory(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]) { prs232 pNew = NULL; int iRet, status; char pError[256]; - if(argc < 4) - { - SCWrite(pCon,"ERROR: insufficient no of arguments to RS232Factory", + if (argc < 4) { + SCWrite(pCon, "ERROR: insufficient no of arguments to RS232Factory", eError); return 0; } /* - create data structure and open port - */ + create data structure and open port + */ pNew = createRS232(argv[2], atoi(argv[3])); - - if(!pNew) - { - SCWrite(pCon,"ERROR: out of memory in RS232Factory",eError); + + if (!pNew) { + SCWrite(pCon, "ERROR: out of memory in RS232Factory", eError); return 0; } status = initRS232(pNew); - if(status != 1) - { - sprintf(pError,"ERROR: failed to connect to %s at port %d", - pNew->pHost, pNew->iPort); - SCWrite(pCon,pError,eError); + if (status != 1) { + snprintf(pError,sizeof(pError)-1, "ERROR: failed to connect to %s at port %d", + pNew->pHost, pNew->iPort); + SCWrite(pCon, pError, eError); } - + /* - create the command - */ - iRet = AddCommand(pSics,argv[1],RS232Action, KillAndFreeRS232, pNew); - if(!iRet) - { - sprintf(pError,"ERROR: duplicate command %s not created", argv[1]); - SCWrite(pCon,pError,eError); - KillAndFreeRS232(pNew); - return 0; - } - return 1; + create the command + */ + iRet = AddCommand(pSics, argv[1], RS232Action, KillAndFreeRS232, pNew); + if (!iRet) { + snprintf(pError,sizeof(pError)-1, "ERROR: duplicate command %s not created", argv[1]); + SCWrite(pCon, pError, eError); + KillAndFreeRS232(pNew); + return 0; + } + return 1; } - - diff --git a/rs232controller.h b/rs232controller.h index 0882b895..833b27aa 100644 --- a/rs232controller.h +++ b/rs232controller.h @@ -14,8 +14,6 @@ #ifndef RS232CONTROLLER #define RS232CONTROLLER #include "network.h" -#include "obdes.h" //PB -#include "conman.h" //PB /* own error codes */ @@ -29,52 +27,50 @@ /*----------------------- a data structure ----------------------------*/ - typedef struct{ - pObjectDescriptor pDes; - char *sendTerminator; - char *replyTerminator; - int timeout; - mkChannel *pSock; - char *pHost; - int iPort; - int debug; - int registered; - } rs232, *prs232; +typedef struct { + pObjectDescriptor pDes; + char *sendTerminator; + char *replyTerminator; + int timeout; + mkChannel *pSock; + char *pHost; + int iPort; + int debug; + int registered; +} rs232, *prs232; /*----------------------- the interface functions --------------------*/ - int RS232Action(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]); - int RS232Factory(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]); +int RS232Action(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]); +int RS232Factory(SConnection * pCon, SicsInterp * pSics, + void *pData, int argc, char *argv[]); - void setRS232SendTerminator(prs232 self, char *term); - void setRS232ReplyTerminator(prs232 self, char *term); - void setRS232Timeout(prs232 self, int timeout); - void setRS232Debug(prs232 self, int deb); +void setRS232SendTerminator(prs232 self, char *term); +void setRS232ReplyTerminator(prs232 self, char *term); +void setRS232Timeout(prs232 self, int timeout); +void setRS232Debug(prs232 self, int deb); - int writeRS232(prs232 self, void *data, int dataLen); - int readRS232(prs232 self, void *data, int *dataLen); - int readRS232TillTerm(prs232 self, void *data, int *datalen); - int readRS232UntilWord(prs232 self, - char *buffer, int buflen, char *word); - int availableRS232(prs232 self); - int availableNetRS232(prs232 self); - int transactRS232(prs232 self, void *send, int sendLen, - void *reply, int replylen); +int writeRS232(prs232 self, void *data, int dataLen); +int readRS232(prs232 self, void *data, int *dataLen); +int readRS232TillTerm(prs232 self, void *data, int *datalen); +int readRS232UntilWord(prs232 self, char *buffer, int buflen, char *word); +int availableRS232(prs232 self); +int availableNetRS232(prs232 self); +int transactRS232(prs232 self, void *send, int sendLen, + void *reply, int replylen); - void getRS232Error(int iCode, char *errorBuffer, - int errorBufferLen); - int fixRS232Error(prs232 self, int iCode); - int getRS232Timeout(prs232 self); - int initRS232(prs232 self); - int initRS232WithFlags(prs232 self, int flags); - int initRS232Finished(prs232 self); - void closeRS232(prs232 self); - prs232 createRS232(char *host, int iPort); - void KillRS232(void *pData); +void getRS232Error(int iCode, char *errorBuffer, int errorBufferLen); +int fixRS232Error(prs232 self, int iCode); +int getRS232Timeout(prs232 self); +int initRS232(prs232 self); +int initRS232WithFlags(prs232 self, int flags); +int initRS232Finished(prs232 self); +void closeRS232(prs232 self); +prs232 createRS232(char *host, int iPort); +void KillRS232(void *pData); #endif diff --git a/rwpuffer.c b/rwpuffer.c new file mode 100644 index 00000000..a678e700 --- /dev/null +++ b/rwpuffer.c @@ -0,0 +1,85 @@ +/** + * This is a buffer to store bytes for reading and writing. + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, January 2009 + */ +#include +#include +#include +#include "rwpuffer.h" +/*----------------------------------------------------------------------*/ +typedef struct __RWBuffer { + char *data; + int length; + int startPtr; + int endPtr; +} RWBuffer; +/*----------------------------------------------------------------------*/ +prwBuffer MakeRWPuffer(int size) +{ + prwBuffer self = NULL; + + self = malloc(sizeof(RWBuffer)); + if (self == NULL) { + return NULL; + } + self->data = calloc(size, sizeof(char)); + if (self->data == NULL) { + return NULL; + } + self->length = size; + self->startPtr = 0; + self->endPtr = 0; + return self; +} + +/*------------------------------------------------------------------------*/ +void KillRWBuffer(prwBuffer self) +{ + if (self == NULL) { + return; + } + if (self->data != NULL) { + free(self->data); + } + free(self); +} + +/*------------------------------------------------------------------------*/ +int StoreRWBuffer(prwBuffer self, void *data, int count) +{ + int length; + + length = self->endPtr - self->startPtr; + if (count + length >= self->length ) { + printf("HELP: RWBuffer overrun!!!!\n"); + return 0; + } + if (count + self->endPtr > self->length) { + memmove(self->data, self->data + self->startPtr, length); + self->startPtr = 0; + self->endPtr = length; + } + memcpy(self->data + self->endPtr, data, count); + self->endPtr += count; + return 1; +} + +/*------------------------------------------------------------------------*/ +void *GetRWBufferData(prwBuffer self, int *length) +{ + *length = self->endPtr - self->startPtr; + return (void *) self->data + self->startPtr; +} + +/*-------------------------------------------------------------------------*/ +void RemoveRWBufferData(prwBuffer self, int count) +{ + self->startPtr += count; + if (self->startPtr >= self->endPtr) { + self->startPtr = 0; + self->endPtr = 0; + } +} diff --git a/rwpuffer.h b/rwpuffer.h new file mode 100644 index 00000000..e69795b4 --- /dev/null +++ b/rwpuffer.h @@ -0,0 +1,46 @@ +/** + * This is a buffer to store bytes for reading and writing. + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, January 2009 + */ +#ifndef RWPUFFER_H_ +#define RWPUFFER_H_ + +typedef struct __RWBuffer *prwBuffer; + +/** + * \brief create a RW buffer. + * \param size The size of the buffer. + * \return NULL on success, else a pointer to t a new rwPuffer + */ +prwBuffer MakeRWPuffer(int size); +/** + * \brief delete a rw buffer. + * \param self The rwPuffer to delete. + */ +void KillRWBuffer(prwBuffer self); +/** + * \brief store some data in the RW buffer + * \param self The rw buffer to store the data in + * \param data pointer to the data to store + * \param count The number of bytes to store + * \return 1 on success, 0 on failure + */ +int StoreRWBuffer(prwBuffer self, void *data, int count); +/** + * \brief Get a pointer to the current buffer data + * \param self the buffer to get the data from + * \param length Will be set to the number of available bytes. + * \return A pointer to the data + */ +void *GetRWBufferData(prwBuffer self, int *length); +/** + * \brief remove data from the buffer + * \param self the buffer to remove data from + * \param count The number of bytes to remove + */ +void RemoveRWBufferData(prwBuffer self, int count); + +#endif /*RWPUFFER_H_ */ diff --git a/s_rnge.c b/s_rnge.c index 5c12b949..88b1566c 100644 --- a/s_rnge.c +++ b/s_rnge.c @@ -7,26 +7,28 @@ extern "C" { /* called when a subscript is out of range */ #ifdef KR_headers -extern VOID sig_die(); -integer s_rnge(varn, offset, procn, line) char *varn, *procn; ftnint offset, line; + extern VOID sig_die(); + integer s_rnge(varn, offset, procn, line) char *varn, *procn; + ftnint offset, line; #else -extern VOID sig_die(char*,int); -integer s_rnge(char *varn, ftnint offset, char *procn, ftnint line) + extern VOID sig_die(char *, int); + integer s_rnge(char *varn, ftnint offset, char *procn, ftnint line) #endif -{ -register int i; + { + register int i; -fprintf(stderr, "Subscript out of range on file line %ld, procedure ", - (long)line); -while((i = *procn) && i != '_' && i != ' ') - putc(*procn++, stderr); -fprintf(stderr, ".\nAttempt to access the %ld-th element of variable ", - (long)offset+1); -while((i = *varn) && i != ' ') - putc(*varn++, stderr); -sig_die(".", 1); -return 0; /* not reached */ -} + fprintf(stderr, "Subscript out of range on file line %ld, procedure ", + (long) line); + while ((i = *procn) && i != '_' && i != ' ') + putc(*procn++, stderr); + fprintf(stderr, + ".\nAttempt to access the %ld-th element of variable ", + (long) offset + 1); + while ((i = *varn) && i != ' ') + putc(*varn++, stderr); + sig_die(".", 1); + return 0; /* not reached */ + } #ifdef __cplusplus } #endif diff --git a/sans.tcl b/sans.tcl deleted file mode 100644 index 41bf129a..00000000 --- a/sans.tcl +++ /dev/null @@ -1,209 +0,0 @@ -# -------------------------------------------------------------------------- -# Initialization script the instrument SANS at SINQ -# -# Dr. Mark Koennecke, June 1997 -#--------------------------------------------------------------------------- -# O P T I O N S -set root "/data/koenneck/src/sics" -# first all the server options are set - -ServerOption SaveFile $root/bin/sansstat.tcl -# File to save the status of the instrument too - -ServerOption ReadTimeOut 10 -# timeout when checking for commands. In the main loop SICS checks for -# pending commands on each connection with the above timeout, has -# PERFORMANCE impact! - -ServerOption AcceptTimeOut 10 -# timeout when checking for connection req. -# Similar to above, but for connections - -ServerOption ReadUserPasswdTimeout 500000 -# time to wiat for a user/passwd to be sent from a client. Increase this -# if there is a problem connecting to a server due to network overload\ - -ServerOption LogFileBaseName $root/log/sanslog -# the path and base name of the internal server logfile to which all -# activity will be logged. - -ServerOption ServerPort 2915 -# the port number the server is going to listen at. The client MUST know -# this number in order to connect. It is in client.ini - -ServerOption InterruptPort 2917 -# The UDP port where the server will wait for Interrupts from clients. -# Obviously, clients wishing to interrupt need to know this number. - -# Telnet Options -ServerOption TelnetPort 1301 -ServerOption TelWord sicslogin - -# The token system -TokenInit connan - -#--------------------------------------------------------------------------- -# U S E R S - -# than the SICS users are specified -# Syntax: SicsUser name password userRightsCode -SicsUser Manager Joachim 1 -SicsUser User Kohl 2 -SicsUser Spy 007 3 - -#-------------------------------------------------------------------------- -# S I M P L E V A R I A B L E S - -# now a few general variables are created -# Syntax: VarMake name type access -# type can be one of: Text, Int, Float -#access can be one of: Internal, Mugger, user, Spy - -VarMake Instrument Text Internal -Instrument "SANS at SINQ,PSI" -#initialisation -Instrument lock - -VarMake title Text User -VarMake User Text User -User "Albert von Villigen" -VarMake SubTitle Text User -VarMake environment Text User -VarMake comment Text User -VarMake SampleName Text User -SampleName KohlSulfid -#----------- Initialize data storage stuff -VarMake SicsDataPath Text Mugger -SicsDataPath $root/data/ -SicsDataPath lock -VarMake SicsDataPrefix Text Mugger -SicsDataPrefix sans -SicsDataPrefix lock -VarMake SicsDataPostFix Text Mugger -SicsDataPostFix ".hdf" -SicsDataPostFix lock -MakeDataNumber SicsDataNumber $root/data/2001/DataNumber -InitSANS $root/sansdict.dic - - -#-------------------------------------------------------------------------- -# D E V I C E S : M O T O R S - -#Motor a4 EL734 LNSP22 4000 5 6 -# EL734 motor with parameters: hostname PortNumber Channel MotorID - -#Motor a4 EL734DC LNSP22 4000 5 6 -# EL734DC motor with parameters: hostname PortNumber Channel MotorID - -# Motor nam SIM -20. 20. 5. 1.0 -# Simulated motor with name nam, lower limit -20, upper limit +20, -# error ratio 5% and speed 1.0. Speed may be omitted - -# Motors for sample movement -Motor schi SIM -22.0 +22. 10. -Motor sphi SIM -22.0 +22.0 10. -Motor som EL734 lnsp25.psi.ch 4000 2 8 -Motor sax EL734 lnsp25.psi.ch 4000 2 6 -Motor say EL734 lnsp25.psi.ch 4000 2 7 -Motor saz EL734 lnsp25.psi.ch 4000 2 1 -Motor spos EL734 lnsp25.psi.ch 4000 2 5 - -#Motors for detector movement -Motor DetectorX EL734DC lnsp25.psi.ch 4000 3 1 -DetectorX Precision 0.5 -Motor DetectorY EL734DC lnsp25.psi.ch 4000 3 2 -DetectorY Precision 0.2 -Motor DetectorRotation EL734DC lnsp25.psi.ch 4000 3 3 -DetectorRotation Precision 0.1 - -#Motors for beamstop -Motor BeamStopX EL734 lnsp25.psi.ch 4000 2 3 -BeamStopX Precision 0.2 -Motor BeamStopY EL734 lnsp25.psi.ch 4000 2 4 -BeamStopY Precision 0.2 - - -#------------------------------------------------------------------------ -# Velocity selector -Motor tilt EL734 lnsp25.psi.ch 4000 2 2 -set dornen(Host) lnsp25.psi.ch -set dornen(Port) 4000 -set dornen(Channel) 6 -set dornen(Timeout) 3000 -VelocitySelector nvs tilt DORNIER dornen -nvs add -20 28800 -nvs add 3800 4500 -nvs add 5900 6700 -nvs add 8100 9600 -unset dornen - -#-------------------------------------------------------------------------- -# P R O C E D U R E S - -# create the drive command -MakeDrive -#-------------------------------------------------------------------------- -# MultiMotor is an object which groups several motors together. - -#--------------------------------- sample position -MakeMulti sample -# creates a MultiMotor with name sample -sample alias schi chi -# alias creates an internal name (chi) for motor schi -sample alias sphi phi -sample alias som omega -sample alias sax x -sample alias say y -sample alias saz z -sample pos Jo schi 0. sphi 0. som 45. sax 2. say 3. saz 10. -# define Jo as a named position. This means with sample Jo you'll reach -# the positions specified -sample pos Mo schi 0. sphi 0. som 180. sax 2. say 3. saz 10. -sample endconfig -# ends configuration of sample and install the command. This is REQUIRED - -#---------------------------------- detector position -MakeMulti detector -detector alias DetectorX X -detector alias DetectorY Y -detector alias DetectorRotation phi -detector endconfig - -#----------------------------------- beamstop -MakeMulti BeamStop -BeamStop alias BeamStopX X -BeamStop alias BeamStopY Y -BeamStop pos out BeamStopX 817. -BeamStop endconfig -#------------------------------------ Shortcuts -SicsAlias BeamStop bs -SicsAlias detector dt -#------------------------------------ Histogram Memory -MakeCounter counter EL737 lnsp25.psi.ch 4000 4 -counter SetExponent 6 - -MakeHM banana SINQHM -banana configure HistMode Normal -banana configure OverFlowMode Ceil -banana configure Rank 1 -banana configure Length 16384 -banana configure BinWidth 4 -banana preset 100. -banana CountMode Timer -banana configure HMComputer lnse02.psi.ch -banana configure HMPort 2400 -banana configure Counter counter -banana init -banana exponent 6 -#----------------------------------------------------------------------------- -# R U E N B U F F E R -MakeRuenBuffer - -#---------------------- some special Tcl commands -source $root/bin/log.tcl -Publish LogBook User - -source $root/bin/count.tcl -Publish count User -Publish Repeat User - diff --git a/sansbc.c b/sansbc.c new file mode 100644 index 00000000..985d70ea --- /dev/null +++ b/sansbc.c @@ -0,0 +1,252 @@ +/** + * This is a little routine to calculate the beam center from SANS data + * in the detector. This is basically a COG or COC (center of contour) + * calculation above a given threshold. Where we make an effor to + * find the threshold ourselves. + * + * copyright: GPL + * + * Mark Koennecke, July 2009 + */ +#include +#include +#include "HistMem.h" +#include "sicsobj.h" +#include "sicshipadaba.h" + +extern float nintf(float x); +/*---------------------------------------------------------------------*/ +static int calculateCOG(int *iData, int xsize, int ysize, + float *i, float *j, int *intensity, float contour, + float level) +{ + int threshold, nCount; + float cogTotal, cogX, cogY, conMin, conMax; + int *iPtr, x, y; + + conMin = contour - (contour *level); + conMax = contour + (contour *level); + + /* + build the sums + */ + nCount = 0; + cogTotal = cogY = cogX = .0; + for (y = 0; y < ysize; y++) { + iPtr = iData + y * xsize; + for (x = 0; x < xsize; x++) { + if (iPtr[x] > conMin && iPtr[x] < conMax) { + nCount++; + cogTotal += iPtr[x]; + cogY += y * iPtr[x]; + cogX += x * iPtr[x]; + } + } + } + if (cogTotal <= .0) { + return 0; + } + + *i = cogX / cogTotal; + *j = cogY / cogTotal; + *intensity = (int) cogTotal; + + return 1; +} +/*------------------------------------------------------------------*/ +static int calculateCOC(int *iData, int xsize, int ysize, + float *i, float *j, int *intensity, float contour) +{ + int threshold, nCount; + float cogTotal, cogX, cogY; + int *iPtr, x, y; + + /* + build the sums + */ + nCount = 0; + cogTotal = cogY = cogX = .0; + for (y = 0; y < ysize; y++) { + iPtr = iData + y * xsize; + for (x = 0; x < xsize; x++) { + if (iPtr[x] > contour) { + nCount++; + cogTotal += 1; + cogY += y * 1; + cogX += x * 1; + } + } + } + if (cogTotal <= .0) { + return 0; + } + + *i = cogX / cogTotal; + *j = cogY / cogTotal; + *intensity = (int) cogTotal; + + return 1; +} +/*-------------------------------------------------------------------------*/ +static int COGCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode, + pHdb par[], int nPar) +{ + pHistMem hm = NULL; + float contour, level, x = .0, y = .0; + int length, intensity, dim[3]; + + if(nPar < 3){ + SCWrite(pCon,"ERROR: need hm-name, contour and level for COG calculation", + eError); + return 0; + } + + hm = FindCommandData(pServ->pSics, + par[0]->value.v.text, "HistMem"); + if(hm == NULL){ + SCPrintf(pCon,eError,"ERROR: hm %s not found", par[0]->value.v.text); + return 0; + } + contour = par[1]->value.v.doubleValue; + level = par[2]->value.v.doubleValue; + + + GetHistDim(hm, dim, &length); + if(length != 2) { + SCPrintf(pCon,eError,"ERROR: hm %s is not 2D", par[0]->value.v.text); + return 0; + } + + calculateCOG(GetHistogramPointer(hm,pCon), + dim[0], dim[1], &x, &y, &intensity, contour, level); + + SCPrintf(pCon,eValue,"BC = %.2f,%.2f", x,y); + return 1; +} +/*-------------------------------------------------------------------------*/ +static int COCCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode, + pHdb par[], int nPar) +{ + pHistMem hm = NULL; + float contour, x, y; + int length, intensity, dim[3]; + + if(nPar < 2){ + SCWrite(pCon,"ERROR: need hm-name and contour for COG calculation", + eError); + return 0; + } + + hm = FindCommandData(pServ->pSics, + par[0]->value.v.text, "HistMem"); + if(hm == NULL){ + SCPrintf(pCon,eError,"ERROR: hm %s not found", par[0]->value.v.text); + return 0; + } + contour = par[1]->value.v.doubleValue; + + GetHistDim(hm, dim, &length); + if(length != 2) { + SCPrintf(pCon,eError,"ERROR: hm %s is not 2D", par[0]->value.v.text); + return 0; + } + + calculateCOC(GetHistogramPointer(hm,pCon), + dim[0], dim[1], &x, &y, &intensity, contour); + + SCPrintf(pCon,eValue,"BC = %.2f,%.2f", x,y); + return 1; +} +/*-------------------------------------------------------------------------*/ +static int StatCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode, + pHdb par[], int nPar) +{ + pHistMem hm = NULL; + long sum, max, min; + double average; + int dim[3], i, length; + HistInt *data = NULL; + + if(nPar < 1){ + SCWrite(pCon,"ERROR: need hm-name for statistics", + eError); + return 0; + } + + hm = FindCommandData(pServ->pSics, + par[0]->value.v.text, "HistMem"); + if(hm == NULL){ + SCPrintf(pCon,eError,"ERROR: hm %s not found", par[0]->value.v.text); + return 0; + } + + GetHistDim(hm, dim, &i); + if(i != 2) { + SCPrintf(pCon,eError,"ERROR: hm %s is not 2D", par[0]->value.v.text); + return 0; + } + data = GetHistogramPointer(hm,pCon); + if(data == NULL){ + SCPrintf(pCon,eError,"ERROR: failed to get data for hm %s", par[0]->value.v.text); + return 0; + } + max = -9999; + min = 99999.99; + length = dim[0]*dim[1]; + for(i = 0, sum = 0; i < length; i++){ + sum += data[i]; + if(data[i] > max){ + max = data[i]; + } + if(data[i] < min ){ + min = data[i]; + } + } + average = (double)sum/(double)length; + + SCPrintf(pCon,eValue,"Stat:sum,max,min,av = %d,%d,%d,%f", sum,max,min,average); + return 1; +} + +/*--------------------------------------------------------------------*/ +int SansBCFactory(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]) +{ + pSICSOBJ pNew = NULL; + pHdb cmd = NULL, node; + + pNew = SetupSICSOBJ(pCon,pSics,pData,argc,argv); + if(pNew == NULL){ + return 0; + } + + cmd = AddSICSHdbPar(pNew->objectNode, "cog", usSpy, + MakeSICSFunc(COGCmd)); + SetHdbProperty(cmd,"type","command"); + SetHdbProperty(cmd,"priv","spy"); + node = MakeSICSHdbPar("hm",usSpy,MakeHdbText("banana")); + AddHipadabaChild(cmd,node,NULL); + node = MakeSICSHdbPar("contour",usSpy,MakeHdbFloat(100.)); + AddHipadabaChild(cmd,node,NULL); + node = MakeSICSHdbPar("level",usSpy,MakeHdbFloat(.1)); + AddHipadabaChild(cmd,node,NULL); + + cmd = AddSICSHdbPar(pNew->objectNode, "coc", usSpy, + MakeSICSFunc(COCCmd)); + SetHdbProperty(cmd,"type","command"); + SetHdbProperty(cmd,"priv","spy"); + node = MakeSICSHdbPar("hm",usSpy,MakeHdbText("banana")); + AddHipadabaChild(cmd,node,NULL); + node = MakeSICSHdbPar("contour",usSpy,MakeHdbFloat(100.)); + AddHipadabaChild(cmd,node,NULL); + + cmd = AddSICSHdbPar(pNew->objectNode, "stat", usSpy, + MakeSICSFunc(StatCmd)); + SetHdbProperty(cmd,"type","command"); + SetHdbProperty(cmd,"priv","spy"); + node = MakeSICSHdbPar("hm",usSpy,MakeHdbText("banana")); + AddHipadabaChild(cmd,node,NULL); + + return 1; +} +/*-------------------------------------------------------------------*/ diff --git a/sansbc.h b/sansbc.h new file mode 100644 index 00000000..cee0faf8 --- /dev/null +++ b/sansbc.h @@ -0,0 +1,16 @@ +/** + * This is a little routine to calculate the beam center from SANS data + * in the detector. This is basically a COG or COC (center of contour) + * calculation above a given threshold. Where we make an effor to + * find the threshold ourselves. + * + * copyright: GPL + * + * Mark Koennecke, July 2009 + */ +#ifndef SANSBC_H_ +#define SANSBC_H_ +int SansBCFactory(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]); + +#endif /*SANSBC_H_*/ diff --git a/savehdb.c b/savehdb.c index b4b29523..11b43d64 100644 --- a/savehdb.c +++ b/savehdb.c @@ -3,12 +3,15 @@ #include "statusfile.h" #include "sicshipadaba.h" -static void SaveHdbBranch(pHdb node, FILE *fil) { +/* this file is obsolete (M.Z. 9.2011) */ + +static void SaveHdbBranch(pHdb node, FILE * fil) +{ pHdb child; char prop[16]; pDynString dyn; char path[1024]; - + if (GetHdbProperty(node, "save", prop, sizeof prop)) { if (strcmp(prop, "me") == 0) { dyn = formatValue(node->value, node); @@ -22,36 +25,39 @@ static void SaveHdbBranch(pHdb node, FILE *fil) { } } -static int SaveHdbTree(void *object, char *name, FILE *fil) { +static int SaveHdbTree(void *object, char *name, FILE * fil) +{ pHdb node; - + SaveHdbBranch(GetHipadabaRoot(), fil); return 1; } -static hdbCallbackReturn SaveHdbCallback(pHdb node, void *userData, - pHdbMessage message) { - pHdbDataMessage mm = NULL; - - if((mm = GetHdbUpdateMessage(message)) == NULL){ - return hdbContinue; +static hdbCallbackReturn SaveHdbCallback(pHdb node, void *userData, + pHdbMessage message) +{ + pHdbDataMessage mm = NULL; + + if ((mm = GetHdbUpdateMessage(message)) == NULL) { + return hdbContinue; } - + StatusFileDirty(); return hdbContinue;; } -static int SaveHdbEnable(SConnection *con, SicsInterp *sics, - void *data, int argc, char *argv[]) { +static int SaveHdbEnable(SConnection * con, SicsInterp * sics, + void *data, int argc, char *argv[]) +{ pHdb node; char prop[16]; pHdbCallback cb; - + if (argc < 2) { SCPrintf(con, eError, "ERROR: should be: %s ", argv[0]); return 0; } - + node = FindHdbNode(NULL, argv[1], con); if (!node) { SCPrintf(con, eError, "ERROR: %s not found", argv[1]); @@ -59,7 +65,7 @@ static int SaveHdbEnable(SConnection *con, SicsInterp *sics, } cb = MakeHipadabaCallback(SaveHdbCallback, NULL, NULL); assert(cb); - AppendHipadabaCallback(node,cb); + AppendHipadabaCallback(node, cb); SetHdbProperty(node, "save", "me"); for (node = node->mama; node != NULL; node = node->mama) { @@ -71,10 +77,12 @@ static int SaveHdbEnable(SConnection *con, SicsInterp *sics, return 1; } -void SaveHdbInit(void) { +void SaveHdbInit(void) +{ pDummy hs = NULL; hs = CreateDummy("hdb saver"); hs->pDescriptor->SaveStatus = SaveHdbTree; - AddCommandWithFlag(pServ->pSics, "hsave", SaveHdbEnable, KillDummy, hs, 0); + AddCommandWithFlag(pServ->pSics, "hsave", SaveHdbEnable, KillDummy, hs, + 0); } diff --git a/scaldate.c b/scaldate.c index e0baf5ae..dbae0d42 100644 --- a/scaldate.c +++ b/scaldate.c @@ -11,45 +11,46 @@ #include "scaldate.h" -int isleap (unsigned yr) +int isleap(unsigned yr) { - return yr % 400 == 0 || (yr % 4 == 0 && yr % 100 != 0); + return yr % 400 == 0 || (yr % 4 == 0 && yr % 100 != 0); } -static unsigned months_to_days (unsigned month) +static unsigned months_to_days(unsigned month) { - return (month * 3057 - 3007) / 100; + return (month * 3057 - 3007) / 100; } -static long years_to_days (unsigned yr) +static long years_to_days(unsigned yr) { - return yr * 365L + yr / 4 - yr / 100 + yr / 400; + return yr * 365L + yr / 4 - yr / 100 + yr / 400; } -long ymd_to_scalar (unsigned yr, unsigned mo, unsigned day) +long ymd_to_scalar(unsigned yr, unsigned mo, unsigned day) { - long scalar; - scalar = day + months_to_days(mo); - if ( mo > 2 ) /* adjust if past February */ - scalar -= isleap(yr) ? 1 : 2; - yr--; - scalar += years_to_days(yr); - return scalar; + long scalar; + scalar = day + months_to_days(mo); + if (mo > 2) /* adjust if past February */ + scalar -= isleap(yr) ? 1 : 2; + yr--; + scalar += years_to_days(yr); + return scalar; } -void scalar_to_ymd (long scalar, unsigned *yr, unsigned *mo, unsigned *day) +void scalar_to_ymd(long scalar, unsigned *yr, unsigned *mo, unsigned *day) { - unsigned n; /* compute inverse of years_to_days() */ + unsigned n; /* compute inverse of years_to_days() */ - for ( n = (unsigned)((scalar * 400L) / 146097L); years_to_days(n) < scalar;) - n++; /* 146097 == years_to_days(400) */ - *yr = n; - n = (unsigned)(scalar - years_to_days(n-1)); - if ( n > 59 ) { /* adjust if past February */ - n += 2; - if ( isleap(*yr) ) - n -= n > 62 ? 1 : 2; - } - *mo = (n * 100 + 3007) / 3057; /* inverse of months_to_days() */ - *day = n - months_to_days(*mo); + for (n = (unsigned) ((scalar * 400L) / 146097L); + years_to_days(n) < scalar;) + n++; /* 146097 == years_to_days(400) */ + *yr = n; + n = (unsigned) (scalar - years_to_days(n - 1)); + if (n > 59) { /* adjust if past February */ + n += 2; + if (isleap(*yr)) + n -= n > 62 ? 1 : 2; + } + *mo = (n * 100 + 3007) / 3057; /* inverse of months_to_days() */ + *day = n - months_to_days(*mo); } diff --git a/scaldate.h b/scaldate.h index 7fb3030f..fb7cd029 100644 --- a/scaldate.h +++ b/scaldate.h @@ -21,19 +21,21 @@ */ #ifndef ISO_CAL - #define ISO_CAL 0 +#define ISO_CAL 0 #endif #if (ISO_CAL != 0 && ISO_CAL != 1) - #error ISO_CAL must be set to either 0 or 1 +#error ISO_CAL must be set to either 0 or 1 #endif #if ISO_CAL - enum DOW_T {DOW_IGNORE = -1, - MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY}; +enum DOW_T { DOW_IGNORE = -1, + MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY +}; #else - enum DOW_T {DOW_IGNORE = -1, - SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY}; +enum DOW_T { DOW_IGNORE = -1, + SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY +}; #endif /* @@ -51,19 +53,19 @@ ** October 31. */ -extern unsigned DST_start_mo; -extern unsigned DST_start_dt; +extern unsigned DST_start_mo; +extern unsigned DST_start_dt; extern enum DOW_T DST_start_dy; -extern unsigned DST_stop_mo; -extern unsigned DST_stop_dt; +extern unsigned DST_stop_mo; +extern unsigned DST_stop_dt; extern enum DOW_T DST_stop_dy; -int isleap (unsigned yr); -long ymd_to_scalar (unsigned yr, unsigned mo, unsigned day); -void scalar_to_ymd (long scalar, unsigned *yr, unsigned *mo, unsigned *day); -int daynum(int year, int month, int day); -int weeknum(int year, int month, int day); +int isleap(unsigned yr); +long ymd_to_scalar(unsigned yr, unsigned mo, unsigned day); +void scalar_to_ymd(long scalar, unsigned *yr, unsigned *mo, unsigned *day); +int daynum(int year, int month, int day); +int weeknum(int year, int month, int day); int valiDate(unsigned yr, unsigned mo, unsigned day); @@ -76,8 +78,8 @@ extern char *MoonPhaseText[8]; unsigned moonphase(unsigned yr, unsigned mo, unsigned dy); -int getfdate (int handle, long *date); -int getdatef (char *fname, long *date); +int getfdate(int handle, long *date); +int getdatef(char *fname, long *date); -#endif /* SCALDATE__H */ +#endif /* SCALDATE__H */ diff --git a/scan.c b/scan.c index 125a005f..07eb4a3a 100644 --- a/scan.c +++ b/scan.c @@ -43,10 +43,11 @@ #include "stdscan.h" /*---------------------------------------------------------------------------*/ - static void DeleteCountEntry(void *pData) - { - free(pData); - } +static void DeleteCountEntry(void *pData) +{ + free(pData); +} + /*---------------------------------------------------------------------------*/ void InitCountEntry(pCountEntry pCount) { @@ -55,332 +56,319 @@ void InitCountEntry(pCountEntry pCount) pCount->lCount = -1L; pCount->i = -1; pCount->fTime = -1.0; - for(i = 0; i < 10; i++) - { + for (i = 0; i < 10; i++) { pCount->Monitors[i] = -1L; } } + /*--------------------------------------------------------------------------*/ - static int DummyWrite(pScanData self) - { - return 1; - } +static int DummyWrite(pScanData self) +{ + return 1; +} + /*--------------------------------------------------------------------------*/ - static int DummyWrite2(pScanData self, int iPoint) - { - return 1; - } +static int DummyWrite2(pScanData self, int iPoint) +{ + return 1; +} + /*---------------------------------------------------------------------------*/ - static void *ScanInterface(void *pData, int iInter) - { - pScanData self = NULL; - - self = (pScanData)pData; - assert(self); - - if(iInter == CALLBACKINTERFACE) - { - return self->pCall; - } - return NULL; - } +static void *ScanInterface(void *pData, int iInter) +{ + pScanData self = NULL; + + self = (pScanData) pData; + assert(self); + + if (iInter == CALLBACKINTERFACE) { + return self->pCall; + } + return NULL; +} + /*------------------------------------------------------------------------*/ static void ConfigureScanDict(pStringDict dict) { - StringDictAddPair(dict,"writeheader","stdscan writeheader"); - StringDictAddPair(dict,"prepare","stdscan prepare"); - StringDictAddPair(dict,"drive","stdscan drive"); - StringDictAddPair(dict,"count","stdscan count"); - StringDictAddPair(dict,"collect","stdscan collect"); - StringDictAddPair(dict,"writepoint","stdscan writepoint"); - StringDictAddPair(dict,"userdata","unknown"); - StringDictAddPair(dict,"finish","stdscan finish"); + StringDictAddPair(dict, "writeheader", "stdscan writeheader"); + StringDictAddPair(dict, "prepare", "stdscan prepare"); + StringDictAddPair(dict, "drive", "stdscan drive"); + StringDictAddPair(dict, "count", "stdscan count"); + StringDictAddPair(dict, "collect", "stdscan collect"); + StringDictAddPair(dict, "writepoint", "stdscan writepoint"); + StringDictAddPair(dict, "userdata", "unknown"); + StringDictAddPair(dict, "finish", "stdscan finish"); } -/*--------------------------------------------------------------------------*/ - pScanData CreateScanObject(char *pRecover, char *pHeader,pCounter pCount, - char *objName) - { - pScanData pNew = NULL; - - pNew = (pScanData)malloc(sizeof(ScanData)); - if(!pNew) - { - return NULL; - } - memset(pNew,0,sizeof(ScanData)); - - /* create an ObjectDescriptor */ - pNew->pDes = CreateDescriptor("ScanObject"); - if(!pNew->pDes) - { - free(pNew); - return NULL; - } - pNew->pDes->GetInterface = ScanInterface; - - /* allocate the dynamic arrays */ - pNew->pScanVar = CreateDynar(0,10,10,DeleteVarEntry); - pNew->pCounts = CreateDynar(0,10,10,DeleteCountEntry); - pNew->scanFunctions = CreateStringDict(); - if( (!pNew->pScanVar) || (!pNew->pCounts) || (!pNew->scanFunctions) ) - { - DeleteDescriptor(pNew->pDes); - free(pNew); - return NULL; - } - - /* make a callback interface */ - pNew->pCall = CreateCallBackInterface(); - if(!pNew->pCall) - { - DeleteScanObject(pNew); - return NULL; - } - - /* assign various things */ - if(pRecover) - { - strcpy(pNew->pRecover,pRecover); - } - if(pHeader) - { - strcpy(pNew->pHeaderFile,pHeader); - } - pNew->iMode = eTimer; - pNew->fPreset = 10.; - strcpy(pNew->pCounterName,pCount->name); - pNew->pCounterData = pCount; - pNew->PrepareScan = PrepareScan; - pNew->WriteHeader = WriteHeader; - pNew->WriteScanPoints = WriteScanPoints; - pNew->ScanDrive = ScanDrive; - pNew->ScanCount = ScanCount; - pNew->CollectScanData = CollectScanData; - pNew->iWindow = 6; - strncpy(pNew->objectName,objName, 131); - ConfigureScanDict(pNew->scanFunctions); - - return pNew; - } -/*---------------------------------------------------------------------------*/ - void DeleteScanObject(void *pData) - { - pScanData self = NULL; - - self = (pScanData)pData; - if(!self) - { - return; - } - if(self->pDes) - { - DeleteDescriptor(self->pDes); - } - if(self->pCall) - { - DeleteCallBackInterface(self->pCall); - } - if(self->pScanVar) - { - DeleteDynar(self->pScanVar); - } - if(self->pCounts) - { - DeleteDynar(self->pCounts); - } - if(self->pCommand) - { - free(self->pCommand); - } - if(self->scanFunctions) - { - DeleteStringDict(self->scanFunctions); - } - free(self); - } /*------------------------------------------------------------------------*/ - int ResetScanFunctions(pScanData self) - { - assert(self); +static void ResetScanDict(pStringDict dict) +{ + StringDictUpdate(dict, "writeheader", "stdscan writeheader"); + StringDictUpdate(dict, "prepare", "stdscan prepare"); + StringDictUpdate(dict, "drive", "stdscan drive"); + StringDictUpdate(dict, "count", "stdscan count"); + StringDictUpdate(dict, "collect", "stdscan collect"); + StringDictUpdate(dict, "writepoint", "stdscan writepoint"); + StringDictUpdate(dict, "userdata", "unknown"); + StringDictUpdate(dict, "finish", "stdscan finish"); +} - self->PrepareScan = PrepareScan; - self->WriteHeader = WriteHeader; - self->WriteScanPoints = WriteScanPoints; - self->ScanDrive = ScanDrive; - self->ScanCount = ScanCount; - self->CollectScanData = CollectScanData; - return 1; - } -/*-------------------------------------------------------------------------*/ - int AddScanVar(pScanData self, SicsInterp *pSics, SConnection *pCon, - char *name, float fStart, float fStep) - { - pVarEntry pVar = NULL; - - if(self->iActive) - { - SCWrite(pCon,"ERROR: cannot change parameters while scan is running", - eError); - return 0; - } - - pVar = MakeScanVar(pSics,pCon,name,fStart,fStep); - if(pVar == NULL) - { - return 0; - } - - /* put it away */ - DynarPut(self->pScanVar,self->iScanVar,pVar); - self->iScanVar++; - - return 1; - } -/*-------------------------------------------------------------------------*/ - int AddLogVar(pScanData self, SicsInterp *pSics, SConnection *pCon, - char *name) - { - pVarEntry pVar = NULL; - - if(self->iActive) - { - SCWrite(pCon,"ERROR: cannot change parameters while scan is running", - eError); - return 0; - } - - pVar = MakeLogVar(pSics,pCon,name); - if(pVar == NULL) - { - return 0; - } - - /* put it away */ - DynarPut(self->pScanVar,self->iScanVar,pVar); - self->iScanVar++; - - return 1; - } /*--------------------------------------------------------------------------*/ - int ClearScanVar(pScanData self) - { - if(self->iActive) - { - return 0; - } +pScanData CreateScanObject(char *pRecover, char *pHeader, pCounter pCount, + char *objName) +{ + pScanData pNew = NULL; - self->iScanVar = 0; - return 1; + pNew = (pScanData) malloc(sizeof(ScanData)); + if (!pNew) { + return NULL; } + memset(pNew, 0, sizeof(ScanData)); + + /* create an ObjectDescriptor */ + pNew->pDes = CreateDescriptor("ScanObject"); + if (!pNew->pDes) { + free(pNew); + return NULL; + } + pNew->pDes->GetInterface = ScanInterface; + + /* allocate the dynamic arrays */ + pNew->pScanVar = CreateDynar(0, 10, 10, DeleteVarEntry); + pNew->pCounts = CreateDynar(0, 10, 10, DeleteCountEntry); + pNew->scanFunctions = CreateStringDict(); + if ((!pNew->pScanVar) || (!pNew->pCounts) || (!pNew->scanFunctions)) { + DeleteDescriptor(pNew->pDes); + free(pNew); + return NULL; + } + + /* make a callback interface */ + pNew->pCall = CreateCallBackInterface(); + if (!pNew->pCall) { + DeleteScanObject(pNew); + return NULL; + } + + /* assign various things */ + if (pRecover) { + strlcpy(pNew->pRecover, pRecover,1024); + } + if (pHeader) { + strlcpy(pNew->pHeaderFile, pHeader,1024); + } + pNew->iMode = eTimer; + pNew->fPreset = 10.; + strlcpy(pNew->pCounterName, pCount->name,511); + pNew->pCounterData = pCount; + pNew->PrepareScan = PrepareScan; + pNew->WriteHeader = WriteHeader; + pNew->WriteScanPoints = WriteScanPoints; + pNew->ScanDrive = ScanDrive; + pNew->ScanCount = ScanCount; + pNew->CollectScanData = CollectScanData; + pNew->iWindow = 6; + strlcpy(pNew->objectName, objName, 131); + ConfigureScanDict(pNew->scanFunctions); + + return pNew; +} + +/*---------------------------------------------------------------------------*/ +void DeleteScanObject(void *pData) +{ + pScanData self = NULL; + + self = (pScanData) pData; + if (!self) { + return; + } + if (self->pDes) { + DeleteDescriptor(self->pDes); + } + if (self->pCall) { + DeleteCallBackInterface(self->pCall); + } + if (self->pScanVar) { + DeleteDynar(self->pScanVar); + } + if (self->pCounts) { + DeleteDynar(self->pCounts); + } + if (self->pCommand) { + free(self->pCommand); + } + if (self->scanFunctions) { + DeleteStringDict(self->scanFunctions); + } + free(self); +} + +/*------------------------------------------------------------------------*/ +int ResetScanFunctions(pScanData self) +{ + assert(self); + + self->PrepareScan = PrepareScan; + self->WriteHeader = WriteHeader; + self->WriteScanPoints = WriteScanPoints; + self->ScanDrive = ScanDrive; + self->ScanCount = ScanCount; + self->CollectScanData = CollectScanData; + return 1; +} + +/*-------------------------------------------------------------------------*/ +int AddScanVar(pScanData self, SicsInterp * pSics, SConnection * pCon, + char *name, float fStart, float fStep) +{ + pVarEntry pVar = NULL; + + if (self->iActive) { + SCWrite(pCon, "ERROR: cannot change parameters while scan is running", + eError); + return 0; + } + + pVar = MakeScanVar(pSics, pCon, name, fStart, fStep); + if (pVar == NULL) { + return 0; + } + + /* put it away */ + DynarPut(self->pScanVar, self->iScanVar, pVar); + self->iScanVar++; + + return 1; +} + +/*-------------------------------------------------------------------------*/ +int AddLogVar(pScanData self, SicsInterp * pSics, SConnection * pCon, + char *name) +{ + pVarEntry pVar = NULL; + + if (self->iActive) { + SCWrite(pCon, "ERROR: cannot change parameters while scan is running", + eError); + return 0; + } + + pVar = MakeLogVar(pSics, pCon, name); + if (pVar == NULL) { + return 0; + } + + /* put it away */ + DynarPut(self->pScanVar, self->iScanVar, pVar); + self->iScanVar++; + + return 1; +} + /*--------------------------------------------------------------------------*/ - static int WriteRecover(pScanData self) - { - FILE *fd; - pVarEntry pVar = NULL; - void *pData = NULL; - pCountEntry pCount = NULL; - int i, j, status; +int ClearScanVar(pScanData self) +{ + if (self->iActive) { + return 0; + } - fd = fopen(self->pRecover,"w"); - if(!fd) - { - return 0; - } - - fprintf(fd,"%s clear\n",self->objectName); + self->iScanVar = 0; + return 1; +} + +/*--------------------------------------------------------------------------*/ +static int WriteRecover(pScanData self) +{ + FILE *fd; + pVarEntry pVar = NULL; + void *pData = NULL; + pCountEntry pCount = NULL; + int i, j, status; + + fd = fopen(self->pRecover, "w"); + if (!fd) { + return 0; + } + + fprintf(fd, "%s clear\n", self->objectName); + + /* write scan vars */ + for (i = 0; i < self->iScanVar; i++) { + DynarGet(self->pScanVar, i, &pData); + pVar = (pVarEntry) pData; + if (pVar) { + if (isLogVar(pVar)) { + fprintf(fd, "%s log %s\n", self->objectName, ScanVarName(pVar)); + } else { + fprintf(fd, "%s add %s %f %f\n", self->objectName, + ScanVarName(pVar), ScanVarStart(pVar), ScanVarStep(pVar)); + } + } + pData = NULL; + } + for (i = 0; i < self->iScanVar; i++) { + DynarGet(self->pScanVar, i, &pData); + pVar = (pVarEntry) pData; + if (pVar) { + status = LLDnodePtr2First(pVar->dataList); + while (status != 0) { + fprintf(fd, "%s appendvarpos %d %f\n", self->objectName, + i, LLDnodeFloat(pVar->dataList)); + status = LLDnodePtr2Next(pVar->dataList); + } + } + pData = NULL; + } + + /* write counts */ + for (i = 0; i < self->iCounts; i++) { + DynarGet(self->pCounts, i, &pData); + pCount = (pCountEntry) pData; + if (pCount != NULL) { + fprintf(fd, + "%s storecounts %ld %f %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", + self->objectName, pCount->lCount, pCount->fTime, + pCount->Monitors[0], pCount->Monitors[1], + pCount->Monitors[2], pCount->Monitors[3], + pCount->Monitors[4], pCount->Monitors[5], + pCount->Monitors[6], pCount->Monitors[7], + pCount->Monitors[8], pCount->Monitors[9]); + } + } + if (self->iMode == eTimer) { + fprintf(fd, "%s continue %d timer %f\n", self->objectName, + self->iNP, self->fPreset); + } else { + fprintf(fd, "%s continue %d monitor %f\n", self->objectName, + self->iNP, self->fPreset); + } + fclose(fd); + return 1; +} - /* write scan vars */ - for(i = 0; i < self->iScanVar; i++) - { - DynarGet(self->pScanVar,i,&pData); - pVar = (pVarEntry)pData; - if(pVar) - { - if(isLogVar(pVar)) - { - fprintf(fd,"%s log %s\n", self->objectName, ScanVarName(pVar)); - } - else - { - fprintf(fd,"%s add %s %f %f\n", self->objectName, ScanVarName(pVar), - ScanVarStart(pVar), ScanVarStep(pVar)); - } - } - pData = NULL; - } - for(i = 0; i < self->iScanVar; i++) - { - DynarGet(self->pScanVar,i,&pData); - pVar = (pVarEntry)pData; - if(pVar) - { - status = LLDnodePtr2First(pVar->dataList); - while(status != 0) { - fprintf(fd,"%s appendvarpos %d %f\n",self->objectName, - i, LLDnodeFloat(pVar->dataList)); - status = LLDnodePtr2Next(pVar->dataList); - } - } - pData = NULL; - } - - /* write counts */ - for(i = 0; i < self->iCounts; i++) - { - DynarGet(self->pCounts,i,&pData); - pCount = (pCountEntry)pData; - if(pCount != NULL) - { - fprintf(fd,"%s storecounts %ld %f %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", - self->objectName, - pCount->lCount, - pCount->fTime, - pCount->Monitors[0], - pCount->Monitors[1], - pCount->Monitors[2], - pCount->Monitors[3], - pCount->Monitors[4], - pCount->Monitors[5], - pCount->Monitors[6], - pCount->Monitors[7], - pCount->Monitors[8], - pCount->Monitors[9]); - } - } - if(self->iMode == eTimer){ - fprintf(fd,"%s continue %d timer %f\n",self->objectName, - self->iNP,self->fPreset); - }else { - fprintf(fd,"%s continue %d monitor %f\n",self->objectName, - self->iNP,self->fPreset); - } - fclose(fd); - return 1; - } /*-------------------------------------------------------------------------*/ int AppendScanLine(pScanData self, char *line) { - /* reopen file */ - self->fd = fopen(self->pFile,"r+"); - if(!self->fd) - { - SCWrite(self->pCon, - "ERROR: Failed to reopen scan file, aborting scan", - eError); - return 0; - } - - /* jump to end of file */ - fseek(self->fd,0,SEEK_END); + /* reopen file */ + self->fd = fopen(self->pFile, "r+"); + if (!self->fd) { + SCWrite(self->pCon, + "ERROR: Failed to reopen scan file, aborting scan", eError); + return 0; + } - /* print */ - fprintf(self->fd,"%s\n",line); + /* jump to end of file */ + fseek(self->fd, 0, SEEK_END); - /* done */ - fclose(self->fd); - self->fd = NULL; - return 1; + /* print */ + fprintf(self->fd, "%s\n", line); + + /* done */ + fclose(self->fd); + self->fd = NULL; + return 1; } + /*-------------------------------------------------------------------------*/ extern char *stptok(const char *s, char *t, int len, char *brk); extern char *trim(char *txt); @@ -392,737 +380,673 @@ int StoreScanCounts(pScanData self, char *data) int iCount = 0; char pBueffel[256]; - if(data == NULL) - { - SCWrite(self->pCon,"WARNING: StoreScanCounts called without data", - eWarning); - return 1; + if (data == NULL) { + SCWrite(self->pCon, "WARNING: StoreScanCounts called without data", + eLog); + return 1; } InitCountEntry(&sCount); /* parse the data */ pPtr = trim(data); - pPtr = stptok(pPtr,pNumber,29," \t"); - if(pPtr != NULL) - { + pPtr = stptok(pPtr, pNumber, 29, " \t"); + if (pPtr != NULL) { sCount.lCount = atoi(pNumber); - } - else - { - SCWrite(self->pCon,"WARNING: No data in StoreScanCounts",eWarning); - snprintf(pBueffel,255,"Received: %s", data); - SCWrite(self->pCon,pBueffel,eWarning); + } else { + SCWrite(self->pCon, "WARNING: No data in StoreScanCounts", eLog); + snprintf(pBueffel, 255, "Received: %s", data); + SCWrite(self->pCon, pBueffel, eLog); return 1; } - pPtr = stptok(pPtr,pNumber,29," \t"); - if(pPtr != NULL) - { + pPtr = stptok(pPtr, pNumber, 29, " \t"); + if (pPtr != NULL) { sCount.fTime = atof(pNumber); - } - if(pPtr == NULL){ + } + if (pPtr == NULL) { return 1; } - while((pPtr = stptok(pPtr,pNumber,29," \t")) != NULL) - { + while ((pPtr = stptok(pPtr, pNumber, 29, " \t")) != NULL) { sCount.Monitors[iCount] = atoi(pNumber); iCount++; - if(iCount >= 10) - { + if (iCount >= 10) { SCWrite(self->pCon, - "ERROR: I have only space for 10 Monitors in count structure", - eError); + "ERROR: I have only space for 10 Monitors in count structure", + eLogError); return 0; } - } + } sCount.i = self->iCounts; - DynarReplace(self->pCounts,self->iCounts,&sCount,sizeof(CountEntry)); + DynarReplace(self->pCounts, self->iCounts, &sCount, sizeof(CountEntry)); self->iCounts++; - if(self->iCounts > self->iNP){ + if (self->iCounts > self->iNP) { self->iNP++; } return 1; } + /*-----------------------------------------------------------------------*/ CountEntry CollectCounterData(pScanData self) { int i, iRet; CountEntry sCount; - char *pAns = NULL, *pPtr = NULL ; + char *pAns = NULL, *pPtr = NULL; Tcl_Interp *pTcl; float fVal; InitCountEntry(&sCount); /* monitors */ - for(i = 1; i < 10; i++) - { - sCount.Monitors[i-1] = GetMonitor((pCounter)self->pCounterData,i, + for (i = 1; i < 10; i++) { + sCount.Monitors[i - 1] = GetMonitor((pCounter) self->pCounterData, i, self->pCon); } - if( self->iChannel != 0 && self->iChannel != -10 ) - { - sCount.Monitors[self->iChannel - 1] = - GetCounts((pCounter)self->pCounterData, - self->pCon); + if (self->iChannel != 0 && self->iChannel != -10) { + sCount.Monitors[self->iChannel - 1] = + GetCounts((pCounter) self->pCounterData, self->pCon); } /* counts, depending on iChannel */ - if(self->iChannel == -10) - { + if (self->iChannel == -10) { /* execute the Tcl-script for getting the data */ pTcl = InterpGetTcl(self->pSics); - if(!self->pCommand) - { + if (!self->pCommand) { SCWrite(self->pCon, - "ERROR: command must be configured for user defined scans", - eError); - SCSetInterrupt(self->pCon,eAbortBatch); + "ERROR: command must be configured for user defined scans", + eError); + SCSetInterrupt(self->pCon, eAbortBatch); return sCount; } - iRet = Tcl_Eval(pTcl,self->pCommand); - if(iRet != TCL_OK) - { - SCWrite(self->pCon,pTcl->result,eError); + iRet = Tcl_Eval(pTcl, self->pCommand); + if (iRet != TCL_OK) { + SCWrite(self->pCon, pTcl->result, eLogError); return sCount; - } + } /* interprete the Tcl result as a list of counts WARNING: this may need to be changed when switching to future versions of Tcl - */ + */ pAns = strdup(pTcl->result); - pPtr = strtok(pAns," "); - if(!pPtr) - { - SCWrite(self->pCon,"ERROR: no counts found in Tcl-result",eError); - } - sscanf(pPtr,"%f",&fVal); - sCount.lCount = (long)fVal; + pPtr = strtok(pAns, " "); + if (!pPtr) { + SCWrite(self->pCon, "ERROR: no counts found in Tcl-result", + eLogError); + } + sscanf(pPtr, "%f", &fVal); + sCount.lCount = (long) fVal; i = 0; - while( (pPtr != NULL) && (i < 10)) - { - pPtr = strtok(NULL," "); - if(pPtr) - { - sscanf(pPtr,"%f",&fVal); - sCount.Monitors[i] = (long)fVal; - i++; + while ((pPtr != NULL) && (i < 10)) { + pPtr = strtok(NULL, " "); + if (pPtr) { + sscanf(pPtr, "%f", &fVal); + sCount.Monitors[i] = (long) fVal; + i++; } - } + } free(pAns); + } else if (self->iChannel == 0) { + sCount.lCount = GetCounts((pCounter) self->pCounterData, self->pCon); + } else { + sCount.lCount = GetMonitor((pCounter) self->pCounterData, + self->iChannel, self->pCon); } - else if(self->iChannel == 0) - { - sCount.lCount = GetCounts((pCounter)self->pCounterData,self->pCon); - } - else - { - sCount.lCount = GetMonitor((pCounter)self->pCounterData, - self->iChannel, self->pCon); - } - + /* get time */ - sCount.fTime = GetCountTime((pCounter)self->pCounterData, - self->pCon); + sCount.fTime = GetCountTime((pCounter) self->pCounterData, self->pCon); /* stow away */ - DynarReplace(self->pCounts,self->iCounts,&sCount,sizeof(CountEntry)); + DynarReplace(self->pCounts, self->iCounts, &sCount, sizeof(CountEntry)); self->iCounts++; - if(self->iCounts > self->iNP){ + if (self->iCounts > self->iNP) { self->iNP++; } return sCount; } + /*---------------------------------------------------------------------------*/ - static int ScanLoop(pScanData self) - { - int i,iInt,iRet,iStatus; - - assert(self); - assert(self->pCon); - - InvokeCallBack(self->pCall,SCANSTART,self); - for(i = self->iCounts; i < self->iNP; i++) - { +static int ScanLoop(pScanData self) +{ + int i, iInt, iRet, iStatus, iHeaderWritten = 0; + + + assert(self); + assert(self->pCon); + + InvokeCallBack(self->pCall, SCANSTART, self); + for (i = self->iCounts; i < self->iNP; i++) { /*--------- drive */ - iRet = self->ScanDrive(self,i); - /* finished, check for interrupts. Whatever happened, user - interrupt or HW interrupt, it will be on our connection - */ - iInt = SCGetInterrupt(self->pCon); - switch(iInt) - { - case eContinue: - break; - case eAbortOperation: - SCSetInterrupt(self->pCon,eContinue); - SCWrite(self->pCon, - "WARNING: skipped scan point due to motor failure", - eWarning); - continue; - break; - case eAbortScan: - SCWrite(self->pCon,"ERROR: Scan aborted",eError); - /* eat the interrupt, the requested op has been - done - */ - SCSetInterrupt(self->pCon,eContinue); - return 0; - break; - default: /* all others */ - SCWrite(self->pCon,"ERROR: Scan aborted",eError); - return 0; - break; - } - if(!iRet) - { - SCWrite(self->pCon,"WARNING: skipped scan point after drive failure", - eWarning); - continue; - } + iRet = self->ScanDrive(self, i); + /* finished, check for interrupts. Whatever happened, user + interrupt or HW interrupt, it will be on our connection + */ + iInt = SCGetInterrupt(self->pCon); + switch (iInt) { + case eContinue: + break; + case eAbortOperation: + SCSetInterrupt(self->pCon, eContinue); + SCWrite(self->pCon, + "WARNING: skipped scan point due to motor failure", eLog); + continue; + break; + case eAbortScan: + SCWrite(self->pCon, "ERROR: Scan aborted", eLogError); + /* eat the interrupt, the requested op has been + done + */ + SCSetInterrupt(self->pCon, eContinue); + return 0; + break; + default: /* all others */ + SCWrite(self->pCon, "ERROR: Scan aborted", eLogError); + return 0; + break; + } + if (!iRet) { + SCWrite(self->pCon, + "WARNING: skipped scan point after drive failure", eLog); + continue; + } + + if(iHeaderWritten == 0) { + iRet = self->WriteHeader(self); + iHeaderWritten++; + if (!iRet) { + SCWrite(self->pCon, "ERROR: cannot open data file, Scan aborted", + eError); + self->pCon = NULL; + self->pSics = NULL; + return 0; + } + } /*-------------- count */ - iRet = self->ScanCount(self, i); - /* finished, check for interrupts. Whatever happened, user - interrupt or HW interrupt, it will be on our connection - */ - iInt = SCGetInterrupt(self->pCon); - switch(iInt) - { - case eContinue: - break; - case eAbortOperation: - continue; - break; - case eAbortScan: - SCWrite(self->pCon,"ERROR: Scan aborted",eError); - /* eat the interrupt, the requested op has been - done - */ - SCSetInterrupt(self->pCon,eContinue); - return 0; - break; - default: /* all others */ - SCWrite(self->pCon,"ERROR: Scan aborted",eError); - return 0; - break; - } - if(!iRet) - { - SCWrite(self->pCon,"WARNING: skipped scan point after count failure", - eWarning); - continue; - } - + iRet = self->ScanCount(self, i); + /* finished, check for interrupts. Whatever happened, user + interrupt or HW interrupt, it will be on our connection + */ + iInt = SCGetInterrupt(self->pCon); + switch (iInt) { + case eContinue: + break; + case eAbortOperation: + continue; + break; + case eAbortScan: + SCWrite(self->pCon, "ERROR: Scan aborted", eLogError); + /* eat the interrupt, the requested op has been + done + */ + SCSetInterrupt(self->pCon, eContinue); + return 0; + break; + default: /* all others */ + SCWrite(self->pCon, "ERROR: Scan aborted", eLogError); + return 0; + break; + } + if (!iRet) { + SCWrite(self->pCon, + "WARNING: skipped scan point after count failure", eLog); + continue; + } + /*-------- scan post processing */ - self->CollectScanData(self,i); - InvokeCallBack(self->pCall,SCANPOINT,self); + self->CollectScanData(self, i); + InvokeCallBack(self->pCall, SCANPOINT, self); - self->WriteScanPoints(self,i); - if(self->pRecover) - { - WriteRecover(self); - } - } - return 1; + self->WriteScanPoints(self, i); + if (self->pRecover) { + WriteRecover(self); + } } + return 1; +} + /*--------------------------------------------------------------------------*/ - int DoScan(pScanData self, int iNP, int iMode, float fPreset, - SicsInterp *pSics, SConnection *pCon) - { - int iRet; - char *pPtr = NULL; - char pBueffel[1024]; - - assert(self); - assert(pCon); - assert(pSics); - - self->pCon = pCon; - self->pSics = pSics; - - /* check arguments */ - if(iNP <= 0) - { - SCWrite(self->pCon,"ERROR: iNP < 0, nothing to do, Scan aborted",eError); - self->pCon = NULL; - self->pSics = NULL; - return 0; - } - if(self->iScanVar <= 0) - { - SCWrite(self->pCon,"WARNING: no scan variables given",eWarning); - } - - if( (iMode != eTimer) && (iMode != ePreset)) - { - SCWrite(self->pCon,"ERROR: Invalid counter mode given",eError); - self->pCon = NULL; - self->pSics = NULL; - return 0; - } - if(self->iActive != 0) - { - SCWrite(pCon,"ERROR: another scan is still running",eError); - self->pCon = NULL; - self->pSics = NULL; - return 0; - } +int DoScan(pScanData self, int iNP, int iMode, float fPreset, + SicsInterp * pSics, SConnection * pCon) +{ + int iRet; + char *pPtr = NULL; + char pBueffel[1024]; - self->iNP = iNP; - self->iMode = iMode; - self->fPreset = fPreset; - - /* do some preprocessing */ - if(self->PrepareScan != NULL) - { - iRet = self->PrepareScan(self); - } - else - { - iRet = 1; - } - if(!iRet) - { - self->pCon = NULL; - self->pSics = NULL; - return 0; - } - + assert(self); + assert(pCon); + assert(pSics); - iRet = self->WriteHeader(self); - if(!iRet) - { - SCWrite(self->pCon,"ERROR: cannot open data file, Scan aborted", - eError); - self->pCon = NULL; - self->pSics = NULL; - return 0; - } + self->pCon = pCon; + self->pSics = pSics; + + /* check arguments */ + if (iNP <= 0) { + SCWrite(self->pCon, "ERROR: iNP < 0, nothing to do, Scan aborted", + eError); + self->pCon = NULL; + self->pSics = NULL; + return 0; + } + if (self->iScanVar <= 0) { + SCWrite(self->pCon, "WARNING: no scan variables given", eWarning); + } + + if ((iMode != eTimer) && (iMode != ePreset)) { + SCWrite(self->pCon, "ERROR: Invalid counter mode given", eError); + self->pCon = NULL; + self->pSics = NULL; + return 0; + } + if (self->iActive != 0) { + SCWrite(pCon, "ERROR: another scan is still running", eError); + self->pCon = NULL; + self->pSics = NULL; + return 0; + } + + self->iNP = iNP; + self->iMode = iMode; + self->fPreset = fPreset; + + /* do some preprocessing */ + if (self->PrepareScan != NULL) { + iRet = self->PrepareScan(self); + } else { + iRet = 1; + } + if (!iRet) { + self->pCon = NULL; + self->pSics = NULL; + return 0; + } + + + self->iActive = 1; + iRet = ScanLoop(self); + ScriptScanFinish(self); + InvokeCallBack(self->pCall, SCANEND, self); + SendQuieck(QUIECK, self->pFile); + self->iActive = 0; + self->pCon = NULL; + self->pSics = NULL; + return iRet; +} - self->iActive = 1; - iRet = ScanLoop(self); - ScriptScanFinish(self); - InvokeCallBack(self->pCall,SCANEND,self); - SendQuieck(QUIECK,self->pFile); - self->iActive = 0; - self->pCon = NULL; - self->pSics = NULL; - return iRet; - } /*---------------------------------------------------------------------------- SilentScan does a scan which does not produce a data file. It is intended for internal use. Only status messages appear on screen. ----------------------------------------------------------------------------*/ - int SilentScan(pScanData self, int iNP, int iMode, float fPreset, - SicsInterp *pSics, SConnection *pCon) - { - int iRet; - char *pPtr = NULL; - char pBueffel[1024]; - int (*HeaderFunc)(pScanData self), (*ScanFunc)(pScanData self, - int iPoint); - - assert(self); - assert(pCon); - assert(pSics); - - /* check arguments */ - if(iNP <= 0) - { - SCWrite(self->pCon,"ERROR: iNP < 0, nothing to do, Scan aborted",eError); - return 0; - } - if(self->iScanVar <= 0) - { - SCWrite(self->pCon,"WARNING: no scan variables given",eWarning); - } - - if( (iMode != eTimer) && (iMode != ePreset)) - { - SCWrite(self->pCon,"ERROR: Invalid counter mode given",eError); - return 0; - } - if(self->iActive != 0) - { - SCWrite(pCon,"ERROR: another scan is still running",eError); - self->pCon = NULL; - self->pSics = NULL; - return 0; - } +---------------------------------------------------------------------------*/ +int SilentScan(pScanData self, int iNP, int iMode, float fPreset, + SicsInterp * pSics, SConnection * pCon) +{ + int iRet; + char *pPtr = NULL; + char pBueffel[1024]; + int (*HeaderFunc) (pScanData self), (*ScanFunc) (pScanData self, + int iPoint); + + assert(self); + assert(pCon); + assert(pSics); + + /* check arguments */ + if (iNP <= 0) { + SCWrite(self->pCon, "ERROR: iNP < 0, nothing to do, Scan aborted", + eError); + return 0; + } + if (self->iScanVar <= 0) { + SCWrite(self->pCon, "WARNING: no scan variables given", eWarning); + } + + if ((iMode != eTimer) && (iMode != ePreset)) { + SCWrite(self->pCon, "ERROR: Invalid counter mode given", eError); + return 0; + } + if (self->iActive != 0) { + SCWrite(pCon, "ERROR: another scan is still running", eError); + self->pCon = NULL; + self->pSics = NULL; + return 0; + } + + HeaderFunc = self->WriteHeader; + self->WriteHeader = DummyWrite; + ScanFunc = self->WriteScanPoints; + self->WriteScanPoints = DummyWrite2; + self->pCon = pCon; + self->pSics = pSics; + self->iNP = iNP; + self->iMode = iMode; + self->fPreset = fPreset; + + /* do some preprocessing */ + iRet = SilentPrepare(self); + if (!iRet) { + self->WriteHeader = HeaderFunc; + self->WriteScanPoints = ScanFunc; + self->pCon = NULL; + self->pSics = NULL; + return 0; + } + + self->iActive = 1; + iRet = ScanLoop(self); + self->iActive = 0; + self->pCon = NULL; + self->pSics = NULL; + self->WriteHeader = HeaderFunc; + self->WriteScanPoints = ScanFunc; + + return iRet; +} - HeaderFunc = self->WriteHeader; - self->WriteHeader = DummyWrite; - ScanFunc = self->WriteScanPoints; - self->WriteScanPoints = DummyWrite2; - self->pCon = pCon; - self->pSics = pSics; - self->iNP = iNP; - self->iMode = iMode; - self->fPreset = fPreset; - - /* do some preprocessing */ - iRet = SilentPrepare(self); - if(!iRet) - { - self->WriteHeader = HeaderFunc; - self->WriteScanPoints = ScanFunc; - self->pCon = NULL; - self->pSics = NULL; - return 0; - } - - self->iActive = 1; - iRet = ScanLoop(self); - self->iActive = 0; - self->pCon = NULL; - self->pSics = NULL; - self->WriteHeader = HeaderFunc; - self->WriteScanPoints = ScanFunc; - - return iRet; - } /*--------------------------------------------------------------------------*/ - int ContinueScan(pScanData self, SicsInterp *pSics, SConnection *pCon, - int argc, char *argv[]) - { - int iRet; - char *pPtr = NULL, pBueffel[512]; - double dVal; - - assert(pSics); - assert(pCon); - - self->pCon = pCon; - self->pSics = pSics; - - if(argc < 5) - { - SCWrite(pCon,"ERROR: not enough arguments to scan continue",eError); - return 0; - } +int ContinueScan(pScanData self, SicsInterp * pSics, SConnection * pCon, + int argc, char *argv[]) +{ + int iRet; + char *pPtr = NULL, pBueffel[512]; + double dVal; - /* get NP */ - iRet = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&self->iNP); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - /* interpret Mode */ - if(strcmp(argv[3],"timer") == 0) - { - self->iMode = eTimer; - } - else if(strcmp(argv[3],"monitor") == 0) - { - self->iMode = ePreset; - } - else - { - sprintf(pBueffel,"ERROR: %s not recognized as valid counter mode", - argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - /* preset */ - iRet = Tcl_GetDouble(InterpGetTcl(pSics),argv[4],&dVal); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - self->fPreset = dVal; - - /* configure counter */ - SetCounterMode((pCounter)self->pCounterData,self->iMode); - SetCounterPreset((pCounter)self->pCounterData, self->fPreset); - + assert(pSics); + assert(pCon); - /* new scan data file */ - pPtr = ScanMakeFileName(self->pSics,self->pCon); - if(!pPtr) - { - SCWrite(self->pCon,"ERROR: cannot allocate new data filename, Scan aborted", - eError); - self->pCon = NULL; - self->pSics = NULL; - return 0; - } - sprintf(pBueffel,"Writing data file: %s ...",pPtr); - SCWrite(self->pCon,pBueffel,eWarning); - strcpy(self->pFile,pPtr); - free(pPtr); - iRet = self->WriteHeader(self); - if(!iRet) - { - SCWrite(self->pCon,"ERROR: cannot open data file, Scan aborted", - eError); - self->pCon = NULL; - self->pSics = NULL; - return 0; - } + self->pCon = pCon; + self->pSics = pSics; + + if (argc < 5) { + SCWrite(pCon, "ERROR: not enough arguments to scan continue", eError); + return 0; + } + + /* get NP */ + iRet = Tcl_GetInt(InterpGetTcl(pSics), argv[2], &self->iNP); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[3]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + /* interpret Mode */ + if (strcmp(argv[3], "timer") == 0) { + self->iMode = eTimer; + } else if (strcmp(argv[3], "monitor") == 0) { + self->iMode = ePreset; + } else { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s not recognized as valid counter mode", + argv[3]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + /* preset */ + iRet = Tcl_GetDouble(InterpGetTcl(pSics), argv[4], &dVal); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[3]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + self->fPreset = dVal; + + /* configure counter */ + SetCounterMode((pCounter) self->pCounterData, self->iMode); + SetCounterPreset((pCounter) self->pCounterData, self->fPreset); + + + /* new scan data file */ + pPtr = ScanMakeFileName(self->pSics, self->pCon); + if (!pPtr) { + SCWrite(self->pCon, + "ERROR: cannot allocate new data filename, Scan aborted", + eError); + self->pCon = NULL; + self->pSics = NULL; + return 0; + } + snprintf(pBueffel,sizeof(pBueffel)-1, "Writing data file: %s ...", pPtr); + SCWrite(self->pCon, pBueffel, eWarning); + strlcpy(self->pFile, pPtr,1023); + free(pPtr); + iRet = self->WriteHeader(self); + if (!iRet) { + SCWrite(self->pCon, "ERROR: cannot open data file, Scan aborted", + eError); + self->pCon = NULL; + self->pSics = NULL; + return 0; + } + + self->iActive = 1; + iRet = ScanLoop(self); + ScriptScanFinish(self); + InvokeCallBack(self->pCall, SCANEND, self); + SendQuieck(QUIECK, self->pFile); + self->iActive = 0; + self->pCon = NULL; + self->pSics = NULL; + return iRet; + +} - self->iActive = 1; - iRet = ScanLoop(self); - ScriptScanFinish(self); - InvokeCallBack(self->pCall,SCANEND,self); - SendQuieck(QUIECK,self->pFile); - self->iActive = 0; - self->pCon = NULL; - self->pSics = NULL; - return iRet; - - } /*--------------------------------------------------------------------------*/ - int GetScanNP(pScanData self) - { - assert(self); - return self->iNP; - } -/*--------------------------------------------------------------------------*/ - float GetScanPreset(pScanData self) - { - assert(self); - return self->fPreset; - } -/*--------------------------------------------------------------------------*/ - int GetScanCounts(pScanData self,long *lData, int iDataLen) - { - int i, iEnd; - pCountEntry pData = NULL; - void *pPtr = NULL; - - assert(self); - /* hanlde iEnd */ - if(self->iCounts < iDataLen) - { - iEnd = self->iCounts; - } - else - { - iEnd = iDataLen; - } - - /* initialise to 0 */ - memset(lData,0,iDataLen*sizeof(long)); - - /* the loop */ - for(i = 0; i < iEnd; i++) - { - DynarGet(self->pCounts,i,&pPtr); - pData = (pCountEntry)pPtr; - if(pData) - { - lData[i] = pData->lCount; - } - pData = NULL; - } - - return 1; - } -/*--------------------------------------------------------------------------*/ - int GetScanMonitor(pScanData self,int iWhich,long *lData, int iDataLen) - { - int i, iEnd; - pCountEntry pData = NULL; - void *pPtr = NULL; - - assert(self); +int GetScanNP(pScanData self) +{ + assert(self); + return self->iNP; +} - /* hanlde iEnd */ - if(self->iCounts < iDataLen) - { - iEnd = self->iCounts; - } - else - { - iEnd = iDataLen; - } - - /* initialise to 0 */ - memset(lData,0,iDataLen*sizeof(long)); - - /* the loop */ - for(i = 0; i < iEnd; i++) - { - DynarGet(self->pCounts,i,&pPtr); - pData = (pCountEntry)pPtr; - if(pData) - { - lData[i] = pData->Monitors[iWhich]; - } - pData = NULL; - } - - return 1; - } /*--------------------------------------------------------------------------*/ - int GetScanVar(pScanData self, int iWhich, float *fData, int iDataLen) - { - int iEnd, i; - pVarEntry pVar = NULL; - void *pPtr = NULL; - - /* does it exist ?*/ - if( (iWhich < 0) || (iWhich >= self->iScanVar) ) - { - return 0; +float GetScanPreset(pScanData self) +{ + assert(self); + return self->fPreset; +} + +/*--------------------------------------------------------------------------*/ +int GetScanCounts(pScanData self, long *lData, int iDataLen) +{ + int i, iEnd; + pCountEntry pData = NULL; + void *pPtr = NULL; + + assert(self); + /* hanlde iEnd */ + if (self->iCounts < iDataLen) { + iEnd = self->iCounts; + } else { + iEnd = iDataLen; + } + + /* initialise to 0 */ + memset(lData, 0, iDataLen * sizeof(long)); + + /* the loop */ + for (i = 0; i < iEnd; i++) { + DynarGet(self->pCounts, i, &pPtr); + pData = (pCountEntry) pPtr; + if (pData) { + lData[i] = pData->lCount; } + pData = NULL; + } - /* handle iEnd */ - if(self->iCounts < iDataLen) - { - iEnd = self->iCounts; - } - else - { - iEnd = iDataLen; - } + return 1; +} - DynarGet(self->pScanVar,iWhich,&pPtr); - pVar = (pVarEntry)pPtr; - if(pVar) - { - /* initialise to theoretical values */ - for(i = 0; i < self->iNP; i++) - { - fData[i] = pVar->fStart + i * pVar->fStep; - } - CopyScanVar(pVar,fData, self->iNP); - return 1; - } - else - { - return 0; - } - - /* not reached */ - assert(0); - } /*--------------------------------------------------------------------------*/ - int GetSoftScanVar(pScanData self, int iWhich, float *fData, int iDataLen) - { - int iEnd, i; - pVarEntry pVar = NULL; - void *pPtr = NULL; - - /* does it exist ?*/ - if( (iWhich < 0) || (iWhich >= self->iScanVar) ) - { - return 0; +int GetScanMonitor(pScanData self, int iWhich, long *lData, int iDataLen) +{ + int i, iEnd; + pCountEntry pData = NULL; + void *pPtr = NULL; + + assert(self); + + /* hanlde iEnd */ + if (self->iCounts < iDataLen) { + iEnd = self->iCounts; + } else { + iEnd = iDataLen; + } + + /* initialise to 0 */ + memset(lData, 0, iDataLen * sizeof(long)); + + /* the loop */ + for (i = 0; i < iEnd; i++) { + DynarGet(self->pCounts, i, &pPtr); + pData = (pCountEntry) pPtr; + if (pData) { + lData[i] = pData->Monitors[iWhich]; } + pData = NULL; + } - /* handle iEnd */ - if(self->iCounts < iDataLen) - { - iEnd = self->iCounts; - } - else - { - iEnd = iDataLen; - } + return 1; +} + +/*--------------------------------------------------------------------------*/ +int GetScanVar(pScanData self, int iWhich, float *fData, int iDataLen) +{ + int iEnd, i; + pVarEntry pVar = NULL; + void *pPtr = NULL; + + /* does it exist ? */ + if ((iWhich < 0) || (iWhich >= self->iScanVar)) { + return 0; + } + + /* handle iEnd */ + if (self->iCounts < iDataLen) { + iEnd = self->iCounts; + } else { + iEnd = iDataLen; + } + + DynarGet(self->pScanVar, iWhich, &pPtr); + pVar = (pVarEntry) pPtr; + if (pVar) { + /* initialise to theoretical values */ + for (i = 0; i < self->iNP; i++) { + fData[i] = pVar->fStart + i * pVar->fStep; + } + CopyScanVar(pVar, fData, self->iNP); + return 1; + } else { + return 0; + } + + /* not reached */ + assert(0); +} + +/*--------------------------------------------------------------------------*/ +int GetSoftScanVar(pScanData self, int iWhich, float *fData, int iDataLen) +{ + int iEnd, i; + pVarEntry pVar = NULL; + void *pPtr = NULL; + + /* does it exist ? */ + if ((iWhich < 0) || (iWhich >= self->iScanVar)) { + return 0; + } + + /* handle iEnd */ + if (self->iCounts < iDataLen) { + iEnd = self->iCounts; + } else { + iEnd = iDataLen; + } + + DynarGet(self->pScanVar, iWhich, &pPtr); + pVar = (pVarEntry) pPtr; + if (pVar) { + /* initialise to theoretical values */ + for (i = 0; i < self->iNP; i++) { + fData[i] = pVar->fStart + i * pVar->fStep; + } + return 1; + } else { + return 0; + } + + /* not reached */ + assert(0); +} - DynarGet(self->pScanVar,iWhich,&pPtr); - pVar = (pVarEntry)pPtr; - if(pVar) - { - /* initialise to theoretical values */ - for(i = 0; i < self->iNP; i++) - { - fData[i] = pVar->fStart + i * pVar->fStep; - } - return 1; - } - else - { - return 0; - } - - /* not reached */ - assert(0); - } /*-------------------------------------------------------------------------*/ - int GetScanVarName(pScanData self, int iWhich, char *pName, int iLength) - { - pVarEntry pVar = NULL; - void *pPtr = NULL; - - /* does it exist ?*/ - if( (iWhich < 0) || (iWhich >= self->iScanVar) ) - { - return 0; - } +int GetScanVarName(pScanData self, int iWhich, char *pName, int iLength) +{ + pVarEntry pVar = NULL; + void *pPtr = NULL; + + /* does it exist ? */ + if ((iWhich < 0) || (iWhich >= self->iScanVar)) { + return 0; + } + + /* get the scan var */ + DynarGet(self->pScanVar, iWhich, &pPtr); + pVar = (pVarEntry) pPtr; + if (pVar) { + strlcpy(pName, ScanVarName(pVar), iLength); + return 1; + } else { + return 0; + } +} - /* get the scan var */ - DynarGet(self->pScanVar,iWhich,&pPtr); - pVar = (pVarEntry)pPtr; - if(pVar) - { - strncpy(pName,ScanVarName(pVar),iLength); - return 1; - } - else - { - return 0; - } - } /*---------------------------------------------------------------------*/ - int GetScanVarStep(pScanData self, int iWhich, float *fStep) - { - pVarEntry pVar = NULL; - void *pPtr = NULL; - - /* does it exist ?*/ - if( (iWhich < 0) || (iWhich >= self->iScanVar) ) - { - return 0; - } +int GetScanVarStep(pScanData self, int iWhich, float *fStep) +{ + pVarEntry pVar = NULL; + void *pPtr = NULL; + + /* does it exist ? */ + if ((iWhich < 0) || (iWhich >= self->iScanVar)) { + return 0; + } + + /* get the scan var */ + DynarGet(self->pScanVar, iWhich, &pPtr); + pVar = (pVarEntry) pPtr; + if (pVar) { + *fStep = ScanVarStep(pVar); + return 1; + } else { + return 0; + } +} - /* get the scan var */ - DynarGet(self->pScanVar,iWhich,&pPtr); - pVar = (pVarEntry)pPtr; - if(pVar) - { - *fStep = ScanVarStep(pVar); - return 1; - } - else - { - return 0; - } - } /*-------------------------------------------------------------------------- ScanIntegrate does an integration of the current scan data. It returns 1 on success or one of the integrate error codes defined in integrate.h -----------------------------------------------------------------------------*/ - int ScanIntegrate(pScanData self, float *fSum, float *fVar) - { - long *lData = NULL; - int iRet; - - assert(self); - - /* no integration if no peak measured */ - if(self->iCounts <= self->iWindow*2) - return INTEGNOPEAK; - - /* get some memory */ - lData = (long *)malloc(self->iNP*sizeof(long)); - if(!lData) - { - return INTEGNOPEAK; - } - /* get counts */ - GetScanCounts(self,lData,self->iNP); - /* Do it */ - iRet = GabePeakIntegrate(self->iWindow,self->iNP,lData, fSum, fVar); - free(lData); - return iRet; - } +int ScanIntegrate(pScanData self, float *fSum, float *fVar) +{ + long *lData = NULL; + int iRet; + + assert(self); + + /* no integration if no peak measured */ + if (self->iCounts <= self->iWindow * 2) + return INTEGNOPEAK; + + /* get some memory */ + lData = (long *) malloc(self->iNP * sizeof(long)); + if (!lData) { + return INTEGNOPEAK; + } + /* get counts */ + GetScanCounts(self, lData, self->iNP); + /* Do it */ + iRet = GabePeakIntegrate(self->iWindow, self->iNP, lData, fSum, fVar); + free(lData); + return iRet; +} + /*-------------------------------------------------------------------------- SimScan is a debugging aid for other modules. It simulates a scan on a variable in the range from 10 -20 degrees in angle and 100 points. Data @@ -1131,1314 +1055,1170 @@ CountEntry CollectCounterData(pScanData self) of 5 counts. The peak will sit on a background of 20 counts. This requires a motor a4 to exist as it will be used for x-axis simulation. This routine will not stop you from simulating shit if you throw shit at it! -----------------------------------------------------------------------------*/ - int SimScan(pScanData self, float fPos, float FWHM, float fHeight) - { - int i, iRet; - SConnection *pCon = NULL; - CountEntry sCount; - pVarEntry pVar = NULL; - void *pDings = NULL; - float x, y, fTmp, fStdDev; - - - assert(self); - - InitCountEntry(&sCount); +----------------------------------------------------------------------------*/ +int SimScan(pScanData self, float fPos, float FWHM, float fHeight) +{ + int i, iRet; + SConnection *pCon = NULL; + CountEntry sCount; + pVarEntry pVar = NULL; + void *pDings = NULL; + float x, y, fTmp, fStdDev; + + + assert(self); + + InitCountEntry(&sCount); + + /* go to a clean state */ + ClearScanVar(self); + + /* put in the scan variable */ + pCon = SCCreateDummyConnection(pServ->pSics); + if (!pCon) { + return 0; + } + iRet = AddScanVar(self, pServ->pSics, pCon, "a4", 10., 0.1); + SCDeleteConnection(pCon); + if (!iRet) { + return 0; + } + + /* do the x-axis of the scan */ + DynarGet(self->pScanVar, 0, &pDings); + pVar = (pVarEntry) pDings; + if (!pVar) { + return 0; + } + + + /* create scan data in loop */ + fStdDev = FWHM / 2.354; + for (i = 0; i < 90; i++) { + x = 10. + 0.1 * i; + AppendScanVar(pVar, x); + sCount.i = i; + /* gaussian */ + fTmp = (x - fPos) / fStdDev; + y = fHeight * 0.4 * exp(-0.5 * fTmp * fTmp); + /* randomize a little */ + y += 7. * (float) rand() / (float) RAND_MAX; + /* add a little background */ + sCount.lCount = (long) (10 + y); + /* stow away */ + DynarReplace(self->pCounts, i, &sCount, sizeof(CountEntry)); + } + self->iCounts = 90; + self->iNP = 90; + return 1; +} - /* go to a clean state */ - ClearScanVar(self); - - /* put in the scan variable */ - pCon = SCCreateDummyConnection(pServ->pSics); - if(!pCon) - { - return 0; - } - //iRet = AddScanVar(self,pServ->pSics,pCon,"a4",10., 0.1); - iRet = AddScanVar(self,pServ->pSics,pCon,"samx",10., 0.1); - SCDeleteConnection(pCon); - if(!iRet) - { - return 0; - } - - /* do the x-axis of the scan */ - DynarGet(self->pScanVar,0,&pDings); - pVar = (pVarEntry)pDings; - if(!pVar) - { - return 0; - } - - - /* create scan data in loop */ - fStdDev = FWHM/2.354; - for(i = 0; i < 90; i++) - { - x = 10. + 0.1 * i; - AppendScanVar(pVar,x); - sCount.i = i; - /* gaussian */ - fTmp = (x - fPos)/fStdDev; - y = fHeight*0.4* exp(-0.5*fTmp*fTmp); - /* randomize a little */ - y += 7. * (float)rand()/(float)RAND_MAX; - /* add a little background */ - sCount.lCount = (long)(10 + y); - /* stow away */ - DynarReplace(self->pCounts,i,&sCount,sizeof(CountEntry)); - } - self->iCounts = 90; - self->iNP = 90; - return 1; - } /*---------------------------------------------------------------------------*/ - int ScanFactory(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - pScanData pNew = NULL; - pCounter pCount = NULL; - pDummy pDum = NULL; - CommandList *pCom = NULL; - char pBueffel[512]; - int iRet; - - if(argc < 5) - { - SCWrite(pCon,"ERROR: Insufficient number of arguments to ScanFactory", - eError); - return 0; - } - - strtolower(argv[1]); - strtolower(argv[2]); - pCom = FindCommand(pSics,argv[2]); - if(!pCom) - { - sprintf(pBueffel,"ERROR: cannot find counter %s",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - pDum = (pDummy)pCom->pData; - if(!pDum) - { - sprintf(pBueffel,"ERROR: counter %s has no data",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - if(!(pDum->pDescriptor->GetInterface(pDum,COUNTID))) - { - sprintf(pBueffel,"ERROR: object %s is NO counter",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - pNew = CreateScanObject(argv[4],argv[3],(pCounter)pCom->pData, - argv[1]); - if(!pNew) - { - SCWrite(pCon,"ERROR: failure to allocate scan data structure", - eError); - return 0; - } - - iRet = AddCommand(pSics, - argv[1], - ScanWrapper, - DeleteScanObject, - pNew); - if(!iRet) - { - sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - /* - ignore this one, this is cheaper then checking for the existence - of another scan object - */ - AddCommand(pSics, - "stdscan", - StandardScanWrapper, - NULL, - NULL); - return 1; - } -/*--------------------------------------------------------------------------*/ - static int ScanInterest(int iEvent, void *pEventData, void *pUser, - commandContext cc) - { - pScanData self = NULL; - SConnection *pCon = NULL; - char *pPtr = NULL, pItem[20]; - long *lData = NULL; - int i; - writeFunc oldWrite; - - self = (pScanData)pEventData; - pCon = (SConnection *)pUser; - - assert(self); - assert(pCon); - - if(iEvent == SCANSTART) - { - SCWriteInContext(pCon,"NewScan",eWarning,cc); - return 1; - } - else if(iEvent == SCANEND) - { - SCWriteInContext(pCon,"ScanEnd",eWarning,cc); - return 1; - } - else if(iEvent == SCANPOINT) - { - /* allocate space */ - pPtr = (char *)malloc((self->iNP*20+20)*sizeof(char)); - if(!pPtr) - { - return 0; - } - memset(pPtr,0,(self->iNP*20+20)*sizeof(char)); - lData = (long *)malloc(self->iNP*sizeof(long)); - if(!lData) - { - return 0; - } - memset(lData,0,self->iNP*sizeof(long)); - - /* get counts */ - GetScanCounts(self,lData,self->iNP); - /* format a message */ - - strcpy(pPtr,"scan.Counts= {"); - for(i = 0; i < self->iNP; i++) - { - sprintf(pItem,"%ld ",lData[i]); - strcat(pPtr,pItem); - } - strcat(pPtr,"}"); - oldWrite = SCGetWriteFunc(pCon); - SCSetWriteFunc(pCon,SCOnlySockWrite); - SCWrite(pCon,pPtr,eWarning); - SCSetWriteFunc(pCon,oldWrite); - free(lData); - free(pPtr); - return 1; - } - return 1; - } -/*--------------------------------------------------------------------------*/ - static int ScanDynInterest(int iEvent, void *pEventData, void *pUser, - commandContext cc) - { - pScanData self = NULL; - SConnection *pCon = NULL; - void *pPtr; - pVarEntry pVar; - pCountEntry pCount = NULL; - float fVal; - long lVal; - int i; - char pBueffel[256]; +int ScanFactory(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pScanData pNew = NULL; + pCounter pCount = NULL; + pDummy pDum = NULL; + CommandList *pCom = NULL; + char pBueffel[512]; + int iRet; + + if (argc < 5) { + SCWrite(pCon, "ERROR: Insufficient number of arguments to ScanFactory", + eError); + return 0; + } + + strtolower(argv[1]); + strtolower(argv[2]); + pCom = FindCommand(pSics, argv[2]); + if (!pCom) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: cannot find counter %s", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + pDum = (pDummy) pCom->pData; + if (!pDum) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: counter %s has no data", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + if (!(pDum->pDescriptor->GetInterface(pDum, COUNTID))) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: object %s is NO counter", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + pNew = CreateScanObject(argv[4], argv[3], (pCounter) pCom->pData, + argv[1]); + if (!pNew) { + SCWrite(pCon, "ERROR: failure to allocate scan data structure", + eError); + return 0; + } + + iRet = AddCommand(pSics, argv[1], ScanWrapper, DeleteScanObject, pNew); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: duplicate command %s not created", argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + /* + ignore this one, this is cheaper then checking for the existence + of another scan object + */ + AddCommand(pSics, "stdscan", StandardScanWrapper, NULL, NULL); + return 1; +} - self = (pScanData)pEventData; - pCon = (SConnection *)pUser; - - assert(self); - assert(pCon); - - if(iEvent == SCANSTART) - { - SCWriteInContext(pCon,"NewScan",eWarning,cc); - return 1; - } - else if(iEvent == SCANEND) - { - SCWriteInContext(pCon,"ScanEnd",eWarning,cc); - return 1; - } - else if(iEvent == SCANPOINT) - { - i = self->iCounts -1; - DynarGet(self->pScanVar,0,&pPtr); - pVar = (pVarEntry)pPtr; - if(pVar != NULL){ - fVal = GetScanVarPos(pVar,i); - } else { - fVal = -9999.99; - } - DynarGet(self->pCounts,i,&pPtr); - pCount =(pCountEntry)pPtr; - if(pCount != NULL){ - lVal = pCount->lCount; - } else { - lVal = -9999.99; - } - snprintf(pBueffel,255,"%s.scanpoint = {%d %f %ld}", - self->objectName,i,fVal,lVal); - SCWriteInContext(pCon,pBueffel,eValue,cc); - } - return 1; - } /*--------------------------------------------------------------------------*/ - static int ScanUUInterest(int iEvent, void *pEventData, void *pUser, - commandContext cc) - { - pScanData self = NULL; - SConnection *pCon = NULL; - char pItem[20]; - long *lData = NULL; - int *iData = NULL; - int i; - - self = (pScanData)pEventData; - pCon = (SConnection *)pUser; - - assert(self); - assert(pCon); - - if(iEvent == SCANSTART) - { - SCWriteInContext(pCon,"NewScan",eWarning,cc); - return 1; - } - else if(iEvent == SCANEND) - { - SCWriteInContext(pCon,"ScanEnd",eWarning,cc); - return 1; - } - else if(iEvent == SCANPOINT) - { - /* allocate space */ - lData = (long *)malloc(self->iNP*sizeof(long)); - iData = (int *)malloc(self->iNP*sizeof(int)); - if(!lData || !iData) - { - return 0; - } - memset(lData,0,self->iNP*sizeof(long)); - memset(iData,0,self->iNP*sizeof(int)); - - /* get counts */ - GetScanCounts(self,lData,self->iNP); - /* put into network byte order */ - for(i = 0; i < self->iNP; i++) - { - iData[i] = htonl((int)lData[i]); - } - SCPushContext2(pCon,cc); - SCWriteUUencoded(pCon,"ScanData",iData,self->iNP*sizeof(int)); - SCPopContext(pCon); - free(lData); - free(iData); - return 1; - } - return 1; - } +static int ScanInterest(int iEvent, void *pEventData, void *pUser) +{ + pScanData self = NULL; + SConnection *pCon = NULL; + char *pPtr = NULL, pItem[20]; + long *lData = NULL; + int i; + writeFunc oldWrite; + + self = (pScanData) pEventData; + pCon = (SConnection *) pUser; + + assert(self); + assert(pCon); + + if (!SCisConnected(pCon)) { + return -1; + } + + if (iEvent == SCANSTART) { + SCWrite(pCon, "NewScan", eLog); + return 1; + } else if (iEvent == SCANEND) { + SCWrite(pCon, "ScanEnd", eLog); + return 1; + } else if (iEvent == SCANPOINT) { + /* allocate space */ + pPtr = (char *) malloc((self->iNP * 20 + 20) * sizeof(char)); + if (!pPtr) { + return 0; + } + memset(pPtr, 0, (self->iNP * 20 + 20) * sizeof(char)); + lData = (long *) malloc(self->iNP * sizeof(long)); + if (!lData) { + return 0; + } + memset(lData, 0, self->iNP * sizeof(long)); + + /* get counts */ + GetScanCounts(self, lData, self->iNP); + /* format a message */ + + strcpy(pPtr, "scan.Counts= {"); + for (i = 0; i < self->iNP; i++) { + snprintf(pItem,sizeof(pItem)-1, "%ld ", lData[i]); + strcat(pPtr, pItem); + } + strcat(pPtr, "}"); + oldWrite = SCGetWriteFunc(pCon); + SCSetWriteFunc(pCon, SCOnlySockWrite); + SCWrite(pCon, pPtr, eLog); + SCSetWriteFunc(pCon, oldWrite); + free(lData); + free(pPtr); + return 1; + } + return 1; +} + /*--------------------------------------------------------------------------*/ -static int GetVarPar(SConnection *pCon, pScanData self, char *scanname, int i) +static int ScanDynInterest(int iEvent, void *pEventData, void *pUser) +{ + pScanData self = NULL; + SConnection *pCon = NULL; + void *pPtr; + pVarEntry pVar; + pCountEntry pCount = NULL; + float fVal; + long lVal; + int i; + char pBueffel[256]; + + self = (pScanData) pEventData; + pCon = (SConnection *) pUser; + + assert(self); + assert(pCon); + + if (!SCisConnected(pCon)) { + return -1; + } + + if (iEvent == SCANSTART) { + SCWrite(pCon, "NewScan", eLog); + return 1; + } else if (iEvent == SCANEND) { + SCWrite(pCon, "ScanEnd", eLog); + return 1; + } else if (iEvent == SCANPOINT) { + i = self->iCounts - 1; + DynarGet(self->pScanVar, 0, &pPtr); + pVar = (pVarEntry) pPtr; + if (pVar != NULL) { + fVal = GetScanVarPos(pVar, i); + } else { + fVal = -9999.99; + } + DynarGet(self->pCounts, i, &pPtr); + pCount = (pCountEntry) pPtr; + if (pCount != NULL) { + lVal = pCount->lCount; + } else { + lVal = -9999.99; + } + snprintf(pBueffel, 255, "%s.scanpoint = {%d %f %ld}", + self->objectName, i, fVal, lVal); + SCWrite(pCon, pBueffel, eLog); + } + return 1; +} + +/*--------------------------------------------------------------------------*/ +static int ScanUUInterest(int iEvent, void *pEventData, void *pUser) +{ + pScanData self = NULL; + SConnection *pCon = NULL, *comCon = NULL; + char pItem[20]; + long *lData = NULL; + int *iData = NULL; + int i; + + self = (pScanData) pEventData; + pCon = (SConnection *) pUser; + + assert(self); + assert(pCon); + /* + printf("ScanUUInterest called for pCon = %p handle %d\n", pCon, pCon->sockHandle); + */ + if (!SCisConnected(pCon)) { + return -1; + } + + if (iEvent == SCANSTART) { + SCWrite(pCon, "NewScan", eLog); + return 1; + } else if (iEvent == SCANEND) { + SCWrite(pCon, "ScanEnd", eLog); + return 1; + } else if (iEvent == SCANPOINT) { + /* allocate space */ + lData = (long *) malloc(self->iNP * sizeof(long)); + iData = (int *) malloc(self->iNP * sizeof(int)); + if (!lData || !iData) { + return 0; + } + memset(lData, 0, self->iNP * sizeof(long)); + memset(iData, 0, self->iNP * sizeof(int)); + + /* get counts */ + GetScanCounts(self, lData, self->iNP); + /* put into network byte order */ + for (i = 0; i < self->iNP; i++) { + iData[i] = htonl((int) lData[i]); + } + SCWriteUUencoded(pCon, "ScanData", iData, self->iNP * sizeof(int)); + free(lData); + free(iData); + return 1; + } + return 1; +} + +/*--------------------------------------------------------------------------*/ +static int GetVarPar(SConnection * pCon, pScanData self, char *scanname, + int i) { char pBueffel[512]; void *pPtr = NULL; - pVarEntry pVar = NULL; + pVarEntry pVar = NULL; assert(pCon); assert(self); - if(i < 0 || i >= self->iScanVar) - { - SCWrite(pCon,"ERROR: scan variable number out of range",eError); + if (i < 0 || i >= self->iScanVar) { + SCWrite(pCon, "ERROR: scan variable number out of range", eError); return 0; } - DynarGet(self->pScanVar,i,&pPtr); - pVar = (pVarEntry)pPtr; - if(pVar != NULL) - { - snprintf(pBueffel, 511,"%s.%s = %f = %f", - scanname, - ScanVarName(pVar), - ScanVarStart(pVar), - ScanVarStep(pVar)); - SCWrite(pCon,pBueffel,eValue); + DynarGet(self->pScanVar, i, &pPtr); + pVar = (pVarEntry) pPtr; + if (pVar != NULL) { + snprintf(pBueffel, 511, "%s.%s = %f = %f", + scanname, + ScanVarName(pVar), ScanVarStart(pVar), ScanVarStep(pVar)); + SCWrite(pCon, pBueffel, eValue); return 1; } return 0; } + /*--------------------------------------------------------------------------*/ -static int AppendVarPos(SConnection *pCon, pScanData self, - int scanVar, float fPos) +static int AppendVarPos(SConnection * pCon, pScanData self, + int scanVar, float fPos) { char pBueffel[512]; void *pPtr = NULL; - pVarEntry pVar = NULL; + pVarEntry pVar = NULL; assert(pCon); assert(self); - if(scanVar < 0 || scanVar >= self->iScanVar) - { - SCWrite(pCon,"ERROR: scan variable number out of range",eError); + if (scanVar < 0 || scanVar >= self->iScanVar) { + SCWrite(pCon, "ERROR: scan variable number out of range", eError); return 0; } - DynarGet(self->pScanVar,scanVar,&pPtr); - pVar = (pVarEntry)pPtr; - if(pVar != NULL) - { - AppendScanVar(pVar,fPos); + DynarGet(self->pScanVar, scanVar, &pPtr); + pVar = (pVarEntry) pPtr; + if (pVar != NULL) { + AppendScanVar(pVar, fPos); return 1; } return 0; -} +} + /*--------------------------------------------------------------------------*/ -static void PrintScanVars(pScanData self, char *scanname, SConnection *pCon){ +static void PrintScanVars(pScanData self, char *scanname, + SConnection * pCon) +{ char pBueffel[1024]; pVarEntry pVar = NULL; - void *pPtr = NULL; + void *pPtr = NULL; int i; assert(pCon); assert(self); - snprintf(pBueffel,1023,"%s.scanvars = { ", scanname); - for(i = 0; i < self->iScanVar; i++){ - DynarGet(self->pScanVar,i,&pPtr); - pVar = (pVarEntry)pPtr; - if(pVar != NULL){ - strncat(pBueffel,ScanVarName(pVar),1023-strlen(pBueffel)); - strcat(pBueffel," "); + snprintf(pBueffel, sizeof pBueffel, "%s.scanvars = { ", scanname); + for (i = 0; i < self->iScanVar; i++) { + DynarGet(self->pScanVar, i, &pPtr); + pVar = (pVarEntry) pPtr; + if (pVar != NULL) { + strlcat(pBueffel, ScanVarName(pVar), sizeof pBueffel); + strlcat(pBueffel, " ", sizeof pBueffel); } } - strcat(pBueffel,"}"); - SCWrite(pCon,pBueffel,eValue); + strlcat(pBueffel, "}", sizeof pBueffel); + SCWrite(pCon, pBueffel, eValue); } + /*--------------------------------------------------------------------------*/ -static int PrintCountsOrMonitors(pScanData self, SConnection *pCon, - char *name, int iWhich) +static int PrintCountsOrMonitors(pScanData self, SConnection * pCon, + char *name, int iWhich) { pDynString data = NULL; long *lData = NULL; char pBueffel[60]; int i; - - if(self->iNP < 1) - { - SCWrite(pCon,"ERROR: no scan data available",eError); + + if (self->iNP < 1) { + SCWrite(pCon, "ERROR: no scan data available", eError); return 0; } - data = CreateDynString(80,80); - lData = (long *)malloc(self->iNP*sizeof(long)); - if(data == NULL || lData == NULL) - { - SCWrite(pCon,"ERROR: out of memory printing counts",eError); + data = CreateDynString(80, 80); + lData = (long *) malloc(self->iNP * sizeof(long)); + if (data == NULL || lData == NULL) { + SCWrite(pCon, "ERROR: out of memory printing counts", eError); return 0; } - memset(lData,0,self->iNP*sizeof(long)); - - if(iWhich < 0) - { - GetScanCounts(self,lData,self->iNP); - snprintf(pBueffel,59,"%s.Counts = {", name); - } - else - { - GetScanMonitor(self,iWhich,lData,self->iNP); - snprintf(pBueffel,59,"%s.mon%2.2d = {", name, iWhich); + memset(lData, 0, self->iNP * sizeof(long)); + + if (iWhich < 0) { + GetScanCounts(self, lData, self->iNP); + snprintf(pBueffel, 59, "%s.Counts = {", name); + } else { + GetScanMonitor(self, iWhich, lData, self->iNP); + snprintf(pBueffel, 59, "%s.mon%2.2d = {", name, iWhich); } - DynStringCopy(data,pBueffel); - for(i = 0; i < self->iNP; i++) - { - snprintf(pBueffel,59," %ld", lData[i]); - DynStringConcat(data,pBueffel); + DynStringCopy(data, pBueffel); + for (i = 0; i < self->iNP; i++) { + snprintf(pBueffel, 59, " %ld", lData[i]); + DynStringConcat(data, pBueffel); } - DynStringConcatChar(data,'}'); - SCWrite(pCon,GetCharArray(data),eValue); + DynStringConcatChar(data, '}'); + SCWrite(pCon, GetCharArray(data), eValue); DeleteDynString(data); free(lData); return 1; } + /*--------------------------------------------------------------------------*/ -static int PrintTimes(pScanData self, SConnection *pCon, - char *name) +static int PrintTimes(pScanData self, SConnection * pCon, char *name) { pDynString data = NULL; char pBueffel[60]; int i, iEnd; pCountEntry pData = NULL; void *pPtr = NULL; - - if(self->iNP < 1) - { - SCWrite(pCon,"ERROR: no scan data available",eError); + + if (self->iNP < 1) { + SCWrite(pCon, "ERROR: no scan data available", eError); return 0; } - data = CreateDynString(80,80); - if(data == NULL) - { - SCWrite(pCon,"ERROR: out of memory printing counts",eError); + data = CreateDynString(80, 80); + if (data == NULL) { + SCWrite(pCon, "ERROR: out of memory printing counts", eError); return 0; } - snprintf(pBueffel,59,"%s.scantimes = { ",name); - DynStringCopy(data,pBueffel); - for(i = 0; i < self->iCounts; i++) - { - DynarGet(self->pCounts,i,&pPtr); - pData = (pCountEntry)pPtr; - if(pData) - { - snprintf(pBueffel,59," %f", pData->fTime); - DynStringConcat(data,pBueffel); - } + snprintf(pBueffel, 59, "%s.scantimes = { ", name); + DynStringCopy(data, pBueffel); + for (i = 0; i < self->iCounts; i++) { + DynarGet(self->pCounts, i, &pPtr); + pData = (pCountEntry) pPtr; + if (pData) { + snprintf(pBueffel, 59, " %f", pData->fTime); + DynStringConcat(data, pBueffel); + } } - DynStringConcatChar(data,'}'); - SCWrite(pCon,GetCharArray(data),eValue); + DynStringConcatChar(data, '}'); + SCWrite(pCon, GetCharArray(data), eValue); DeleteDynString(data); return 1; } + /*------------------------------------------------------------------------*/ -static int ScanInvokeCallback(pScanData self, SConnection *pCon, char *name) +static int ScanInvokeCallback(pScanData self, SConnection * pCon, + char *name) { int eventID; - if(strcmp(name,"scanstart") == 0){ + if (strcmp(name, "scanstart") == 0) { eventID = SCANSTART; - }else if(strcmp(name,"scanpoint") == 0){ + } else if (strcmp(name, "scanpoint") == 0) { eventID = SCANPOINT; - }else if(strcmp(name,"scanend") == 0){ + } else if (strcmp(name, "scanend") == 0) { eventID = SCANEND; } else { - SCWrite(pCon,"ERROR: callback ID not recognised",eError); + SCWrite(pCon, "ERROR: callback ID not recognised", eError); return 0; } - InvokeCallBack(self->pCall,eventID, self); + InvokeCallBack(self->pCall, eventID, self); SCSendOK(pCon); return 1; } + /*-----------------------------------------------------------------------*/ -static void ListScanFunctions(pScanData self, SConnection *pCon){ +static void ListScanFunctions(pScanData self, SConnection * pCon) +{ pDynString result = NULL; char pValue[256], *pPtr = NULL; - result = CreateDynString(80,80); - if(result == NULL){ - SCWrite(pCon,"ERROR: failed to allocate memory in function list",eError); + result = CreateDynString(80, 80); + if (result == NULL) { + SCWrite(pCon, "ERROR: failed to allocate memory in function list", + eError); return; } - while( (pPtr = (char *)StringDictGetNext(self->scanFunctions, - pValue,255)) != NULL){ + while ((pPtr = (char *) StringDictGetNext(self->scanFunctions, + pValue, 255)) != NULL) { DynStringConcat(result, pPtr); - DynStringConcat(result," = "); + DynStringConcat(result, " = "); DynStringConcat(result, pValue); DynStringConcatChar(result, '\n'); } - SCWrite(pCon,GetCharArray(result), eValue); + SCWrite(pCon, GetCharArray(result), eValue); DeleteDynString(result); } + /*-------------------------------------------------------------------------*/ -static int InterpretScanFunctions(pScanData self, SConnection *pCon, - int argc, char *argv[]){ +static int InterpretScanFunctions(pScanData self, SConnection * pCon, + int argc, char *argv[]) +{ char pValue[256]; char response[512]; - if(argc < 3){ - SCWrite(pCon,"ERROR: need subcommand to scan function",eError); + if (argc < 3) { + SCWrite(pCon, "ERROR: need subcommand to scan function", eError); return 0; } strtolower(argv[2]); - if(strcmp(argv[2],"list") == 0){ - ListScanFunctions(self,pCon); + if (strcmp(argv[2], "list") == 0) { + ListScanFunctions(self, pCon); return 1; } - if(argc > 3){ + if (argc > 3) { /* - set case - */ - Arg2Text(argc-3,&argv[3],pValue,255); - if(!StringDictUpdate(self->scanFunctions,argv[2],pValue)){ - snprintf(pValue,255,"ERROR: scan function %s not found",argv[2]); - SCWrite(pCon,pValue,eError); + set case + */ + Arg2Text(argc - 3, &argv[3], pValue, 255); + if (!StringDictUpdate(self->scanFunctions, argv[2], pValue)) { + snprintf(pValue, 255, "ERROR: scan function %s not found", argv[2]); + SCWrite(pCon, pValue, eError); return 0; } } /* - request case - */ - if(StringDictGet(self->scanFunctions,argv[2],pValue,255)){ - snprintf(response,511,"%s function %s = %s",argv[0],argv[2], - pValue); - SCWrite(pCon,response,eValue); + request case + */ + if (StringDictGet(self->scanFunctions, argv[2], pValue, 255)) { + snprintf(response, 511, "%s function %s = %s", argv[0], argv[2], + pValue); + SCWrite(pCon, response, eValue); return 1; } else { - snprintf(pValue,255,"ERROR: scan function %s not found",argv[2]); - SCWrite(pCon,pValue,eError); + snprintf(pValue, 255, "ERROR: scan function %s not found", argv[2]); + SCWrite(pCon, pValue, eError); return 0; } return 0; } + /*--------------------------------------------------------------------------*/ -static int DumpScan(pScanData self, SConnection *pCon) +static int DumpScan(pScanData self, SConnection * pCon) { - int i; - SConnection *oldCon; - char pFile[1024]; - - if(self->iActive) - { - SCWrite(pCon,"ERROR: cannot dump scan while running",eError); - return 0; - } - if(!self->pSics) - { - self->pSics = pServ->pSics; - } - /* - * save old file etc status - */ - oldCon = self->pCon; - pFile[0] = '\0'; - strncpy(pFile,self->pFile,1023); - prepareDataFile(self); - self->pCon = pCon; - self->WriteHeader(self); - for(i = 0; i < self->iNP; i++) - { - self->WriteScanPoints(self,i); - } - SCWrite(pCon,"Scan dumped", eValue); - self->pCon = oldCon; - strncpy(self->pFile,pFile,1023); - return 1; -} + int i; + SConnection *oldCon; + char pFile[1024]; + + if (self->iActive) { + SCWrite(pCon, "ERROR: cannot dump scan while running", eError); + return 0; + } + if (!self->pSics) { + self->pSics = pServ->pSics; + } + /* + * save old file etc status + */ + oldCon = self->pCon; + pFile[0] = '\0'; + strlcpy(pFile, self->pFile, 1023); + prepareDataFile(self); + self->pCon = pCon; + self->WriteHeader(self); + for (i = 0; i < self->iNP; i++) { + self->WriteScanPoints(self, i); + } + SCWrite(pCon, "Scan dumped", eValue); + self->pCon = oldCon; + strlcpy(self->pFile, pFile, 1023); + return 1; +} + /*---------------------------------------------------------------------------*/ - int ScanWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - pScanData self = NULL; - char pBueffel[512], varname[512]; - double fStep, fStart, fPreset; - float *fData = NULL; - int lNP; - int iChannel; - int iRet, iMode,i, varnum; - char *pPtr = NULL, pItem[20]; - long *lData = NULL, lID; - int *iData; - void *pVarData = NULL; - pVarEntry pVar = NULL; - float fSum, fVar; - double x; - float fPos, FWHM, fHeight; - pSite site = NULL; - SConnection *conSave; - - self = (pScanData)pData; - assert(self); - - argtolower(argc,argv); - if(argc < 2) - { - sprintf(pBueffel,"ERROR: not enough arguments for %s",argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* - first interpret commands which do not require user rights - */ +int ScanWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pScanData self = NULL; + char pBueffel[512]; + double fStep, fStart, fPreset; + float *fData = NULL; + int lNP; + int iChannel; + int iRet, iMode, i; + char *pPtr = NULL, pItem[20]; + long *lData = NULL, lID; + int *iData; + void *pVarData = NULL; + pVarEntry pVar = NULL; + float fSum, fVar; + double x; + float fPos, FWHM, fHeight; + pSite site = NULL; + SConnection *conSave; + + self = (pScanData) pData; + assert(self); + + argtolower(argc, argv); + if (argc < 2) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: not enough arguments for %s", argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* + first interpret commands which do not require user rights + */ /*---------- getfile */ - if(strcmp(argv[1],"getfile") == 0) - { - sprintf(pBueffel,"scan.File = %s",self->pFile); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - if(strcmp(argv[1],"getscanvars") == 0) - { - PrintScanVars(self,argv[0],pCon); - return 1; - } + if (strcmp(argv[1], "getfile") == 0) { + snprintf(pBueffel,sizeof(pBueffel)-1, "scan.File = %s", self->pFile); + SCWrite(pCon, pBueffel, eValue); + return 1; + } + if (strcmp(argv[1], "getscanvars") == 0) { + PrintScanVars(self, argv[0], pCon); + return 1; + } /*--------- getcounts */ - else if(strcmp(argv[1],"getcounts") == 0) - { - return PrintCountsOrMonitors(self,pCon,argv[0],-77); - } + else if (strcmp(argv[1], "getcounts") == 0) { + return PrintCountsOrMonitors(self, pCon, argv[0], -77); + } /*------------ getmonitor */ - else if(strcmp(argv[1],"getmonitor") == 0) - { - if(argc < 3) - { - SCWrite(pCon,"ERROR: need monitor number to print",eError); - return 0; - } - iRet = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&i); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: expected integer, got %s",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - return PrintCountsOrMonitors(self,pCon,argv[0],i); - } + else if (strcmp(argv[1], "getmonitor") == 0) { + if (argc < 3) { + SCWrite(pCon, "ERROR: need monitor number to print", eError); + return 0; + } + iRet = Tcl_GetInt(InterpGetTcl(pSics), argv[2], &i); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected integer, got %s", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + return PrintCountsOrMonitors(self, pCon, argv[0], i); + } /*--------- gettimes */ - else if(strcmp(argv[1],"gettimes") == 0) - { - return PrintTimes(self,pCon,argv[0]); - } + else if (strcmp(argv[1], "gettimes") == 0) { + return PrintTimes(self, pCon, argv[0]); + } /*---------- uucounts */ - else if(strcmp(argv[1],"uucounts") == 0) - { - /* get some memory */ - if(self->iNP < 1) - { - SCWrite(pCon,"ERROR: no counts available",eError); - return 0; - } - lData = (long *)malloc(self->iNP*sizeof(long)); - iData = (int *)malloc((self->iNP + 1)*sizeof(int)); - if(!lData || !iData ) - { - SCWrite(pCon,"ERROR: out of memory in scan",eError); - return 0; - } - - /* get counts */ - GetScanCounts(self,lData,self->iNP); - /* copy them */ - memset(iData,0,self->iNP+1); - iData[0] = htonl(self->iNP); - for(i = 0; i < self->iNP; i++) - { - iData[i+1] = htonl(lData[i]); - } - SCWriteUUencoded(pCon,"ScanCounts",iData, - (self->iNP + 1)*sizeof(int)); - return 1; - } -/*--------- noscanvar */ - else if(strcmp(argv[1],"noscanvar") == 0) - { - sprintf(pBueffel,"%s.noscanvar = %d",argv[0], - self->iScanVar); - SCWrite(pCon,pBueffel,eValue); - return 1; - } -/*-------- NP */ - else if(strcmp(argv[1],"np") == 0) - { - sprintf(pBueffel,"%s.nP = %d",argv[0], - self->iNP); - SCWrite(pCon,pBueffel,eValue); - return 1; - } -/*--------- getvardata */ - else if(strcmp(argv[1],"getvardata") == 0) - { - /* we need an integer parameter saying which */ - if(argc >= 3) - { - iRet = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&i); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: expected integer, got %s",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - } - else - { - SCWrite(pCon,"ERROR: expected number of variable to retrieve data for ", - eError); - return 0; - } - /* check the int for validity */ - if( (i < 0) || (i >= self->iScanVar)) - { - SCWrite(pCon,"ERROR: non existent scan variable requested!",eError); - return 0; - } - - /* get some memory */ - fData = (float *)malloc(self->iNP*sizeof(float)); - if(!fData) - { - SCWrite(pCon,"ERROR: out of memory in scan",eError); - return 0; - } - pPtr = (char *)malloc((self->iNP*20+20)*sizeof(char)); - if(!pPtr) - { - SCWrite(pCon,"ERROR: out of memory in scan",eError); - return 0; - } - memset(pPtr,0,(self->iNP*20+20)*sizeof(char)); - - /* get data */ - GetScanVar(self,i,fData,self->iNP); - - /* get name of ScanVar */ - DynarGet(self->pScanVar,i,&pVarData); - pVar = (pVarEntry)pVarData; - if(!pVar) - { - SCWrite(pCon,"ERROR: Corrupted data structures, inform Programmer", - eError); - return 0; - } - - /* format them */ - sprintf(pPtr,"scan.%s = ", ScanVarName(pVar)); - for(i = 0; i < self->iNP; i++) - { - sprintf(pItem,"{%12.3f} ",fData[i]); - strcat(pPtr,pItem); - } - SCWrite(pCon,pPtr,eValue); - free(fData); - free(pPtr); - return 1; - } -/*---------getvarpar */ - else if(strcmp(argv[1],"getvarpar") == 0) - { - /* we need an integer parameter saying which */ - if(argc >= 3) - { - iRet = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&i); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: expected integer, got %s",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - } - else - { - SCWrite(pCon,"ERROR: expected number of variable to retrieve data for ", - eError); - return 0; - } - return GetVarPar(pCon,self,argv[0],i); - } -/*-------- interest */ - else if(strcmp(argv[1],"interest") == 0) - { - lID = RegisterCallback(self->pCall, SCGetContext(pCon),SCANSTART, ScanInterest, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); - lID = RegisterCallback(self->pCall, SCGetContext(pCon),SCANEND, ScanInterest, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); - lID = RegisterCallback(self->pCall, SCGetContext(pCon),SCANPOINT, ScanInterest, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); - SCSendOK(pCon); - return 1; - } -/*-------- interest */ - else if(strcmp(argv[1],"dyninterest") == 0) - { - lID = RegisterCallback(self->pCall, SCGetContext(pCon),SCANSTART, ScanDynInterest, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); - lID = RegisterCallback(self->pCall, SCGetContext(pCon), SCANEND, ScanDynInterest, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); - lID = RegisterCallback(self->pCall, SCGetContext(pCon),SCANPOINT, ScanDynInterest, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); - SCSendOK(pCon); - return 1; - } -/*-------- uuinterest */ - else if(strcmp(argv[1],"uuinterest") == 0) - { - lID = RegisterCallback(self->pCall, SCGetContext(pCon),SCANSTART, ScanUUInterest, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); - lID = RegisterCallback(self->pCall, SCGetContext(pCon),SCANEND, ScanUUInterest, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); - lID = RegisterCallback(self->pCall, SCGetContext(pCon),SCANPOINT, ScanUUInterest, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); - SCSendOK(pCon); - return 1; - } -/* ------- uninterest */ - else if(strcmp(argv[1],"uninterest") == 0) - { - RemoveCallback2(self->pCall,pCon); - SCUnregister(pCon,self->pCall); - SCSendOK(pCon); - return 1; - } + else if (strcmp(argv[1], "uucounts") == 0) { + /* get some memory */ + if (self->iNP < 1) { + SCWrite(pCon, "ERROR: no counts available", eError); + return 0; + } + lData = (long *) malloc(self->iNP * sizeof(long)); + iData = (int *) malloc((self->iNP + 1) * sizeof(int)); + if (!lData || !iData) { + SCWrite(pCon, "ERROR: out of memory in scan", eError); + return 0; + } -/*------- deal with command needing user rights in all cases */ - - /* check User Rights */ - if(!(SCMatchRights(pCon,usUser))) - { - SCWrite(pCon,"ERROR: You are NOT authorised to use scan",eError); - return 0; - } -/*---------- add command */ - if(strcmp(argv[1],"add") == 0) - { - if(argc < 5) - { - sprintf(pBueffel, - "ERROR: Insufficient number of arguments given for %s add", - argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - /* check for duplicate scanvar */ - for (varnum=0; varnum < self->iScanVar; varnum++) { - GetScanVarName(self, varnum, varname, 512); - if (strcmp(argv[2],varname) == 0) { - sprintf(pBueffel,"ERROR: Scan variable %s has already been added.",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - } - /* get numbers */ - iRet = Tcl_GetDouble(InterpGetTcl(pSics),argv[3],&fStart); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - iRet = Tcl_GetDouble(InterpGetTcl(pSics),argv[4],&fStep); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - iRet = AddScanVar(self,pSics,pCon,argv[2], - (float)fStart,(float)fStep); - if(iRet) - { - SCSendOK(pCon); - } - return iRet; - } - else if(strcmp(argv[1],"log") == 0) - { - if(argc < 3) - { - sprintf(pBueffel, - "ERROR: Insufficient number of arguments given for %s log", - argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - iRet = AddLogVar(self,pSics,pCon,argv[2]); - if(iRet) - { - SCSendOK(pCon); - } - return iRet; - } -/* --------clear */ - else if(strcmp(argv[1],"clear") == 0) - { - iRet = ClearScanVar(self); - if(iRet) - { - SCSendOK(pCon); - } - else - { - SCWrite(pCon,"ERROR: cannot change parameters while scanning", - eError); - return 0; - } - return 1; - } -/*------------ dump */ - else if(strcmp(argv[1],"dump") == 0) - { - return DumpScan(self,pCon); - } -/* --------callback */ - else if(strcmp(argv[1],"callback") == 0) - { - if(argc < 3) - { - SCWrite(pCon,"ERROR: need callback ID for invocation",eError); - return 0; - } - return ScanInvokeCallback(self,pCon,argv[2]); - } -/*------------ configure */ - else if(strcmp(argv[1],"configure") == 0) - { - if(argc < 3) - { - SCWrite(pCon,"ERROR: missing configure option",eError); - return 0; - } - /* this is for users only */ - if(!SCMatchRights(pCon,usUser)) - return 0; - strtolower(argv[2]); - if(strcmp(argv[2],"standard") == 0) - { - ResetScanFunctions(self); - SCSendOK(pCon); - return 1; - } - else if(strcmp(argv[2],"user") == 0) - { - ConfigureUserScan(self); - SCSendOK(pCon); - return 1; - } - else if(strcmp(argv[2],"script") == 0) - { - ConfigureScript(self); - SCSendOK(pCon); - return 1; - } - else - { - site = getSite(); - if(site != NULL){ - iRet = site->ConfigureScan(self,argv[2]); - } - if(!iRet){ - sprintf(pBueffel,"ERROR: option %s not recognized by configure", - argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } else { - SCSendOK(pCon); - return 1; - } - } - } -/*------------ functions */ - else if(strcmp(argv[1],"function") == 0) - { - return InterpretScanFunctions(self, pCon, argc, argv); - } -/*---------- scan */ - else if(strcmp(argv[1],"run") == 0) - { - if (argc < 5) { - sprintf(pBueffel,"ERROR: not enough arguments for %s run",argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - /* get NP */ - iRet = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&lNP); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - /* interpret Mode */ - if(strcmp(argv[3],"timer") == 0) - { - iMode = eTimer; - } - else if(strcmp(argv[3],"monitor") == 0) - { - iMode = ePreset; - } - else - { - sprintf(pBueffel,"ERROR: %s not recognized as valid counter mode", - argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - /* preset */ - iRet = Tcl_GetDouble(InterpGetTcl(pSics),argv[4],&fPreset); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - iRet = DoScan(self,(int)lNP,iMode,(float)fPreset, - pSics,pCon); - if(iRet) - { - SCSendOK(pCon); - } - return iRet; - } -/*------------ continue */ - else if(strcmp(argv[1],"continue") == 0) - { - return ContinueScan(self,pSics,pCon,argc,argv); - } -/*---------- silent */ - else if(strcmp(argv[1],"silent") == 0) - { - if (argc < 5) { - sprintf(pBueffel,"ERROR: not enough arguments for %s silent",argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - /* get NP */ - iRet = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&lNP); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - /* interpret Mode */ - if(strcmp(argv[3],"timer") == 0) - { - iMode = eTimer; - } - else if(strcmp(argv[3],"monitor") == 0) - { - iMode = ePreset; - } - else - { - sprintf(pBueffel,"ERROR: %s not recognized as valid counter mode", - argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - /* preset */ - iRet = Tcl_GetDouble(InterpGetTcl(pSics),argv[4],&fPreset); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - iRet = SilentScan(self,(int)lNP,iMode,(float)fPreset, - pSics,pCon); - if(iRet) - { - SCSendOK(pCon); - } - return iRet; - } -/*----------- getnumchan */ - else if(strcmp(argv[1],"getnumchan") == 0) { - snprintf(pBueffel,511,"%s.getnumchan = %d", argv[0], GetNMonitor((pCounter)self->pCounterData)); - SCWrite(pCon,pBueffel,eValue); - } -/*----------- setchannel */ - else if(strcmp(argv[1],"setchannel") == 0) - { - if(argc < 3) - { - SCWrite(pCon,"ERROR: setchannel expects an integer argument",eError); - return 0; - } - /* convert to int */ - iRet = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&iChannel); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: expected integer, got %s", argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - if( ((iChannel < 0) && (iChannel != -10)) || - (iChannel >= GetNMonitor((pCounter)self->pCounterData)) ) - { - SCWrite(pCon,"ERROR: requested counter channel out of range ", - eError); - return 0; - } - self->iChannel = iChannel; - SetControlMonitor((pCounter)self->pCounterData, iChannel); - SCSendOK(pCon); - return 1; - } -/*--------- command */ - else if(strcmp(argv[1],"command") == 0) - { - /* inquire */ - if(argc < 3) - { - sprintf(pBueffel,"%s.command = %s",argv[0], - self->pCommand); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - /* set case */ - Arg2Text(argc-2,&argv[2],pBueffel,511); - if(self->pCommand) - free(self->pCommand); - self->pCommand = strdup(pBueffel); - SCSendOK(pCon); - return 1; - } -/*--------- integration window */ - else if(strcmp(argv[1],"window") == 0) - { - if(argc > 2) - { - /* set value */ - iRet = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&iChannel); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - if(iChannel < 0) - { - SCWrite(pCon,"ERROR: new integration window size out of range", - eError); - return 0; - } - self->iWindow = iChannel; - SCSendOK(pCon); - return 1; - } - else - { - /* request the value */ - sprintf(pBueffel,"Integration Window = %d",self->iWindow); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - } -/*------------- integrate */ - else if(strcmp(argv[1],"integrate") == 0) - { - iRet = ScanIntegrate(self,&fSum,&fVar); - switch(iRet) - { - case INTEGLEFT: - SCWrite(pCon,"ERROR: no left limit found for peak",eError); - return 0; - break; - case INTEGRIGHT: - SCWrite(pCon,"ERROR: no right limit found for peak",eError); - return 0; - break; - case INTEGNOPEAK: - SCWrite(pCon,"ERROR: no data found for peak",eError); - return 0; - break; - case INTEGFUNNYBACK: - SCWrite(pCon,"WARNING: background asymmetric or worse",eWarning); - default: - sprintf(pBueffel,"Intensity = %f, Variance = %f",fSum,fVar); - SCWrite(pCon,pBueffel,eValue); - return 1; - break; - } - } -/*---------- simscan */ - else if(strcmp(argv[1],"simscan") == 0) - { - if(argc < 5) - { - SCWrite(pCon,"ERROR expected fPos FWHM Height parameters",eError); - return 0; - } - iRet = Tcl_GetDouble(InterpGetTcl(pSics),argv[2],&x); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - fPos = x; - iRet = Tcl_GetDouble(InterpGetTcl(pSics),argv[3],&x); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - FWHM = x; - iRet = Tcl_GetDouble(InterpGetTcl(pSics),argv[4],&x); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - fHeight = x; - iRet = SimScan(self,fPos,FWHM,fHeight); - if(!iRet) - { - SCWrite(pCon,"ERROR: cannot create simulated scan data",eError); - return 0; - } - SCSendOK(pCon); - return 1; - } -/*----------------- line */ - else if(strcmp(argv[1],"line") == 0) - { - Arg2Text(argc-2,&argv[2],pBueffel,511); - return AppendScanLine(self,pBueffel); - } -/*----------------- storecounts */ - else if(strcmp(argv[1],"storecounts") == 0) - { - Arg2Text(argc-2,&argv[2],pBueffel,511); - return StoreScanCounts(self,pBueffel); - } -/*----------------- appendvarpos */ - else if(strcmp(argv[1],"appendvarpos") == 0) - { - if(argc < 4) - { - SCWrite(pCon, - "ERROR: insufficient number of arguments to appendvarpos", - eError); - return 0; - } - iRet = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&i); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - iRet = Tcl_GetDouble(InterpGetTcl(pSics),argv[3],&fStep); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - return AppendVarPos(pCon,self,i,(float)fStep); - } -/*------- savecounter */ - else if(strcmp(argv[1],"savecounter") == 0) - { - conSave = self->pCon; - self->pCon = pCon; - CollectCounterData(self); - self->pCon = conSave; - if(SCGetInterrupt(pCon) >= eAbortScan){ - return 0; - } - } - else - { - sprintf(pBueffel,"ERROR: %s not recognized as subcommand to %s", - argv[1], argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } + /* get counts */ + GetScanCounts(self, lData, self->iNP); + /* copy them */ + memset(iData, 0, self->iNP + 1); + iData[0] = htonl(self->iNP); + for (i = 0; i < self->iNP; i++) { + iData[i + 1] = htonl(lData[i]); + } + SCWriteUUencoded(pCon, "ScanCounts", iData, + (self->iNP + 1) * sizeof(int)); + return 1; + } +/*--------- noscanvar */ + else if (strcmp(argv[1], "noscanvar") == 0) { + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.noscanvar = %d", argv[0], self->iScanVar); + SCWrite(pCon, pBueffel, eValue); + return 1; + } +/*-------- NP */ + else if (strcmp(argv[1], "np") == 0) { + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.nP = %d", argv[0], self->iNP); + SCWrite(pCon, pBueffel, eValue); + return 1; + } +/*--------- getvardata */ + else if (strcmp(argv[1], "getvardata") == 0) { + /* we need an integer parameter saying which */ + if (argc >= 3) { + iRet = Tcl_GetInt(InterpGetTcl(pSics), argv[2], &i); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected integer, got %s", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + } else { + SCWrite(pCon, + "ERROR: expected number of variable to retrieve data for ", + eError); + return 0; + } + /* check the int for validity */ + if ((i < 0) || (i >= self->iScanVar)) { + SCWrite(pCon, "ERROR: non existent scan variable requested!", + eError); + return 0; + } + + /* get some memory */ + fData = (float *) malloc(self->iNP * sizeof(float)); + if (!fData) { + SCWrite(pCon, "ERROR: out of memory in scan", eError); + return 0; + } + pPtr = (char *) malloc((self->iNP * 20 + 20) * sizeof(char)); + if (!pPtr) { + SCWrite(pCon, "ERROR: out of memory in scan", eError); + return 0; + } + memset(pPtr, 0, (self->iNP * 20 + 20) * sizeof(char)); + + /* get data */ + GetScanVar(self, i, fData, self->iNP); + + /* get name of ScanVar */ + DynarGet(self->pScanVar, i, &pVarData); + pVar = (pVarEntry) pVarData; + if (!pVar) { + SCWrite(pCon, "ERROR: Corrupted data structures, inform Programmer", + eError); + return 0; + } + + /* format them */ + sprintf(pPtr, "scan.%s = ", ScanVarName(pVar)); + for (i = 0; i < self->iNP; i++) { + snprintf(pItem,sizeof(pItem)-1, "{%12.4f} ", fData[i]); + strcat(pPtr, pItem); + } + SCWrite(pCon, pPtr, eValue); + free(fData); + free(pPtr); + return 1; + } +/*---------getvarpar */ + else if (strcmp(argv[1], "getvarpar") == 0) { + /* we need an integer parameter saying which */ + if (argc >= 3) { + iRet = Tcl_GetInt(InterpGetTcl(pSics), argv[2], &i); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected integer, got %s", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + } else { + SCWrite(pCon, + "ERROR: expected number of variable to retrieve data for ", + eError); + return 0; + } + return GetVarPar(pCon, self, argv[0], i); + } +/*-------- interest */ + else if (strcmp(argv[1], "interest") == 0) { + /* + printf("Registering scan callbacks on handle %d\n", pCon->sockHandle); + */ + lID = RegisterCallback(self->pCall, SCANSTART, ScanInterest, + SCCopyConnection(pCon), SCDeleteConnection); + lID = RegisterCallback(self->pCall, SCANEND, ScanInterest, + SCCopyConnection(pCon), SCDeleteConnection); + lID = RegisterCallback(self->pCall, SCANPOINT, ScanInterest, + SCCopyConnection(pCon), SCDeleteConnection); + SCSendOK(pCon); + return 1; + } +/*-------- interest */ + else if (strcmp(argv[1], "dyninterest") == 0) { + /* + printf("Registering scanDyn callbacks on handle %d\n", pCon->sockHandle); + */ + lID = RegisterCallback(self->pCall, SCANSTART, ScanDynInterest, + SCCopyConnection(pCon), SCDeleteConnection); + lID = RegisterCallback(self->pCall, SCANEND, ScanDynInterest, + SCCopyConnection(pCon), SCDeleteConnection); + lID = RegisterCallback(self->pCall, SCANPOINT, ScanDynInterest, + SCCopyConnection(pCon), SCDeleteConnection); + SCSendOK(pCon); + return 1; + } +/*-------- uuinterest */ + else if (strcmp(argv[1], "uuinterest") == 0) { + /* + printf("Registering scanUU callbacks on handle %d, con = %p\n", + conSave->sockHandle, conSave); + */ + lID = RegisterCallback(self->pCall, SCANSTART, ScanUUInterest, + SCCopyConnection(pCon), SCDeleteConnection); + lID = RegisterCallback(self->pCall, SCANEND, ScanUUInterest, + SCCopyConnection(pCon), SCDeleteConnection); + lID = RegisterCallback(self->pCall, SCANPOINT, ScanUUInterest, + SCCopyConnection(pCon), SCDeleteConnection); + SCSendOK(pCon); + return 1; + } +/* ------- uninterest */ + else if (strcmp(argv[1], "uninterest") == 0) { + RemoveCallbackCon(self->pCall, pCon); + SCSendOK(pCon); + return 1; + } + +/*------- deal with command needing user rights in all cases */ + + /* check User Rights */ + if (!(SCMatchRights(pCon, usUser))) { + SCWrite(pCon, "ERROR: You are NOT authorised to use scan", eError); return 0; - } + } +/*---------- add command */ + if (strcmp(argv[1], "add") == 0) { + if (argc < 5) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: Insufficient number of arguments given for %s add", + argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + /* get numbers */ + iRet = Tcl_GetDouble(InterpGetTcl(pSics), argv[3], &fStart); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[3]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + iRet = Tcl_GetDouble(InterpGetTcl(pSics), argv[4], &fStep); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[3]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + iRet = AddScanVar(self, pSics, pCon, argv[2], + (float) fStart, (float) fStep); + if (iRet) { + SCSendOK(pCon); + } + return iRet; + } else if (strcmp(argv[1], "log") == 0) { + if (argc < 3) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: Insufficient number of arguments given for %s log", + argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + iRet = AddLogVar(self, pSics, pCon, argv[2]); + if (iRet) { + SCSendOK(pCon); + } + return iRet; + } +/* --------clear */ + else if (strcmp(argv[1], "clear") == 0) { + iRet = ClearScanVar(self); + if (iRet) { + SCSendOK(pCon); + } else { + SCWrite(pCon, "ERROR: cannot change parameters while scanning", + eError); + return 0; + } + return 1; + } +/*------------ dump */ + else if (strcmp(argv[1], "dump") == 0) { + return DumpScan(self, pCon); + } +/* --------callback */ + else if (strcmp(argv[1], "callback") == 0) { + if (argc < 3) { + SCWrite(pCon, "ERROR: need callback ID for invocation", eError); + return 0; + } + return ScanInvokeCallback(self, pCon, argv[2]); + } +/*------------ configure */ + else if (strcmp(argv[1], "configure") == 0) { + if (argc < 3) { + SCWrite(pCon, "ERROR: missing configure option", eError); + return 0; + } + /* this is for users only */ + if (!SCMatchRights(pCon, usUser)) + return 0; + strtolower(argv[2]); + if (strcmp(argv[2], "standard") == 0) { + ResetScanFunctions(self); + SCSendOK(pCon); + return 1; + } else if (strcmp(argv[2], "user") == 0) { + ConfigureUserScan(self); + SCSendOK(pCon); + return 1; + } else if (strcmp(argv[2], "script") == 0) { + ConfigureScript(self); + ResetScanDict(self->scanFunctions); + SCSendOK(pCon); + return 1; + } else { + site = getSite(); + if (site != NULL) { + iRet = site->ConfigureScan(self, argv[2]); + } + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: option %s not recognized by configure", + argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } else { + SCSendOK(pCon); + return 1; + } + } + } +/*------------ functions */ + else if (strcmp(argv[1], "function") == 0) { + return InterpretScanFunctions(self, pCon, argc, argv); + } +/*---------- scan */ + else if (strcmp(argv[1], "run") == 0) { + if (argc < 5) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: not enough arguments for %s run", argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + /* get NP */ + iRet = Tcl_GetInt(InterpGetTcl(pSics), argv[2], &lNP); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + /* interpret Mode */ + if (strcmp(argv[3], "timer") == 0) { + iMode = eTimer; + } else if (strcmp(argv[3], "monitor") == 0) { + iMode = ePreset; + } else { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s not recognized as valid counter mode", + argv[3]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + /* preset */ + iRet = Tcl_GetDouble(InterpGetTcl(pSics), argv[4], &fPreset); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[3]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + iRet = DoScan(self, (int) lNP, iMode, (float) fPreset, pSics, pCon); + if (iRet) { + SCSendOK(pCon); + } + return iRet; + } +/*------------ continue */ + else if (strcmp(argv[1], "continue") == 0) { + return ContinueScan(self, pSics, pCon, argc, argv); + } +/*---------- silent */ + else if (strcmp(argv[1], "silent") == 0) { + if (argc < 5) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: not enough arguments for %s silent", + argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + /* get NP */ + iRet = Tcl_GetInt(InterpGetTcl(pSics), argv[2], &lNP); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + /* interpret Mode */ + if (strcmp(argv[3], "timer") == 0) { + iMode = eTimer; + } else if (strcmp(argv[3], "monitor") == 0) { + iMode = ePreset; + } else { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s not recognized as valid counter mode", + argv[3]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + /* preset */ + iRet = Tcl_GetDouble(InterpGetTcl(pSics), argv[4], &fPreset); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[3]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + iRet = SilentScan(self, (int) lNP, iMode, (float) fPreset, + pSics, pCon); + if (iRet) { + SCSendOK(pCon); + } + return iRet; + } +/*----------- getnumchan */ + else if (strcmp(argv[1], "getnumchan") == 0) { + snprintf(pBueffel, 511, "%s.getnumchan = %d", argv[0], + GetNMonitor((pCounter) self->pCounterData)); + SCWrite(pCon, pBueffel, eValue); + } +/*----------- setchannel */ + else if (strcmp(argv[1], "setchannel") == 0) { + if (argc < 3) { + SCWrite(pCon, "ERROR: setchannel expects an integer argument", + eError); + return 0; + } + /* convert to int */ + iRet = Tcl_GetInt(InterpGetTcl(pSics), argv[2], &iChannel); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected integer, got %s", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + if (((iChannel < 0) && (iChannel != -10)) || + (iChannel >= GetNMonitor((pCounter) self->pCounterData))) { + SCWrite(pCon, "ERROR: requested counter channel out of range ", + eError); + return 0; + } + self->iChannel = iChannel; + SCSendOK(pCon); + return 1; + } +/*--------- command */ + else if (strcmp(argv[1], "command") == 0) { + /* inquire */ + if (argc < 3) { + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.command = %s", argv[0], self->pCommand); + SCWrite(pCon, pBueffel, eValue); + return 1; + } + /* set case */ + Arg2Text(argc - 2, &argv[2], pBueffel, 511); + if (self->pCommand) + free(self->pCommand); + self->pCommand = strdup(pBueffel); + SCSendOK(pCon); + return 1; + } +/*--------- integration window */ + else if (strcmp(argv[1], "window") == 0) { + if (argc > 2) { + /* set value */ + iRet = Tcl_GetInt(InterpGetTcl(pSics), argv[2], &iChannel); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[3]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + if (iChannel < 0) { + SCWrite(pCon, "ERROR: new integration window size out of range", + eError); + return 0; + } + self->iWindow = iChannel; + SCSendOK(pCon); + return 1; + } else { + /* request the value */ + snprintf(pBueffel,sizeof(pBueffel)-1, "Integration Window = %d", self->iWindow); + SCWrite(pCon, pBueffel, eValue); + return 1; + } + } +/*------------- integrate */ + else if (strcmp(argv[1], "integrate") == 0) { + iRet = ScanIntegrate(self, &fSum, &fVar); + switch (iRet) { + case INTEGLEFT: + SCWrite(pCon, "ERROR: no left limit found for peak", eError); + return 0; + break; + case INTEGRIGHT: + SCWrite(pCon, "ERROR: no right limit found for peak", eError); + return 0; + break; + case INTEGNOPEAK: + SCWrite(pCon, "ERROR: no data found for peak", eError); + return 0; + break; + case INTEGFUNNYBACK: + SCWrite(pCon, "WARNING: background asymmetric or worse", eWarning); + default: + snprintf(pBueffel,sizeof(pBueffel)-1, "Intensity = %f, Variance = %f", fSum, fVar); + SCWrite(pCon, pBueffel, eValue); + return 1; + break; + } + } +/*---------- simscan */ + else if (strcmp(argv[1], "simscan") == 0) { + if (argc < 5) { + SCWrite(pCon, "ERROR expected fPos FWHM Height parameters", eError); + return 0; + } + iRet = Tcl_GetDouble(InterpGetTcl(pSics), argv[2], &x); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[3]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + fPos = x; + iRet = Tcl_GetDouble(InterpGetTcl(pSics), argv[3], &x); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[3]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + FWHM = x; + iRet = Tcl_GetDouble(InterpGetTcl(pSics), argv[4], &x); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[3]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + fHeight = x; + iRet = SimScan(self, fPos, FWHM, fHeight); + if (!iRet) { + SCWrite(pCon, "ERROR: cannot create simulated scan data", eError); + return 0; + } + SCSendOK(pCon); + return 1; + } +/*----------------- line */ + else if (strcmp(argv[1], "line") == 0) { + Arg2Text(argc - 2, &argv[2], pBueffel, 511); + return AppendScanLine(self, pBueffel); + } +/*----------------- storecounts */ + else if (strcmp(argv[1], "storecounts") == 0) { + Arg2Text(argc - 2, &argv[2], pBueffel, 511); + return StoreScanCounts(self, pBueffel); + } +/*----------------- appendvarpos */ + else if (strcmp(argv[1], "appendvarpos") == 0) { + if (argc < 4) { + SCWrite(pCon, + "ERROR: insufficient number of arguments to appendvarpos", + eError); + return 0; + } + iRet = Tcl_GetInt(InterpGetTcl(pSics), argv[2], &i); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[3]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + iRet = Tcl_GetDouble(InterpGetTcl(pSics), argv[3], &fStep); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[3]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + return AppendVarPos(pCon, self, i, (float) fStep); + } +/*------- savecounter */ + else if (strcmp(argv[1], "savecounter") == 0) { + conSave = self->pCon; + self->pCon = pCon; + CollectCounterData(self); + self->pCon = conSave; + if (SCGetInterrupt(pCon) >= eAbortScan) { + return 0; + } + } else { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s not recognized as subcommand to %s", + argv[1], argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + return 0; +} diff --git a/scan.h b/scan.h index 09ad15b7..f9e2ca2e 100644 --- a/scan.h +++ b/scan.h @@ -12,71 +12,68 @@ -----------------------------------------------------------------------------*/ #ifndef SICSSCAN1 #define SICSSCAN1 - typedef struct __ScanData *pScanData; +typedef struct __ScanData *pScanData; /*--------------------------------------------------------------------------*/ #include "counter.h" /*------------------------- live & death ----------------------------------*/ - pScanData CreateScanObject(char *pRecover, char *pHeader, - pCounter pCount, char *objName); - void DeleteScanObject(void *self); +pScanData CreateScanObject(char *pRecover, char *pHeader, + pCounter pCount, char *objName); +void DeleteScanObject(void *self); /*-------------------------------------------------------------------------*/ - int AddScanVar(pScanData self, SicsInterp *pSics, SConnection *pCon, - char *name, float fStart, float fStep); - int ClearScanVar(pScanData self); - - int DoScan(pScanData self, int iNP, int iMode, float fPreset, - SicsInterp *pSics, SConnection *pCon); - int SilentScan(pScanData self, int iNP, int iMode, float fPreset, - SicsInterp *pSics, SConnection *pCon); - int RecoverScan(pScanData self, SicsInterp *pSics, SConnection *pCon); - - int GetScanCounts(pScanData self, long *lData, int iDataLen); - int GetScanVar(pScanData self, int iWhich, float *fData, int iDataLen); - int GetSoftScanVar(pScanData self, int iWhich, float *fData, int iDataLen); +int AddScanVar(pScanData self, SicsInterp * pSics, SConnection * pCon, + char *name, float fStart, float fStep); +int ClearScanVar(pScanData self); - int GetScanVarName(pScanData self, int iWhich, - char *pName, int iLength); - int GetScanVarStep(pScanData self, int iWhich, - float *fStep); - int GetScanMonitor(pScanData self, int iWhich, - long *lData, int iDataLen); - int GetScanNP(pScanData self); - float GetScanPreset(pScanData self); - - int ScanIntegrate(pScanData self, float *fSum, float *fVariance); - - int SimScan(pScanData self, float fPos, float FHWM, float fHeight); +int DoScan(pScanData self, int iNP, int iMode, float fPreset, + SicsInterp * pSics, SConnection * pCon); +int SilentScan(pScanData self, int iNP, int iMode, float fPreset, + SicsInterp * pSics, SConnection * pCon); +int RecoverScan(pScanData self, SicsInterp * pSics, SConnection * pCon); + +int GetScanCounts(pScanData self, long *lData, int iDataLen); +int GetScanVar(pScanData self, int iWhich, float *fData, int iDataLen); +int GetSoftScanVar(pScanData self, int iWhich, float *fData, int iDataLen); + +int GetScanVarName(pScanData self, int iWhich, char *pName, int iLength); +int GetScanVarStep(pScanData self, int iWhich, float *fStep); +int GetScanMonitor(pScanData self, int iWhich, long *lData, int iDataLen); +int GetScanNP(pScanData self); +float GetScanPreset(pScanData self); + +int ScanIntegrate(pScanData self, float *fSum, float *fVariance); + +int SimScan(pScanData self, float fPos, float FHWM, float fHeight); /* creates a simulated gaussian shaped peak with the parameters given. - */ - int ResetScanFunctions(pScanData self); + */ +int ResetScanFunctions(pScanData self); /* resets the configurable scan functions to their default values. - */ - int NonCheckPrepare(pScanData self); + */ +int NonCheckPrepare(pScanData self); /* - a function for the PrepareScan field in the scan data structure - which does not check the boundaries of the scan as the default - PrepareScan does. - */ - int AppendScanLine(pScanData self, char *line); + a function for the PrepareScan field in the scan data structure + which does not check the boundaries of the scan as the default + PrepareScan does. + */ +int AppendScanLine(pScanData self, char *line); /* - AppendScanLine appends a line to the scan data file. When finished - it updates the position pointer in the file to point behind the - added line. - */ - int StoreScanCounts(pScanData self, char *data); + AppendScanLine appends a line to the scan data file. When finished + it updates the position pointer in the file to point behind the + added line. + */ +int StoreScanCounts(pScanData self, char *data); /* - parses the numbers in data and stores them as the count and - monitor data for the current scan point. - */ + parses the numbers in data and stores them as the count and + monitor data for the current scan point. + */ /*------------------------ Interpreter Interface --------------------------*/ - int ScanFactory(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); +int ScanFactory(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); - int ScanWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); +int ScanWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); #endif diff --git a/scanvar.c b/scanvar.c index 800c2a6a..e8aa0793 100644 --- a/scanvar.c +++ b/scanvar.c @@ -16,96 +16,104 @@ #include "lld.h" #include "devexec.h" /*----------------------------------------------------------------------*/ -pVarEntry MakeScanVar(SicsInterp *pSics, SConnection *pCon, char - *name, float start, float step){ +pVarEntry MakeScanVar(SicsInterp * pSics, SConnection * pCon, char + *name, float start, float step) +{ CommandList *pCom = NULL; - pIDrivable pDriv = NULL; - pDummy pData = NULL; - pVarEntry pVar = NULL; + pIDrivable pDriv = NULL; + pDummy pData = NULL; + pVarEntry pVar = NULL; char pBueffel[512]; /* - allocate space - */ - pVar = (pVarEntry)malloc(sizeof(VarEntry)); - if(pVar == NULL){ - SCWrite(pCon,"ERROR: out of memory allocating scan variable",eError); + allocate space + */ + pVar = (pVarEntry) malloc(sizeof(VarEntry)); + if (pVar == NULL) { + SCWrite(pCon, "ERROR: out of memory allocating scan variable", eError); return NULL; } - memset(pVar,0,sizeof(VarEntry)); + memset(pVar, 0, sizeof(VarEntry)); /* find the thing */ - pCom = FindCommand(pSics,name); - if(!pCom){ - snprintf(pBueffel,511,"ERROR: Cannot find variable %s to scan",name); - SCWrite(pCon,pBueffel,eError); + pCom = FindCommand(pSics, name); + if (!pCom) { + snprintf(pBueffel, 511, "ERROR: Cannot find variable %s to scan", + name); + SCWrite(pCon, pBueffel, eError); return NULL; } - pData = (pDummy)pCom->pData; - if(!pData){ - snprintf(pBueffel,511,"ERROR: Cannot find data for variable %s",name); - SCWrite(pCon,pBueffel,eError); + pData = (pDummy) pCom->pData; + if (!pData) { + snprintf(pBueffel, 511, "ERROR: Cannot find data for variable %s", + name); + SCWrite(pCon, pBueffel, eError); return NULL; } - pDriv = pData->pDescriptor->GetInterface(pData,DRIVEID); - if(!pDriv){ - snprintf(pBueffel,511, - "ERROR: variable %s is NOT driveable and cannot be scanned",name); - SCWrite(pCon,pBueffel,eError); - return NULL; + pDriv = pData->pDescriptor->GetInterface(pData, DRIVEID); + if (!pDriv) { + snprintf(pBueffel, 511, + "ERROR: variable %s is NOT driveable and cannot be scanned", + name); + SCWrite(pCon, pBueffel, eError); + return NULL; } /* got everything, fill in the VarEntry structure */ - strcpy(pVar->Name,name); + strlcpy(pVar->Name, name,131); pVar->pInter = pDriv; pVar->pObject = pData; pVar->fStart = start; - pVar->fStep = step; + pVar->fStep = step; pVar->dataList = LLDcreate(sizeof(float)); return pVar; } + /*----------------------------------------------------------------------*/ -pVarEntry MakeLogVar(SicsInterp *pSics, SConnection *pCon, char *name){ +pVarEntry MakeLogVar(SicsInterp * pSics, SConnection * pCon, char *name) +{ CommandList *pCom = NULL; - pIDrivable pDriv = NULL; - pDummy pData = NULL; - pVarEntry pVar = NULL; + pIDrivable pDriv = NULL; + pDummy pData = NULL; + pVarEntry pVar = NULL; char pBueffel[512]; /* - allocate space - */ - pVar = (pVarEntry)malloc(sizeof(VarEntry)); - if(pVar == NULL){ - SCWrite(pCon,"ERROR: out of memory allocating scan variable",eError); + allocate space + */ + pVar = (pVarEntry) malloc(sizeof(VarEntry)); + if (pVar == NULL) { + SCWrite(pCon, "ERROR: out of memory allocating scan variable", eError); return NULL; } - memset(pVar,0,sizeof(VarEntry)); + memset(pVar, 0, sizeof(VarEntry)); /* find the thing */ - pCom = FindCommand(pSics,name); - if(!pCom){ - snprintf(pBueffel,511,"ERROR: Cannot find variable %s to log",name); - SCWrite(pCon,pBueffel,eError); + pCom = FindCommand(pSics, name); + if (!pCom) { + snprintf(pBueffel, 511, "ERROR: Cannot find variable %s to log", name); + SCWrite(pCon, pBueffel, eError); return NULL; } - pData = (pDummy)pCom->pData; - if(!pData){ - snprintf(pBueffel,511,"ERROR: Cannot find data for variable %s",name); - SCWrite(pCon,pBueffel,eError); + pData = (pDummy) pCom->pData; + if (!pData) { + snprintf(pBueffel, 511, "ERROR: Cannot find data for variable %s", + name); + SCWrite(pCon, pBueffel, eError); return NULL; } - pDriv = pData->pDescriptor->GetInterface(pData,DRIVEID); - if(!pDriv){ - snprintf(pBueffel,511, - "ERROR: variable %s is NOT driveable and cannot be logged",name); - SCWrite(pCon,pBueffel,eError); - return NULL; + pDriv = pData->pDescriptor->GetInterface(pData, DRIVEID); + if (!pDriv) { + snprintf(pBueffel, 511, + "ERROR: variable %s is NOT driveable and cannot be logged", + name); + SCWrite(pCon, pBueffel, eError); + return NULL; } /* got everything, fill in the VarEntry structure */ - strcpy(pVar->Name,name); + strlcpy(pVar->Name, name,131); pVar->pInter = pDriv; pVar->pObject = pData; pVar->logVar = 1; @@ -115,40 +123,51 @@ pVarEntry MakeLogVar(SicsInterp *pSics, SConnection *pCon, char *name){ } /*------------------------------------------------------------------*/ -void InitScanVar(pVarEntry pVar){ +void InitScanVar(pVarEntry pVar) +{ LLDdelete(pVar->dataList); pVar->dataList = LLDcreate(sizeof(float)); } + /*--------------------------------------------------------------------*/ -void DeleteVarEntry(void *pData){ +void DeleteVarEntry(void *pData) +{ pVarEntry pVar = NULL; - - pVar = (pVarEntry)pData; - - if(pVar == NULL){ + + pVar = (pVarEntry) pData; + + if (pVar == NULL) { return; } - - if(pVar->fData){ + + if (pVar->fData) { free(pVar->fData); } LLDdelete(pVar->dataList); free(pVar); } + /*------------------------------------------------------------------------*/ -char *ScanVarName(pVarEntry pVar){ +char *ScanVarName(pVarEntry pVar) +{ return pVar->Name; } + /*------------------------------------------------------------------------*/ -float ScanVarStart(pVarEntry pVar){ +float ScanVarStart(pVarEntry pVar) +{ return pVar->fStart; } + /*-------------------------------------------------------------------------*/ -float ScanVarStep(pVarEntry pVar){ +float ScanVarStep(pVarEntry pVar) +{ return pVar->fStep; } + /*------------------------------------------------------------------------*/ -int StartScanVar(pVarEntry pVar, SConnection *pCon, int i){ +int StartScanVar(pVarEntry pVar, SConnection * pCon, int i) +{ float fVal; pDummy pDum; char pBueffel[512]; @@ -157,84 +176,91 @@ int StartScanVar(pVarEntry pVar, SConnection *pCon, int i){ /** * logged variables are not started */ - if(pVar->logVar == 1){ + if (pVar->logVar == 1) { return 1; } - pDum = (pDummy)pVar->pObject; - fVal = pVar->fStart + i * pVar->fStep; - status = StartDevice(pServ->pExecutor, - pVar->Name, - pDum->pDescriptor, - pVar->pObject, - pCon, - fVal); - if(!status){ - snprintf(pBueffel,511,"ERROR: Failed to start %s",pVar->Name); - SCWrite(pCon,pBueffel,eError); + pDum = (pDummy) pVar->pObject; + fVal = pVar->fStart + i * pVar->fStep; + status = StartDevice(pServ->pExecutor, + pVar->Name, + pDum->pDescriptor, pVar->pObject, pCon, + RUNDRIVE, fVal); + if (!status) { + snprintf(pBueffel, 511, "ERROR: Failed to start %s", pVar->Name); + SCWrite(pCon, pBueffel, eError); return 0; - } + } return 1; } -/*-------------------------------------------------------------------------*/ -int CheckScanVar(pVarEntry pVar, SConnection *pCon, int np){ - int status; - char pError[132], pBueffel[512]; - if(pVar->logVar == 1){ - return 1; - } - - status = pVar->pInter->CheckLimits(pVar->pObject, - pVar->fStart,pError,131); - if(status != 1){ - snprintf(pBueffel,511,"ERROR: %s, scan aborted",pError); - SCWrite(pCon,pBueffel,eError); - return 0; - } - status = pVar->pInter->CheckLimits(pVar->pObject, - pVar->fStart + np * pVar->fStep, - pError,131); - if(status != 1){ - snprintf(pBueffel,511,"ERROR: %s, scan aborted",pError); - SCWrite(pCon,pBueffel,eError); - return 0; - } - return 1; -} /*-------------------------------------------------------------------------*/ -void AppendScanVar(pVarEntry pVar, float pos){ - float fVal = pos; - LLDnodeAppendFrom(pVar->dataList,&fVal); +int CheckScanVar(pVarEntry pVar, SConnection * pCon, int np) +{ + int status; + char pError[132], pBueffel[512]; + + if (pVar->logVar == 1) { + return 1; + } + + status = pVar->pInter->CheckLimits(pVar->pObject, + pVar->fStart, pError, 131); + if (status != 1) { + snprintf(pBueffel, 511, "ERROR: %s, scan aborted", pError); + SCWrite(pCon, pBueffel, eError); + return 0; + } + status = pVar->pInter->CheckLimits(pVar->pObject, + pVar->fStart + np * pVar->fStep, + pError, 131); + if (status != 1) { + snprintf(pBueffel, 511, "ERROR: %s, scan aborted", pError); + SCWrite(pCon, pBueffel, eError); + return 0; + } + return 1; } + +/*-------------------------------------------------------------------------*/ +void AppendScanVar(pVarEntry pVar, float pos) +{ + float fVal = pos; + LLDnodeAppendFrom(pVar->dataList, &fVal); +} + /*------------------------------------------------------------------------*/ -float GetScanVarPos(pVarEntry pVar, int i){ +float GetScanVarPos(pVarEntry pVar, int i) +{ int count = 0, status; status = LLDnodePtr2First(pVar->dataList); - while(count < i && (status = LLDnodePtr2Next(pVar->dataList)) != 0){ + while (count < i && (status = LLDnodePtr2Next(pVar->dataList)) != 0) { count++; } - if(count == i){ + if (count == i) { return LLDnodeFloat(pVar->dataList); } else { return -99999.99; } } + /*------------------------------------------------------------------------*/ -void CopyScanVar(pVarEntry pVar, float *fData, int np){ +void CopyScanVar(pVarEntry pVar, float *fData, int np) +{ int i, count = 0, status; status = LLDnodePtr2First(pVar->dataList); - while(status > 0 && count < np){ + while (status > 0 && count < np) { fData[count] = LLDnodeFloat(pVar->dataList); count++; status = LLDnodePtr2Next(pVar->dataList); } } -/*-------------------------------------------------------------------------*/ -int isLogVar(pVarEntry pVar){ - return pVar->logVar; -} +/*-------------------------------------------------------------------------*/ +int isLogVar(pVarEntry pVar) +{ + return pVar->logVar; +} diff --git a/scanvar.h b/scanvar.h index e73c5080..99f6e40c 100644 --- a/scanvar.h +++ b/scanvar.h @@ -13,16 +13,16 @@ #define SICSSCANVAR #include "sics.h" - typedef struct { - char Name[132]; - pIDrivable pInter; - pDummy pObject; - float fStart; - float fStep; - float *fData; - int dataList; - int logVar; - }VarEntry, *pVarEntry; +typedef struct { + char Name[132]; + pIDrivable pInter; + pDummy pObject; + float fStart; + float fStep; + float *fData; + int dataList; + int logVar; +} VarEntry, *pVarEntry; /*---------------------------------------------------------------------*/ @@ -37,44 +37,43 @@ * @return A pointer to a new scan variable object on success, NULL * else */ - pVarEntry MakeScanVar(SicsInterp *pSics, SConnection *pCon, char - *name, float start, float step); +pVarEntry MakeScanVar(SicsInterp * pSics, SConnection * pCon, char + *name, float start, float step); /** * make a variable which is logged during the scan but not driven. * @param pSics The interpreter in order to locate the variable. * @param pCon A connection object for error reporting * @param name The name of the variable to log */ - pVarEntry MakeLogVar(SicsInterp *pSics, - SConnection *pCon, char *name); +pVarEntry MakeLogVar(SicsInterp * pSics, SConnection * pCon, char *name); /** * InitScanVar clears the list of scan points * @param pvar The scna variable to clear */ - void InitScanVar(pVarEntry pVar); +void InitScanVar(pVarEntry pVar); /** * DeleteVarEntry deletes a scan variable. * @param pData The scan variable entry to delete. */ - void DeleteVarEntry(void *pData); +void DeleteVarEntry(void *pData); /** * ScanVarName returns the name of the scan variable * @param pVar The scan variable to query. * @return The name of the scan variable. Do not delete pointer. */ - char *ScanVarName(pVarEntry pVar); +char *ScanVarName(pVarEntry pVar); /** * ScanVarStart returns the start value for the scan * @param pVar The scan variable to query. * @return The start point for the scan. */ - float ScanVarStart(pVarEntry pVar); +float ScanVarStart(pVarEntry pVar); /** * ScanVarStep returns the start value for the scan * @param pVar The scan variable to query. * @return The step width for the scan. */ - float ScanVarStep(pVarEntry pVar); +float ScanVarStep(pVarEntry pVar); /** * StartScanVar starts the scan variable to drive to the next * position. @@ -83,28 +82,28 @@ * @param i The position number to drive to * @return 1 on success, 0 on failure */ - int StartScanVar(pVarEntry pVar, SConnection *pCon, int i); +int StartScanVar(pVarEntry pVar, SConnection * pCon, int i); /** * AppendScanVar appends a position to the list of positions * reached while scanning this variable. * @param pVar The scan variable to append to. * @param pos The position to append. */ - void AppendScanVar(pVarEntry pVar, float pos); +void AppendScanVar(pVarEntry pVar, float pos); /** * GetScanVarPos returns a position for an index. * @param pVar The scan variable to append to. * @param i The position number to retrieve * @return The positiopn or -99999.99 for an error */ - float GetScanVarPos(pVarEntry pVar, int i); +float GetScanVarPos(pVarEntry pVar, int i); /** * CopyScanVar copies the scan positions to the array given. * @param pVar The scan variable to copy from * @param fData The array to copy to. * @param np The number of slots in fData. */ - void CopyScanVar(pVarEntry pVar, float *fData, int np); +void CopyScanVar(pVarEntry pVar, float *fData, int np); /** * CheckScanVar checks if the scan variable can be driven through the * whole range. @@ -113,12 +112,12 @@ * @param np The number of points to check for. * @return 0 on failuyre, 1 on success */ - int CheckScanVar(pVarEntry pVar, SConnection *pCon, int np); +int CheckScanVar(pVarEntry pVar, SConnection * pCon, int np); /** * queries if the variable is alogged variable or a drive one. * @param pVar The variable to query. * @return 1 if log var, 0 else */ - int isLogVar(pVarEntry pVar); +int isLogVar(pVarEntry pVar); #endif diff --git a/scontroller.c b/scontroller.c deleted file mode 100644 index 141a59a4..00000000 --- a/scontroller.c +++ /dev/null @@ -1,282 +0,0 @@ -/*-------------------------------------------------------------------------- - - Some code to connect to a serial port through the SINQ system. - - Just a wrapper around serialsinq derived from David Maden's - EL734 routines. - - You are free to use and modify this software for noncommercial - usage. - - No warranties or liabilities of any kind taken by me or my employer - - Very primitive device to send commands to a motor from Tcl - - Modified version for use within SICS. -----------------------------------------------------------------------------*/ -#include "sinq_prototypes.h" -/* #include */ -#include -#include -#include -#include -#include "rs232c_def.h" -#include "el734_def.h" -#include "psi/hardsup/serialsinq.h" -#include "sics.h" - -#define False 0 -#define True 1 - -/*--------------------------------------------------------------------------- - Tcl has a high niceness level. It deletes a command properly when - exiting, reinitializing etc. I use this facility to kill off the - motor initialised in Controller. ----------------------------------------------------------------------------*/ -EXTERN void SerialMurder(ClientData pData) -{ - /* - NetReadRemoveUserSocket(pServ->pReader, SerialGetSocket(&(pData))); - */ - SerialClose(&(pData)); - free(pData); -} -/*------------------ a forward declaration -----------------------------*/ -EXTERN int SurielSend(ClientData clientData, Tcl_Interp *interp, - int argc, char *argv[]); - -/*---------------------------------------------------------------------------- - Controller is the main entry point for this stuff. It connects to a motor - and, on success, creates a new command with the name of the motor. - Syntax: - Controller name host port channel ----------------------------------------------------------------------------*/ - -int Controller(ClientData clientData, Tcl_Interp *interp, - int argc, char *argv[]) -{ - int iRet; - int iPort, iChannel, iMotor; - char *pErr = NULL; - char pBueffel[80]; - void **pData = NULL; - - /* check arguments */ - if(argc < 5) - { - Tcl_AppendResult(interp, - " Insufficient arguments: Controller name host port channel index" - , (char *) NULL); - return TCL_ERROR; - } - - /* convert arguments */ - iRet = Tcl_GetInt(interp,argv[3],&iPort); - if(iRet == TCL_ERROR) - { - Tcl_AppendResult(interp,"Need integer value for port", - (char *)NULL); - return iRet; - } - - iRet = Tcl_GetInt(interp,argv[4],&iChannel); - if(iRet == TCL_ERROR) - { - Tcl_AppendResult(interp,"Need integer value for channel", - (char *)NULL); - return iRet; - } - - iMotor = 1; - - - /* make a new pointer, initialise EL734st */ - pData = malloc(sizeof(void *)); - if(pData ==NULL) - { - Tcl_AppendResult(interp,"No memory in SerialSinq",NULL); - return TCL_ERROR; - } - - /* check for optional force flag */ - if(argc > 5) - { - iRet = SerialForceOpen(pData, argv[2],iPort,iChannel); - } - - /* open the motor, finally */ - iRet = SerialOpen(pData, argv[2],iPort,iChannel); - if(iRet == 1) /* success */ - { - /* handle TCL, create new command: the serial line */ - Tcl_CreateCommand(interp,strdup(argv[1]),SurielSend, - *pData,SerialMurder); - strcpy(pBueffel,argv[1]); - Tcl_AppendResult(interp,strdup(argv[1]),(char *)NULL); - if(pServ->pReader != NULL) - { - NetReadRegisterUserSocket(pServ->pReader, - SerialGetSocket(pData)); - } - return TCL_OK; - } - else - { - SerialError(iRet,pBueffel,79); - Tcl_AppendResult(interp,pBueffel,(char *) NULL); - SerialClose(pData); - free(pData); - return TCL_ERROR; - } -} -/*-------------------------------------------------------------------------- - Now, this interprets some commands: - -tmo val - will set a timeout value for the connection. Everything - else will be concatenated and sent to the device. - -sendterm text - defines the terminator which will be appended automatically - to each command. - -replyterm text - sets the expected reply terminator from the Macintosh - Serial Port server. - -----------------------------------------------------------------------------*/ -EXTERN int SurielSend(ClientData clientData, Tcl_Interp *interp, - int argc, char *argv[]) -{ - char pBueffel[256]; - char pAnswer[256]; - char *pErr = NULL; - int iRet, iMSR; - int i; - void *pData; - - pData = clientData; - - if(argc >= 2) - { - if(strcmp(argv[1],"-tmo") == 0) - { - if(argc >= 3) - { - iRet = Tcl_GetInt(interp,argv[2],&iMSR); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"%s is not a valid number",argv[2]); - Tcl_AppendResult(interp,pBueffel,NULL); - return TCL_ERROR; - } - SerialConfig(&(pData),iMSR); - return TCL_OK; - } - else - { - Tcl_AppendResult(interp, "Expected parameter after -tmo",NULL); - return TCL_ERROR; - } - } - else if(strcmp(argv[1],"-sendterm") == 0) - { - if(argc < 3) - { - Tcl_AppendResult(interp, "Expected parameter after -tmo",NULL); - return TCL_ERROR; - } - iRet = SerialSendTerm(&(pData),argv[2]); - if(iRet != 1) - { - Tcl_AppendResult(interp,"To many characters for terminator",NULL); - return TCL_ERROR; - } - return TCL_OK; - } - else if(strcmp(argv[1],"-replyterm") == 0) - { - if(argc < 3) - { - Tcl_AppendResult(interp, "Expected parameter after -tmo",NULL); - return TCL_ERROR; - } - iRet = SerialATerm(&(pData),argv[2]); - if(!iRet) - { - Tcl_AppendResult(interp,"To many characters for terminator",NULL); - return TCL_ERROR; - } - return TCL_OK; - } - else if(strcmp(argv[1],"-put") == 0) - { - NetReadResetUser(pServ->pReader,SerialGetSocket(&(pData))); - if(argc > 2) - { - strcpy(pBueffel,argv[2]); - } - for(i = 3; i < argc; i++) - { - strcat(pBueffel," "); - strcat(pBueffel,argv[i]); - } - iRet = SerialSend(&(pData),pBueffel); - if(iRet != 1) - { - Tcl_AppendResult(interp,pAnswer,NULL); - return TCL_ERROR; - } - return TCL_OK; - } - else if(strcmp(argv[1],"-readable") == 0) - { - iRet = NetReadReadable(pServ->pReader,SerialGetSocket(&(pData))); - if(iRet) - { - Tcl_AppendResult(interp,"1",NULL); - return TCL_OK; - } - else - { - Tcl_AppendResult(interp,"0",NULL); - return TCL_OK; - } - } - else if(strcmp(argv[1],"-get") == 0) - { - if(NetReadReadable(pServ->pReader,SerialGetSocket(&(pData)))) - { - iRet = SerialReceive(&(pData),pAnswer, 255); - Tcl_AppendResult(interp,pAnswer,NULL); - if(iRet == 1) - { - return TCL_OK; - } - else - { - return TCL_ERROR; - } - } - Tcl_AppendResult(interp,"Not Readable",NULL); - return TCL_ERROR; - } - } - - - if(argc >= 2) - { - strcpy(pBueffel,argv[1]); - } - for(i = 2; i < argc; i++) - { - strcat(pBueffel," "); - strcat(pBueffel,argv[i]); - } - i = strlen(pBueffel); - iRet = SerialWriteRead(&(pData),pBueffel,pAnswer,254); - if(iRet != 1) - { - Tcl_AppendResult(interp,pAnswer,NULL); - return TCL_ERROR; - } - Tcl_AppendResult(interp,pAnswer,NULL); - return TCL_OK; -} diff --git a/script.c b/script.c index a539ca7c..5568e3cf 100644 --- a/script.c +++ b/script.c @@ -55,515 +55,514 @@ #include "status.h" #include "script.h" #include "devexec.h" - - extern Tcl_Interp *InterpGetTcl(SicsInterp *pSics); - extern void SNXFormatTime(char *pBueffel, int iLen); /* in nxdata.c */ - + +extern Tcl_Interp *InterpGetTcl(SicsInterp * pSics); +extern void SNXFormatTime(char *pBueffel, int iLen); /* in nxdata.c */ + /* -------------------------- Interrupts -----------------------------------*/ - int GetSICSInterrupt(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - char pBueffel[132]; - SConnection *pOwner = NULL; - pExeList pDev = NULL; - - assert(pCon); - assert(pSics); +int GetSICSInterrupt(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + char pBueffel[132]; + SConnection *pOwner = NULL; + pExeList pDev = NULL; - /* we are interested in the interrupt pending in the executor. If - not specified, use our very own - */ - pDev = GetExecutor(); - assert(pDev); - pOwner = GetExeOwner(pDev); - if(pOwner) - { - Interrupt2Text(SCGetInterrupt(pOwner),pBueffel,131); - SCWrite(pCon,pBueffel,eStatus); - } - else - { - Interrupt2Text(SCGetInterrupt(pCon),pBueffel,131); - SCWrite(pCon,pBueffel,eStatus); - } - return 1; - } -/*-------------------------------------------------------------------------*/ - int SetSICSInterrupt(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - int iInt; - char pBueffel[132]; - SConnection *pOwner = NULL; - pExeList pDev = NULL; - - assert(pCon); - assert(pSics); - - /* minimum user privelege */ - if(!SCMatchRights(pCon,usUser)) - { - SCWrite(pCon,"ERROR: you are not priviledged to set interrupts",eError); - return 0; - } - - /* only in script processing */ - if(!SCinMacro(pCon)) - { - SCWrite(pCon,"ERROR: Interrupt manipulation only permitted in Macros", - eError); - return 0; - } - - /* is there a value ? */ - if(argc < 2) - { - SCWrite(pCon,"ERROR: missing parameter for SetInterrupt",eError); - return 0; - } - - /* actually do a job */ - strtolower(argv[1]); - iInt = Text2Interrupt(argv[1]); - if(iInt < 0) - { - sprintf(pBueffel,"ERROR: %s not recognized as Interrupt code", - argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } + assert(pCon); + assert(pSics); + + /* we are interested in the interrupt pending in the executor. If + not specified, use our very own + */ + pDev = GetExecutor(); + assert(pDev); + pOwner = GetExeOwner(pDev); + if (pOwner) { + Interrupt2Text(SCGetInterrupt(pOwner), pBueffel, 131); + SCWrite(pCon, pBueffel, eValue); + } else { + Interrupt2Text(SCGetInterrupt(pCon), pBueffel, 131); + SCWrite(pCon, pBueffel, eValue); + } + return 1; +} + +/*-------------------------------------------------------------------------*/ +int SetSICSInterrupt(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + int iInt; + char pBueffel[132]; + SConnection *pOwner = NULL; + pExeList pDev = NULL; + + assert(pCon); + assert(pSics); + + /* minimum user privelege */ + if (!SCMatchRights(pCon, usUser)) { + SCWrite(pCon, "ERROR: you are not priviledged to set interrupts", + eError); + return 0; + } + + /* only in script processing */ + if (!SCinMacro(pCon)) { + SCWrite(pCon, "ERROR: Interrupt manipulation only permitted in Macros", + eError); + return 0; + } + + /* is there a value ? */ + if (argc < 2) { + SCWrite(pCon, "ERROR: missing parameter for SetInterrupt", eError); + return 0; + } + + /* actually do a job */ + strtolower(argv[1]); + iInt = Text2Interrupt(argv[1]); + if (iInt < 0) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s not recognized as Interrupt code", + argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* we want to change the interrupt pending in the executor. If none + there, charnge our own. + */ + pDev = GetExecutor(); + assert(pDev); + pOwner = GetExeOwner(pDev); + if (pOwner) { + SCSetInterrupt(pOwner, iInt); + } else { + SCSetInterrupt(pCon, iInt); + } + SCSendOK(pCon); + return 1; +} + +/*-------------------------------------------------------------------------*/ +int SetSICSStatus(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + int iInt; + char pBueffel[132]; + + assert(pCon); + assert(pSics); + + /* minimum user privelege */ + if (!SCMatchRights(pCon, usUser)) { + SCWrite(pCon, "ERROR: you are not priviledged to set status", eError); + return 0; + } + + /* only in script processing */ + if (!SCinMacro(pCon)) { + SCWrite(pCon, "ERROR: status manipulation only permitted in Macros", + eError); + return 0; + } + + /* is there a value ? */ + if (argc < 2) { + SCWrite(pCon, "ERROR: missing parameter for SetStatus", eError); + return 0; + } + + /* actually do a job */ + strtolower(argv[1]); + iInt = SetStatusFromText(argv[1]); + if (iInt) { + SCSendOK(pCon); + return 1; + } else { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s not recognized as status code", argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } +} - /* we want to change the interrupt pending in the executor. If none - there, charnge our own. - */ - pDev = GetExecutor(); - assert(pDev); - pOwner = GetExeOwner(pDev); - if(pOwner) - { - SCSetInterrupt(pOwner,iInt); - } - else - { - SCSetInterrupt(pCon,iInt); - } - SCSendOK(pCon); - return 1; - } -/*-------------------------------------------------------------------------*/ - int SetSICSStatus(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - int iInt; - char pBueffel[132]; - - assert(pCon); - assert(pSics); - - /* minimum user privelege */ - if(!SCMatchRights(pCon,usUser)) - { - SCWrite(pCon,"ERROR: you are not priviledged to set status",eError); - return 0; - } - - /* only in script processing */ - if(!SCinMacro(pCon)) - { - SCWrite(pCon,"ERROR: status manipulation only permitted in Macros", - eError); - return 0; - } - - /* is there a value ? */ - if(argc < 2) - { - SCWrite(pCon,"ERROR: missing parameter for SetStatus",eError); - return 0; - } - - /* actually do a job */ - strtolower(argv[1]); - iInt = SetStatusFromText(argv[1]); - if(iInt) - { - SCSendOK(pCon); - return 1; - } - else - { - sprintf(pBueffel,"ERROR: %s not recognized as status code",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - } /*-----------------------------------------------------------------------*/ - static int isNum(char *pText) - { - int i; - int iRet = 1; - - for(i = 0; i < strlen(pText); i++) - { - if(!isdigit(pText[i])) - { - if(!((pText[i] == '+') || (pText[i] == '-') || (pText[i] == '.'))) - { - iRet = 0; - break; - } - } +static int isNum(char *pText) +{ + int i; + int iRet = 1; + + for (i = 0; i < strlen(pText); i++) { + if (!isdigit(pText[i])) { + if (!((pText[i] == '+') || (pText[i] == '-') || (pText[i] == '.'))) { + iRet = 0; + break; } - return iRet; - } - + } + } + return iRet; +} + /*--------------------------- Type Checking ------------------------------- classifies a given string: numeric, countable, drivable, sicsobject, text */ - - int SICSType(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - CommandList *pCom = NULL; - Dummy *pDum = NULL; - char pBueffel[132]; - - - assert(pCon); - assert(pSics); - - /* is there a parameter anyway */ - if(argc < 2) - { - SCWrite(pCon,"ERROR: no object to test specified!",eError); - return 0; - } - - /* test, one by one */ - strtolower(argv[1]); - if(isNum(argv[1])) - { - SCWrite(pCon,"NUM",eValue); + +int SICSType(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + CommandList *pCom = NULL; + Dummy *pDum = NULL; + char pBueffel[132]; + + + assert(pCon); + assert(pSics); + + /* is there a parameter anyway */ + if (argc < 2) { + SCWrite(pCon, "ERROR: no object to test specified!", eError); + return 0; + } + + /* test, one by one */ + strtolower(argv[1]); + if (isNum(argv[1])) { + SCWrite(pCon, "NUM", eValue); + return 1; + } + + pCom = FindCommand(pSics, argv[1]); + if (pCom) { + pDum = (Dummy *) pCom->pData; + if (pDum) { + if (pDum->pDescriptor->GetInterface(pDum, DRIVEID)) { + SCWrite(pCon, "DRIV", eValue); return 1; - } - - pCom = FindCommand(pSics,argv[1]); - if(pCom) - { - pDum = (Dummy *)pCom->pData; - if(pDum) - { - if(pDum->pDescriptor->GetInterface(pDum,DRIVEID)) - { - SCWrite(pCon,"DRIV",eValue); - return 1; - } - if(pDum->pDescriptor->GetInterface(pDum,COUNTID)) - { - SCWrite(pCon,"COUNT",eValue); - return 1; - } - } - SCWrite(pCon,"COM",eValue); - return 1; - } - - SCWrite(pCon,"TEXT",eValue); - return 1; - } - + } + if (pDum->pDescriptor->GetInterface(pDum, COUNTID)) { + SCWrite(pCon, "COUNT", eValue); + return 1; + } + } + SCWrite(pCon, "COM", eValue); + return 1; + } + + SCWrite(pCon, "TEXT", eValue); + return 1; +} + /*----------------- Bounds checking for all driveables ---------------------*/ - int SICSBounds(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - CommandList *pCom = NULL; - pIDrivable pInt = NULL; - Dummy *pDum = NULL; - char pBueffel[132]; - float fVal; - int iRet; - - assert(pCon); - assert(pSics); - - if(argc < 3) - { - SCWrite(pCon,"ERROR: not enough parameters specified",eError); - return 0; - } - - /* argv[1] should be drivable */ - pCom = FindCommand(pSics,argv[1]); - if(!pCom) - { - sprintf(pBueffel,"ERROR: %s is no Sics Object",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - pDum = (Dummy *)pCom->pData; - if(!pDum) - { - sprintf(pBueffel,"ERROR: %s is no valid Sics Object",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - pInt = pDum->pDescriptor->GetInterface(pDum,DRIVEID); - if(!pInt) - { - sprintf(pBueffel,"ERROR: %s is not drivable!",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* argv[2] should be a numeric */ - if(!isNum(argv[2])) - { - sprintf(pBueffel,"ERROR: %s is not a number!",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* do a job */ - fVal = atof(argv[2]); - iRet = pInt->CheckLimits(pCom->pData,fVal,pBueffel,131); - if(iRet) - { - SCWrite(pCon,"OK",eValue); - return 1; - } - else - { - SCWrite(pCon,pBueffel,eWarning); - return 0; - } - return 0; /* not reached */ - } +int SICSBounds(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + CommandList *pCom = NULL; + pIDrivable pInt = NULL; + Dummy *pDum = NULL; + char pBueffel[132]; + float fVal; + int iRet; + + assert(pCon); + assert(pSics); + + if (argc < 3) { + SCWrite(pCon, "ERROR: not enough parameters specified", eError); + return 0; + } + + /* argv[1] should be drivable */ + pCom = FindCommand(pSics, argv[1]); + if (!pCom) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s is no Sics Object", argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + pDum = (Dummy *) pCom->pData; + if (!pDum) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s is no valid Sics Object", argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + pInt = pDum->pDescriptor->GetInterface(pDum, DRIVEID); + if (!pInt) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s is not drivable!", argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* argv[2] should be a numeric */ + if (!isNum(argv[2])) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s is not a number!", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* do a job */ + fVal = atof(argv[2]); + iRet = pInt->CheckLimits(pCom->pData, fVal, pBueffel, 131); + if (iRet) { + SCWrite(pCon, "OK", eValue); + return 1; + } else { + SCWrite(pCon, pBueffel, eWarning); + return 0; + } + return 0; /* not reached */ +} + /*----------------- Status checking for Sics Objects ---------------------*/ - int SICSStatus(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - CommandList *pCom = NULL; - Dummy *pDum = NULL; - pIDrivable pDInt = NULL; - pICountable pCInt = NULL; - char pBueffel[132]; - float fVal; - int iRet; - - assert(pCon); - assert(pSics); - - if(argc < 2) - { - SCWrite(pCon,"ERROR: not enough parameters specified",eError); - return 0; - } - - /* argv[1] should be drivable */ - pCom = FindCommand(pSics,argv[1]); - if(!pCom) - { - sprintf(pBueffel,"ERROR: %s is no Sics Object",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - pDum = (Dummy *)pCom->pData; - if(!pDum) - { - sprintf(pBueffel,"ERROR: %s is no valid Sics Object",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - pDInt = pDum->pDescriptor->GetInterface(pDum,DRIVEID); - pCInt = pDum->pDescriptor->GetInterface(pDum,COUNTID); - if(pDInt) - { - iRet = pDInt->CheckStatus(pDum,pCon); - sprintf(pBueffel,"%d",iRet); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - else if(pCInt) - { - iRet = pCInt->CheckCountStatus(pDum,pCon); - sprintf(pBueffel,"%d",iRet); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - else - { - sprintf(pBueffel,"ERROR: %s is neither drivable nor countable",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - /* not reached */ - return 0; +int SICSStatus(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + CommandList *pCom = NULL; + Dummy *pDum = NULL; + pIDrivable pDInt = NULL; + pICountable pCInt = NULL; + char pBueffel[132]; + float fVal; + int iRet; - } -/*--------------------------------------------------------------------------*/ - int SICSDebug(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - char pBueffel[256]; - Tcl_Interp *pTcl = NULL; - int iRet; - char *cmd; - - assert(pCon); - assert(pSics); - - if(!SCMatchRights(pCon,usInternal)) - { - SCWrite(pCon,"ERROR: no privilege to interact with Tcl for you", - eError); - return 0; - } - - pTcl = InterpGetTcl(pSics); - assert(pTcl); - - cmd = Arg2Tcl(argc-1,&argv[1],pBueffel,sizeof pBueffel); - if (!cmd) { - SCWrite(pCon,"ERROR: no more memory",eError); - return 0; - } - iRet = Tcl_Eval(pTcl,cmd); - if (cmd != pBueffel) free(cmd); - if(strlen(pTcl->result) > 1) - { - SCWrite(pCon,pTcl->result,eValue); - } - return iRet; - } -/*--------------------------------------------------------------------------*/ - int SICSTime(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - char pBueffel[256]; + assert(pCon); + assert(pSics); - SNXFormatTime(pBueffel,255); - SCWrite(pCon,pBueffel,eValue); - return 1; - } + if (argc < 2) { + SCWrite(pCon, "ERROR: not enough parameters specified", eError); + return 0; + } + + /* argv[1] should be drivable */ + pCom = FindCommand(pSics, argv[1]); + if (!pCom) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s is no Sics Object", argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + pDum = (Dummy *) pCom->pData; + if (!pDum) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s is no valid Sics Object", argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + pDInt = pDum->pDescriptor->GetInterface(pDum, DRIVEID); + pCInt = pDum->pDescriptor->GetInterface(pDum, COUNTID); + if (pDInt) { + iRet = pDInt->CheckStatus(pDum, pCon); + snprintf(pBueffel,sizeof(pBueffel)-1, "%d", iRet); + SCWrite(pCon, pBueffel, eValue); + return 1; + } else if (pCInt) { + iRet = pCInt->CheckCountStatus(pDum, pCon); + snprintf(pBueffel,sizeof(pBueffel)-1, "%d", iRet); + SCWrite(pCon, pBueffel, eValue); + return 1; + } else { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s is neither drivable nor countable", + argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + /* not reached */ + return 0; + +} + +/*--------------------------------------------------------------------------*/ +int SICSDebug(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + char pBueffel[256]; + Tcl_Interp *pTcl = NULL; + int iRet; + char *cmd; + + assert(pCon); + assert(pSics); + + if (!SCMatchRights(pCon, usInternal)) { + SCWrite(pCon, "ERROR: no privilege to interact with Tcl for you", + eError); + return 0; + } + + pTcl = InterpGetTcl(pSics); + assert(pTcl); + + cmd = Arg2Tcl(argc - 1, &argv[1], pBueffel, sizeof pBueffel); + if (!cmd) { + SCWrite(pCon, "ERROR: no more memory", eError); + return 0; + } + iRet = Tcl_Eval(pTcl, cmd); + if (cmd != pBueffel) + free(cmd); + if (strlen(pTcl->result) > 1) { + SCWrite(pCon, pTcl->result, eValue); + } + return iRet; +} + +/*--------------------------------------------------------------------------*/ +int SICSTime(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + char pBueffel[256]; + + SNXFormatTime(pBueffel, 255); + SCWrite(pCon, pBueffel, eValue); + return 1; +} +/*-------------------------------------------------------------------------*/ +int SICSDoubleTime(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + double dtime; + + dtime = DoubleTime(); + SCPrintf(pCon,eValue,"%lf",dtime); + return 1; +} /*-------------------------------------------------------------------------- Kill a command from SICS -*/ - int SICSKill(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - CommandList *pCom = NULL, *pCurrent = NULL; - void *pDat = NULL; - char *pPtr = NULL; - - if(!SCMatchRights(pCon,usMugger)) - { - SCWrite(pCon,"ERROR: you may not kill commands here, no privilege", - eError); - return 0; - } - - if(argc < 2) - { - SCWrite(pCon,"ERROR: need name of command to kill",eError); - return 0; - } +*/ +int SICSKill(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + CommandList *pCom = NULL, *pCurrent = NULL; + void *pDat = NULL; + char *pPtr = NULL; + + if (!SCMatchRights(pCon, usMugger)) { + SCWrite(pCon, "ERROR: you may not kill commands here, no privilege", + eError); + return 0; + } + + if (argc < 2) { + SCWrite(pCon, "ERROR: need name of command to kill", eError); + return 0; + } + + /* memorise data for alias search */ + pCom = FindCommand(pSics, argv[1]); + if (pCom) { + pDat = pCom->pData; + } else { + pDat = NULL; + } + RemoveCommand(pSics, argv[1]); + if (!pDat) { /* no data, no alias */ + SCSendOK(pCon); + return 0; + } + + /* kill aliases */ + pPtr = FindAlias(pSics, pDat); + while (pPtr) { + RemoveCommand(pSics, pPtr); + pPtr = FindAlias(pSics, pDat); + } + SCSendOK(pCon); + return 1; +} - /* memorise data for alias search */ - pCom = FindCommand(pSics,argv[1]); - if(pCom) - { - pDat = pCom->pData; - } - else - { - pDat = NULL; - } - RemoveCommand(pSics,argv[1]); - if(!pDat) /* no data, no alias */ - { - SCSendOK(pCon); - return 0; - } - - /* kill aliases */ - pPtr = FindAlias(pSics,pDat); - while(pPtr) - { - RemoveCommand(pSics,pPtr); - pPtr = FindAlias(pSics,pDat); - } - SCSendOK(pCon); - return 1; - } /*------------------------------------------------------------------------*/ - int SicsPrompt(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - char pBueffel[512]; - int iRet; +int SicsPrompt(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + char pBueffel[512]; + int iRet; + + /* all arguments are optional */ + if (argc < 1) { + iRet = SCPrompt(pCon, "SICS> ", pBueffel, 511); + } else { + iRet = SCPrompt(pCon, argv[1], pBueffel, 511); + } + if (iRet == 1) { + SCWrite(pCon, pBueffel, eValue); + return 1; + } else { + SCWrite(pCon, "ERROR: Interrupted while waiting for data", eError); + return 0; + } +} - /* all arguments are optional */ - if(argc < 1) - { - iRet = SCPrompt(pCon, "SICS> ", - pBueffel, 511); - } - else - { - iRet = SCPrompt(pCon, argv[1], - pBueffel, 511); - } - if(iRet == 1) - { - SCWrite(pCon,pBueffel,eValue); - return 1; - } - else - { - SCWrite(pCon,"ERROR: Interrupted while waiting for data",eError); - return 0; - } - } /*----------------------- get object descriptor name ------------------------------- get the name of the object descriptor */ +int SICSDescriptor(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + CommandList *pCom = NULL; + Dummy *pDum = NULL; + char pBueffel[132]; + + + assert(pCon); + assert(pSics); + + /* is there a parameter anyway */ + if (argc < 2) { + SCWrite(pCon, "ERROR: no object specified!", eError); + return 0; + } + + pCom = FindCommand(pSics, argv[1]); + if (pCom) { + pDum = (Dummy *) pCom->pData; + if (pDum) { + SCWrite(pCon, pDum->pDescriptor->name, eValue); + return 1; + } + SCWrite(pCon, "empty", eValue); + return 1; + } + + SCWrite(pCon, "notfound", eValue); + return 1; +} +/*------------------------------------------------------------------------*/ +int SICSSilent(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]) { + Tcl_Interp *pTcl = NULL; + int iRet; + char *cmd; + char *result; + writeFunc oldWrite; - int SICSDescriptor(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - CommandList *pCom = NULL; - Dummy *pDum = NULL; - char pBueffel[132]; - - - assert(pCon); - assert(pSics); - - /* is there a parameter anyway */ - if(argc < 2) - { - SCWrite(pCon,"ERROR: no object specified!",eError); - return 0; - } - - pCom = FindCommand(pSics,argv[1]); - if(pCom) - { - pDum = (Dummy *)pCom->pData; - if(pDum) - { - SCWrite(pCon,pDum->pDescriptor->name,eValue); - return 1; - } - SCWrite(pCon,"empty",eValue); - return 1; - } - - SCWrite(pCon,"notfound",eValue); - return 1; - } - + assert(pCon); + assert(pSics); + + if (!SCinMacro(pCon)) { + SCPrintf(pCon, eError, + "ERROR: %s may only be called in scripts", argv[0]); + return 0; + } + pTcl = InterpGetTcl(pSics); + assert(pTcl); + if (argc < 3) { + SCWrite(pCon, "ERROR: should be: silent ", eError); + return 0; + } + cmd = Arg2Tcl(argc-2,&argv[2],NULL,0); + assert(cmd); + + oldWrite = SCGetWriteFunc(pCon); + SCSetWriteFunc(pCon,SCNotWrite); + iRet = Tcl_EvalEx(pTcl, cmd, strlen(cmd), 0); + SCSetWriteFunc(pCon,oldWrite); + + if (iRet == TCL_OK) { + result = strdup((char *)Tcl_GetStringResult(pTcl)); + SCWrite(pCon, result, eValue); + free(result); + } else { + SCWrite(pCon, argv[1], eValue); + } + free(cmd); + return 1; +} diff --git a/script.h b/script.h index 29cbafad..82859058 100644 --- a/script.h +++ b/script.h @@ -11,43 +11,44 @@ #define SICSSCRIPT /* -------------------------- Interrupts -----------------------------------*/ - int GetSICSInterrupt(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - - int SetSICSInterrupt(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - +int GetSICSInterrupt(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); + +int SetSICSInterrupt(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); + /*---------------------------- Status -------------------------------------*/ - int SetSICSStatus(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - +int SetSICSStatus(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); + /*--------------------------- Type Checking -------------------------------*/ - int SICSType(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - +int SICSType(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); + /*----------------- Bounds checking for all driveables ---------------------*/ - int SICSBounds(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); +int SICSBounds(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); /*------------------ Status checking for SicsObjects ----------------------- */ - int SICSStatus(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); +int SICSStatus(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); /*------------------ Type directly to Tcl ----------------------- */ - int SICSDebug(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); +int SICSDebug(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); /*-----------------------------------------------------------------------*/ - int SICSTime(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); +int SICSTime(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); /*----------------------------------------------------------------------*/ - int SICSKill(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); +int SICSKill(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); /*----------------------------------------------------------------------*/ - int SicsPrompt(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); +int SicsPrompt(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); /*----------------------------------------------------------------------*/ - int SICSDescriptor(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); +int SICSDescriptor(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); +/*----------------------------------------------------------------------*/ +int SICSSilent(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]); #endif - - diff --git a/scriptcontext.c b/scriptcontext.c index 59d62f1f..dc22c30d 100644 --- a/scriptcontext.c +++ b/scriptcontext.c @@ -13,51 +13,62 @@ #include "devser.h" #include "ascon.h" #include "macro.h" +#include "syncedprot.h" #include "scriptcontext.h" - -#define MAX_HDB_PATH 1024 - typedef struct ContextItem { struct ContextItem *next; Hdb *node; - Hdb *controllerNode; + SctController *controller; } ContextItem; typedef struct ScriptContext { ObjectDescriptor *desc; ContextItem *nodes; ContextItem *trash; + Hdb *sendNode; + int sendCalled; } ScriptContext; struct SctController { DevSer *devser; - Hdb *node; /* the controller node */ - SCStore *conn; + Hdb *node; /* the controller node */ + SConnection *conn; int verbose; + FILE *fd; }; /* action data and write callback data */ typedef struct SctData { char *name; SctController *controller; - SCStore *conCtx; + SConnection *conCtx; int answered; + int inMacro; Hdb *node; + long syncid; } SctData; +/* data for updatescript */ +typedef struct SctUpdatescript { + char *name; + SctController *controller; +} SctUpdatescript; + + static ScriptContext *sct = NULL; -static SCStore *currentCon = NULL; +static SctData *queueData = NULL; static struct { char *name; } actionCallback; -static char *mainCallback = "main callback"; +static struct SctUpdatescript updatescriptCallback; -void PushContext(Hdb *node, Hdb *controllerNode) { +void PushContext(Hdb * node, SctController * controller) +{ ContextItem *new; - + if (sct->trash == NULL) { new = calloc(1, sizeof(*new)); } else { @@ -67,12 +78,13 @@ void PushContext(Hdb *node, Hdb *controllerNode) { new->next = sct->nodes; sct->nodes = new; new->node = node; - new->controllerNode = controllerNode; + new->controller = controller; } -void PopContext(void) { +void PopContext(void) +{ ContextItem *c; - + c = sct->nodes; assert(c); sct->nodes = c->next; @@ -80,167 +92,277 @@ void PopContext(void) { sct->trash = c; } -void CleanStack(Hdb *node) { +void CleanStack(Hdb * node) +{ ContextItem *s; - + /* clean context from killed nodes */ for (s = sct->nodes; s != NULL; s = s->next) { if (s->node == node) { s->node = NULL; } - if (s->controllerNode == node) { - s->controllerNode = NULL; + if (s->controller->node == node) { + s->controller = NULL; } } } -static void SetProp(Hdb *node, Hdb *cNode, char *key, char *value) { +static char *GetPropAndNode(Hdb * node, Hdb * cNode, char *key, Hdb **foundNode) +{ char *val; - - if (node == NULL) { - if (cNode == NULL) return; - node = cNode; - } else { - val = GetHdbProp(node, key); - if (val == NULL && cNode != NULL) { - val = GetHdbProp(cNode, key); + Hdb *mama; + + if (key[0] == '@') { + /* for keys starting with @ look also at the ancestors */ + for (mama = node; mama != NULL; mama = mama->mama) { + val = GetHdbProp(mama, key); if (val != NULL) { - node = cNode; + *foundNode = mama; + return val; } } } - if (value == NULL) { - if (GetHdbProperty(node, key, NULL, 0) > 0) { - SetHdbProperty(node, key, ""); - } - } else { - SetHdbProperty(node, key, value); - } -} - -static char *GetProp(Hdb *node, Hdb *cNode, char *key) { - char *val; - if (node != NULL) { val = GetHdbProp(node, key); - if (val != NULL) return val; + if (val != NULL) { + *foundNode = node; + return val; + } } if (cNode != NULL) { val = GetHdbProp(cNode, key); + if (val != NULL) { + *foundNode = cNode; + return val; + } } - return val; + *foundNode = node; + return NULL; +} + +static void SetProp(Hdb * node, Hdb * cNode, char *key, char *value) +{ + Hdb *propNode; + char *val; + + val = GetPropAndNode(node, cNode, key, &propNode); + if (value == NULL) { + if (val != NULL) { + SetHdbProperty(propNode, key, ""); + } + } else { + SetHdbProperty(propNode, key, value); + } +} + +static char *GetProp(Hdb * node, Hdb * cNode, char *key) +{ + Hdb *propNode; + return GetPropAndNode(node, cNode, key, &propNode); } /* * This is the actual sct command available in scripts. */ -int SctCommand(SConnection *con, SicsInterp *sics, void *object, - int argc, char *argv[]) { +int SctCommand(SConnection * con, SicsInterp * sics, void *object, + int argc, char *argv[]) +{ static char value[1024]; char *val; char error[512]; Hdb *node = NULL; Hdb *cNode = NULL; hdbValue v; - double dtime; + SctController *controller; assert(sct == object); if (sct->nodes != NULL) { node = sct->nodes->node; - cNode = sct->nodes->controllerNode; + controller = sct->nodes->controller; } - if (node == NULL && cNode == NULL) { + if (node == NULL || controller == NULL || controller->node == NULL) { SCPrintf(con, eError, "ERROR: %s may be called only in proper context", - argv[0]); + argv[0]); return 0; } + + /* + * get path (pure sct command) + */ if (argc <= 1) { GetHdbPath(node, value, sizeof value); SCWrite(con, value, eValue); return 1; } - + /* * update command */ - if(strcmp(argv[1],"update") == 0){ - cloneHdbValue(&node->value, &v); - Arg2Text(argc-2, argv+2, value, sizeof value); - if(!readHdbValue(&v, value, error, 512)){ - SCWrite(con, error, eError); - return 0; - } - UpdateHipadabaPar(node,v,con); - SetHdbProperty(node,"geterror", NULL); - return 1; + if (strcmp(argv[1], "update") == 0) { + cloneHdbValue(&node->value, &v); + Arg2Text(argc - 2, argv + 2, value, sizeof value); + if (!readHdbValue(&v, value, error, 512)) { + SCWrite(con, error, eError); + return 0; + } + UpdateHipadabaPar(node, v, con); + ReleaseHdbValue(&v); + SetHdbProperty(node, "geterror", NULL); + return 1; } /* * print */ - if(strcmp(argv[1],"print") == 0){ - Arg2Text(argc-2, argv+2, value, sizeof value); - SCWrite(con,value,eWarning); - return 1; + if (strcmp(argv[1], "print") == 0) { + if (queueData != NULL) { + queueData->answered = 1; + SCsetMacro(con, queueData->inMacro); /* take macro flag stored at set callback */ + } + Arg2Text(argc - 2, argv + 2, value, sizeof value); + SCWrite(con, value, eLog); + SCsetMacro(con, 1); /* we are always in Macro */ + return 1; } - + + /** + * controller + */ + if (strcmp(argv[1], "controller") == 0) { + SCWrite(con, controller->node->name, eValue); + return 1; + } + /* * time stamping - */ - if(strcmp(argv[1],"utime") == 0){ - if(argc < 3){ - SCWrite(con,"ERROR: need property to write time stamp too", - eError); - return 0; - } - dtime = DoubleTime(); - snprintf(value,1024,"%.3f",dtime); - SetHdbProperty(node,argv[2], value); - return 1; + */ + if (strcmp(argv[1], "utime") == 0) { + snprintf(value, 1024, "%.3f", DoubleTime()); + if (argc > 2) { /* if no property is given, use only return value */ + SetHdbProperty(node, argv[2], value); + } + /* write time as return value */ + SCWrite(con, value, eValue); + return 1; } - + + /* + * with command (execute a script in the context of an other node) + */ + if (strcmp(argv[1], "with") == 0) { + if (argc < 3) { + SCPrintf(con, eError, "ERROR: syntax must be: %s %s node script", + argv[0], argv[1]); + return 0; + } + GetHdbPath(node, value, sizeof value); + node = FindHdbNode(value, argv[2], con); /* get a relative path */ + if (node == NULL) { + SCPrintf(con, eError, "ERROR: %s %s: node %s not found", + argv[0], argv[1], argv[2]); + return 0; + } + if (SctCallInContext(con, argv[3], node, controller, &val) == 0) { + SCPrintf(con, eError, "ERROR: in %s %s %s {%s}: %s", + argv[0], argv[1], argv[2], argv[3], val); + return 0; + } + return 1; + } + + /* + * parent command (return path of parent node) + */ + if (strcmp(argv[1], "parent") == 0) { + if (argc > 3) { + SCPrintf(con, eError, "ERROR: syntax must be: %s %s [path]", + argv[0], argv[1]); + return 0; + } + if (argc == 3) { + node = FindHdbNode(NULL, argv[2], con); + } + GetHdbPath(node->mama, value, sizeof value); + /* returns an empty string on error */ + SCWrite(con, value, eValue); + return 1; + } + + /* + * send command + */ + if (strcmp(argv[1], "send") == 0 && argc > 2) { + if (sct->sendNode != node) { + SCPrintf(con, eError, "ERROR: %s may be called only in action scripts", + argv[0]); + return 0; + } + sct->sendCalled = 1; + /* continue with property handling */ + } + /* * property handling */ - if (argc == 2) { /* get case */ - val = GetProp(node, cNode, argv[1]); + if (argc == 2) { /* get case */ + val = GetProp(node, controller->node, argv[1]); if (val == NULL) { SCPrintf(con, eError, "ERROR: %s %s not found", argv[0], argv[1]); return 0; } SCWrite(con, val, eValue); - } else { /* set case */ + } else { /* set case */ if (argc == 3) { - SetProp(node, cNode, argv[1], argv[2]); + SetProp(node, controller->node, argv[1], argv[2]); } else { - val = Arg2Tcl(argc-2, argv+2, value, sizeof value); - SetProp(node, cNode, argv[1], val); - if (val != NULL && val != value) free(val); + val = Arg2Tcl(argc - 2, argv + 2, value, sizeof value); + SetProp(node, controller->node, argv[1], val); + if (val != NULL && val != value) + free(val); } } return 1; } -int SctCallInContext(SConnection *con, char *script, Hdb *node, - SctController *controller, char **resPtr) { +double secondsOfMinute() { + double now=DoubleTime(); + return (now/60-floor(now/60))*60; +} + +int SctCallInContext(SConnection * con, char *script, Hdb * node, + SctController * controller, char **resPtr) +{ Tcl_Interp *pTcl = InterpGetTcl(pServ->pSics); int ret, l; char *result = NULL; int iRet = 1; int verbose = controller->verbose; - PushContext(node, controller->node); + PushContext(node, controller); if (verbose) { - SCPrintf(con, eInError, "\nscript: %s\n", script); + SCPrintf(con, eLog, "%6.3f script: %s", secondsOfMinute(), script); } - + if (controller->fd != NULL) { + fprintf(controller->fd,"%6.3f script: %s\n", secondsOfMinute(), script); + } + MacroPush(con); l = strlen(script); ret = Tcl_EvalEx(pTcl, script, l, 0); - result = (char *)Tcl_GetStringResult(pTcl); - if (ret != TCL_OK && result[0]!='\0') { + result = (char *) Tcl_GetStringResult(pTcl); + if (ret != TCL_OK && result[0] != '\0') { + if (strncmp(result, "ERROR:", 6) == 0) { + /* remove "ERROR:", as it will be added later */ + result += 6; + if (result[0] == ' ') { + result++; + } + } if (verbose) { - SCPrintf(con, eInError, "\nerror: %s\n", result); + SCPrintf(con, eLog, "%6.3f error: %s", secondsOfMinute(), result); + } + if(controller->fd != NULL){ + fprintf(controller->fd, "%6.3f error: %s\n", secondsOfMinute(), result); } iRet = 0; } @@ -251,123 +373,320 @@ int SctCallInContext(SConnection *con, char *script, Hdb *node, return iRet; } -static int SctMatch(void *data1, void *data2) { +static int SctMatch(void *data1, void *data2) +{ SctData *a = data1; SctData *b = data2; - + return a->node == b->node && strcasecmp(a->name, b->name) == 0; } -static char *SctActionHandler(void *actionData, char *lastReply) { +/* + * This routine is running the script chain. It is called repeatedly + * with response data from the device serializer (devser). This function + * basically: + * - Figures out which script to run + * - Runs the script + * - Based on the result either returns the next string to send to the + * device or NULL when the script chain is done with + */ +static char *SctActionHandler(void *actionData, char *lastReply, + int commError) +{ SctData *data = actionData; Hdb *node = data->node; SctController *controller = data->controller; char *state; char *result; - char *script; + char *script = NULL; + char *errorScript = NULL; char *send = NULL; int i; SConnection *con; + char eprop[80]; + char msg[1024]; + char path[MAX_HDB_PATH]; + char origScript[80]; + char *blank; + char *emsg; + size_t l; + int cnt; + int ret; char timeKey[50], timeVal[50]; + int iMacro; - if (currentCon) { - con = SCStorePush(currentCon); + assert(data->name); + if (queueData != NULL && queueData->conCtx != NULL) { + con = queueData->conCtx; } else { - con = SCStorePush(controller->conn); + con = controller->conn; } - if (lastReply != NULL) { - SetProp(node, controller->node, "result", lastReply); + /* + * If this is a followup call, the I/O system will have set the + * property result to the data from the device. Read this now and + * print it if diagnostics is required. + */ + SetProp(node, controller->node, "result", lastReply); + script = NULL; + if (!commError && controller->verbose && lastReply != NULL + && *lastReply != '\0') { + SCPrintf(con, eLog, "%6.3f reply : %s\n", secondsOfMinute(), lastReply); } - if (controller->verbose && lastReply != NULL && *lastReply != '\0') { - SCPrintf(con, eWarning, "reply : %s", lastReply); + if(!commError && controller->fd != NULL && lastReply != NULL && *lastReply != '\0'){ + fprintf(controller->fd, "%6.3f reply : %s\n", secondsOfMinute(), lastReply); } + if(lastReply != NULL && *lastReply != '\0'){ + if(data != NULL && data->controller != NULL){ + traceIO(data->controller->node->name, "reply:%s", lastReply); + } else { + traceIO("sctunknown", "reply:%s", lastReply); + } + } + + /* + * When this is a followup, we use the content of the + * state field as the property storing the next script to + * run. If this is the start of a chain this is set to the + * data->name which is mostly either read or write + */ state = GetProp(node, controller->node, "state"); if (state == NULL || strcasecmp(state, "idle") == 0) { state = data->name; SetProp(node, controller->node, "state", state); } + + /* + * Sometimes one wishes to call multiple scripts in succession + * before returning into I/O. Such scripts then do not set the + * send property. The loop is taking care of this. Not more + * then 10 scripts can be chained in this way. + */ for (i = 0; i < 10; i++) { - SetProp(node, controller->node, "send", NULL); + /* + * read the script to invoke from the property living + * in state + */ script = GetProp(node, controller->node, state); - if (script == NULL) script = state; - - if (! SctCallInContext(con, script, node, data->controller, &result)) { - SCPrintf(con, eError, "ERROR: %s", result); - goto finish; + if (script == NULL) + script = state; + snprintf(origScript, sizeof origScript, "%s", script); + if (commError) { + errorScript = GetProp(node, controller->node, "commerror"); + if (errorScript != NULL) + script = errorScript; + commError = 0; } - state = result; - if (strcasecmp(state, "idle") == 0) { - if (currentCon && ! data->answered) { - SCWrite(con, "o.k.", eValue); + /* + * Set the context and invoke the script + */ + script = strdup(script); + sct->sendNode = node; + sct->sendCalled = 0; + SyncedBegin(data->syncid); + ret = SctCallInContext(con, script, node, controller, &result); + SyncedEnd(data->syncid); + sct->sendNode = NULL; + if (ret == 0) { + /* + * an error occurred in the script: store error message in + * a property, and write the error message the first time it + * occurs. + * + * Replaced <> by - because it messed up XML for Gumtree + * Mark Koennecke + * replaced by {} MZ + */ + snprintf(eprop, sizeof eprop, "error_during_%s", data->name); + emsg = GetHdbProp(node, eprop); + if (emsg == NULL || con != controller->conn) { + GetHdbPath(node, path, sizeof path); + SCPrintf(con, eLogError, + "ERROR: action {%s} in {%s} node %s:\nERROR: %s", + data->name, origScript, path, result); + if(data != NULL && data->controller != NULL){ + traceIO(data->controller->node->name, "ERROR: action {%s} in {%s} node %s:\nERROR: %s", + data->name, origScript, path, result); + } else { + traceIO("sctunknown", "reply:%s", "ERROR: action {%s} in {%s} node %s:\nERROR: %s", + data->name, origScript, path, result); + } } - if(strcmp(data->name,"write") == 0){ - SetHdbProperty(data->node,"writestatus","commandsent"); + snprintf(msg, sizeof msg, "{%s} %s", origScript, result); + if (strcasecmp(data->name, "read") == 0) { + SetHdbProperty(node, "geterror", result); } - snprintf(timeKey,50,"%s_time",data->name); - snprintf(timeVal,50,"%.3f", DoubleTime()); - SetHdbProperty(data->node,timeKey,timeVal); - send = NULL; - goto finish; - } - SetProp(node, controller->node, "state", state); - send = GetProp(node, controller->node, "send"); - if (send != NULL && send[0] != '\0') { - if (controller->verbose) { - SCPrintf(con, eWarning, "send : %s", send); - } - if (currentCon) { - SCStorePop(currentCon); + SetHdbProperty(node, eprop, msg); + blank = strchr(origScript, ' '); + if (blank != NULL) { + l = blank - origScript; } else { - SCStorePop(controller->conn); + l = strlen(origScript); + } + snprintf(eprop, sizeof eprop, "error_in_%.*s", l, origScript); + emsg = GetHdbProp(node, eprop); + cnt = 0; + if (emsg != NULL) { + sscanf(emsg, "%d", &cnt); + } + cnt++; + snprintf(msg, sizeof msg, "%dx {%s}: %s", cnt, origScript, result); + SetHdbProperty(node, eprop, msg); + send = NULL; + free(script); + goto finish; + } + /* + * The script executed OK. + * The next state is the result + */ + state = result; + /* + * if the new state is idle, clean everything up + * and terminate the script chain + */ + if (strcasecmp(state, "idle") == 0 || strcasecmp(state, "unpoll") == 0) { + if (queueData == data) { /* it was a write action */ + SetHdbProperty(node, "requested", NULL); + if (!data->answered) { + if (queueData->inMacro == 0) { + /* + * send an O.k. if there was no other reply on write's + */ + iMacro = SCinMacro(con); + con->iMacro = 0; + SCWrite(con, "o.k.", eWarning); + SCsetMacro(con, iMacro); + } + } + } + snprintf(eprop, sizeof eprop, "error_during_%s", data->name); + emsg = GetHdbProp(node, eprop); + if (emsg != NULL) { + GetHdbPath(node, path, sizeof path); + SCPrintf(con, eError, + "action {%s}: success after error message (%s)\n %s", + data->name, path, emsg); + SetHdbProperty(node, eprop, NULL); + } + snprintf(timeKey, sizeof timeKey, "%s_time", data->name); + snprintf(timeVal, sizeof timeVal, "%.3f", DoubleTime()); + SetHdbProperty(node, timeKey, timeVal); + send = NULL; + free(script); + goto finish; + } + /* + * set the state property to the next state for + * the next invocation of this routine + */ + SetProp(node, controller->node, "state", state); + free(script); + script = NULL; + /* + * If there is data to send, check it and do so + */ + if (sct->sendCalled) { + send = GetProp(node, controller->node, "send"); + if (send == NULL) + send = ""; + if (controller->verbose) { + SCPrintf(con, eLog, "%6.3f send : %s", secondsOfMinute(), send); + } + if (controller->fd != NULL) { + fprintf(controller->fd, "%6.3f send : %s\n", secondsOfMinute(), send); + } + if(data != NULL && data->controller != NULL){ + traceIO(data->controller->node->name, "send:%s", send); + } else { + traceIO("sctunknown", "send:%s", send); } return send; } } - SCPrintf(con, eError, "ERROR: too many quick scripts chained"); + SCPrintf(con, eLogError, "ERROR: too many quick scripts chained"); finish: - SetProp(node, controller->node, "state", "idle"); - if (currentCon) { - SCStorePop(currentCon); - } else { - SCStorePop(controller->conn); + if (strcmp(data->name, "write") == 0) { + if (GetHdbProp(node, "writestatus") != NULL) { + SetHdbProperty(node, "writestatus", "commandsent"); + } } + if (strcasecmp(state, "unpoll") == 0) { + DevUnschedule(controller->devser, data, SctActionHandler, SctMatch); + send = NULL; + } + SetProp(node, controller->node, "state", "idle"); if (data->conCtx != NULL) { - SCStoreFree(data->conCtx); + SCDeleteConnection(data->conCtx); data->conCtx = NULL; } return send; } -static char *SctWriteHandler(void *actionData, char *lastReply) { +static char *SctWriteHandler(void *actionData, char *lastReply, + int commError) +{ SctData *data = actionData; - SCStore *old; + SctData *old; char *result; - - old = currentCon; - currentCon = data->conCtx; - result = SctActionHandler(data, lastReply); - currentCon = old; + + old = queueData; + queueData = data; + result = SctActionHandler(data, lastReply, commError); + queueData = old; return result; } -static int SctMatchNode(void *vNode, void *vData) { +static int SctMatchNode(void *vNode, void *vData) +{ Hdb *node = vNode; SctData *d = vData; - + return node == d->node; } -static hdbCallbackReturn SctMainCallback(Hdb *node, void *userData, - hdbMessage *msg) { +static char * SctDataInfo(void *d) +{ + SctData *data = d; + char text[256]; + int l; + + snprintf(text, sizeof text, "%s ", data->name); + l = strlen(text); + GetHdbPath(data->node, text + l, sizeof text - l); + return strdup(text); +} + +static void SctEndData(void *d) +{ + /* no kill, only decrement sync counter */ + SctData *data = d; + + if (data->syncid > 0) { + SyncedDecr(data->syncid); + data->syncid = SYNCED_NO_ID; + } +} + +/* + * This is the callback for all nodes participating in the + * scriptcontext system + */ +static hdbCallbackReturn SctMainCallback(Hdb * node, void *userData, + hdbMessage * msg) +{ SctController *controller = userData; hdbDataSearch *dsm; hdbDataMessage *mm; hdbPtrMessage *pm; hdbMessage *km; - ContextItem *s; SConnection *con; char *geterror; + char error[256]; + if (controller->devser == NULL) { + /* defunct controller */ + return hdbContinue; + } pm = GetKillPtrMessage(msg); if (pm != NULL) { if (controller == pm->pPtr) { @@ -386,7 +705,8 @@ static hdbCallbackReturn SctMainCallback(Hdb *node, void *userData, km = GetHdbKillNodeMessage(msg); if (km != NULL) { /* unschedule all actions related to this node */ - DevUnschedule(controller->devser, node, SctActionHandler, SctMatchNode); + DevUnschedule(controller->devser, node, SctActionHandler, + SctMatchNode); CleanStack(node); return hdbContinue; } @@ -395,21 +715,31 @@ static hdbCallbackReturn SctMainCallback(Hdb *node, void *userData, con = mm->callData; geterror = GetHdbProp(node, "geterror"); if (geterror != NULL) { - SCPrintf(con, eError, "ERROR: %s", geterror); + snprintf(error,255,"ERROR: %s", geterror); + SCWrite(con, error, eError); + if (mm->v->dataType == HIPTEXT) { + if (mm->v->v.text != NULL) { + free(mm->v->v.text); + } + mm->v->v.text = strdup(error); + } return hdbAbort; } return hdbContinue; } - + return hdbContinue; } - -static hdbCallbackReturn SctActionCallback(Hdb *node, void *userData, - hdbMessage *msg) { +/* + * This is the callback registered for nodes which + * are written too. + */ +static hdbCallbackReturn SctActionCallback(Hdb * node, void *userData, + hdbMessage * msg) +{ hdbDataSearch *dsm; hdbDataMessage *mm; hdbPtrMessage *pm; - hdbMessage *km; SctData *data = userData; Hdb *target; char *script; @@ -420,8 +750,9 @@ static hdbCallbackReturn SctActionCallback(Hdb *node, void *userData, char *writeprio; char *error; SConnection *con; - SConnection *con2; char path[MAX_HDB_PATH]; + char *sicsCommand; + int iMacro; pm = GetKillPtrMessage(msg); if (pm != NULL) { @@ -440,7 +771,7 @@ static hdbCallbackReturn SctActionCallback(Hdb *node, void *userData, } return hdbContinue; } - + mm = GetHdbSetMessage(msg); if (mm != NULL) { con = mm->callData; @@ -448,18 +779,22 @@ static hdbCallbackReturn SctActionCallback(Hdb *node, void *userData, /* set target value */ text = formatValue(*(mm->v), node); SetHdbProperty(node, "target", GetCharArray(text)); - - /* call check script, if available */ + SetHdbProperty(node, "requested", GetCharArray(text)); + + /* call check script, if available */ script = GetProp(node, data->controller->node, "check"); if (script != NULL) { - if (SctCallInContext(con, script, node, data->controller, &error) == 0) { - SCPrintf(con, eError, "ERROR: %s", error); - SetHdbProperty(node,"target", NULL); + if (SctCallInContext(con, script, node, data->controller, &error) == + 0) { + /* SCPrintf(con, eError, "ERROR: in {%s}: %s", script, error); */ + SCPrintf(con, eError, "ERROR: %s", error); /* nicer for the user */ + SetHdbProperty(node, "target", NULL); + SetHdbProperty(node, "requested", NULL); return hdbAbort; } } - - + + /* enqueue write action */ writeprio = GetProp(node, data->controller->node, "writeprio"); if (writeprio != NULL) { @@ -471,44 +806,67 @@ static hdbCallbackReturn SctActionCallback(Hdb *node, void *userData, } else { prio = WritePRIO; } - + + /* + * check for duplicate sets on a node. + */ if (data->conCtx != NULL) { - con2 = SCStorePush(data->conCtx); - GetHdbPath(node, path, sizeof path); - SCPrintf(con2, eValue, "%s target changed to %s before completion", - path, GetCharArray(text)); - SCStorePop(data->conCtx); + if (data->inMacro == 0) { + GetHdbPath(node, path, sizeof path); + SCsetMacro(data->conCtx, 0); + SCPrintf(data->conCtx, eWarning, + "%s target changed to %s before completion", path, + GetCharArray(text)); + } + /* + * the node has already been queued for execution. But as we never + * know if the script chain is already running, the only clean + * solution is to requeue the node. + */ + SCDeleteConnection(data->conCtx); } - DeleteDynString(text); - data->conCtx = SCSave(con, data->conCtx); + data->conCtx = SCCopyConnection(con); data->answered = 0; + data->inMacro = SCinMacro(con); + tracePar(node->name,"Queued %s to %s",node->name, GetCharArray(text)); + data->syncid = SyncedIncr(0); DevQueue(data->controller->devser, data, prio, - SctWriteHandler, SctMatch, NULL); - /* no kill function in DevQueue: data is owned by the node (callback list) */ + SctWriteHandler, SctMatch, SctEndData, SctDataInfo); + /* kill function SctEndData does not kill, data is owned by the node (callback list) */ + DeleteDynString(text); return hdbContinue; } mm = GetHdbUpdateMessage(msg); if (mm != NULL) { - if (currentCon) { /* update called from a write action */ - data->answered = 1; - GetHdbPath(node, path, sizeof path); - con = SCStorePush(currentCon); + if (queueData != NULL && queueData->conCtx != NULL && queueData->answered != 1) { + /* update called from a write action */ text = formatValue(*(mm->v), node); - SCPrintf(con, eStatus, "%s = %s", path, - GetCharArray(text)); + if (queueData->inMacro == 0 && queueData->node == node) { + queueData->answered = 1; + iMacro = SCinMacro(queueData->conCtx); + SCsetMacro(queueData->conCtx, 0); + sicsCommand = GetHdbProp(node, "sicscommand"); + if (sicsCommand) { + SCPrintf(queueData->conCtx, eWarning, "OK: %s %s", sicsCommand, GetCharArray(text)); + } else { + GetHdbPath(node, path, sizeof path); + SCPrintf(queueData->conCtx, eWarning, "OK: hset %s %s", path, GetCharArray(text)); + } + SCsetMacro(queueData->conCtx, iMacro); + } DeleteDynString(text); - SCStorePop(currentCon); } return hdbContinue; } return hdbContinue; } -static char *ParText(Hdb *cmdNode, char *name, - int nPar, char *defaultValue) { +static char *ParText(Hdb * cmdNode, char *name, + int nPar, char *defaultValue) +{ Hdb *par; - + for (par = cmdNode->child; nPar > 0 && par != NULL; par = par->next, nPar--) { if (strcasecmp(par->name, name) == 0) { @@ -520,66 +878,85 @@ static char *ParText(Hdb *cmdNode, char *name, return defaultValue; } -static double ParValue(Hdb *cmdNode, char *name, - int nPar, double defaultValue) { +static double ParValue(Hdb * cmdNode, char *name, + int nPar, double defaultValue) +{ Hdb *par; - + for (par = cmdNode->child; nPar > 0 && par != NULL; par = par->next, nPar--) { if (strcasecmp(par->name, name) == 0) { switch (par->value.dataType) { - case HIPINT: return par->value.v.intValue; - case HIPFLOAT: return par->value.v.doubleValue; + case HIPINT: + return par->value.v.intValue; + case HIPFLOAT: + return par->value.v.doubleValue; } } } return defaultValue; } -static void SctKillData(void *d) { +static void SctKillData(void *d) +{ SctData *data = d; + + if (data->syncid > 0) { + SyncedDecr(data->syncid); + data->syncid = SYNCED_NO_ID; + } - if (data->name) free(data->name); - if (data->conCtx) SCStoreFree(data->conCtx); + if (data->name) { + free(data->name); + data->name = NULL; + } + if (data->conCtx) + SCDeleteConnection(data->conCtx); free(data); } -static void SctKillCBData(void *d) { +static void SctKillCBData(void *d) +{ SctData *data = d; - - DevRemoveAction(data->controller->devser, data); + + if (data->controller->devser != NULL) { + DevRemoveAction(data->controller->devser, data); + } SctKillData(d); } -int SctAddPollNode(SctController *controller, Hdb *node, double interval, - DevPrio prio, char *action) { +int SctAddPollNode(SctController * controller, Hdb * node, double interval, + DevPrio prio, char *action) +{ SctData *data; hdbCallback *cb; - char nodePath[512], info[1024]; - if (! FindHdbCallbackData(node, controller)) { + if (!FindHdbCallbackData(node, controller)) { cb = MakeHipadabaCallback(SctMainCallback, controller, NULL); assert(cb); AppendHipadabaCallback(node, cb); - GetHdbPath(node, nodePath, sizeof nodePath); - snprintf(info, 1023, "%s: Not read yet", nodePath); - SetHdbProperty(node,"geterror",info); + SetHdbProperty(node, "geterror", "Not read yet"); } data = calloc(1, sizeof(*data)); assert(data); data->controller = controller; data->node = node; - data->conCtx = NULL; + data->conCtx = NULL; /* we might need a dummy connection here */ data->name = strdup(action); - return DevSchedule(controller->devser, data, prio, interval, - SctActionHandler, SctMatch, SctKillData); - + data->syncid = SyncedIncr(0); + if (DevSchedule(controller->devser, data, prio, interval, + SctActionHandler, SctMatch, SctKillData, SctDataInfo)) { + return 1; + } else { + return 0; + } } -static int SctPollCmd(pSICSOBJ ccmd, SConnection *con, - Hdb *cmdNode, Hdb *par[], int nPar) { +static int SctPollCmd(pSICSOBJ ccmd, SConnection * con, + Hdb * cmdNode, Hdb * par[], int nPar) +{ Hdb *node; SctController *controller; double interval; @@ -587,11 +964,11 @@ static int SctPollCmd(pSICSOBJ ccmd, SConnection *con, DevPrio prio; char *action; char *prioText; - - if(nPar < 1){ - SCPrintf(con,eError, - "ERROR: should be: %s poll ( )", - ccmd->objectNode->name); + + if (nPar < 1) { + SCPrintf(con, eError, + "ERROR: should be: %s poll ( )", + ccmd->objectNode->name); return 0; } controller = ccmd->pPrivate; @@ -605,36 +982,37 @@ static int SctPollCmd(pSICSOBJ ccmd, SConnection *con, prioText = ParText(cmdNode, "prio", nPar, "read"); prio = DevText2Prio(prioText); if (prio == NullPRIO) { - SCPrintf(con,eError, "ERROR: unknown priority: %s", prioText); + SCPrintf(con, eError, "ERROR: unknown priority: %s", prioText); return 0; } action = ParText(cmdNode, "action", nPar, "read"); - if (SctAddPollNode(controller, node, interval, prio, action) > 0) { + if (SctAddPollNode(controller, node, interval, prio, action)) { SCPrintf(con, eValue, - "%s poll on %s changed to %g sec, %s prio", - action, path, interval, prioText); + "%s poll registered on %s (%g sec, %s prio)", + action, path, interval, prioText); } else { SCPrintf(con, eValue, - "%s poll registered on %s (%g sec, %s prio)", - action, path, interval, prioText); + "%s poll on %s changed to %g sec, %s prio", + action, path, interval, prioText); } return 1; } -static int SctUnpollCmd(pSICSOBJ ccmd, SConnection *con, - Hdb *cmdNode, Hdb *par[], int nPar) { +static int SctUnpollCmd(pSICSOBJ ccmd, SConnection * con, + Hdb * cmdNode, Hdb * par[], int nPar) +{ SctController *controller; double interval; char *path; DevPrio prio; char *prioText; SctData data; - - if(nPar < 1){ - SCPrintf(con,eError, - "ERROR: should be: %s poll ()", - ccmd->objectNode->name); + + if (nPar < 1) { + SCPrintf(con, eError, + "ERROR: should be: %s unpoll ()", + ccmd->objectNode->name); return 0; } controller = ccmd->pPrivate; @@ -645,26 +1023,27 @@ static int SctUnpollCmd(pSICSOBJ ccmd, SConnection *con, return 0; } data.name = ParText(cmdNode, "action", nPar, "read"); - if (DevUnschedule(controller->devser, &data, SctActionHandler, SctMatch) == 0) { - SCPrintf(con, eValue, - "%s poll not found on %s", data.name, path); + if (DevUnschedule(controller->devser, &data, SctActionHandler, SctMatch) + == 0) { + SCPrintf(con, eValue, "%s poll not found on %s", data.name, path); } else { SCSendOK(con); } return 1; } -static int SctConnectCmd(pSICSOBJ ccmd, SConnection *con, - Hdb *cmdNode, Hdb *par[], int nPar) { +static int SctConnectCmd(pSICSOBJ ccmd, SConnection * con, + Hdb * cmdNode, Hdb * par[], int nPar) +{ Hdb *node; SctController *controller; char *path; hdbCallback *cb; - - if(nPar < 1){ - SCPrintf(con,eError, - "ERROR: should be: %s connect ", - ccmd->objectNode->name); + + if (nPar < 1) { + SCPrintf(con, eError, + "ERROR: should be: %s connect ", + ccmd->objectNode->name); return 0; } controller = ccmd->pPrivate; @@ -675,7 +1054,7 @@ static int SctConnectCmd(pSICSOBJ ccmd, SConnection *con, return 0; } - if (! FindHdbCallbackData(node, controller)) { + if (!FindHdbCallbackData(node, controller)) { cb = MakeHipadabaCallback(SctMainCallback, controller, NULL); assert(cb); AppendHipadabaCallback(node, cb); @@ -684,17 +1063,18 @@ static int SctConnectCmd(pSICSOBJ ccmd, SConnection *con, return 1; } -int SctAddWriteNode(SctController *controller, Hdb *node) { +int SctAddWriteNode(SctController * controller, Hdb * node) +{ hdbCallback *cb; SctData *data; - if (! FindHdbCallbackData(node, controller)) { + if (!FindHdbCallbackData(node, controller)) { cb = MakeHipadabaCallback(SctMainCallback, controller, NULL); assert(cb); AppendHipadabaCallback(node, cb); } - actionCallback.name = "write"; /* local, so no strdup here */ + actionCallback.name = "write"; /* local, so no strdup here */ data = FindHdbCallbackData(node, &actionCallback); if (data != NULL) { return 0; @@ -714,16 +1094,17 @@ int SctAddWriteNode(SctController *controller, Hdb *node) { return 1; } -static int SctWriteCmd(pSICSOBJ ccmd, SConnection *con, - Hdb *cmdNode, Hdb *par[], int nPar) { +static int SctWriteCmd(pSICSOBJ ccmd, SConnection * con, + Hdb * cmdNode, Hdb * par[], int nPar) +{ Hdb *node; SctController *controller; double interval; char *path; - - if(nPar < 1){ + + if (nPar < 1) { SCPrintf(con, eError, "ERROR: should be: %s write ", - ccmd->objectNode->name); + ccmd->objectNode->name); return 0; } controller = ccmd->pPrivate; @@ -734,21 +1115,21 @@ static int SctWriteCmd(pSICSOBJ ccmd, SConnection *con, return 0; } if (SctAddWriteNode(controller, node) == 0) { - SCPrintf(con, eError, - "ERROR: %s has already a write action", path); + SCPrintf(con, eError, "ERROR: %s has already a write action", path); return 0; } - + SCSendOK(con); return 1; } -void SctQueueNode(SctController *controller, Hdb *node, - DevPrio prio, char *action, SConnection *con) { +void SctQueueNode(SctController * controller, Hdb * node, + DevPrio prio, char *action, SConnection * con) +{ SctData *data; hdbCallback *cb; - if (! FindHdbCallbackData(node, controller)) { + if (!FindHdbCallbackData(node, controller)) { cb = MakeHipadabaCallback(SctMainCallback, controller, NULL); assert(cb); AppendHipadabaCallback(node, cb); @@ -760,17 +1141,22 @@ void SctQueueNode(SctController *controller, Hdb *node, data->node = node; data->name = strdup(action); data->conCtx = NULL; - - DevQueue(data->controller->devser, data, prio, - SctWriteHandler, SctMatch, SctKillData); - if (con != NULL) { - data->conCtx = SCSave(con, NULL); + data->answered = 1; + + data->syncid = SyncedIncr(0); + + if (DevQueue(data->controller->devser, data, prio, + SctWriteHandler, SctMatch, SctKillData, SctDataInfo)) { + if (con != NULL) { + data->conCtx = SCCopyConnection(con); + } } return; } -static int SctQueueCmd(pSICSOBJ ccmd, SConnection *con, - Hdb *cmdNode, Hdb *par[], int nPar) { +static int SctQueueCmd(pSICSOBJ ccmd, SConnection * con, + Hdb * cmdNode, Hdb * par[], int nPar) +{ Hdb *node; SctController *controller; double interval; @@ -779,11 +1165,11 @@ static int SctQueueCmd(pSICSOBJ ccmd, SConnection *con, DevPrio prio; SctData *data; char *prioText; - - if(nPar < 2){ - SCPrintf(con,eError, - "ERROR: should be: %s queue ", - ccmd->objectNode->name); + + if (nPar < 2) { + SCPrintf(con, eError, + "ERROR: should be: %s queue ", + ccmd->objectNode->name); return 0; } controller = ccmd->pPrivate; @@ -796,7 +1182,7 @@ static int SctQueueCmd(pSICSOBJ ccmd, SConnection *con, prioText = ParText(cmdNode, "prio", nPar, "write"); prio = DevText2Prio(prioText); if (prio == NullPRIO) { - SCPrintf(con,eError, "ERROR: unknown priority: %s", prioText); + SCPrintf(con, eError, "ERROR: unknown priority: %s", prioText); return 0; } action = ParText(cmdNode, "action", nPar, "write"); @@ -805,94 +1191,487 @@ static int SctQueueCmd(pSICSOBJ ccmd, SConnection *con, return 1; } +static void SctKillUpdatescript(void *d) +{ + SctUpdatescript *us = d; + + if (us->name) { + free(us->name); + } + free(us); +} + +/* + * This is the callback for update scripts + */ +static hdbCallbackReturn SctUpdatescriptCallback(Hdb * node, + void *userData, + hdbMessage * msg) +{ + SctUpdatescript *us = userData; + hdbDataSearch *dsm; + hdbDataMessage *mm; + hdbPtrMessage *pm; + SConnection *con; + char *result; + char *script; + char path[MAX_HDB_PATH]; + pDynString text; + char *arg; + + pm = GetKillPtrMessage(msg); + if (pm != NULL) { + if (us->controller == pm->pPtr) { + return hdbKill; + } + if (pm->pPtr == &updatescriptCallback + && strcmp(us->name, updatescriptCallback.name) == 0 + && us->controller == updatescriptCallback.controller) { + return hdbKill; + } + return hdbContinue; + } + dsm = GetHdbDataSearchMessage(msg); + if (dsm != NULL) { + if (dsm->testPtr == &updatescriptCallback) { + if (strcasecmp(us->name, updatescriptCallback.name) == 0 && + us->controller == updatescriptCallback.controller) { + dsm->result = us; + } + return hdbAbort; + } + return hdbContinue; + } + mm = GetHdbUpdateMessage(msg); + if (mm != NULL) { + con = mm->callData; + + script = GetProp(node, us->controller->node, us->name); + if (script == NULL) script = us->name; + + text = formatValue(*(mm->v), node); + arg = GetCharArray(text); + arg = Arg2Tcl(1, &arg, NULL, 0); + DynStringCopy(text, script); + DynStringConcat(text, " "); + DynStringConcat(text, arg); + free(arg); + script = GetCharArray(text); + + if (!SctCallInContext(con, script, node, us->controller, &result)) { + + GetHdbPath(node, path, sizeof path); + SCPrintf(con, eError, "ERROR: in updatescript {%s} node %s: %s", + script, path, result); + } + DeleteDynString(text); + return hdbContinue; + } + + return hdbContinue; +} + +int SctUpdatescriptNode(SctController * controller, Hdb * node, char *action) +{ + SctUpdatescript *us; + hdbCallback *cb; + + updatescriptCallback.name = action; + updatescriptCallback.controller = controller; + us = FindHdbCallbackData(node, &updatescriptCallback); + if (us != NULL) { + return 0; + } + us = calloc(1, sizeof(*us)); + us->name = strdup(action); + us->controller = controller; + cb = MakeHipadabaCallback(SctUpdatescriptCallback, us, SctKillUpdatescript); + assert(cb); + AppendHipadabaCallback(node, cb); + + return 1; +} + +int SctUpdatescriptKill(SctController * controller, Hdb * node, char *action) +{ + updatescriptCallback.name = action; + updatescriptCallback.controller = controller; + RemoveSICSInternalCallbackFrom(node, &updatescriptCallback); + return 1; +} + +static int SctUpdatescriptCmd(pSICSOBJ ccmd, SConnection * con, + Hdb * cmdNode, Hdb * par[], int nPar) +{ + Hdb *node; + SctController *controller; + double interval; + char *path; + char *action; + SctData *data; + char *prioText; + + if (nPar < 2) { + SCPrintf(con, eError, + "ERROR: should be: %s updatescript ", + ccmd->objectNode->name); + return 0; + } + controller = ccmd->pPrivate; + path = ParText(cmdNode, "node", nPar, ""); + node = FindHdbNode(NULL, path, con); + if (node == NULL) { + SCPrintf(con, eError, "ERROR: %s not found", path); + return 0; + } + action = ParText(cmdNode, "action", nPar, "updatescript"); + + if (SctUpdatescriptNode(controller, node, action)) { + SCPrintf(con, eValue, "%s registered for update on %s", action, path); + } else { + SCPrintf(con, eValue, "%s already registered for update on %s", action, path); + } + return 1; +} + +static int SctKillUpdatescriptCmd(pSICSOBJ ccmd, SConnection * con, + Hdb * cmdNode, Hdb * par[], int nPar) +{ + Hdb *node; + SctController *controller; + double interval; + char *path; + char *action; + SctData *data; + char *prioText; + + if (nPar < 2) { + SCPrintf(con, eError, + "ERROR: should be: %s killupdatescript ", + ccmd->objectNode->name); + return 0; + } + controller = ccmd->pPrivate; + path = ParText(cmdNode, "node", nPar, ""); + node = FindHdbNode(NULL, path, con); + if (node == NULL) { + SCPrintf(con, eError, "ERROR: %s not found", path); + return 0; + } + action = ParText(cmdNode, "action", nPar, "updatescript"); + + SctUpdatescriptKill(controller, node, action); + SCPrintf(con, eValue, "kill %s updatescript on %s", action, path); + return 1; +} + typedef struct SctTransact { - char *command; - int sent; - SConnection *con; -}SctTransact, *pSctTransact; + char *command; + char *reply; + int sent; + SConnection *con; + SctController *controller; +} SctTransact, *pSctTransact; -static void KillSctTransact(void *data){ - pSctTransact self = (pSctTransact)data; - if(self == NULL){ - return; - } - if(self->command){ - free(self->command); - } - free(self); +static void KillSctTransact(void *data) +{ + pSctTransact self = (pSctTransact) data; + if (self == NULL) { + return; + } + if (self->command) { + free(self->command); + } + if (self->reply) { + free(self->reply); + } + if (self->con) { + SCDeleteConnection(self->con); + } + free(self); } -static char *TransactionHandler(void *actionData, char *lastReply){ - pSctTransact st = (pSctTransact)actionData; - - if(st->sent == 0){ - st->sent = 1; - return st->command; - } else { - st->sent = 2; - SCWrite(st->con,lastReply, eValue); - return NULL; - } -} -static int SctTransactMatch(void *d1, void *d2){ - return d1 == d2; +static char *TransactionHandler(void *actionData, char *lastReply, + int commError) +{ + pSctTransact st = (pSctTransact) actionData; + + if (st->sent == 0) { + st->sent = 1; + if (st->controller->verbose) { + SCPrintf(st->con, eLog, "%6.3f send : %s", secondsOfMinute(), st->command); + } + if (st->controller->fd != NULL) { + fprintf(st->controller->fd, "%6.3f send : %s\n", secondsOfMinute(), st->command); + } + if(st->controller != NULL){ + traceIO(st->controller->node->name, "transsend:%s", st->command); + } else { + traceIO("sctunknown", "transsend:%s", st->command); + } + return st->command; + } else { + st->sent = 2; + /* + if (st->controller->verbose) { + SCPrintf(st->con, eLog, "%6.3f reply : %s", secondsOfMinute(), lastReply); + } + if (st->controller->fd != NULL) { + fprintf(st->controller->fd,"%6.3f reply : %s\n", secondsOfMinute(), lastReply); + } + */ + /* printf("Transact: %s got %s\n", st->command, lastReply); */ + if (lastReply == NULL) { + lastReply = ""; + } + if(st->controller != NULL){ + traceIO(st->controller->node->name, "transreply:%s", lastReply); + } else { + traceIO("sctunknown", "transreply:%s", lastReply); + } + if(lastReply != NULL){ + st->reply = strdup(lastReply); + } + return NULL; + } } -static int SctTransactCmd(pSICSOBJ ccmd, SConnection *con, - Hdb *cmdNode, Hdb *par[], int nPar) { - pSctTransact st = NULL; - SctController *c; - - c = (SctController *)ccmd->pPrivate; - - st = calloc(sizeof(SctTransact),1); - if(st == NULL){ - SCWrite(con,"ERROR: out of memory in SctTransactCommand", eError); - return 0; - } - st->con = con; - st->command = strdup(par[0]->value.v.text); - - DevQueue(c->devser, st, WritePRIO, - TransactionHandler, SctTransactMatch, NULL); - while(st->sent != 2){ - TaskYield(pServ->pTasker); - if(SCGetInterrupt(con) != eContinue){ - break; - } - } - KillSctTransact(st); - return 1; +static char *SendHandler(void *actionData, char *lastReply, + int commError) +{ + pSctTransact st = (pSctTransact) actionData; + char *result = TransactionHandler(actionData, lastReply, commError); + + if (st->sent == 2) { + SetHdbProperty(st->controller->node, "reply", lastReply); + if (st->controller->verbose) { + SCPrintf(st->con, eLog, "%6.3f reply : %s", secondsOfMinute(), lastReply); + } + if (st->controller->fd != NULL) { + fprintf(st->controller->fd, "%6.3f reply : %s\n", secondsOfMinute(), lastReply); + } + } + return result; } -static int SctSendCmd(pSICSOBJ ccmd, SConnection *con, - Hdb *cmdNode, Hdb *par[], int nPar) { - pSctTransact st = NULL; - SctController *c; - - c = (SctController *)ccmd->pPrivate; - - st = calloc(sizeof(SctTransact),1); - if(st == NULL){ - SCWrite(con,"ERROR: out of memory in SctSendCmd", eError); - return 0; - } - st->con = con; - st->command = strdup(par[0]->value.v.text); - - DevQueue(c->devser, st, WritePRIO, - TransactionHandler, SctTransactMatch, KillSctTransact); - return 1; +static int SctTransactMatch(void *d1, void *d2) +{ + return d1 == d2; } +static int SctTransactCmd(pSICSOBJ ccmd, SConnection * con, + Hdb * cmdNode, Hdb * par[], int nPar) +{ + pSctTransact st = NULL; + SctController *c; -static hdbCallbackReturn SctDebugCallback(Hdb *node, void *userData, - hdbMessage *msg) { + c = (SctController *) ccmd->pPrivate; + + if(nPar < 1 || par[0] == NULL){ + SCWrite(con,"ERROR: no data to transact found", eError); + return 0; + } + + st = calloc(sizeof(SctTransact), 1); + if (st == NULL) { + SCWrite(con, "ERROR: out of memory in SctTransactCommand", eError); + return 0; + } + st->con = SCCopyConnection(con); + st->command = strdup(par[0]->value.v.text); + st->controller = c; + st->sent = 0; + st->reply = NULL; + + DevQueue(c->devser, st, WritePRIO, + TransactionHandler, SctTransactMatch, NULL, NULL); + while (st->sent != 2) { + TaskYield(pServ->pTasker); + /* not yet tested: + if (SCGetInterrupt(con) != eContinue) { + DevUnschedule(c->devser, st, TransactionHandler, SctTransactMatch); + break; + } + */ + } + if (st->reply != NULL) { + SCWrite(con,st->reply,eValue); + } else { + SCWrite(con,"ERROR: no reply!",eError); + } + KillSctTransact(st); + return 1; +} + +static int SctSendCmd(pSICSOBJ ccmd, SConnection * con, + Hdb * cmdNode, Hdb * par[], int nPar) +{ + pSctTransact st = NULL; + SctController *c; + char *prioText = NULL; + int prio; + + c = (SctController *) ccmd->pPrivate; + + st = calloc(sizeof(SctTransact), 1); + if (st == NULL) { + SCWrite(con, "ERROR: out of memory in SctSendCmd", eError); + return 0; + } + st->con = SCCopyConnection(con); + st->command = strdup(par[0]->value.v.text); + st->controller = c; + + prioText = ParText(cmdNode, "prio", nPar, "write"); + prio = DevText2Prio(prioText); + if (prio == NullPRIO) { + prio = WritePRIO; + } + + SetHdbProperty(c->node, "reply", ""); + DevQueue(c->devser, st, prio, + SendHandler, SctTransactMatch, KillSctTransact, NULL); + return 1; +} + +static int SctDisconnect(pSICSOBJ ccmd, SConnection * con, + Hdb * cmdNode, Hdb * par[], int nPar) +{ + SctController *c; + + c = (SctController *) ccmd->pPrivate; + DevDisconnect(c->devser); + return 1; +} + +static int SctReconnect(pSICSOBJ ccmd, SConnection * con, + Hdb * cmdNode, Hdb * par[], int nPar) +{ + SctController *c; + char *reconnectScript, *result; + + c = (SctController *) ccmd->pPrivate; + DevReconnect(c->devser, ParText(cmdNode, "hostport", nPar, "")); + reconnectScript = GetProp(c->node, c->node, "reconnect_script"); + if (reconnectScript && reconnectScript[0] != '\0') { + if (SctCallInContext(con, reconnectScript, c->node, c, &result) == 0) { + SCPrintf(con, eError, "ERROR: %s", result); + return 0; + } + } + return 1; +} + +static int SctListActions(pSICSOBJ ccmd, SConnection * con, + Hdb * cmdNode, Hdb * par[], int nPar) +{ + SctController *c; + char *result; + + c = (SctController *) ccmd->pPrivate; + result = DevList(c->devser); + SCWrite(con, result, eValue); + return 1; +} + +static int SctStatistics(pSICSOBJ ccmd, SConnection * con, + Hdb * cmdNode, Hdb * par[], int nPar) +{ + SctController *c; + double avg, max; + long errCount; + int errState, maxState, maxCount; + char state[16]; + + c = (SctController *) ccmd->pPrivate; + DevStatistics(c->devser,&avg, &max, &maxCount, &errCount, &errState); + if(errState == 1){ + strcpy(state,"in error"); + } else { + strcpy(state,"good"); + } + SCPrintf(con,eValue,"Average roundtrip time: %lf, maximum roundtrip time %lf, count max roundtrip/2 %d, com error count: %ld, com state: %s", + avg, max, maxCount, errCount, state); + DevAsconStatistics(c->devser,&avg, &max, &maxState, &maxCount); + SCPrintf(con,eValue,"Average time in AsconTask: %lf, maximum time spent in AsconTask %lf, state of Ascon on max %d, count > max/2 %d", + avg, max, maxState, maxCount); + + return 1; +} + +static int SctHostport(pSICSOBJ ccmd, SConnection * con, + Hdb * cmdNode, Hdb * par[], int nPar) +{ + SctController *c; + char *result; + + c = (SctController *) ccmd->pPrivate; + result = DevHostport(c->devser); + SCWrite(con, result, eValue); + return 1; +} + +static int SctTimeout(pSICSOBJ ccmd, SConnection * con, + Hdb * cmdNode, Hdb * par[], int nPar) +{ + SctController *c; + char *result; + hdbValue *v = &cmdNode->child->value; + + c = (SctController *) ccmd->pPrivate; + v->v.doubleValue = DevGetSetTimeout(c->devser, v->v.doubleValue, nPar); + SCPrintf(con, eValue, "%.6g", v->v.doubleValue); + return 1; +} + +static int SctStatus(pSICSOBJ ccmd, SConnection * con, + Hdb * cmdNode, Hdb * par[], int nPar) +{ + SctController *c; + char *result; + + c = (SctController *) ccmd->pPrivate; + result = DevStatus(c->devser); + SCWrite(con, result, eValue); + return 1; +} + +static int SctLog(pSICSOBJ ccmd, SConnection * con, + Hdb * cmdNode, Hdb * par[], int nPar) +{ + SctController *c; + char *filename = NULL; + + c = (SctController *) ccmd->pPrivate; + filename = par[0]->value.v.text; + if(strcmp(filename,"close") == 0 ){ + if(c->fd != NULL){ + fclose(c->fd); + c->fd = NULL; + } + } else { + if(c->fd != NULL){ + fclose(c->fd); + } + c->fd = fopen(filename,"w"); + if(c->fd == NULL){ + SCPrintf(con,eError,"ERROR: failed to open %s for logging", filename); + return 0; + } else { + SCPrintf(con,eValue,"Logging to %s", filename); + } + } + return 1; +} + +static hdbCallbackReturn SctDebugCallback(Hdb * node, void *userData, + hdbMessage * msg) +{ hdbDataMessage *mm; SctController *controller = userData; SConnection *con; int i; - + mm = GetHdbSetMessage(msg); if (mm != NULL) { i = mm->v->v.intValue; @@ -910,108 +1689,192 @@ static hdbCallbackReturn SctDebugCallback(Hdb *node, void *userData, return hdbContinue; } -static void SctKillController(void *c) { - SctController *controller = c; - SConnection *con; - - CleanStack(controller->node); - RemoveSICSInternalCallback(controller); - if (controller->conn) { - con = SCLoad(controller->conn); - SCDeleteConnection(con); - SCStoreFree(controller->conn); - } - DevKill(controller->devser); - free(controller); +static void SctDeferredFree(void *data) +{ + free(data); + return; } -static int SctMakeController(SConnection *con, SicsInterp *sics, - void *object, int argc, char *argv[]) { +static int SctDeferredTask(void *data) +{ + return 0; +} + +static void SctKillController(void *c) +{ + SctController *controller = c; + SConnection *con; + hdbPtrMessage m; + + CleanStack(controller->node); + RemoveSICSInternalCallback(controller); + RemoveSICSInternalCallbackFrom(controller->node, controller); + + if (controller->conn) { + SCDeleteConnection(controller->conn); + } + DevKill(controller->devser); + controller->devser = NULL; + + if(controller->fd != NULL){ + fclose(controller->fd); + controller->fd = NULL; + } + + if (pServ->pTasker) { + TaskRegister(pServ->pTasker, SctDeferredTask, NULL, SctDeferredFree, + controller, 0); + } else { + free(controller); + } +} + +static int SctMakeController(SConnection * con, SicsInterp * sics, + void *object, int argc, char *argv[]) +{ SICSOBJ *ccmd; Hdb *parent, *par, *cmd; - char *nodeName; + char *objName; hdbCallback *cb; SctController *controller; - + if (argc < 2) { SCPrintf(con, eError, - "ERROR: should be %s ...", - argv[0]); + "ERROR: should be %s ...", + argv[0]); return 0; } - - parent = FindHdbParent(NULL, argv[1], &nodeName, con); - if (parent == NULL) return 0; /* error message already written */ - + + if (strchr(argv[1], '/') == NULL) { + /* object name only -> do not anchor in tree */ + parent = NULL; + objName = argv[1]; + } else { + /* full path given -> install into the hipadaba */ + parent = FindHdbParent(NULL, argv[1], &objName, con); + if (parent == NULL) + return 0; /* error message already written */ + } + controller = calloc(1, sizeof(*controller)); assert(controller); controller->verbose = 0; - - ccmd = MakeSICSOBJv(nodeName, "SctController", HIPNONE, usSpy); + + ccmd = MakeSICSOBJv(objName, "SctController", HIPNONE, usSpy); controller->node = ccmd->objectNode; - controller->conn = SCSave(SCCreateDummyConnection(pServ->pSics), NULL); + controller->conn = SCCreateDummyConnection(pServ->pSics); assert(ccmd); assert(controller->node->mama == NULL); ccmd->pPrivate = controller; ccmd->KillPrivate = SctKillController; - AddHipadabaChild(parent, controller->node, con); + if (parent != NULL) { + AddHipadabaChild(parent, controller->node, con); + } controller->devser = DevMake(con, argc - 2, argv + 2); - if (!controller->devser) return 0; + if (!controller->devser) + return 0; + + + SetHdbProperty(controller->node, "controllerName", objName); + SetHdbProperty(controller->node, "sicsdev", objName); - AddCommand(pServ->pSics, nodeName, InvokeSICSOBJ, KillSICSOBJ, ccmd); + AddCommand(pServ->pSics, objName, InterInvokeSICSOBJ, KillSICSOBJ, ccmd); + RegisterSICSOBJKillCmd(ccmd, objName); SetDescriptorKey(ccmd->pDes, "creationCommand", "0"); cmd = AddSICSHdbPar(controller->node, - "poll", usMugger, MakeSICSFunc(SctPollCmd)); - AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText("")); - AddSICSHdbPar(cmd, "interval", usMugger, MakeHdbFloat(5.0)); - AddSICSHdbPar(cmd, "prio", usMugger, MakeHdbText("read")); - AddSICSHdbPar(cmd, "action", usMugger, MakeHdbText("read")); - - cmd = AddSICSHdbPar(controller->node, - "unpoll", usMugger, MakeSICSFunc(SctUnpollCmd)); - AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText("")); - AddSICSHdbPar(cmd, "action", usMugger, MakeHdbText("read")); - - cmd = AddSICSHdbPar(controller->node, - "connect", usMugger, MakeSICSFunc(SctConnectCmd)); - AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText("")); - - cmd = AddSICSHdbPar(controller->node, - "write", usMugger, MakeSICSFunc(SctWriteCmd)); + "poll", usMugger, MakeSICSFunc(SctPollCmd)); AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText("")); - + AddSICSHdbPar(cmd, "interval", usMugger, MakeHdbFloat(5.0)); + AddSICSHdbPar(cmd, "prio", usMugger, MakeHdbText("read")); + AddSICSHdbPar(cmd, "action", usMugger, MakeHdbText("read")); cmd = AddSICSHdbPar(controller->node, - "queue", usMugger, MakeSICSFunc(SctQueueCmd)); + "unpoll", usMugger, MakeSICSFunc(SctUnpollCmd)); + AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText("")); + AddSICSHdbPar(cmd, "action", usMugger, MakeHdbText("read")); + + cmd = AddSICSHdbPar(controller->node, + "connect", usMugger, MakeSICSFunc(SctConnectCmd)); + AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText("")); + + cmd = AddSICSHdbPar(controller->node, + "write", usMugger, MakeSICSFunc(SctWriteCmd)); + AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText("")); + + + cmd = AddSICSHdbPar(controller->node, + "queue", usMugger, MakeSICSFunc(SctQueueCmd)); AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText("")); AddSICSHdbPar(cmd, "prio", usMugger, MakeHdbText("write")); AddSICSHdbPar(cmd, "action", usMugger, MakeHdbText("write")); cmd = AddSICSHdbPar(controller->node, - "transact", usMugger, MakeSICSFunc(SctTransactCmd)); + "updatescript", usMugger, MakeSICSFunc(SctUpdatescriptCmd)); + AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText("")); + AddSICSHdbPar(cmd, "action", usMugger, MakeHdbText("updatescript")); + + cmd = AddSICSHdbPar(controller->node, + "killupdatescript", usMugger, MakeSICSFunc(SctKillUpdatescriptCmd)); + AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText("")); + AddSICSHdbPar(cmd, "action", usMugger, MakeHdbText("updatescript")); + + cmd = AddSICSHdbPar(controller->node, + "log", usMugger, MakeSICSFunc(SctLog)); + AddSICSHdbPar(cmd, "filename", usMugger, MakeHdbText("")); + + cmd = AddSICSHdbPar(controller->node, + "transact", usMugger, MakeSICSFunc(SctTransactCmd)); AddSICSHdbPar(cmd, "data", usMugger, MakeHdbText("")); cmd = AddSICSHdbPar(controller->node, - "send", usMugger, MakeSICSFunc(SctSendCmd)); + "send", usMugger, MakeSICSFunc(SctSendCmd)); AddSICSHdbPar(cmd, "data", usMugger, MakeHdbText("")); - - + AddSICSHdbPar(cmd, "prio", usMugger, MakeHdbText("")); + + cmd = AddSICSHdbPar(controller->node, + "disconnect", usMugger, MakeSICSFunc(SctDisconnect)); + + cmd = AddSICSHdbPar(controller->node, + "reconnect", usMugger, MakeSICSFunc(SctReconnect)); + AddSICSHdbPar(cmd, "hostport", usMugger, MakeHdbText("")); + par = AddSICSHdbPar(controller->node, "debug", usUser, MakeHdbInt(-1)); + cmd = AddSICSHdbPar(controller->node, + "actions", usUser, MakeSICSFunc(SctListActions)); + + cmd = AddSICSHdbPar(controller->node, + "statistics", usSpy, MakeSICSFunc(SctStatistics)); + + cmd = AddSICSHdbPar(controller->node, + "hostport", usSpy, MakeSICSFunc(SctHostport)); + + cmd = AddSICSHdbPar(controller->node, + "status", usSpy, MakeSICSFunc(SctStatus)); + + cmd = AddSICSHdbPar(controller->node, + "timeout", usSpy, MakeSICSFunc(SctTimeout)); + AddSICSHdbPar(cmd, "value", usUser, MakeHdbFloat(-1.0)); + + /* get the actual timeout value */ + SctTimeout(ccmd, con, cmd, &par, 0); + cb = MakeHipadabaCallback(SctDebugCallback, controller, NULL); - if (cb) AppendHipadabaCallback(par, cb); - + if (cb) + AppendHipadabaCallback(par, cb); + return 1; } -void SctKill(void *object) { +void SctKill(void *object) +{ assert(sct == object); ContextItem *p, *q; - + for (p = sct->nodes; p != NULL; p = q) { q = p->next; free(p); @@ -1027,8 +1890,10 @@ void SctKill(void *object) { sct = NULL; } -void SctInit(void) { - if (sct) return; +void SctInit(void) +{ + if (sct) + return; sct = calloc(1, sizeof(*sct)); assert(sct); sct->desc = CreateDescriptor("ScriptContext"); @@ -1036,6 +1901,8 @@ void SctInit(void) { AddCmd("makesctcontroller", SctMakeController); } -int SctVerbose(SctController *c){ - return c->verbose; +int SctVerbose(SctController * c) +{ + return c->verbose; } + diff --git a/scriptcontext.h b/scriptcontext.h index 30c5bc87..5e71c0a3 100644 --- a/scriptcontext.h +++ b/scriptcontext.h @@ -6,7 +6,7 @@ /* \brief an sct controller */ -typedef struct SctController SctController; +typedef struct SctController SctController; /** \brief queue node action to a controller * @@ -16,9 +16,9 @@ typedef struct SctController SctController; * \param action the initial state * \param con an optional connection to be used by the action scripts */ -void SctQueueNode(SctController *controller, Hdb *node, - DevPrio prio, char *action, SConnection *con); - +void SctQueueNode(SctController * controller, Hdb * node, + DevPrio prio, char *action, SConnection * con); + /** \brief call a script and configure the sct command to be used * in connection with the given node and controller * @@ -27,12 +27,13 @@ void SctQueueNode(SctController *controller, Hdb *node, * \param the node to which the sct command * \return 0 when this was a new action, > 0 when an action was overwritten */ -int SctCallInContext(SConnection *con, char *script, Hdb *node, - SctController *controller, char **resPtr); +int SctCallInContext(SConnection * con, char *script, Hdb * node, + SctController * controller, char **resPtr); /** * test the controller verbose flag * \param c The SctController to test * \return 1 for verbose, 0 for silent */ -int SctVerbose(SctController *c); +int SctVerbose(SctController * c); + #endif diff --git a/sctdriveadapter.c b/sctdriveadapter.c index 6b496fee..98cf6739 100644 --- a/sctdriveadapter.c +++ b/sctdriveadapter.c @@ -24,40 +24,45 @@ #include "scriptcontext.h" /*---------------------------------------------------------------*/ typedef struct { - pObjectDescriptor pDes; - pIDrivable pDriv; - pHdb node; - SctController *c; -}SctDrive, *pSctDrive; + pObjectDescriptor pDes; + pIDrivable pDriv; + pHdb node; + SctController *c; +} SctDrive, *pSctDrive; /*---------------------------------------------------------------*/ -static void *SCTDRIVGetInterface(void *data, int iD){ - pSctDrive self = NULL; - - self = (pSctDrive)data; - if(self != NULL && iD == DRIVEID){ - if (self->node == NULL) return NULL; - return self->pDriv; - } else { - return NULL; - } - return NULL; +static void *SCTDRIVGetInterface(void *data, int iD) +{ + pSctDrive self = NULL; + + self = (pSctDrive) data; + if (self != NULL && iD == DRIVEID) { + if (self->node == NULL) + return NULL; + return self->pDriv; + } else { + return NULL; + } + return NULL; } + /*---------------------------------------------------------------- This routine can return either OKOK or HWFault when thing go wrong. However, the return value of Halt is usually ignored! ------------------------------------------------------------------*/ -static int SCTDRIVHalt(void *data) { - pSctDrive self = NULL; - char dummy[16]; - - self = (pSctDrive)data; - if (GetHdbProperty(self->node,"halt", dummy, sizeof dummy)) { - SctQueueNode(self->c, self->node, HaltPRIO, "halt", NULL); - } else if (GetHdbProperty(self->node, "status", dummy, sizeof dummy)) { - SetHdbProperty(self->node, "status", "idle"); - } - return OKOK; +static int SCTDRIVHalt(void *data) +{ + pSctDrive self = NULL; + char dummy[16]; + + self = (pSctDrive) data; + if (GetHdbProperty(self->node, "halt", dummy, sizeof dummy)) { + SctQueueNode(self->c, self->node, HaltPRIO, "halt", NULL); + } else if (GetHdbProperty(self->node, "status", dummy, sizeof dummy)) { + SetHdbProperty(self->node, "status", "idle"); + } + return OKOK; } + /*---------------------------------------------------------------- This routine can return either 1 or 0. 1 means the position can be reached, 0 NOT @@ -65,30 +70,32 @@ static int SCTDRIVHalt(void *data) { about which limit was violated ------------------------------------------------------------------*/ static int SCTDRIVCheckLimits(void *data, float val, - char *error, int errlen){ - pSctDrive self = NULL; - char script[1024]; - int status; - Tcl_Interp *pTcl = NULL; - char *result; - - self = (pSctDrive)data; - snprintf(script,1024,"%f", val); - SetHdbProperty(self->node,"target", script); - if(GetHdbProperty(self->node,"checklimits",script,1024)){ - status = SctCallInContext(pServ->dummyCon, script, - self->node, self->c, &result); - if(SctVerbose(self->c)){ - SCPrintf(pServ->dummyCon, eWarning, "script %s called with result %s\n ", - script, result); - } - if(status == 0){ - strncpy(error,result,errlen); - return 0; - } + char *error, int errlen) +{ + pSctDrive self = NULL; + char script[1024]; + int status; + Tcl_Interp *pTcl = NULL; + char *result; + + self = (pSctDrive) data; + snprintf(script, 1024, "%f", val); + SetHdbProperty(self->node, "target", script); + if (GetHdbProperty(self->node, "checklimits", script, 1024)) { + status = SctCallInContext(pServ->dummyCon, script, + self->node, self->c, &result); + if (SctVerbose(self->c)) { + SCPrintf(pServ->dummyCon, eWarning, + "script %s called with result %s\n ", script, result); } - return 1; + if (status == 0) { + strlcpy(error, result, errlen); + return 0; + } + } + return 1; } + /*---------------------------------------------------------------- This routine can return 0 when a limit problem occurred OKOK when the motor was successfully started @@ -98,22 +105,24 @@ static int SCTDRIVCheckLimits(void *data, float val, to start the motor in question val is the value to drive the motor too ------------------------------------------------------------------*/ -static long SCTDRIVSetValue(void *data, SConnection *pCon, float val){ - pSctDrive self = NULL; - int status; - hdbValue v; - - self = (pSctDrive)data; - v.dataType = HIPFLOAT; - v.v.doubleValue = (double)val; - SetHdbProperty(self->node,"writestatus", "start"); - status = SetHipadabaPar(self->node, v, pCon); - if(status == 1){ - return OKOK; - } else { - return HWFault; - } +static long SCTDRIVSetValue(void *data, SConnection * pCon, float val) +{ + pSctDrive self = NULL; + int status; + hdbValue v; + + self = (pSctDrive) data; + v.dataType = HIPFLOAT; + v.v.doubleValue = (double) val; + SetHdbProperty(self->node, "writestatus", "start"); + status = SetHipadabaPar(self->node, v, pCon); + if (status == 1) { + return OKOK; + } else { + return HWFault; + } } + /*---------------------------------------------------------------- Checks the status of a running motor. Possible return values HWBusy The motor is still running @@ -124,199 +133,211 @@ static long SCTDRIVSetValue(void *data, SConnection *pCon, float val){ For real motors CheckStatus again shall try hard to fix any issues with the motor ------------------------------------------------------------------*/ -static int SCTDRIVCheckStatus(void *data, SConnection *pCon){ - pSctDrive self = NULL; - char script[1024]; - int status; - Tcl_Interp *pTcl = NULL; - char *result; - SConnection *con; - - self = (pSctDrive)data; - - /* - * check if the write command has gone through - */ - if(GetHdbProperty(self->node,"writestatus", script,1024)){ - if(strcmp(script,"start") == 0){ - return HWBusy; - } - } - - /* - * run the checkstatus script - */ - if(!GetHdbProperty(self->node,"checkstatus",script,1024)){ - if (!GetHdbProperty(self->node,"status",script,1024)){ - SCWrite(pCon, - "ERROR: configuration problem: no checkstatus script!", eError); - return HWFault; - } - result = script; - } else { - status = SctCallInContext(pCon,script, self->node, - self->c, &result); - if (status == 0) { - SCPrintf(pCon,eError," script %s returned %s", - script, result); - return HWFault; - } - if(SctVerbose(self->c)){ - SCPrintf(pCon,eError," script %s returned %s", - script, result); - } - } - if(strstr(result,"busy") != NULL){ +static int SCTDRIVCheckStatus(void *data, SConnection * pCon) +{ + pSctDrive self = NULL; + char script[1024]; + int status; + Tcl_Interp *pTcl = NULL; + char *result; + SConnection *con; + + self = (pSctDrive) data; + + /* + * check if the write command has gone through + */ + if (GetHdbProperty(self->node, "writestatus", script, 1024)) { + if (strcmp(script, "start") == 0) { return HWBusy; - } else if(strstr(result,"posfault") != NULL){ - return HWPosFault; - } else if(strstr(result,"fault") != NULL){ - return HWFault; - } else if(strstr(result,"idle") != NULL){ - return HWIdle; - } else { - SCPrintf(pCon,eError, - "ERROR: invalid status code %s returned from checkstatus script", - result); + } + } + + /* + * run the checkstatus script + */ + if (!GetHdbProperty(self->node, "checkstatus", script, 1024)) { + if (!GetHdbProperty(self->node, "status", script, 1024)) { + SCWrite(pCon, + "ERROR: configuration problem: no checkstatus script!", + eError); return HWFault; } + result = script; + } else { + status = SctCallInContext(pCon, script, self->node, self->c, &result); + if (status == 0) { + SCPrintf(pCon, eError, " script %s returned %s", script, result); + return HWFault; + } + if (SctVerbose(self->c)) { + SCPrintf(pCon, eError, " script %s returned %s", script, result); + } + } + if (strstr(result, "busy") != NULL) { + return HWBusy; + } else if (strstr(result, "posfault") != NULL) { + return HWPosFault; + } else if (strstr(result, "fault") != NULL) { return HWFault; + } else if (strstr(result, "idle") != NULL) { + return HWIdle; + } else { + SCPrintf(pCon, eError, + "ERROR: invalid status code %s returned from checkstatus script", + result); + return HWFault; + } + return HWFault; } + /*---------------------------------------------------------------- GetValue is supposed to read a motor position On errors, -99999999.99 is returned and messages printed to pCon ------------------------------------------------------------------*/ -static float SCTDRIVGetValue(void *data, SConnection *pCon){ - pSctDrive self = NULL; - float val = -99999999.99; - int status; - char error[256]; - hdbValue v; - - self = (pSctDrive)data; - if(GetHdbProperty(self->node,"geterror", error, 256)){ - SCWrite(pCon,error, eError); - return val; - } - return (float)self->node->value.v.doubleValue; +static float SCTDRIVGetValue(void *data, SConnection * pCon) +{ + pSctDrive self = NULL; + float val = -99999999.99; + int status; + char error[256]; + hdbValue v; + + self = (pSctDrive) data; + if (GetHdbProperty(self->node, "geterror", error, 256)) { + SCWrite(pCon, error, eError); + return val; + } + return (float) self->node->value.v.doubleValue; } + /*---------------------------------------------------------------- returns NULL on failure, a new datastructure else ------------------------------------------------------------------*/ -static pSctDrive SCTDRIVMakeObject(){ - pSctDrive self = NULL; +static pSctDrive SCTDRIVMakeObject() +{ + pSctDrive self = NULL; - self = calloc(sizeof(SctDrive),1); - if(self == NULL){ - return NULL; - } - self->pDes = CreateDescriptor("SctDriveAdapter"); - self->pDriv = CreateDrivableInterface(); - if(self->pDes == NULL || self->pDriv == NULL){ - free(self); - return NULL; - } - - self->pDes->GetInterface = SCTDRIVGetInterface; - self->pDriv->Halt = SCTDRIVHalt; - self->pDriv->CheckLimits = SCTDRIVCheckLimits; - self->pDriv->SetValue = SCTDRIVSetValue; - self->pDriv->CheckStatus = SCTDRIVCheckStatus; - self->pDriv->GetValue = SCTDRIVGetValue; + self = calloc(sizeof(SctDrive), 1); + if (self == NULL) { + return NULL; + } + self->pDes = CreateDescriptor("SctDriveAdapter"); + self->pDriv = CreateDrivableInterface(); + if (self->pDes == NULL || self->pDriv == NULL) { + free(self); + return NULL; + } - return self; + self->pDes->GetInterface = SCTDRIVGetInterface; + self->pDriv->Halt = SCTDRIVHalt; + self->pDriv->CheckLimits = SCTDRIVCheckLimits; + self->pDriv->SetValue = SCTDRIVSetValue; + self->pDriv->CheckStatus = SCTDRIVCheckStatus; + self->pDriv->GetValue = SCTDRIVGetValue; + + return self; } + /*-----------------------------------------------------------------*/ -static int SctDriveCommand(SConnection *pCon, SicsInterp *sics, void *object, - int argc, char *argv[]) { - pSctDrive self = (pSctDrive)object; - float val; - - assert(self != NULL); - - if (self->node == NULL) { - SCWrite(pCon, "ERROR: defunct object", eError); - return 0; - } - /* - * only action: print value - */ - val = self->pDriv->GetValue(self,pCon); - SCPrintf(pCon,eValue,"%s = %f", argv[0], val); - return 1; +static int SctDriveCommand(SConnection * pCon, SicsInterp * sics, + void *object, int argc, char *argv[]) +{ + pSctDrive self = (pSctDrive) object; + float val; + + assert(self != NULL); + + if (self->node == NULL) { + SCWrite(pCon, "ERROR: defunct object", eError); + return 0; + } + /* + * only action: print value + */ + val = self->pDriv->GetValue(self, pCon); + SCPrintf(pCon, eValue, "%s = %f", argv[0], val); + return 1; } + /*----------------------------------------------------------------*/ -static void SctDriveKill(void *data){ - pSctDrive self = (pSctDrive)data; - - if(self == NULL){ - return; - } - if(self->pDriv != NULL){ - free(self->pDriv); - } - if(self->pDes != NULL){ - DeleteDescriptor(self->pDes); - } - free(self); +static void SctDriveKill(void *data) +{ + pSctDrive self = (pSctDrive) data; + + if (self == NULL) { + return; + } + if (self->pDriv != NULL) { + free(self->pDriv); + } + if (self->pDes != NULL) { + DeleteDescriptor(self->pDes); + } + free(self); } + /*----------------------------------------------------------------*/ -static hdbCallbackReturn SctDummyCallback(Hdb *node, void *userData, - hdbMessage *msg) { +static hdbCallbackReturn SctDummyCallback(Hdb * node, void *userData, + hdbMessage * msg) +{ return hdbContinue; } + /*----------------------------------------------------------------*/ -static void SctDriveDeleteNode(void *data) { - pSctDrive self = (pSctDrive)data; +static void SctDriveDeleteNode(void *data) +{ + pSctDrive self = (pSctDrive) data; self->node = NULL; } + /*---------------------------------------------------------------*/ -int SctMakeDriveAdapter(SConnection *pCon, SicsInterp *pSics, void *object, - int argc, char *argv[]) { - pSctDrive pNew = NULL; - pSICSOBJ obj = NULL; +int SctMakeDriveAdapter(SConnection * pCon, SicsInterp * pSics, + void *object, int argc, char *argv[]) +{ + pSctDrive pNew = NULL; + pSICSOBJ obj = NULL; hdbCallback *cb; - - pNew = SCTDRIVMakeObject(); - if(pNew == NULL){ - SCWrite(pCon,"ERROR: out of memory in SctMakeDriveAdapter", - eError); - return 0; - } - - if(argc < 4){ - SCWrite(pCon,"ERROR: not enough arguments for SctMakeDriveAdapter", eError); - return 0; - } - - pNew->node = FindHdbNode(NULL,argv[2], pCon); - obj = FindCommandData(pSics,argv[3], "SctController"); - if(pNew->node == NULL || obj == NULL){ - SCWrite(pCon,"ERROR: node or controller not found", eError); - SctDriveKill(pNew); - return 0; - } - pNew->c =(SctController *)obj->pPrivate; - - if (strcasecmp(argv[0],"dynsctdrive") == 0) { + + pNew = SCTDRIVMakeObject(); + if (pNew == NULL) { + SCWrite(pCon, "ERROR: out of memory in SctMakeDriveAdapter", eError); + return 0; + } + + if (argc < 4) { + SCPrintf(pCon, eError, + "ERROR: should be %s ", + argv[0]); + return 0; + } + + pNew->node = FindHdbNode(NULL, argv[2], pCon); + obj = FindCommandData(pSics, argv[3], "SctController"); + if (pNew->node == NULL || obj == NULL) { + SCWrite(pCon, "ERROR: node or controller not found", eError); + SctDriveKill(pNew); + return 0; + } + pNew->c = (SctController *) obj->pPrivate; + + if (strcasecmp(argv[0], "dynsctdrive") == 0) { /* make object dynamic by defining a descriptor command */ SetDescriptorKey(pNew->pDes, "creationCommand", "0"); } - AddCommand(pSics, argv[1], SctDriveCommand, SctDriveKill, pNew); - SetHdbProperty(pNew->node,"sicsdev",argv[1]); - + AddCommand(pSics, argv[1], SctDriveCommand, SctDriveKill, pNew); + SetHdbProperty(pNew->node, "sicsdev", argv[1]); + cb = MakeHipadabaCallback(SctDummyCallback, pNew, SctDriveDeleteNode); assert(cb); AppendHipadabaCallback(pNew->node, cb); - - return 1; -} -/*---------------------------------------------------------------*/ -int SctMakeDriveObject(SConnection *pCon, SicsInterp *pSics, void *object, - int argc, char *argv[]); -void SctDriveInit(void) { + return 1; +} + +/*---------------------------------------------------------------*/ +void SctDriveAdapterInit(void) +{ AddCmd("makesctdrive", SctMakeDriveAdapter); AddCmd("dynsctdrive", SctMakeDriveAdapter); - AddCmd("makesctdriveobj",SctMakeDriveObject); } diff --git a/sctdriveobj.c b/sctdriveobj.c index e747a863..dc0d4b18 100644 --- a/sctdriveobj.c +++ b/sctdriveobj.c @@ -3,6 +3,19 @@ * scriptcontext to control the actual driving operation. This can also * serve as a drivable adapter to nodes in other objects. * + * Some cooperation from the node is required: It has to provide + * certain properties the value of which define scripts which + * have to be called at various stages. These are: + * + * checklimits, for limits checking + * checkstatus, for evaluating progress + * halt , for halting things + * + * If no checklimits script is given, nothing is checked. + * If no checkstatus scripts is given, the value of the status property is + * returned. In that case the status value should be updated by some poll script. + * If no halt script is given, the status is set to idle. M.Z. Sept. 08 + * * copyright: see file COPYRIGHT * * Mark Koennecke, June-July 2008 @@ -14,43 +27,68 @@ #include typedef struct { - pIDrivable pDriv; - SctController *c; - int doNotKillNode; + pIDrivable pDriv; + SctController *c; + int doNotKillNode; + SConnection *pCon; } DrivObjPriv, *pDrivObjPriv; -/*---------------------------------------------------------------*/ -static void *SCTDRIVGetInterface(void *data, int iD){ - pSICSOBJ self = NULL; - pDrivObjPriv pPriv; - - self = (pSICSOBJ)data; - pPriv = (pDrivObjPriv)self->pPrivate; - if(self != NULL && pPriv != NULL && iD == DRIVEID){ - if (self->objectNode == NULL) return NULL; - return pPriv->pDriv; - } else { - return NULL; - } - return NULL; +/*--------------------------------------------------------------*/ +static void KillDrivePriv(void *data) +{ + pDrivObjPriv priv = (pDrivObjPriv) data; + if (priv == NULL) { + return; + } + if (priv->pDriv != NULL) { + free(priv->pDriv); + } + if (priv->pCon != NULL) { + SCDeleteConnection(priv->pCon); + } + free(priv); } + +/*---------------------------------------------------------------*/ +static void *SCTDRIVGetInterface(void *data, int iD) +{ + pSICSOBJ self = NULL; + pDrivObjPriv pPriv; + + self = (pSICSOBJ) data; + pPriv = (pDrivObjPriv) self->pPrivate; + if (self != NULL && pPriv != NULL && iD == DRIVEID) { + if (self->objectNode == NULL) + return NULL; + return pPriv->pDriv; + } else { + return NULL; + } + return NULL; +} + /*---------------------------------------------------------------- This routine can return either OKOK or HWFault when thing go wrong. However, the return value of Halt is usually ignored! ------------------------------------------------------------------*/ -static int SCTDRIVHalt(void *data) { - pSICSOBJ self = NULL; - pDrivObjPriv pPriv; - char dummy[16]; - - self = (pSICSOBJ)data; - pPriv = (pDrivObjPriv)self->pPrivate; - if (GetHdbProperty(self->objectNode,"halt", dummy, sizeof dummy)) { - SctQueueNode(pPriv->c, self->objectNode, HaltPRIO, "halt", NULL); - } else if (GetHdbProperty(self->objectNode, "status", dummy, sizeof dummy)) { - SetHdbProperty(self->objectNode, "status", "idle"); - } - return OKOK; +static int SCTDRIVHalt(void *data) +{ + pSICSOBJ self = NULL; + pDrivObjPriv pPriv; + char dummy[16]; + + self = (pSICSOBJ) data; + pPriv = (pDrivObjPriv) self->pPrivate; + if (GetHdbProperty(self->objectNode, "halt", dummy, sizeof dummy)) { + SctQueueNode(pPriv->c, self->objectNode, HaltPRIO, "halt", + pPriv->pCon); + } else + if (GetHdbProperty(self->objectNode, "status", dummy, sizeof dummy)) + { + SetHdbProperty(self->objectNode, "status", "idle"); + } + return OKOK; } + /*---------------------------------------------------------------- This routine can return either 1 or 0. 1 means the position can be reached, 0 NOT @@ -58,32 +96,35 @@ static int SCTDRIVHalt(void *data) { about which limit was violated ------------------------------------------------------------------*/ static int SCTDRIVCheckLimits(void *data, float val, - char *error, int errlen){ - pSICSOBJ self = NULL; - pDrivObjPriv pPriv; - char script[1024]; - int status; - Tcl_Interp *pTcl = NULL; - char *result; - - self = (pSICSOBJ)data; - pPriv = (pDrivObjPriv)self->pPrivate; - snprintf(script,1024,"%f", val); - SetHdbProperty(self->objectNode,"target", script); - if(GetHdbProperty(self->objectNode,"checklimits",script,1024)){ - status = SctCallInContext(pServ->dummyCon, script, - self->objectNode, pPriv->c, &result); - if(SctVerbose(pPriv->c)){ - SCPrintf(pServ->dummyCon, eWarning, "script %s called with result %s\n ", - script, result); - } - if(status == 0){ - strncpy(error,result,errlen); - return 0; - } + char *error, int errlen) +{ + pSICSOBJ self = NULL; + pDrivObjPriv pPriv; + char script[1024]; + int status; + Tcl_Interp *pTcl = NULL; + char *result; + + self = (pSICSOBJ) data; + pPriv = (pDrivObjPriv) self->pPrivate; + snprintf(script, 1024, "%g", val); + /* set target. This not yet done, as SetValue is called later */ + SetHdbProperty(self->objectNode, "target", script); + if (GetHdbProperty(self->objectNode, "checklimits", script, 1024)) { + status = SctCallInContext(pServ->dummyCon, script, + self->objectNode, pPriv->c, &result); + if (SctVerbose(pPriv->c)) { + SCPrintf(pServ->dummyCon, eWarning, + "script %s called with result %s\n ", script, result); } - return 1; + if (status == 0) { + strlcpy(error, result, errlen); + return 0; + } + } + return 1; } + /*---------------------------------------------------------------- This routine can return 0 when a limit problem occurred OKOK when the motor was successfully started @@ -93,25 +134,32 @@ static int SCTDRIVCheckLimits(void *data, float val, to start the motor in question val is the value to drive the motor too ------------------------------------------------------------------*/ -static long SCTDRIVSetValue(void *data, SConnection *pCon, float val){ - pSICSOBJ self = NULL; - pDrivObjPriv pPriv; - int status; - hdbValue v; - - self = (pSICSOBJ)data; - pPriv = (pDrivObjPriv)self->pPrivate; +static long SCTDRIVSetValue(void *data, SConnection * pCon, float val) +{ + pSICSOBJ self = NULL; + pDrivObjPriv pPriv; + int status; + hdbValue v; - v.dataType = HIPFLOAT; - v.v.doubleValue = (double)val; - SetHdbProperty(self->objectNode,"writestatus", "start"); - status = SetHipadabaPar(self->objectNode, v, pCon); - if(status == 1){ - return OKOK; - } else { - return HWFault; - } + self = (pSICSOBJ) data; + pPriv = (pDrivObjPriv) self->pPrivate; + if (pPriv->pCon != NULL) { + SCDeleteConnection(pPriv->pCon); + } + pPriv->pCon = SCCopyConnection(pCon); + + StopByData(pServ->pExecutor, data); + + v = MakeHdbFloat(val); + SetHdbProperty(self->objectNode, "writestatus", "start"); + status = SetHipadabaPar(self->objectNode, v, pCon); + if (status == 1) { + return OKOK; + } else { + return HWFault; + } } + /*---------------------------------------------------------------- Checks the status of a running motor. Possible return values HWBusy The motor is still running @@ -122,216 +170,242 @@ static long SCTDRIVSetValue(void *data, SConnection *pCon, float val){ For real motors CheckStatus again shall try hard to fix any issues with the motor ------------------------------------------------------------------*/ -static int SCTDRIVCheckStatus(void *data, SConnection *pCon){ - pSICSOBJ self = NULL; - pDrivObjPriv pPriv; - char script[1024]; - int status; - Tcl_Interp *pTcl = NULL; - char *result; - SConnection *con; - - self = (pSICSOBJ)data; - pPriv = (pDrivObjPriv)self->pPrivate; - - /* - * check if the write command has gone through - */ - if(GetHdbProperty(self->objectNode,"writestatus", script,1024)){ - if(strcmp(script,"start") == 0){ - return HWBusy; - } - } - - /* - * run the checkstatus script - */ - if(!GetHdbProperty(self->objectNode,"checkstatus",script,1024)){ - if (!GetHdbProperty(self->objectNode,"status",script,1024)){ - SCWrite(pCon, - "ERROR: configuration problem: no checkstatus script!", eError); - return HWFault; - } - result = script; - } else { - status = SctCallInContext(pCon,script, self->objectNode, - pPriv->c, &result); - if (status == 0) { - SCPrintf(pCon,eError," script %s returned %s", - script, result); - return HWFault; - } - if(SctVerbose(pPriv->c)){ - SCPrintf(pCon,eError," script %s returned %s", - script, result); - } - } - if(strstr(result,"busy") != NULL){ +static int SCTDRIVCheckStatus(void *data, SConnection * pCon) +{ + pSICSOBJ self = NULL; + pDrivObjPriv pPriv; + char script[1024]; + int status; + Tcl_Interp *pTcl = NULL; + char *result; + SConnection *con; + + self = (pSICSOBJ) data; + pPriv = (pDrivObjPriv) self->pPrivate; + + /* + * check if the write command has gone through + */ + if (GetHdbProperty(self->objectNode, "writestatus", script, 1024)) { + if (strcmp(script, "start") == 0) { return HWBusy; - } else if(strstr(result,"posfault") != NULL){ - return HWPosFault; - } else if(strstr(result,"fault") != NULL){ - return HWFault; - } else if(strstr(result,"idle") != NULL){ - return HWIdle; - } else { - SCPrintf(pCon,eError, - "ERROR: invalid status code %s returned from checkstatus script", - result); + } + } + + /* + * run the checkstatus script + */ + if (!GetHdbProperty(self->objectNode, "checkstatus", script, 1024)) { + if (!GetHdbProperty(self->objectNode, "status", script, 1024)) { + SCWrite(pCon, + "ERROR: configuration problem: no checkstatus script!", + eError); return HWFault; } + result = script; + } else { + status = SctCallInContext(pCon, script, self->objectNode, + pPriv->c, &result); + if (status == 0) { + SCPrintf(pCon, eError, " script %s returned %s", script, result); + return HWFault; + } + if (SctVerbose(pPriv->c)) { + SCPrintf(pCon, eError, " script %s returned %s", script, result); + } + } + if (strstr(result, "busy") != NULL) { + return HWBusy; + } else if (strstr(result, "posfault") != NULL) { + return HWPosFault; + } else if (strstr(result, "fault") != NULL) { return HWFault; + } else if (strstr(result, "idle") != NULL) { + return HWIdle; + } else { + SCPrintf(pCon, eError, + "ERROR: invalid status code %s returned from checkstatus script", + result); + return HWFault; + } + return HWFault; } + /*---------------------------------------------------------------- GetValue is supposed to read a motor position On errors, -99999999.99 is returned and messages printed to pCon ------------------------------------------------------------------*/ -static float SCTDRIVGetValue(void *data, SConnection *pCon){ - pSICSOBJ self = NULL; - pDrivObjPriv pPriv; - float val = -99999999.99; - int status; - char error[256]; - hdbValue v; - - self = (pSICSOBJ)data; - pPriv = (pDrivObjPriv)self->pPrivate; - if(GetHdbProperty(self->objectNode,"geterror", error, 256)){ - SCWrite(pCon,error, eError); - return val; - } - return (float)self->objectNode->value.v.doubleValue; +static float SCTDRIVGetValue(void *data, SConnection * pCon) +{ + pSICSOBJ self = NULL; + pDrivObjPriv pPriv; + float val = -99999999.99; + int status; + char error[256]; + hdbValue v; + + self = (pSICSOBJ) data; + pPriv = (pDrivObjPriv) self->pPrivate; + if (GetHdbProperty(self->objectNode, "geterror", error, 256)) { + SCWrite(pCon, error, eError); + return val; + } + return (float) self->objectNode->value.v.doubleValue; } + /*-----------------------------------------------------------------*/ -void AssignSctDrive(pIDrivable pDriv){ - pDriv->Halt = SCTDRIVHalt; - pDriv->CheckLimits = SCTDRIVCheckLimits; - pDriv->SetValue = SCTDRIVSetValue; - pDriv->CheckStatus = SCTDRIVCheckStatus; - pDriv->GetValue = SCTDRIVGetValue; +void AssignSctDrive(pIDrivable pDriv) +{ + pDriv->Halt = SCTDRIVHalt; + pDriv->CheckLimits = SCTDRIVCheckLimits; + pDriv->SetValue = SCTDRIVSetValue; + pDriv->CheckStatus = SCTDRIVCheckStatus; + pDriv->GetValue = SCTDRIVGetValue; } + /*---------------------------------------------------------------------------*/ -static void KillDriveOBJ(void *data){ - pSICSOBJ self = (pSICSOBJ)data; - pDrivObjPriv pPriv; +static void KillDriveOBJ(void *data) +{ + pSICSOBJ self = (pSICSOBJ) data; + pDrivObjPriv pPriv; - if(self == NULL){ - return; - } + if (self == NULL) { + return; + } - pPriv = (pDrivObjPriv)self->pPrivate; - if(pPriv->doNotKillNode && self->pDes != NULL){ - if(self->pDes->name) free(self->pDes->name); - if(self->pDes->pKeys) IFDeleteOptions(self->pDes->pKeys); - free(self->pDes); - } else { - DeleteDescriptor(self->pDes); /* kill descriptor including node */ - } - if(self->KillPrivate != NULL && self->pPrivate != NULL){ - self->KillPrivate(self->pPrivate); - } - RemoveHdbNodeFromParent(self->objectNode, pServ->dummyCon); - free(self); + pPriv = (pDrivObjPriv) self->pPrivate; + if (pPriv->doNotKillNode && GetDescriptorKey(self->pDes, "creationCommand") == NULL /* it's not a dynamic object */ + && self->pDes != NULL) { + self->objectNode = NULL; /* do not call RemoveHdbNodeFromParent in KillSICSOBJ */ + self->pDes->parNode = NULL; /* do not kill the node in KillSICSOBJ/DeleteDescriptor */ + } + KillSICSOBJ(self); } + /*-----------------------------------------------------------------------------*/ -pSICSOBJ MakeSctDriveObj(pHdb node, char *class, SctController *c){ - pSICSOBJ pNew = NULL; - pDrivObjPriv pPriv = NULL; - hdbValue val; - - pNew = (pSICSOBJ)malloc(sizeof(SICSOBJ)); - pPriv = (pDrivObjPriv)malloc(sizeof(DrivObjPriv)); - if(pNew == NULL || pPriv == NULL){ - return NULL; - } - memset(pNew,0,sizeof(SICSOBJ)); - memset(pPriv,0,sizeof(DrivObjPriv)); - - pNew->pDes = CreateDescriptor(class); - pPriv->pDriv = CreateDrivableInterface(); - if(pNew->pDes == NULL || pPriv->pDriv == NULL){ - free(pNew); - free(pPriv); - return(NULL); - } - pNew->objectNode = node; - AssignSctDrive(pPriv->pDriv); - pPriv->c = c; - pNew->pDes->parNode = pNew->objectNode; - pNew->pDes->GetInterface = SCTDRIVGetInterface; - pNew->pPrivate = pPriv; - pNew->KillPrivate = DefaultKill; - return pNew; +pSICSOBJ MakeSctDriveObj(pHdb node, char *class, SctController * c, + int doNotKillNode) +{ + pSICSOBJ pNew = NULL; + pDrivObjPriv pPriv = NULL; + hdbValue val; + + pNew = (pSICSOBJ) malloc(sizeof(SICSOBJ)); + pPriv = (pDrivObjPriv) malloc(sizeof(DrivObjPriv)); + if (pNew == NULL || pPriv == NULL) { + return NULL; + } + memset(pNew, 0, sizeof(SICSOBJ)); + memset(pPriv, 0, sizeof(DrivObjPriv)); + + pNew->pDes = CreateDescriptor(class); + pNew->pDes->SaveStatus = SaveSICSOBJ; + pPriv->pDriv = CreateDrivableInterface(); + if (pNew->pDes == NULL || pPriv->pDriv == NULL) { + free(pNew); + free(pPriv); + return (NULL); + } + pNew->objectNode = node; + AssignSctDrive(pPriv->pDriv); + pPriv->c = c; + pPriv->doNotKillNode = doNotKillNode; + pNew->pDes->parNode = pNew->objectNode; + pNew->pDes->GetInterface = SCTDRIVGetInterface; + pNew->pPrivate = pPriv; + pNew->KillPrivate = KillDrivePriv; + return pNew; } + /*-------------------------------------------------------------------------- * This actually has two syntaxes: * makesctdrive name path-to-existing-node class SctController - * makesctdrive name type priv class SctController + * makesctdrive name float priv class SctController *--------------------------------------------------------------------------*/ -int SctMakeDriveObject(SConnection *pCon, SicsInterp *pSics, void *object, - int argc, char *argv[]) { - pHdb node = NULL; - pDrivObjPriv pPriv = NULL; - pSICSOBJ pNew = NULL; - pSICSOBJ pSct = NULL; - SctController *c = NULL; - int priv, type, status; - hdbValue val; - - if(argc < 5){ - SCWrite(pCon,"ERROR: not enough arguments to SctMakeDriveObject", eError); - return 0; - } - - node = FindHdbNode(NULL,argv[2], pCon); - if(node != NULL){ - pSct = FindCommandData(pSics,argv[4], "SctController"); - if(pSct == NULL){ - SCPrintf(pCon,eError, "ERROR: SctController %s not found", argv[4]); - return 0; - } - c = (SctController *)pSct->pPrivate; - pNew = MakeSctDriveObj(node,argv[3],c); - pPriv = (pDrivObjPriv)pNew->pPrivate; - pPriv->doNotKillNode = 1; /* the node is owned by someone else*/ - } else { - /* convert privilege */ - priv = decodeSICSPriv(argv[3]); - /* convert datatype */ - strtolower(argv[4]); - type = convertHdbType(argv[2]); - if (type == HIPNONE) { - node = MakeHipadabaNode(argv[1], HIPNONE, 1); - } else { - val = makeHdbValue(type,0); - node = MakeSICSHdbPar(argv[1], priv, val); - ReleaseHdbValue(&val); - } - if(node == NULL){ - SCWrite(pCon,"ERROR: node creation failed", eError); - return 0; - } - c = FindCommandData(pSics,argv[5], "SctController"); - if(c == NULL){ - SCPrintf(pCon,eError, "ERROR: SctController %s not found", argv[4]); - return 0; - } - pNew = MakeSctDriveObj(node,argv[3],c); - } - if(pNew == NULL){ - SCWrite(pCon,"ERROR: failed to create drive object", eError); - return 0; - } - status = AddCommand(pSics, - argv[1], - InterInvokeSICSOBJ, - KillDriveOBJ, - pNew); - if(status != 1){ - KillSICSOBJ(pNew); - SCPrintf(pCon,eError,"ERROR: failed create duplicate command %s", argv[1]); - return 0; - } - return 1; -} +int SctMakeDriveObject(SConnection * pCon, SicsInterp * pSics, + void *object, int argc, char *argv[]) +{ + pHdb node = NULL; + pDrivObjPriv pPriv = NULL; + pSICSOBJ pNew = NULL; + pSICSOBJ pSct = NULL; + SctController *c = NULL; + int priv, type, status, doNotKillNode; + hdbValue val; + char *sctName; + char *class; + if (argc < 5) + goto Usage; + + if (argc == 5) { + node = FindHdbNode(NULL, argv[2], pCon); + if (node == NULL) { + SCPrintf(pCon, eError, "ERROR: node %s not found", argv[2]); + goto Usage; + } + sctName = argv[4]; + class = argv[3]; + doNotKillNode = 1; /* the node is owned by someone else */ + } else { + /* convert datatype */ + type = convertHdbType(argv[2]); + /* convert privilege */ + priv = decodeSICSPriv(argv[3]); + if (priv < 0 || type != HIPFLOAT) + goto Usage; + node = MakeSICSHdbPar(argv[1], priv, MakeHdbFloat(0.0)); + if (node == NULL) { + SCWrite(pCon, "ERROR: node creation failed", eError); + return 0; + } + SetHdbProperty(node, "sicscommand", argv[1]); + sctName = argv[5]; + class = argv[4]; + doNotKillNode = 0; /* kill the node with the command */ + } + + pSct = FindCommandData(pSics, sctName, "SctController"); + if (pSct == NULL) { + SCPrintf(pCon, eError, "ERROR: SctController %s not found", sctName); + goto Usage; + } + c = (SctController *) pSct->pPrivate; + pNew = MakeSctDriveObj(node, class, c, doNotKillNode); + SetHdbProperty(node, "objectName", argv[1]); + + if (pNew == NULL) { + SCWrite(pCon, "ERROR: failed to create drive object", eError); + return 0; + } + if (strcasecmp(argv[0], "dynsctdriveobj") == 0) { + /* make object dynamic by defining a creation command */ + SetDescriptorKey(pNew->pDes, "creationCommand", "0"); + RegisterSICSOBJKillCmd(pNew, argv[1]); + } + SetHdbProperty(pNew->objectNode, "sicsdev", argv[1]); + SetHdbProperty(pNew->objectNode, "type", "drivable"); + status = AddCommand(pSics, + argv[1], InterInvokeSICSOBJ, KillDriveOBJ, pNew); + if (status != 1) { + KillSICSOBJ(pNew); + SCPrintf(pCon, eError, "ERROR: failed create duplicate command %s", + argv[1]); + return 0; + } + return 1; +Usage: + SCPrintf(pCon, eError, + "ERROR: should be %s ", + argv[0]); + SCPrintf(pCon, eError, + "ERROR: or %s ", + argv[0]); + return 0; +} +/*---------------------------------------------------------------*/ +void SctDriveObjInit(void) +{ + AddCmd("makesctdriveobj", SctMakeDriveObject); + AddCmd("dynsctdriveobj", SctMakeDriveObject); +} diff --git a/sdynar.c b/sdynar.c index 313a0b50..843b7298 100644 --- a/sdynar.c +++ b/sdynar.c @@ -15,184 +15,171 @@ #include "sdynar.i" /*---------------------------------------------------------------------------*/ - pDynar CreateDynar(int iStart, int iEnd, int iGrain, - void (*DataFree)(void *pData)) - { - pDynar pNew = NULL; - int iSize; - - pNew = (pDynar)malloc(sizeof(Dynar)); - if(!pNew) - { - return NULL; - } - memset(pNew, 0, sizeof(Dynar)); - - pNew->iStart = iStart; - pNew->iEnd = iEnd; - pNew->iGrain = iGrain; - pNew->DataFree = DataFree; - iSize = iEnd - iStart; - assert(iSize > 0); - pNew->pArray = (void **)malloc(iSize * sizeof(void *)); - if(!pNew->pArray) - { - free(pNew); - return NULL; - } - memset(pNew->pArray,0,iSize * sizeof(void *)); - return pNew; - } -/*----------------------------------------------------------------------------*/ - void DeleteDynar(pDynar self) - { - int i, iSize; - - assert(self); - - iSize = self->iEnd - self->iStart; - for(i = 0; i < iSize; i++) - { - if(self->pArray[i]) - { - if(self->DataFree) - { - self->DataFree(self->pArray[i]); - } - } - } - free(self->pArray); - free(self); - } -/*---------------------------------------------------------------------------*/ - static int DynarResize(pDynar self, int iRequest) - { - void **pNew = NULL; - int i, iNewStart, iNewEnd, iOldSize, iNewSize, iOffset; +pDynar CreateDynar(int iStart, int iEnd, int iGrain, + void (*DataFree) (void *pData)) +{ + pDynar pNew = NULL; + int iSize; - assert(self); - iOldSize = self->iEnd - self->iStart; - - iNewStart = self->iStart; - iNewEnd = self->iEnd; - if(iRequest <= self->iStart) - { - iNewStart -= self->iGrain; - } - if(iRequest >= (self->iEnd - 1)) - { - iNewEnd += self->iGrain; - } - iNewSize = iNewEnd - iNewStart; - - pNew = (void **)malloc(iNewSize * sizeof(void *)); - if(!pNew) - { - return 0; - } - memset(pNew,0,iNewSize*sizeof(void *)); - - iOffset = self->iStart - iNewStart; - if(iOffset < 0) - { - iOffset = - iOffset; - } - for(i = 0; i < iOldSize; i++) - { - pNew[i+iOffset] = self->pArray[i]; - } - self->iStart = iNewStart; - self->iEnd = iNewEnd; - free(self->pArray); - self->pArray = pNew; - return 1; - } -/*----------------------------------------------------------------------------*/ - int DynarPut(pDynar self, int iIndex, void *pData) - { - int iReal, iRet; - - assert(self); - - if( (iIndex < self->iStart) || (iIndex > self->iEnd -1) ) - { - iRet = DynarResize(self,iIndex); - if(!iRet) - { - return 0; - } - } - - iReal = iIndex - self->iStart; - if(self->pArray[iReal]) - { - if(self->DataFree) - { - self->DataFree(self->pArray[iReal]); - } - } - self->pArray[iReal] = pData; - return 1; + pNew = (pDynar) malloc(sizeof(Dynar)); + if (!pNew) { + return NULL; } -/*-------------------------------------------------------------------------*/ - int DynarPutCopy(pDynar self, int iIndex, void *pBuffer, int iDataLen) - { - char *pPtr = NULL; - - pPtr = (char *)malloc(iDataLen); - if(!pPtr) - { + memset(pNew, 0, sizeof(Dynar)); + + pNew->iStart = iStart; + pNew->iEnd = iEnd; + pNew->iGrain = iGrain; + pNew->DataFree = DataFree; + iSize = iEnd - iStart; + assert(iSize > 0); + pNew->pArray = (void **) malloc(iSize * sizeof(void *)); + if (!pNew->pArray) { + free(pNew); + return NULL; + } + memset(pNew->pArray, 0, iSize * sizeof(void *)); + return pNew; +} + +/*----------------------------------------------------------------------------*/ +void DeleteDynar(pDynar self) +{ + int i, iSize; + + assert(self); + + iSize = self->iEnd - self->iStart; + for (i = 0; i < iSize; i++) { + if (self->pArray[i]) { + if (self->DataFree) { + self->DataFree(self->pArray[i]); + } + } + } + free(self->pArray); + free(self); +} + +/*---------------------------------------------------------------------------*/ +static int DynarResize(pDynar self, int iRequest) +{ + void **pNew = NULL; + int i, iNewStart, iNewEnd, iOldSize, iNewSize, iOffset; + + assert(self); + iOldSize = self->iEnd - self->iStart; + + iNewStart = self->iStart; + iNewEnd = self->iEnd; + if (iRequest <= self->iStart) { + iNewStart -= self->iGrain; + } + if (iRequest >= (self->iEnd - 1)) { + iNewEnd += self->iGrain; + } + iNewSize = iNewEnd - iNewStart; + + pNew = (void **) malloc(iNewSize * sizeof(void *)); + if (!pNew) { + return 0; + } + memset(pNew, 0, iNewSize * sizeof(void *)); + + iOffset = self->iStart - iNewStart; + if (iOffset < 0) { + iOffset = -iOffset; + } + for (i = 0; i < iOldSize; i++) { + pNew[i + iOffset] = self->pArray[i]; + } + self->iStart = iNewStart; + self->iEnd = iNewEnd; + free(self->pArray); + self->pArray = pNew; + return 1; +} + +/*----------------------------------------------------------------------------*/ +int DynarPut(pDynar self, int iIndex, void *pData) +{ + int iReal, iRet; + + assert(self); + + if ((iIndex < self->iStart) || (iIndex > self->iEnd - 1)) { + iRet = DynarResize(self, iIndex); + if (!iRet) { return 0; } - memcpy(pPtr,pBuffer,iDataLen); - return DynarPut(self,iIndex,pPtr); - } -/*--------------------------------------------------------------------------*/ - int DynarReplace(pDynar self, int iIndex, void *pData, int iDataLen) - { - int iReal, iRet; - - assert(self); - - if( (iIndex < self->iStart) || (iIndex >= self->iEnd -1) ) - { - iRet = DynarResize(self,iIndex); - if(!iRet) - { - return 0; - } - } - - iReal = iIndex - self->iStart; - if(self->pArray[iReal]) - { - memcpy(self->pArray[iReal],pData,iDataLen); - return 1; - } - else - { - return DynarPutCopy(self,iIndex,pData,iDataLen); - } } -/*---------------------------------------------------------------------------*/ - int DynarGet(pDynar self, int iIndex, void **pData) - { - int iReal; - - assert(self); - - iReal = iIndex - self->iStart; - *pData = self->pArray[iReal]; - return 1; + + iReal = iIndex - self->iStart; + if (self->pArray[iReal]) { + if (self->DataFree) { + self->DataFree(self->pArray[iReal]); + } } + self->pArray[iReal] = pData; + return 1; +} + /*-------------------------------------------------------------------------*/ - int DynarGetCopy(pDynar self, int iIndex, void *pData, int iDataLen) - { - int iReal; - - assert(self); - - iReal = iIndex - self->iStart; - memcpy(pData,self->pArray[iReal],iDataLen); - return 1; +int DynarPutCopy(pDynar self, int iIndex, void *pBuffer, int iDataLen) +{ + char *pPtr = NULL; + + pPtr = (char *) malloc(iDataLen); + if (!pPtr) { + return 0; } + memcpy(pPtr, pBuffer, iDataLen); + return DynarPut(self, iIndex, pPtr); +} + +/*--------------------------------------------------------------------------*/ +int DynarReplace(pDynar self, int iIndex, void *pData, int iDataLen) +{ + int iReal, iRet; + + assert(self); + + if ((iIndex < self->iStart) || (iIndex >= self->iEnd - 1)) { + iRet = DynarResize(self, iIndex); + if (!iRet) { + return 0; + } + } + + iReal = iIndex - self->iStart; + if (self->pArray[iReal]) { + memcpy(self->pArray[iReal], pData, iDataLen); + return 1; + } else { + return DynarPutCopy(self, iIndex, pData, iDataLen); + } +} + +/*---------------------------------------------------------------------------*/ +int DynarGet(pDynar self, int iIndex, void **pData) +{ + int iReal; + + assert(self); + + iReal = iIndex - self->iStart; + *pData = self->pArray[iReal]; + return 1; +} + +/*-------------------------------------------------------------------------*/ +int DynarGetCopy(pDynar self, int iIndex, void *pData, int iDataLen) +{ + int iReal; + + assert(self); + + iReal = iIndex - self->iStart; + memcpy(pData, self->pArray[iReal], iDataLen); + return 1; +} diff --git a/sdynar.h b/sdynar.h index 04d61d3b..b14542a9 100644 --- a/sdynar.h +++ b/sdynar.h @@ -13,19 +13,18 @@ #ifndef SICSDYNAR #define SICSDYNAR - typedef struct __SDynar *pDynar; +typedef struct __SDynar *pDynar; /*-------------------------------------------------------------------------*/ - pDynar CreateDynar(int iStart, int iEnd, int iGrain, - void (*DataFree)(void *pData)); - void DeleteDynar(pDynar self); +pDynar CreateDynar(int iStart, int iEnd, int iGrain, + void (*DataFree) (void *pData)); +void DeleteDynar(pDynar self); /*------------------------------------------------------------------------*/ - int DynarPut(pDynar self, int iIndex, void *pData); - int DynarPutCopy(pDynar self, int iIndex, void *pData, int iDataLen); - int DynarReplace(pDynar self, int iIndex, void *pData, int iDatLen); - - int DynarGet(pDynar self, int iIndex, void **pData); - int DynarGetCopy(pDynar self, int iIndex, void *pData, int iDataLen); +int DynarPut(pDynar self, int iIndex, void *pData); +int DynarPutCopy(pDynar self, int iIndex, void *pData, int iDataLen); +int DynarReplace(pDynar self, int iIndex, void *pData, int iDatLen); + +int DynarGet(pDynar self, int iIndex, void **pData); +int DynarGetCopy(pDynar self, int iIndex, void *pData, int iDataLen); #endif - diff --git a/sel2.c b/sel2.c deleted file mode 100644 index 9501c84e..00000000 --- a/sel2.c +++ /dev/null @@ -1,528 +0,0 @@ -/************************************************************************/ -/* Hahn-Meitner-Institut Berlin */ -/* Bereich Strukturforschung */ -/* Abteilung NI / BENSC */ -/* Glienicker Strasse 100 */ -/* D-14109 Berlin (Wannsee) */ -/* Software:K. Emmelmann, Tel.(030)8062-2588, Mail: klaus@dvwbs5.hmi.de */ -/************************************************************************/ -/* Datei: SEL.C */ -/* Teil von: KWS.C */ -/* Anwendung bei: V4 - KWS */ -/* Titel: Treiberprogramm fuer Geschwindigkeitsselektor DORNIER */ -/* Version: 1.0 vom: 30.1.96 */ -/************************************************************************/ -/* -Legende -======= - -30.1.96 Emmelmann Implementierung -1.2.96 Emmelmann Statusdekodierung eingebaut -27.2.96 Emmelmann Strom wird auch im Status geliefert - - -Das Handbuch sagt Empfangsterminator ist Linefeed. - - -Jeder Befehl erzeugt ein Echo; argumentlose Befehle werden im Echo -zusaetzlich mit einer Zahl versehen, deren Bedeutung unbekannt ist. - - -FEHLERMELDUNGEN, die bekannt sind: -**************************************** - - 1. Solldrehzahl zu klein ! - 2. Solldrehzahl zu gross ! - 3. derzeit keine Ausfuehrung moeglich ! - 4. Solldrehzahl in einem kritischen Bereich - - return to m - 5. HOCHFAHREN 1 - 6. - -zu 3: Abfrage der Istgeschwindigkeit ist waehrend des Hochfahrens aus dem - Stillstand nur ueber Lesen des Gesamtstatus moeglich -zu 4: es gibt verbotene Geschwindigkeitsbereiche -zu 5: beim Uebergang von Stop in den gestarteten Zustand - -Zeitliches Protokollverhalten ------------------------------ - Wird ein Befehl bearbeitet, werden alle weiteren ueber die serielle - Schnittstelle einlaufenden Befehle ignoriert - auch nicht gepuffert ! - - Max. Befahlsrate: 1 Befehl / 5 Sekunden - -Geraete-Verhalten ------------------ -Der Startbefehl faehrt den Selektor auf die Minimalgeschwindigkeit (3100U/min) - -Das Protokoll: fuer jeden Befehl erzeugt der Selektor-PC ein Echo ! - -Host -> Selektor ------------------------- -REM (disabled) Remote-Betrieb einschalten - Rueckmeldung: ENABLED / Host nicht betriebsbereit! - -TTY (disabled) Local-Betrieb einschalten - Rueckmeldung: DISABLED - -??? Sende Status (Status ist nicht fest und geht von der - Interpretation der Kennworte aus !) - -TIM (disabled) Setzen des Zeitintervalles zur Time-Out-Ueberwachung des PCs - ???? - -SST Start des Selektors und Ausregeln der Drehzahl (Nur wenn der - Selektor steht !); liefert als Rueckmeldung die Solldrehzahl - -SDR nnnnn Vorgabe einer Soll-Drehzahl und geregelten Betrieb einschalten. - 3100 => nnnnn <=28300 U/min; liegt der Wert in einem kritischen - Bereich (geht aus Setup-Menue hervor), kommt eine entsprechende - Rueckmeldung - -FDR Sende die Solldrehzahl (Format 'RPM n') - -STB Leerlauf ohne Regelung - -BRE Beginne eine Verlustleistungsmessung - ist bei Statusabruf - lesbar, wenn dort die Betriebsart regeln erscheint ! - -HAL Bremse Selektor bis zum Stillstand ab (unterhalb 3000 U/min.) - -*/ -#include stdio.h -#include descrip.h -#include iodef.h -#include errno.h -#include lnmdef.h - -#define FALSE 0 -#define TRUE !FALSE - -#define OK 0L -#define NOT_OK !OK - -#define LIMIT_U 3100 /* niedrigste Drehzahl */ -#define LIMIT_O 28300 - -/* Verbotene Drehzahlbereiche (Resonanzgefahr) */ - -#define RESONANZ_1U 3648 -#define RESONANZ_1O 4552 -#define RESONANZ_2U 5248 -#define RESONANZ_2O 6449 -#define RESONANZ_3U 9148 -#define RESONANZ_3O 9949 - -#define TOK_BUF_L 25 - -#define SELE_LUN 0 - -extern FILE *fs; - -static short chan_s=6; - -/* *********************************************************************** */ -/* ------------------------------------------------------------------------ */ -long select_setup() -{ -register rc; -$DESCRIPTOR(dev_descr, "TXA1:"); -chan_s=SELE_LUN; -if ((rc=sys$assign(&dev_descr, &chan_s, NULL,NULL)) != 1) - {printf("Error in Selector_SETUP: Ret = %d\n",rc); return(NOT_OK);} -return(OK); -} - -/* ------------------------------------------------------------------------ */ -/* Function liest ueberprueft das Befehlsecho */ -long sele_test_echo(cmd, lng) -char *cmd[]; -int lng; -{ -char echo[80]; -if (sele_read(&echo)!= OK) return(NOT_OK); -if (strncmp(&echo, cmd, lng) != 0) - {printf("Selector:protocol error%s\n",echo); return(NOT_OK);} - else - return(OK); -} -/* ------------------------------------------------------------------------ */ -/* Function prueft die Anzahl der sich im Typeahead-Buffer befindenden Bytes - und liefert das naechste dort anstehende Zeichen, jedoch ohne es - aus dem Puffer zu entnehmen. -*/ -long tst_buf_s(bt) -int *bt; -{ -int bytes; -register rc; -struct {unsigned short status, bytes; - int pid; } iosb; -if ((rc=sys$qiow(NULL,chan_s,IO$_SENSEMODE | IO$M_TYPEAHDCNT,&iosb, - NULL, NULL, &bytes, NULL, NULL, NULL, NULL, NULL)) != 1) - {print_error(fs,"Error in QIOW"); return(NOT_OK);} -/**ch = (bytes >> 16) & 0xff;*/ -*bt = bytes & 0xffff; -return(OK); -} - -/* ------------------------------------------------------------------------ */ -long sele_read(message) -char *message; -{ -char char_l[8], *ptr; -register rc; - struct {unsigned short status, bytes; - int pid; } iosb; -ptr = message; -for (;;) - { - if ((rc=sys$qiow(NULL,chan_s,IO$_READVBLK | IO$M_NOECHO, - &iosb,NULL, - NULL, char_l, 1, NULL, NULL, NULL, NULL)) != 1) - {printf("Error in QIOW, READ_MESS: %d\n", rc);return(NOT_OK);} - *ptr = char_l[0]; - /* Terminator (linefeed) ? */ - ptr++; - if (char_l[0] == '\n') break; - } -return(OK); -} -/* ------------------------------------------------------------------------ */ -/* Pruefe ob der Selektor eine Fehlermeldung erzeugt hat und gib sie aus */ - -long select_error_msg(err) -long *err; -{ -char chr[10], msg[80]; -float waiti=3.0; /* Selektor PC hat 3 Sekunden Reaktionszeit !! */ - -/* Warte ein wenig - es koennte auf den Befehl hin eine Fehlermeldung erscheinen */ -lib$wait(&waiti); - -/* Es koennen auch mehrere Zeilen sein */ -*err = FALSE; -for (;;) - {if (tst_buf_s(&chr) != OK) return(NOT_OK); - if (chr[0] != NULL) - { - if (sele_read(&msg) != OK) return(NOT_OK); - printf("Selektor failure:"); - printf("%s\n\7",msg); - *err = TRUE; - } - else - return(OK); - } -} -/* ------------------------------------------------------------------------ */ -long sele_write(message) -char message[]; -{ -char msg[80]; -long err; -register rc; -struct - { - unsigned short status, bytes; - int pid; } iosb; - -if (select_error_msg(&err) != OK) return(NOT_OK); -if (err == TRUE) return(NOT_OK); - -if ((rc=sys$qiow(NULL,chan_s,IO$_WRITEVBLK,&iosb,NULL, NULL, - message, strlen(message), NULL, NULL, NULL, NULL)) != 1) - {printf("Error in QIOW: %d\n",rc); return(NOT_OK);} -return(OK); -} - -/* -------------------------------------------------------------------------- */ -/* - Ein-/ Ausschalten von Stoerungsmeldungen vom Selektor an den Host - Diese Funktion ist z.Z. nur vom Selektor-PC aktivierbar -*/ -long select_msg(tim) -long tim; -{ -int sts; -long err; -char cmd[20] = "TIM "; -sprintf(&cmd+4,"%5u\0",tim); -sts = sele_write(cmd); -if (sele_test_echo(&cmd,3)!= OK) lib$stop(-1); -if (select_error_msg(&err) != OK) return(NOT_OK); -if (err == TRUE) return(NOT_OK); -return(OK); -} -/* -------------------------------------------------------------------------- */ -/* Einschaltung der Fremdsteuerung des Selektors - Diese Funktion ist z.Z. nur vom Selektor-PC aktivierbar -*/ -long select_remote() -{ -int sts; -long err; -char cmd[] = "REM"; -sts = sele_write(cmd); -if (sele_test_echo(&cmd,3)!= OK) lib$stop(-1); -if (select_error_msg(&err) != OK) return(NOT_OK); -if (err == TRUE) return(NOT_OK); -} -/* -------------------------------------------------------------------------- */ -/* Ausschaltung der Fremdsteuerung des Selektors - - ein Steuerung kann dann nur noch ueber den PC des Geraetes - erfolgen. - Diese Funktion ist z.Z. nur vom Selektor-PC aktivierbar -*/ -long select_local() -{ -int sts; -long err; -char cmd[] = "TTY"; -sts = sele_write(cmd); -if (sele_test_echo(&cmd,3)!= OK) lib$stop(-1); -if (select_error_msg(&err) != OK) return(NOT_OK); -if (err == TRUE) return(NOT_OK); -} -/* -------------------------------------------------------------------------- */ -/* Starten des Selektors nach Stillstand auf die Minimaldrehzahl -*/ -long select_start() -{ -int sts; -long err; -char cmd[] = "SST"; -sts = sele_write(cmd); -if (sele_test_echo(&cmd,3)!= OK) lib$stop(-1); -if (select_error_msg(&err) != OK) return(NOT_OK); -if (err == TRUE) return(NOT_OK); -} -/* -------------------------------------------------------------------------- */ -/* Bremsen des Selektors bis zum Stillstand; eine - Drehzahlanzeige unterhalb 3000 U/min ist nicht moeglich. -*/ -long select_stop() -{ -int sts; -long err; -char cmd[] = "HAL"; -sts = sele_write(cmd); -if (sele_test_echo(&cmd,3)!= OK) lib$stop(-1); -if (select_error_msg(&err) != OK) return(NOT_OK); -if (err == TRUE) return(NOT_OK); -} -/* -------------------------------------------------------------------------- */ -/* Einschalten des geregelten Betriebes mit dem Setzen eines Sollwertes - der Drehzahl. - Aenderungen werden spontan uebernommen und ausgefuehrt. - Neben dem absoluten Minimum und Maximum existieren verbotene - Drehzahlbereiche, die z.Z. noch nicht exakt bekannt sind. -*/ -long select_set_rpm(rpm) -int rpm; -{ -int sts; -long err; -char cmd[] = "SDR", s_dat[10] = "SDR 00000"; -if ((rpm < LIMIT_U) || (rpm > LIMIT_O)) - { - print_error(fs,"nominal value out of allowed range"); - return; - } -/* Resonanzbereiche sind auch verboten */ -if ( -((rpm >= RESONANZ_1U) && (rpm <= RESONANZ_1O)) || -((rpm >= RESONANZ_2U) && (rpm <= RESONANZ_2O)) || -((rpm >= RESONANZ_3U) && (rpm <= RESONANZ_3O))) - { - print_error(fs,"nominal value within inhibited range"); - return; - } -sprintf(&s_dat+4,"%5u",rpm); -sts = sele_write(s_dat); -if (sele_test_echo(&cmd,3)!= OK) lib$stop(-1); -if (select_error_msg(&err) != OK) return(NOT_OK); -if (err == TRUE) return(NOT_OK); -} -/* -------------------------------------------------------------------------- */ -/* Leerlauf des Selektors einschalten; weder Antrieb noch - Verzoegerung erfolgen - eine anschliessende Abbremsung oder - ein Uebergang zum geregelten Betrieb ist moeglich. -*/ -long select_set_idle() -{ -int sts; -long err; -char cmd[] = "STB"; -sts = sele_write(cmd); -if (sele_test_echo(&cmd,3)!= OK) lib$stop(-1); -if (select_error_msg(&err) != OK) return(NOT_OK); -if (err == TRUE) return(NOT_OK); -} -/* -------------------------------------------------------------------------- */ -/* Starten der Messung der elektrischen Verlustleistung des - Selektors. Anscheinend wird waehrend der Zeit die - Regelung deaktiviert. - Nach Abschluss der Messung erfolgt ein Uebergang in den\ - geregelten Berieb. - Das Messergebnis wird in den Statusinformationsblock eingetragen. -*/ -long select_read_power() -{ -int sts; -long err; -char cmd[] = "BRE"; -sts = sele_write(cmd); -if (sele_test_echo(&cmd,3)!= OK) lib$stop(-1); -if (select_error_msg(&err) != OK) return(NOT_OK); -if (err == TRUE) return(NOT_OK); -} -/* -------------------------------------------------------------------------- */ -/* Lesen der aktuellen Drehzahl des Selektors */ -long select_read_rpm(rpm) -int *rpm; -{ -int sts, tmp; -long err; -char status[80], cmd[] = "FDR"; -sts = sele_write(cmd); -if (sele_test_echo(&cmd,3)!= OK) lib$stop(-1); - -sts = sele_read(&status); -sscanf(&status+4,"%d",&tmp); -*rpm = tmp; -if (select_error_msg(&err) != OK) return(NOT_OK); -if (err == TRUE) return(NOT_OK); -} - -/* -------------------------------------------------------------------------- */ -/* Auslesen des kompletten Statusblockes des Selektors. - Der Informationseintrag 'Verlustleistung' ist anscheinend nur dann - aktuell, wenn zuvor eine Verlustleistungsmessung aktiviert wurde. - Argumente: -rm = Betriebsstatus - [REG == regelnd] - [STB == im Leerlauf] - [BRE == bremsend] -nom_rpm = Soll der Drehzahl (U/min) -cur_rpm = Ist der Drehzahl (U/min) -pwr = Verlustleistung (W) -curr = elektr. Stomstaerke (A) -rot_temp= Temperatur des Rotors (C) -cont_temp= Temperatur des Gehaeuses (C) -inl_temp= Temperatur Kuehlwasser-Einlass -outl_temp= Temperatur Kuehlwasser-Abfluss -cool_wat= Kuehlwasser-Durchfluss (l/min) -vacuum = Betriebsvakuum (mbar) -accel = Rotationsbeschleunigung (g) -komm = Kommunikation zwischen Selektor-PC und Host - 'ENABLED' oder "DISABLED' -dat = Tagesdatum dd.m.yyyy -tim = Tageszeit hh.mm.s - -*/ -long select_read_status(rm,nom_rpm, cur_rpm, pwr, curr, rot_temp, cont_temp, - inl_temp, outl_temp, cool_wat, vacuum, accel, komm, dat, tim) -char *rm[]; -int *nom_rpm, *cur_rpm, *pwr, *rot_temp, *cont_temp, *inl_temp, *outl_temp; -float *cool_wat, *vacuum, *accel, *curr; -char *dat[], *tim[]; -short *komm; -{ -int cnt, key_id, sl, sts; -long err; -char ena_str[] = "ENABLED"; -char dis_str[] = "DISABLED"; -char keys[15][9] = - { - "Status:\0 ", - "S_DREH:\0 ", - "I_DREH:\0 ", - "P_VERL:\0 ", - "STROM:\0 ", - "T_ROT:\0 ", - "T_GEH:\0 ", - "T_VOR:\0 ", - "T_RUECK:\0", - "DURCHFL:\0", - "VAKUUM:\0 ", - "BESCHL:\0 ", - "KOM: \0 ", - "DATE: \0 ", - "TIME: \0 "}; - -char tok_buf[TOK_BUF_L], *ptr_token, *ptr_src, *ptr, tok_c[] = "/\0"; - -char status[255], cmd[] = "???"; - -if (sele_write(cmd) != OK) return(NOT_OK); - -if (sele_test_echo(&cmd, 3) == NOT_OK) lib$stop(-1); - -if (sele_read(&status) != OK) return(NOT_OK); /* Und nun der Status */ -ptr_src = &status; -for (;;) - { - /* Lies Zeichenfolge bis zum naechsten Trennzeichen '/' */ - ptr_token = strtok(ptr_src, &tok_c); - ptr_src = NULL; /* fuer die weitere Suche notwendig */ - if (ptr_token == NULL) break; - strcpy(&tok_buf,ptr_token); - - for (key_id = 0; key_id<=14; key_id++) - { - /* Ist das Schluesselwort enthalten ? */ - sl = strlen(keys[key_id]); - if (strncmp(&keys[key_id][0], &tok_buf, sl) == NULL) - { - /* Schiebe das Schluesselwort raus */ - for (cnt=0;cnt+sl < TOK_BUF_L; cnt++) - tok_buf[cnt] = tok_buf[cnt+sl]; - switch (key_id) - { - case 0: - { - ptr = rm; - strcpy(ptr, &tok_buf); - break; - } - case 1: {sscanf(&tok_buf,"%d",nom_rpm); break;} - case 2: {sscanf(&tok_buf,"%d",cur_rpm); break;} - case 3: {sscanf(&tok_buf,"%d",pwr); break;} - case 4: {sscanf(&tok_buf,"%f",curr); break;} - case 5: {sscanf(&tok_buf,"%d",rot_temp); break;} - case 6: {sscanf(&tok_buf,"%d",cont_temp); break;} - case 7: {sscanf(&tok_buf,"%d",inl_temp); break;} - case 8: {sscanf(&tok_buf,"%d",outl_temp); break;} - case 9: {sscanf(&tok_buf,"%f",cool_wat); break;} - case 10: {sscanf(&tok_buf,"%f",vacuum); break;} - case 11: {sscanf(&tok_buf,"%f",accel); break;} - case 12: - { - if (strcmp(&tok_buf, &ena_str) == NULL) - {*komm = TRUE; break;} - if (strcmp(&tok_buf, &dis_str) == NULL) - {*komm = FALSE;break;} - printf("Invalid Communication value"); - break; - } - case 13: - { - ptr = dat; - strcpy(ptr, &tok_buf); - break; - } - case 14: - { - ptr = tim; - strcpy(ptr, &tok_buf); - break; - } - } - } - } - } -if (select_error_msg(&err) != OK) return(NOT_OK); -if (err == TRUE) return(NOT_OK); -return(OK); -} diff --git a/selector.c b/selector.c index ac817eda..76f887df 100644 --- a/selector.c +++ b/selector.c @@ -62,324 +62,307 @@ #define LATD 9 #define RIGHTS 10 /*------------------------------------------------------------------------*/ - typedef struct __SicsSelector { - ObjectDescriptor *pDes; - ObPar *pParams; - char *name; - pMotor pTheta; - pMotor pTwoTheta; - pMotor pBend1; - pMotor pBend2; - char *pType; - } SicsSelector; +typedef struct __SicsSelector { + ObjectDescriptor *pDes; + ObPar *pParams; + char *name; + pMotor pTheta; + pMotor pTwoTheta; + pMotor pBend1; + pMotor pBend2; + char *pType; +} SicsSelector; /*-------------------------------------------------------------------------*/ - char *MonoGetType(pSicsSelector self) - { - assert(self); - return self->pType; - } -/*---------------------------------------------------------------------------*/ - pSicsSelector CreateSelector(char *name, pMotor pTheta, pMotor pTwoTheta, - pMotor pBend1, pMotor pBend2) - { - pSicsSelector pRes = NULL; - int iRet; - float fVal; +char *MonoGetType(pSicsSelector self) +{ + assert(self); + return self->pType; +} - assert(pTheta); - assert(pTwoTheta); - - /* allocate memory */ - pRes = (pSicsSelector)malloc(sizeof(SicsSelector)); - if(!pRes) - { - return NULL; - } - - /* create ObjectDescriptor */ - pRes->pDes = CreateDescriptor("CrystalSelector"); - if(!pRes->pDes) - { - free(pRes); - return NULL; - } - - /* create Parameter Array */ - pRes->pParams = ObParCreate(11); - if(!pRes->pParams) - { - free(pRes->pDes); - free(pRes); - return NULL; - } - - /* create all the parameters */ - ObParInit(pRes->pParams,SS, "ss",1.,usUser); - ObParInit(pRes->pParams,B1C1, "vk1",1.,usInternal); - ObParInit(pRes->pParams,B1C2, "vk2",1.,usInternal); - ObParInit(pRes->pParams,B2C1, "hk1",1.,usInternal); - ObParInit(pRes->pParams,B2C2, "hk2",1.,usInternal); - ObParInit(pRes->pParams,LATD, "dd",2.087,usMugger); - ObParInit(pRes->pParams,RIGHTS, "access",usUser,usMugger); - - /* assign motors */ - pRes->pTheta = pTheta; - pRes->pTwoTheta = pTwoTheta; - - /* provide default values for Bender Parameters in order to make - things look nice - */ - fVal = 0.; - ObParInit(pRes->pParams,B1MIN, "vmin",fVal,usInternal); - ObParInit(pRes->pParams,B1MAX, "vmax",fVal,usInternal); - ObParInit(pRes->pParams,B2MIN, "hmin",fVal,usInternal); - ObParInit(pRes->pParams,B2MAX, "hmax",fVal,usInternal); - - - /* handle benders, if present */ - pRes->pBend1 = pBend1; - if(pBend1) - { - iRet = MotorGetPar(pBend1,"hardlowerlim",&fVal); - assert(iRet); - ObParInit(pRes->pParams,B1MIN, "vmin",fVal,usInternal); - iRet = MotorGetPar(pBend1,"hardupperlim",&fVal); - assert(iRet); - ObParInit(pRes->pParams,B1MAX, "vmax",fVal,usInternal); - } - pRes->pBend2 = pBend2; - if(pBend2) - { - iRet = MotorGetPar(pBend2,"hardlowerlim",&fVal); - assert(iRet); - ObParInit(pRes->pParams,B2MIN, "hmin",fVal,usInternal); - iRet = MotorGetPar(pBend2,"hardupperlim",&fVal); - assert(iRet); - ObParInit(pRes->pParams,B2MAX, "hmax",fVal,usInternal); - } - pRes->name = strdup(name); - pRes->pType = strdup("Unknown"); - return pRes; - } /*---------------------------------------------------------------------------*/ - void DeleteSelector(void *self) - { - pSicsSelector pSelf; - - assert(self); - - pSelf = (pSicsSelector)self; - - if(pSelf->pDes) - { - DeleteDescriptor(pSelf->pDes); - } - if(pSelf->pParams) - { - ObParDelete(pSelf->pParams); - } - if(pSelf->name) - { - free(pSelf->name); - } - if(pSelf->pType) - { - free(pSelf->pType); - } - free(pSelf); +pSicsSelector CreateSelector(char *name, pMotor pTheta, pMotor pTwoTheta, + pMotor pBend1, pMotor pBend2) +{ + pSicsSelector pRes = NULL; + int iRet; + float fVal; + + assert(pTheta); + assert(pTwoTheta); + + /* allocate memory */ + pRes = (pSicsSelector) malloc(sizeof(SicsSelector)); + if (!pRes) { + return NULL; } + + /* create ObjectDescriptor */ + pRes->pDes = CreateDescriptor("CrystalSelector"); + if (!pRes->pDes) { + free(pRes); + return NULL; + } + + /* create Parameter Array */ + pRes->pParams = ObParCreate(11); + if (!pRes->pParams) { + free(pRes->pDes); + free(pRes); + return NULL; + } + + /* create all the parameters */ + ObParInit(pRes->pParams, SS, "ss", 1., usUser); + ObParInit(pRes->pParams, B1C1, "vk1", 1., usInternal); + ObParInit(pRes->pParams, B1C2, "vk2", 1., usInternal); + ObParInit(pRes->pParams, B2C1, "hk1", 1., usInternal); + ObParInit(pRes->pParams, B2C2, "hk2", 1., usInternal); + ObParInit(pRes->pParams, LATD, "dd", 2.087, usMugger); + ObParInit(pRes->pParams, RIGHTS, "access", usUser, usMugger); + + /* assign motors */ + pRes->pTheta = pTheta; + pRes->pTwoTheta = pTwoTheta; + + /* provide default values for Bender Parameters in order to make + things look nice + */ + fVal = 0.; + ObParInit(pRes->pParams, B1MIN, "vmin", fVal, usInternal); + ObParInit(pRes->pParams, B1MAX, "vmax", fVal, usInternal); + ObParInit(pRes->pParams, B2MIN, "hmin", fVal, usInternal); + ObParInit(pRes->pParams, B2MAX, "hmax", fVal, usInternal); + + + /* handle benders, if present */ + pRes->pBend1 = pBend1; + if (pBend1) { + iRet = MotorGetPar(pBend1, "hardlowerlim", &fVal); + assert(iRet); + ObParInit(pRes->pParams, B1MIN, "vmin", fVal, usInternal); + iRet = MotorGetPar(pBend1, "hardupperlim", &fVal); + assert(iRet); + ObParInit(pRes->pParams, B1MAX, "vmax", fVal, usInternal); + } + pRes->pBend2 = pBend2; + if (pBend2) { + iRet = MotorGetPar(pBend2, "hardlowerlim", &fVal); + assert(iRet); + ObParInit(pRes->pParams, B2MIN, "hmin", fVal, usInternal); + iRet = MotorGetPar(pBend2, "hardupperlim", &fVal); + assert(iRet); + ObParInit(pRes->pParams, B2MAX, "hmax", fVal, usInternal); + } + pRes->name = strdup(name); + pRes->pType = strdup("Unknown"); + return pRes; +} + +/*---------------------------------------------------------------------------*/ +void DeleteSelector(void *self) +{ + pSicsSelector pSelf; + + assert(self); + + pSelf = (pSicsSelector) self; + + if (pSelf->pDes) { + DeleteDescriptor(pSelf->pDes); + } + if (pSelf->pParams) { + ObParDelete(pSelf->pParams); + } + if (pSelf->name) { + free(pSelf->name); + } + if (pSelf->pType) { + free(pSelf->pType); + } + free(pSelf); +} + /*-------------------------------------------------------------------------- Syntax: MonoInit name Type ThetaMotor TwoThetaMotor Bend1Motor Bend2Motor with Bend1Motor, Bend2Motor beeing optional. -*/ +*/ - int MonoInit(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - pSicsSelector pRes = NULL; - pMotor pTheta = NULL; - pMotor pTwoTheta = NULL; - pMotor pBend1 = NULL; - pMotor pBend2 = NULL; - TokenList *pList = NULL; - int iRet = 0; - TokenList *pCurrent; - char pBueffel[132]; - char pName[132]; - char *pType = NULL; +int MonoInit(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pSicsSelector pRes = NULL; + pMotor pTheta = NULL; + pMotor pTwoTheta = NULL; + pMotor pBend1 = NULL; + pMotor pBend2 = NULL; + TokenList *pList = NULL; + int iRet = 0; + TokenList *pCurrent; + char pBueffel[132]; + char pName[132]; + char *pType = NULL; - assert(pCon); - assert(pSics); - - /* split arguments */ - argtolower(argc,argv); - pList = SplitArguments(argc,argv); - if(!pList) - { - sprintf(pBueffel,"ERROR: parsing arguments in %s",argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* advance and search name */ - pCurrent = pList->pNext; - if(!pCurrent) - { - sprintf(pBueffel,"ERRROR: Insufficient number of arguments to %s", - argv[0]); - SCWrite(pCon,pBueffel,eError); - goto end; - } - strcpy(pName,pCurrent->text); - - /* advance and find Type string */ - pCurrent = pCurrent->pNext; - if(!pCurrent) - { - sprintf(pBueffel,"ERRROR: Insufficient number of arguments to %s", - argv[0]); - SCWrite(pCon,pBueffel,eError); - goto end; - } - pType = pCurrent->text; - - /* advance and find Theta motor */ - pCurrent = pCurrent->pNext; - if(!pCurrent) - { - sprintf(pBueffel,"ERRROR: Insufficient number of arguments to %s", - argv[0]); - SCWrite(pCon,pBueffel,eError); - goto end; - } - pTheta = FindMotor(pSics,pCurrent->text); - if(!pTheta) - { - sprintf(pBueffel,"ERROR: Cannot find motor %s for driving Theta", - pCurrent->text); - SCWrite(pCon,pBueffel,eError); - goto end; - } + assert(pCon); + assert(pSics); - /* advance and find Two Theta motor */ - pCurrent = pCurrent->pNext; - if(!pCurrent) - { - sprintf(pBueffel,"ERRROR: Insufficient number of arguments to %s", - argv[0]); - SCWrite(pCon,pBueffel,eError); - goto end; - } - pTwoTheta = FindMotor(pSics,pCurrent->text); - if(!pTwoTheta) - { - sprintf(pBueffel,"ERROR: Cannot find motor %s for driving Two Theta", - pCurrent->text); - SCWrite(pCon,pBueffel,eError); - goto end; - } - iRet = 1; /* we are now able to install a monochromator */ - - /* try find first bending motor */ - pCurrent = pCurrent->pNext; - if(pCurrent) - { - pBend1 = FindMotor(pSics,pCurrent->text); - if(!pBend1) - { - sprintf(pBueffel,"ERROR: Cannot find motor %s for driving vertical bender", - pCurrent->text); - SCWrite(pCon,pBueffel,eError); - goto end; - } - } - else - { - goto end; - } - - /* find second bender */ - pCurrent = pCurrent->pNext; - if(pCurrent) - { - pBend2 = FindMotor(pSics,pCurrent->text); - if(!pBend2) - { - sprintf(pBueffel,"ERROR: Cannot find motor %s for driving horizontal bender", - pCurrent->text); - SCWrite(pCon,pBueffel,eError); - goto end; - } - } + /* split arguments */ + argtolower(argc, argv); + pList = SplitArguments(argc, argv); + if (!pList) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: parsing arguments in %s", argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* advance and search name */ + pCurrent = pList->pNext; + if (!pCurrent) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERRROR: Insufficient number of arguments to %s", + argv[0]); + SCWrite(pCon, pBueffel, eError); + goto end; + } + strcpy(pName, pCurrent->text); + + /* advance and find Type string */ + pCurrent = pCurrent->pNext; + if (!pCurrent) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERRROR: Insufficient number of arguments to %s", + argv[0]); + SCWrite(pCon, pBueffel, eError); + goto end; + } + pType = pCurrent->text; + + /* advance and find Theta motor */ + pCurrent = pCurrent->pNext; + if (!pCurrent) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERRROR: Insufficient number of arguments to %s", + argv[0]); + SCWrite(pCon, pBueffel, eError); + goto end; + } + pTheta = FindMotor(pSics, pCurrent->text); + if (!pTheta) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Cannot find motor %s for driving Theta", + pCurrent->text); + SCWrite(pCon, pBueffel, eError); + goto end; + } + + /* advance and find Two Theta motor */ + pCurrent = pCurrent->pNext; + if (!pCurrent) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERRROR: Insufficient number of arguments to %s", + argv[0]); + SCWrite(pCon, pBueffel, eError); + goto end; + } + pTwoTheta = FindMotor(pSics, pCurrent->text); + if (!pTwoTheta) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Cannot find motor %s for driving Two Theta", + pCurrent->text); + SCWrite(pCon, pBueffel, eError); + goto end; + } + iRet = 1; /* we are now able to install a monochromator */ + + /* try find first bending motor */ + pCurrent = pCurrent->pNext; + if (pCurrent) { + pBend1 = FindMotor(pSics, pCurrent->text); + if (!pBend1) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: Cannot find motor %s for driving vertical bender", + pCurrent->text); + SCWrite(pCon, pBueffel, eError); + goto end; + } + } else { + goto end; + } + + /* find second bender */ + pCurrent = pCurrent->pNext; + if (pCurrent) { + pBend2 = FindMotor(pSics, pCurrent->text); + if (!pBend2) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: Cannot find motor %s for driving horizontal bender", + pCurrent->text); + SCWrite(pCon, pBueffel, eError); + goto end; + } + } end: - if(iRet) - { - pRes = CreateSelector(pName, pTheta, pTwoTheta,pBend1,pBend2); - if(!pRes) - { - iRet = 0; - } - else - { - if(pRes->pType) - { - free(pRes->pType); - } - pRes->pType = strdup(pType); - iRet = AddCommand(pSics, pName,MonoAction,DeleteSelector,(void *)pRes); - if(!iRet) - { - sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[2]); - SCWrite(pCon,pBueffel,eError); - DeleteTokenList(pList); - DeleteSelector((void *)pRes); - return 0; - } - } + if (iRet) { + pRes = CreateSelector(pName, pTheta, pTwoTheta, pBend1, pBend2); + if (!pRes) { + iRet = 0; + } else { + if (pRes->pType) { + free(pRes->pType); + } + pRes->pType = strdup(pType); + iRet = + AddCommand(pSics, pName, MonoAction, DeleteSelector, + (void *) pRes); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: duplicate command %s not created", + argv[2]); + SCWrite(pCon, pBueffel, eError); + DeleteTokenList(pList); + DeleteSelector((void *) pRes); + return 0; + } } - - DeleteTokenList(pList); - return iRet; - } + + DeleteTokenList(pList); + return iRet; + +} + /*--------------------------------------------------------------------------- a private function used in MonoAction to print all relevant features of the monochromator */ - static void MonoList(pSicsSelector self, SConnection *pCon) - { - char pBueffel[512]; - int i, iLen; - - /* print known parameters */ - iLen = ObParLength(self->pParams); - sprintf(pBueffel,"Parameter Listing for %s\n",self->name); - SCWrite(pCon,pBueffel,eStatus); - for(i = 0; i < iLen; i++) - { - sprintf(pBueffel,"%s.%s = %f\n",self->name, - self->pParams[i].name,self->pParams[i].fVal); - SCWrite(pCon,pBueffel,eStatus); - } - - /* print motornames as well */ - sprintf(pBueffel,"%s.ThetaMotor = %s\n",self->name,self->pTheta->name); - SCWrite(pCon,pBueffel,eStatus); - sprintf(pBueffel,"%s.TwoThetaMotor = %s\n",self->name,self->pTwoTheta->name); - SCWrite(pCon,pBueffel,eStatus); - if(self->pBend1) - { - sprintf(pBueffel,"%s.VerticalBenderMotor = %s\n",self->name,self->pBend1->name); - SCWrite(pCon,pBueffel,eStatus); - } - if(self->pBend2) - { - sprintf(pBueffel,"%s.HorizontalBenderMotor = %s\n",self->name,self->pBend2->name); - SCWrite(pCon,pBueffel,eStatus); - } +static void MonoList(pSicsSelector self, SConnection * pCon) +{ + char pBueffel[512]; + int i, iLen; + + /* print known parameters */ + iLen = ObParLength(self->pParams); + snprintf(pBueffel,sizeof(pBueffel)-1, "Parameter Listing for %s\n", self->name); + SCWrite(pCon, pBueffel, eValue); + for (i = 0; i < iLen; i++) { + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.%s = %f\n", self->name, + self->pParams[i].name, self->pParams[i].fVal); + SCWrite(pCon, pBueffel, eValue); } + + /* print motornames as well */ + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.ThetaMotor = %s\n", self->name, + self->pTheta->name); + SCWrite(pCon, pBueffel, eValue); + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.TwoThetaMotor = %s\n", self->name, + self->pTwoTheta->name); + SCWrite(pCon, pBueffel, eValue); + if (self->pBend1) { + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.VerticalBenderMotor = %s\n", self->name, + self->pBend1->name); + SCWrite(pCon, pBueffel, eValue); + } + if (self->pBend2) { + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.HorizontalBenderMotor = %s\n", self->name, + self->pBend2->name); + SCWrite(pCon, pBueffel, eValue); + } +} + /*----------------------------------------------------------------------------- The Action function. Syntax: mononame list -- list all pars @@ -387,468 +370,423 @@ end: mononame parname value -- tries changing the parameter */ - int MonoAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - pSicsSelector pSelf = NULL; - TokenList *pList = NULL; - TokenList *pCurrent; - int iRet; - char pBueffel[132]; - char pName[132]; - float fVal; - ObPar *pPar = NULL; - - assert(pCon); - assert(pSics); - assert(pData); - - pSelf = (pSicsSelector)pData; - - /* split arguments */ - argtolower(argc,argv); - pList = SplitArguments(argc,argv); - if(!pList) - { - sprintf(pBueffel,"ERROR: parsing arguments in %s",argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } +int MonoAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pSicsSelector pSelf = NULL; + TokenList *pList = NULL; + TokenList *pCurrent; + int iRet; + char pBueffel[132]; + char pName[132]; + float fVal; + ObPar *pPar = NULL; - pCurrent = pList->pNext; - /* now we can have "list" or a parametername */ - /* check for list first */ - if(!pCurrent) - { - sprintf(pBueffel,"ERROR: Insufficient number of arguments to %s", - argv[0]); - SCWrite(pCon,pBueffel,eError); - goto end; - } - if(strcmp(pCurrent->text,"list") == 0) - { - MonoList(pSelf,pCon); - iRet = 1; - goto end; - } - - /* must be parametername now */ - strcpy(pName,pCurrent->text); - - /* find out if it is a set or a get. On set there is another paremeter, - else none - */ - pCurrent = pCurrent->pNext; - if(pCurrent) /* set */ - { - /* check if input is proper */ - if(pCurrent->Type == eFloat) - { - fVal = pCurrent->fVal; - } - else if(pCurrent->Type == eInt) - { - fVal = (float)pCurrent->iVal; - } - else - { - sprintf(pBueffel,"ERROR: Illegal parameter %s given to %s", - pCurrent->text, argv[0]); - SCWrite(pCon,pBueffel,eError); - goto end; - } - iRet = ObParSet(pSelf->pParams,argv[0],pName,fVal,pCon); - goto end; - } - else /* get */ - { - pPar = ObParFind(pSelf->pParams,pName); - if(!pPar) - { - sprintf(pBueffel,"ERROR: Parameter %s not found in %s",pName, argv[0]); - SCWrite(pCon,pBueffel,eError); - goto end; - } - else - { - sprintf(pBueffel,"%s.%s = %f",argv[0],pName,pPar->fVal); - SCWrite(pCon,pBueffel,eValue); - iRet = 1; - DeleteTokenList(pList); - return 1; - } - } + assert(pCon); + assert(pSics); + assert(pData); + + pSelf = (pSicsSelector) pData; + + /* split arguments */ + argtolower(argc, argv); + pList = SplitArguments(argc, argv); + if (!pList) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: parsing arguments in %s", argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + pCurrent = pList->pNext; + /* now we can have "list" or a parametername */ + /* check for list first */ + if (!pCurrent) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Insufficient number of arguments to %s", + argv[0]); + SCWrite(pCon, pBueffel, eError); + goto end; + } + if (strcmp(pCurrent->text, "list") == 0) { + MonoList(pSelf, pCon); + iRet = 1; + goto end; + } + + /* must be parametername now */ + strcpy(pName, pCurrent->text); + + /* find out if it is a set or a get. On set there is another paremeter, + else none + */ + pCurrent = pCurrent->pNext; + if (pCurrent) { /* set */ + /* check if input is proper */ + if (pCurrent->Type == eFloat) { + fVal = pCurrent->fVal; + } else if (pCurrent->Type == eInt) { + fVal = (float) pCurrent->iVal; + } else { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Illegal parameter %s given to %s", + pCurrent->text, argv[0]); + SCWrite(pCon, pBueffel, eError); + goto end; + } + iRet = ObParSet(pSelf->pParams, argv[0], pName, fVal, pCon); + goto end; + } else { /* get */ + + pPar = ObParFind(pSelf->pParams, pName); + if (!pPar) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Parameter %s not found in %s", pName, + argv[0]); + SCWrite(pCon, pBueffel, eError); + goto end; + } else { + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.%s = %f", argv[0], pName, pPar->fVal); + SCWrite(pCon, pBueffel, eValue); + iRet = 1; + DeleteTokenList(pList); + return 1; + } + } end: - DeleteTokenList(pList); - if(iRet) - SCSendOK(pCon); - return iRet; - } + DeleteTokenList(pList); + if (iRet) + SCSendOK(pCon); + return iRet; +} + /*--------------------------------------------------------------------------*/ - struct SelPos { - float fTheta, fTwoTheta, fVert, fHor; - }; +struct SelPos { + float fTheta, fTwoTheta, fVert, fHor; +}; #define PI 3.14159265358979323846264338327950 #define RD 57.29577951308232087679815481410517 /* ------------------- C has no proper abs -------------------------------*/ - static double absd(double f) - { - if(f < .0) - { - f = -f; - } - return f; +static double absd(double f) +{ + if (f < .0) { + f = -f; } -/*-------------------------------------------------------------------------*/ - static struct SelPos CalculatePosition(pSicsSelector self, float fWaveLength) - { - struct SelPos pRes; - double fD; - - /* Theta, TwoTheta first */ - fD = fWaveLength/(2.0* ObVal(self->pParams,LATD)); - if(fD > 1.0) - { - pRes.fTheta = 1000.; /* error indication: energy to big */ - return pRes; - } - fD = asin(fD); - pRes.fTheta = fD*ObVal(self->pParams,SS)*RD; - pRes.fTwoTheta = 2 * pRes.fTheta; - - /* now first bender */ - if(self->pBend1) - { - pRes.fVert = ObVal(self->pParams,B1C1)+(ObVal(self->pParams,B1C2)/ - sin(fD)); - } + return f; +} +/*-------------------------------------------------------------------------*/ +static struct SelPos CalculatePosition(pSicsSelector self, + float fWaveLength) +{ + struct SelPos pRes; + double fD; - /* now second bender */ - if(self->pBend2) - { - pRes.fHor = ObVal(self->pParams,B2C1)+ (ObVal(self->pParams,B2C2)/ - sin(fD)); - } + /* Theta, TwoTheta first */ + fD = fWaveLength / (2.0 * ObVal(self->pParams, LATD)); + if (fD > 1.0) { + pRes.fTheta = 1000.; /* error indication: energy to big */ return pRes; - } -/*--------------------------------------------------------------------------*/ - int MonoLimits(pSicsSelector self, float fWaveLength, - char *error, int iErrLen) - { - struct SelPos sNeu; - char pBueffel[132]; - pIDrivable pDrivInt = NULL; - - /* get Position */ - sNeu = CalculatePosition(self,fWaveLength); - if(sNeu.fTheta > 900.) /* invalid wavelength or energy */ - { - sprintf(pBueffel,"ERROR: Invalid wavelength or energy to high: %f", - fWaveLength); - strncpy(error,pBueffel,iErrLen-1); - return 0; - } - - /* check each motor in turn */ - pDrivInt = self->pTheta->pDescriptor->GetInterface(self->pTheta,DRIVEID); - if(!pDrivInt->CheckLimits(self->pTheta,sNeu.fTheta,error,iErrLen)) - { - return 0; - } - pDrivInt = self->pTwoTheta->pDescriptor->GetInterface(self->pTwoTheta, - DRIVEID); - if(!pDrivInt->CheckLimits(self->pTwoTheta,sNeu.fTwoTheta, - error,iErrLen)) - { - return 0; - } - - if(self->pBend1) - { - pDrivInt = self->pBend1->pDescriptor->GetInterface(self->pBend1,DRIVEID); - if(!pDrivInt->CheckLimits(self->pBend1,sNeu.fVert, - error,iErrLen)) - { - return 0; - } - } - if(self->pBend2) - { - pDrivInt = self->pBend2->pDescriptor->GetInterface(self->pBend2,DRIVEID); - if(!pDrivInt->CheckLimits(self->pBend2,sNeu.fHor, - error,iErrLen)) - { - return 0; - } - } - return 1; - } -/*--------------------------------------------------------------------------*/ - int MonoHalt(pSicsSelector self) - { - pIDrivable pDrivInt = NULL; - - /* halt each motor in turn */ - pDrivInt = self->pTheta->pDescriptor->GetInterface(self->pTheta,DRIVEID); - if(pDrivInt) - { - pDrivInt->Halt(self->pTheta); - } - - pDrivInt = self->pTwoTheta->pDescriptor->GetInterface(self->pTwoTheta, - DRIVEID); - if(pDrivInt) - { - pDrivInt->Halt(self->pTwoTheta); - } - - if(self->pBend1) - { - pDrivInt = self->pBend1->pDescriptor->GetInterface(self->pBend1, - DRIVEID); - if(pDrivInt) - { - pDrivInt->Halt(self->pBend1); - } - } - if(self->pBend2) - { - pDrivInt = self->pBend2->pDescriptor->GetInterface(self->pBend2, - DRIVEID); - if(pDrivInt) - { - pDrivInt->Halt(self->pBend2); - } - } - - - return 1; - } -/*-------------------------------------------------------------------------*/ - int MonoRun(pSicsSelector self, SConnection *pCon, float fWaveLength) - { - struct SelPos sNeu; - char pBueffel[132]; - int iRet; - - /* Check authorisation */ - if(!SCMatchRights(pCon,(int)ObVal(self->pParams,RIGHTS))) - { - sprintf(pBueffel, - "ERROR: You are not authorised to move the monochromator %s",self->name); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* get Position */ - sNeu = CalculatePosition(self,fWaveLength); - if(sNeu.fTheta > 900.) /* invalid wavelength or energy */ - { - sprintf(pBueffel,"ERROR: Invalid wavelength or energy to high: %f", - fWaveLength); - return 0; - } - - /* start each motor in turn */ - iRet = StartDevice(GetExecutor(),self->pTheta->name, - self->pTheta->pDescriptor, - self->pTheta, - pCon,sNeu.fTheta); - if(!iRet) - { - return 0; - } - iRet = StartDevice(GetExecutor(),self->pTwoTheta->name, - self->pTwoTheta->pDescriptor, - self->pTwoTheta, - pCon,sNeu.fTwoTheta); - if(!iRet) - { - return 0; - } - - - /* bending motors */ - if(self->pBend1) - { - iRet = StartDevice(GetExecutor(),self->pBend1->name, - self->pBend1->pDescriptor, - self->pBend1, - pCon,sNeu.fVert); - if(!iRet) - { - return 0; - } - - } - if(self->pBend2) - { - iRet = StartDevice(GetExecutor(),self->pBend2->name, - self->pBend2->pDescriptor, - self->pBend2, - pCon,sNeu.fHor); - if(!iRet) - { - return 0; - } - } - return OKOK; } -/*--------------------------------------------------------------------------*/ - int MonoCheck(pSicsSelector self, SConnection *pCon) - { - int iRet; - pIDrivable pDrivInt = NULL; + fD = asin(fD); + pRes.fTheta = fD * ObVal(self->pParams, SS) * RD; + pRes.fTwoTheta = 2 * pRes.fTheta; - /* cheack each motor in turn */ - pDrivInt = self->pTheta->pDescriptor->GetInterface(self->pTheta,DRIVEID); - if(pDrivInt) - { - iRet = pDrivInt->CheckStatus(self->pTheta,pCon); - if( (iRet != OKOK) && (iRet != HWIdle)) - { - return iRet; - } - } - - pDrivInt = self->pTwoTheta->pDescriptor->GetInterface(self->pTwoTheta, - DRIVEID); - if(pDrivInt) - { - iRet = pDrivInt->CheckStatus(self->pTwoTheta,pCon); - if( (iRet != OKOK) && (iRet != HWIdle)) - { - return iRet; - } - } - - if(self->pBend1) - { - pDrivInt = self->pBend1->pDescriptor->GetInterface(self->pBend1, - DRIVEID); - if(pDrivInt) - { - iRet = pDrivInt->CheckStatus(self->pBend1,pCon); - if( (iRet != OKOK) && (iRet != HWIdle)) - { - return iRet; - } - } - } - - if(self->pBend2) - { - pDrivInt = self->pBend2->pDescriptor->GetInterface(self->pBend2, - DRIVEID); - if(pDrivInt) - { - iRet = pDrivInt->CheckStatus(self->pBend2,pCon); - if( (iRet != OKOK) && (iRet != HWIdle)) - { - return iRet; - } - } - } - - - return HWIdle; + /* now first bender */ + if (self->pBend1) { + pRes.fVert = ObVal(self->pParams, B1C1) + (ObVal(self->pParams, B1C2) / + sin(fD)); } + + + /* now second bender */ + if (self->pBend2) { + pRes.fHor = ObVal(self->pParams, B2C1) + (ObVal(self->pParams, B2C2) / + sin(fD)); + } + return pRes; +} + +/*--------------------------------------------------------------------------*/ +int MonoLimits(pSicsSelector self, float fWaveLength, + char *error, int iErrLen) +{ + struct SelPos sNeu; + char pBueffel[132]; + pIDrivable pDrivInt = NULL; + + /* get Position */ + sNeu = CalculatePosition(self, fWaveLength); + if (sNeu.fTheta > 900.) { /* invalid wavelength or energy */ + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Invalid wavelength or energy to high: %f", + fWaveLength); + strlcpy(error, pBueffel, iErrLen - 1); + return 0; + } + + /* check each motor in turn */ + pDrivInt = + self->pTheta->pDescriptor->GetInterface(self->pTheta, DRIVEID); + if (!pDrivInt->CheckLimits(self->pTheta, sNeu.fTheta, error, iErrLen)) { + return 0; + } + pDrivInt = self->pTwoTheta->pDescriptor->GetInterface(self->pTwoTheta, + DRIVEID); + if (!pDrivInt->CheckLimits(self->pTwoTheta, sNeu.fTwoTheta, + error, iErrLen)) { + return 0; + } + + if (self->pBend1) { + pDrivInt = + self->pBend1->pDescriptor->GetInterface(self->pBend1, DRIVEID); + if (!pDrivInt->CheckLimits(self->pBend1, sNeu.fVert, error, iErrLen)) { + return 0; + } + } + if (self->pBend2) { + pDrivInt = + self->pBend2->pDescriptor->GetInterface(self->pBend2, DRIVEID); + if (!pDrivInt->CheckLimits(self->pBend2, sNeu.fHor, error, iErrLen)) { + return 0; + } + } + return 1; +} + +/*--------------------------------------------------------------------------*/ +int MonoHalt(pSicsSelector self) +{ + pIDrivable pDrivInt = NULL; + + /* halt each motor in turn */ + pDrivInt = + self->pTheta->pDescriptor->GetInterface(self->pTheta, DRIVEID); + if (pDrivInt) { + pDrivInt->Halt(self->pTheta); + } + + pDrivInt = self->pTwoTheta->pDescriptor->GetInterface(self->pTwoTheta, + DRIVEID); + if (pDrivInt) { + pDrivInt->Halt(self->pTwoTheta); + } + + if (self->pBend1) { + pDrivInt = self->pBend1->pDescriptor->GetInterface(self->pBend1, + DRIVEID); + if (pDrivInt) { + pDrivInt->Halt(self->pBend1); + } + } + if (self->pBend2) { + pDrivInt = self->pBend2->pDescriptor->GetInterface(self->pBend2, + DRIVEID); + if (pDrivInt) { + pDrivInt->Halt(self->pBend2); + } + } + + + return 1; +} + +/*-------------------------------------------------------------------------*/ +int MonoRun(pSicsSelector self, SConnection * pCon, float fWaveLength) +{ + struct SelPos sNeu; + char pBueffel[132]; + int iRet; + + /* Check authorisation */ + if (!SCMatchRights(pCon, (int) ObVal(self->pParams, RIGHTS))) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: You are not authorised to move the monochromator %s", + self->name); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* get Position */ + sNeu = CalculatePosition(self, fWaveLength); + if (sNeu.fTheta > 900.) { /* invalid wavelength or energy */ + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Invalid wavelength or energy to high: %f", + fWaveLength); + return 0; + } + + /* start each motor in turn */ + iRet = StartDevice(GetExecutor(), self->pTheta->name, + self->pTheta->pDescriptor, + self->pTheta, pCon, pCon->runLevel, sNeu.fTheta); + if (!iRet) { + return 0; + } + iRet = StartDevice(GetExecutor(), self->pTwoTheta->name, + self->pTwoTheta->pDescriptor, + self->pTwoTheta, pCon, pCon->runLevel, sNeu.fTwoTheta); + if (!iRet) { + return 0; + } + + + /* bending motors */ + if (self->pBend1) { + iRet = StartDevice(GetExecutor(), self->pBend1->name, + self->pBend1->pDescriptor, + self->pBend1, pCon, pCon->runLevel, sNeu.fVert); + if (!iRet) { + return 0; + } + + } + if (self->pBend2) { + iRet = StartDevice(GetExecutor(), self->pBend2->name, + self->pBend2->pDescriptor, + self->pBend2, pCon, pCon->runLevel, sNeu.fHor); + if (!iRet) { + return 0; + } + } + return OKOK; +} + +/*--------------------------------------------------------------------------*/ +int MonoCheck(pSicsSelector self, SConnection * pCon) +{ + int iRet; + pIDrivable pDrivInt = NULL; + + /* cheack each motor in turn */ + pDrivInt = + self->pTheta->pDescriptor->GetInterface(self->pTheta, DRIVEID); + if (pDrivInt) { + iRet = pDrivInt->CheckStatus(self->pTheta, pCon); + if ((iRet != OKOK) && (iRet != HWIdle)) { + return iRet; + } + } + + pDrivInt = self->pTwoTheta->pDescriptor->GetInterface(self->pTwoTheta, + DRIVEID); + if (pDrivInt) { + iRet = pDrivInt->CheckStatus(self->pTwoTheta, pCon); + if ((iRet != OKOK) && (iRet != HWIdle)) { + return iRet; + } + } + + if (self->pBend1) { + pDrivInt = self->pBend1->pDescriptor->GetInterface(self->pBend1, + DRIVEID); + if (pDrivInt) { + iRet = pDrivInt->CheckStatus(self->pBend1, pCon); + if ((iRet != OKOK) && (iRet != HWIdle)) { + return iRet; + } + } + } + + if (self->pBend2) { + pDrivInt = self->pBend2->pDescriptor->GetInterface(self->pBend2, + DRIVEID); + if (pDrivInt) { + iRet = pDrivInt->CheckStatus(self->pBend2, pCon); + if ((iRet != OKOK) && (iRet != HWIdle)) { + return iRet; + } + } + } + + + return HWIdle; +} + /*-------------------------------------------------------------------------- returns the current Wavelength the monochromator is adjusted to */ - float GetMonoPosition(pSicsSelector self, SConnection *pCon) - { - double fVal, dTheta; - float fTheta, fTwoTheta; - char pBueffel[132]; - int iRet; - - /* get the two positions */ - iRet = MotorGetSoftPosition(self->pTheta,pCon,&fTheta); - if(!iRet) - { - sprintf(pBueffel,"ERROR: cannot read Theta motor for monochromator %s\n", - self->name); - SCWrite(pCon,pBueffel,eError); - return 0.; - } - iRet = MotorGetSoftPosition(self->pTwoTheta,pCon,&fTwoTheta); - if(!iRet) - { - sprintf(pBueffel, - "ERROR: cannot read TwoTheta motor for monochromator %s\n", - self->name); - SCWrite(pCon,pBueffel,eError); - return 0.; - } - - /* check for sync */ - fVal = fTwoTheta - 2* fTheta; - if(fVal < 0.)fVal = -fVal; - if(fVal > 0.01) - { - sprintf(pBueffel,"WARNING: monochromator %s out of sync by %f\n", - self->name,fVal); - SCWrite(pCon,pBueffel,eStatus); - } - - /* calculate wavelength from angles */ - dTheta =(double)fTheta; - dTheta = dTheta *(1.0/RD); - fVal = 2.0 * (double)ObVal(self->pParams,LATD); - fVal = fVal * sin(dTheta) * ObVal(self->pParams,SS); - return fVal; +float GetMonoPosition(pSicsSelector self, SConnection * pCon) +{ + double fVal, dTheta; + float fTheta, fTwoTheta; + char pBueffel[132]; + int iRet; + + /* get the two positions */ + iRet = MotorGetSoftPosition(self->pTheta, pCon, &fTheta); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: cannot read Theta motor for monochromator %s\n", + self->name); + SCWrite(pCon, pBueffel, eError); + return 0.; } + iRet = MotorGetSoftPosition(self->pTwoTheta, pCon, &fTwoTheta); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: cannot read TwoTheta motor for monochromator %s\n", + self->name); + SCWrite(pCon, pBueffel, eError); + return 0.; + } + + /* check for sync */ + fVal = fTwoTheta - 2 * fTheta; + if (fVal < 0.) + fVal = -fVal; + if (fVal > 0.01) { + snprintf(pBueffel,sizeof(pBueffel)-1, "WARNING: monochromator %s out of sync by %f\n", + self->name, fVal); + SCWrite(pCon, pBueffel, eWarning); + } + + /* calculate wavelength from angles */ + dTheta = (double) fTheta; + dTheta = dTheta * (1.0 / RD); + fVal = 2.0 * (double) ObVal(self->pParams, LATD); + fVal = fVal * sin(dTheta) * ObVal(self->pParams, SS); + return fVal; +} + /*--------------------------------------------------------------------------*/ - int GetMonoPositions(pSicsSelector self, SConnection *pCon, - float *fTh, float *f2TH, float *fB1, float *fB2) - { - int iRet; - char pBueffel[512]; +int GetMonoPositions(pSicsSelector self, SConnection * pCon, + float *fTh, float *f2TH, float *fB1, float *fB2) +{ + int iRet; + char pBueffel[512]; - iRet = MotorGetSoftPosition(self->pTheta,pCon,fTh); - if(!iRet) - { - sprintf(pBueffel,"ERROR: cannot read Theta motor for monochromator %s\n", + iRet = MotorGetSoftPosition(self->pTheta, pCon, fTh); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: cannot read Theta motor for monochromator %s\n", + self->name); + SCWrite(pCon, pBueffel, eError); + return 0.; + } + iRet = MotorGetSoftPosition(self->pTwoTheta, pCon, f2TH); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: cannot read TwoTheta motor for monochromator %s\n", + self->name); + SCWrite(pCon, pBueffel, eError); + return 0.; + } + + if (self->pBend1) { + iRet = MotorGetSoftPosition(self->pBend1, pCon, fB1); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: cannot read vertical bender motor for monochromator %s\n", self->name); - SCWrite(pCon,pBueffel,eError); + SCWrite(pCon, pBueffel, eError); return 0.; } - iRet = MotorGetSoftPosition(self->pTwoTheta,pCon,f2TH); - if(!iRet) - { - sprintf(pBueffel, - "ERROR: cannot read TwoTheta motor for monochromator %s\n", + } + if (self->pBend2) { + iRet = MotorGetSoftPosition(self->pBend2, pCon, fB2); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: cannot read horizontal bender motor for monochromator %s\n", self->name); - SCWrite(pCon,pBueffel,eError); + SCWrite(pCon, pBueffel, eError); return 0.; } - - if(self->pBend1) - { - iRet = MotorGetSoftPosition(self->pBend1,pCon,fB1); - if(!iRet) - { - sprintf(pBueffel, - "ERROR: cannot read vertical bender motor for monochromator %s\n", - self->name); - SCWrite(pCon,pBueffel,eError); - return 0.; - } - } - if(self->pBend2) - { - iRet = MotorGetSoftPosition(self->pBend2,pCon,fB2); - if(!iRet) - { - sprintf(pBueffel, - "ERROR: cannot read horizontal bender motor for monochromator %s\n", - self->name); - SCWrite(pCon,pBueffel,eError); - return 0.; - } - } - return 1; - } - + } + return 1; +} diff --git a/selector.h b/selector.h index ddeb0421..9380cb09 100644 --- a/selector.h +++ b/selector.h @@ -26,35 +26,34 @@ #define SICSMONO #include "motor.h" - typedef struct __SicsSelector *pSicsSelector; - - - /* birth and death: The Selector himself */ - pSicsSelector CreateSelector(char *name, pMotor pTheta, pMotor pTwoTheta, - pMotor pBend1, pMotor pBend2); - - int MonoInit(SConnection *pCon,SicsInterp *pSics, void *pData, - int argc, char *argv[]); +typedef struct __SicsSelector *pSicsSelector; + + + /* birth and death: The Selector himself */ +pSicsSelector CreateSelector(char *name, pMotor pTheta, pMotor pTwoTheta, + pMotor pBend1, pMotor pBend2); + +int MonoInit(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); + +void DeleteSelector(void *self); - void DeleteSelector(void *self); - /* Action! */ - - int MonoAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - int MonoRun(pSicsSelector self, SConnection *pCon, float fWaveLength); - struct __ComEntry *GetSelectorMotors(pSicsSelector self, SConnection *pCon, - float fNew); - int MonoLimits(pSicsSelector self, float fWaveLength, char *error, - int iErrLen); - int MonoCheck(pSicsSelector self, SConnection *pCon); - int MonoHalt(pSicsSelector self); - float GetMonoPosition(pSicsSelector self, SConnection *pCon); - char *MonoGetType(pSicsSelector self); - int GetMonoPositions(pSicsSelector self, SConnection *pCon, - float *fTheta, float *fTwtTh, float *fB1, float *fB2); - -#endif +int MonoAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); +int MonoRun(pSicsSelector self, SConnection * pCon, float fWaveLength); +struct __ComEntry *GetSelectorMotors(pSicsSelector self, + SConnection * pCon, float fNew); +int MonoLimits(pSicsSelector self, float fWaveLength, char *error, + int iErrLen); +int MonoCheck(pSicsSelector self, SConnection * pCon); +int MonoHalt(pSicsSelector self); +float GetMonoPosition(pSicsSelector self, SConnection * pCon); +char *MonoGetType(pSicsSelector self); +int GetMonoPositions(pSicsSelector self, SConnection * pCon, + float *fTheta, float *fTwtTh, float *fB1, float *fB2); + +#endif diff --git a/selvar.c b/selvar.c index a8533910..46a4fc81 100644 --- a/selvar.c +++ b/selvar.c @@ -58,446 +58,432 @@ lots of static functions necessary to initialize the ObjectDescriptor structures of our variables. ----------------------------------------------------------------------------*/ - static void *SelVarGetInterface(void *pData, int iID) - { - pSelVar self = NULL; - - self = (pSelVar)pData; - assert(self); - - if(iID == DRIVEID) - { - return self->pDrivInt; - } - else if(iID == CALLBACKINTERFACE) - { - return self->pCall; - } - return NULL; +static void *SelVarGetInterface(void *pData, int iID) +{ + pSelVar self = NULL; + + self = (pSelVar) pData; + assert(self); + + if (iID == DRIVEID) { + return self->pDrivInt; + } else if (iID == CALLBACKINTERFACE) { + return self->pCall; } + return NULL; +} /*--------------------------------------------------------------------------*/ - static float Energy2Wave(float fVal, SConnection *pCon) - { - float fWave; - char pBueffel[132]; - - if(fVal < .0) - { - sprintf(pBueffel,"ERROR: Invalid energy %f specified, defaulted to 20.", - fVal); - SCWrite(pCon,pBueffel,eError); - fWave = 20./2.07; - } - fWave = fVal/1000.; - fWave = sqrt(fWave); - fWave = 0.286/fWave; - return fWave; - } -/*--------------------------------------------------------------------------*/ - static int CheckWLLimits(void *pSelf, float fNew, char *error, int iErrLen) - { - pSelVar self = NULL; - - self = (pSelVar)pSelf; - assert(self); - assert(self->pDes); - assert(strcmp(self->pDes->name,"SicsSelVar") == 0); - assert(self->pSel); - - return MonoLimits(self->pSel,fNew,error,iErrLen); - } -/*--------------------------------------------------------------------------*/ - static int CheckELimits(void *pSelf, float fNew, char *error, int iErrLen) - { - pSelVar self = NULL; - float fWave; - char pBueffel[132]; - - self = (pSelVar)pSelf; - assert(self); - assert(self->pDes); - assert(strcmp(self->pDes->name,"SicsSelVar") == 0); - assert(self->pSel); +static float Energy2Wave(float fVal, SConnection * pCon) +{ + float fWave; + char pBueffel[132]; + + if (fVal < .0) { + snprintf(pBueffel,sizeof(pBueffel)-1, + "ERROR: Invalid energy %f specified, defaulted to 20.", fVal); + SCWrite(pCon, pBueffel, eError); + fWave = 20. / 2.07; + } + fWave = fVal / 1000.; + fWave = sqrt(fWave); + fWave = 0.286 / fWave; + return fWave; +} + +/*--------------------------------------------------------------------------*/ +static int CheckWLLimits(void *pSelf, float fNew, char *error, int iErrLen) +{ + pSelVar self = NULL; + + self = (pSelVar) pSelf; + assert(self); + assert(self->pDes); + assert(strcmp(self->pDes->name, "SicsSelVar") == 0); + assert(self->pSel); + + return MonoLimits(self->pSel, fNew, error, iErrLen); +} + +/*--------------------------------------------------------------------------*/ +static int CheckELimits(void *pSelf, float fNew, char *error, int iErrLen) +{ + pSelVar self = NULL; + float fWave; + char pBueffel[132]; + + self = (pSelVar) pSelf; + assert(self); + assert(self->pDes); + assert(strcmp(self->pDes->name, "SicsSelVar") == 0); + assert(self->pSel); + + fWave = fNew / 2.07; + if (fWave < .0) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Invalid energy %f specified", fNew); + strlcpy(error, pBueffel, iErrLen); + return 0; + } + fWave = sqrt(fWave); + + return MonoLimits(self->pSel, fWave, error, iErrLen); +} - fWave = fNew/2.07; - if(fWave < .0) - { - sprintf(pBueffel,"ERROR: Invalid energy %f specified", - fNew); - strncpy(error,pBueffel,iErrLen); - return 0; - } - fWave = sqrt(fWave); - - return MonoLimits(self->pSel,fWave,error,iErrLen); - } /*-------------------------------------------------------------------------*/ - static long SetWL(void *pSelf, SConnection *pCon, float fNew ) - { - pSelVar self = NULL; - - self = (pSelVar)pSelf; - assert(self); - assert(self->pDes); - assert(strcmp(self->pDes->name,"SicsSelVar") == 0); - assert(self->pSel); - - return MonoRun(self->pSel,pCon,fNew); - } - +static long SetWL(void *pSelf, SConnection * pCon, float fNew) +{ + pSelVar self = NULL; + + self = (pSelVar) pSelf; + assert(self); + assert(self->pDes); + assert(strcmp(self->pDes->name, "SicsSelVar") == 0); + assert(self->pSel); + + return MonoRun(self->pSel, pCon, fNew); +} + /*-------------------------------------------------------------------------*/ - static long SetEnergy(void *pSelf, SConnection *pCon, float fNew) - { - pSelVar self = NULL; - - self = (pSelVar)pSelf; - assert(self); - assert(self->pDes); - assert(strcmp(self->pDes->name,"SicsSelVar") == 0); - assert(self->pSel); - - return MonoRun(self->pSel,pCon,Energy2Wave(fNew,pCon)); - } +static long SetEnergy(void *pSelf, SConnection * pCon, float fNew) +{ + pSelVar self = NULL; + + self = (pSelVar) pSelf; + assert(self); + assert(self->pDes); + assert(strcmp(self->pDes->name, "SicsSelVar") == 0); + assert(self->pSel); + + return MonoRun(self->pSel, pCon, Energy2Wave(fNew, pCon)); +} + /*------------------------------------------------------------------------*/ - static int CheckVal(void *pSelf, SConnection *pCon ) - { - pSelVar self = NULL; - int status; - - self = (pSelVar)pSelf; - assert(self); - assert(self->pDes); - assert(strcmp(self->pDes->name,"SicsSelVar") == 0); - assert(self->pSel); - assert(pCon); - - self->pCon = pCon; +static int CheckVal(void *pSelf, SConnection * pCon) +{ + pSelVar self = NULL; + int status; + + self = (pSelVar) pSelf; + assert(self); + assert(self->pDes); + assert(strcmp(self->pDes->name, "SicsSelVar") == 0); + assert(self->pSel); + assert(pCon); + + self->pCon = pCon; + InvokeCallBack(self->pCall, WLCHANGE, self); + status = MonoCheck(self->pSel, pCon); + if (status != HWBusy) { InvokeCallBack(self->pCall, WLCHANGE, self); - status = MonoCheck(self->pSel,pCon); - if(status != HWBusy) - { - InvokeCallBack(self->pCall, WLCHANGE, self); - } - return status; - } -/*------------------------------------------------------------------------*/ - static int HaltSelVar(void *pSelf) - { - pSelVar self = NULL; - - self = (pSelVar)pSelf; - assert(self); - assert(self->pDes); - assert(strcmp(self->pDes->name,"SicsSelVar") == 0); - assert(self->pSel); - - return MonoHalt(self->pSel); - } -/*-------------------------------------------------------------------------*/ - static float GetWL(void *pData, SConnection *pCon) - { - pSelVar pVar; - - pVar = (pSelVar)pData; - assert(pVar); - return GetMonoPosition(pVar->pSel,pCon); - } -/*-------------------------------------------------------------------------*/ - static float GetEE(void *pData, SConnection *pCon) - { - float fWave = 0; - pSelVar pVar; - - pVar = (pSelVar)pData; - assert(pVar); - - fWave = GetMonoPosition(pVar->pSel,pCon); - fWave = 0.286/fWave; - fWave = fWave*fWave*1000.; - return fWave; - } -/*------------------------------------------------------------------------*/ - pSelVar CreateWLVar(char *name, pSicsSelector pSel) - { - pSelVar pNew = NULL; - - assert(pSel); - assert(name); - - /* allocate memory */ - pNew = (pSelVar)malloc(sizeof(SelVar)); - if(!pNew) - { - return NULL; - } - pNew->pDes = CreateDescriptor("SicsSelVar"); - if(!pNew->pDes) - { - free(pNew); - return NULL; - } - - pNew->pCall = CreateCallBackInterface(); - if(!pNew->pCall) - { - free(pNew); - return NULL; - } - /* initialize Descriptor */ - pNew->pDes->GetInterface = SelVarGetInterface; - - - /* initialise Drivable interface */ - pNew->pDrivInt = CreateDrivableInterface(); - if(!pNew->pDrivInt) - { - DeleteDescriptor(pNew->pDes); - free(pNew); - return NULL; - } - pNew->pDrivInt->SetValue = SetWL; - pNew->pDrivInt->CheckStatus = CheckVal; - pNew->pDrivInt->GetValue = GetWL; - pNew->pDrivInt->CheckLimits = CheckWLLimits; - pNew->pDrivInt->Halt = HaltSelVar; - - /* intialize Rest */ - pNew->pSel = pSel; - pNew->name = strdup(name); - - return pNew; - } -/*------------------------------------------------------------------------*/ - pSelVar CreateEnergy(char *name, pSicsSelector pSel) - { - pSelVar pNew = NULL; - - assert(pSel); - assert(name); - - /* allocate memory */ - pNew = (pSelVar)malloc(sizeof(SelVar)); - if(!pNew) - { - return NULL; - } - pNew->pDes = CreateDescriptor("SicsSelVar"); - if(!pNew->pDes) - { - free(pNew); - return NULL; - } - - /* create call back interface */ - pNew->pCall = CreateCallBackInterface(); - if(!pNew->pCall) - { - free(pNew); - return NULL; - } - - /* initialize Descriptor */ - pNew->pDes->GetInterface = SelVarGetInterface; - - /* initialise Drivable interface */ - pNew->pDrivInt = CreateDrivableInterface(); - if(!pNew->pDrivInt) - { - DeleteDescriptor(pNew->pDes); - free(pNew); - return NULL; - } - pNew->pDrivInt->Halt = HaltSelVar; - pNew->pDrivInt->CheckLimits = CheckELimits; - pNew->pDrivInt->SetValue = SetEnergy; - pNew->pDrivInt->CheckStatus = CheckVal; - pNew->pDrivInt->GetValue = GetEE; - /* intialize Rest */ - pNew->pSel = pSel; - pNew->name = strdup(name); - - return pNew; - } -/*------------------------------------------------------------------------*/ - void DeleteSelVar(void *pSelf) - { - pSelVar self = NULL; - - assert(pSelf); - self = (pSelVar)pSelf; - assert(self->pDes); - assert(strcmp(self->pDes->name, "SicsSelVar") == 0); - - if(self->pDes) - { - DeleteDescriptor(self->pDes); - } - if(self->pDrivInt) - { - free(self->pDrivInt); - } - if(self->pCall) - { - DeleteCallBackInterface(self->pCall); - } - if(self->name) - { - free(self->name); - } - free(self); - } -/*------------------------------------------------------------------------*/ - float GetSelValue(pSelVar self, SConnection *pCon) - { - assert(self); - return self->pDrivInt->GetValue(self,pCon); } - + return status; +} + +/*------------------------------------------------------------------------*/ +static int HaltSelVar(void *pSelf) +{ + pSelVar self = NULL; + + self = (pSelVar) pSelf; + assert(self); + assert(self->pDes); + assert(strcmp(self->pDes->name, "SicsSelVar") == 0); + assert(self->pSel); + + return MonoHalt(self->pSel); +} + +/*-------------------------------------------------------------------------*/ +static float GetWL(void *pData, SConnection * pCon) +{ + pSelVar pVar; + + pVar = (pSelVar) pData; + assert(pVar); + return GetMonoPosition(pVar->pSel, pCon); +} + +/*-------------------------------------------------------------------------*/ +static float GetEE(void *pData, SConnection * pCon) +{ + float fWave = 0; + pSelVar pVar; + + pVar = (pSelVar) pData; + assert(pVar); + + fWave = GetMonoPosition(pVar->pSel, pCon); + fWave = 0.286 / fWave; + fWave = fWave * fWave * 1000.; + return fWave; +} + +/*------------------------------------------------------------------------*/ +pSelVar CreateWLVar(char *name, pSicsSelector pSel) +{ + pSelVar pNew = NULL; + + assert(pSel); + assert(name); + + /* allocate memory */ + pNew = (pSelVar) malloc(sizeof(SelVar)); + if (!pNew) { + return NULL; + } + pNew->pDes = CreateDescriptor("SicsSelVar"); + if (!pNew->pDes) { + free(pNew); + return NULL; + } + + pNew->pCall = CreateCallBackInterface(); + if (!pNew->pCall) { + free(pNew); + return NULL; + } + /* initialize Descriptor */ + pNew->pDes->GetInterface = SelVarGetInterface; + + + /* initialise Drivable interface */ + pNew->pDrivInt = CreateDrivableInterface(); + if (!pNew->pDrivInt) { + DeleteDescriptor(pNew->pDes); + free(pNew); + return NULL; + } + pNew->pDrivInt->SetValue = SetWL; + pNew->pDrivInt->CheckStatus = CheckVal; + pNew->pDrivInt->GetValue = GetWL; + pNew->pDrivInt->CheckLimits = CheckWLLimits; + pNew->pDrivInt->Halt = HaltSelVar; + + /* intialize Rest */ + pNew->pSel = pSel; + pNew->name = strdup(name); + + return pNew; +} + +/*------------------------------------------------------------------------*/ +pSelVar CreateEnergy(char *name, pSicsSelector pSel) +{ + pSelVar pNew = NULL; + + assert(pSel); + assert(name); + + /* allocate memory */ + pNew = (pSelVar) malloc(sizeof(SelVar)); + if (!pNew) { + return NULL; + } + pNew->pDes = CreateDescriptor("SicsSelVar"); + if (!pNew->pDes) { + free(pNew); + return NULL; + } + + /* create call back interface */ + pNew->pCall = CreateCallBackInterface(); + if (!pNew->pCall) { + free(pNew); + return NULL; + } + + /* initialize Descriptor */ + pNew->pDes->GetInterface = SelVarGetInterface; + + /* initialise Drivable interface */ + pNew->pDrivInt = CreateDrivableInterface(); + if (!pNew->pDrivInt) { + DeleteDescriptor(pNew->pDes); + free(pNew); + return NULL; + } + pNew->pDrivInt->Halt = HaltSelVar; + pNew->pDrivInt->CheckLimits = CheckELimits; + pNew->pDrivInt->SetValue = SetEnergy; + pNew->pDrivInt->CheckStatus = CheckVal; + pNew->pDrivInt->GetValue = GetEE; + /* intialize Rest */ + pNew->pSel = pSel; + pNew->name = strdup(name); + + return pNew; +} + +/*------------------------------------------------------------------------*/ +void DeleteSelVar(void *pSelf) +{ + pSelVar self = NULL; + + assert(pSelf); + self = (pSelVar) pSelf; + assert(self->pDes); + assert(strcmp(self->pDes->name, "SicsSelVar") == 0); + + if (self->pDes) { + DeleteDescriptor(self->pDes); + } + if (self->pDrivInt) { + free(self->pDrivInt); + } + if (self->pCall) { + DeleteCallBackInterface(self->pCall); + } + if (self->name) { + free(self->name); + } + free(self); +} + +/*------------------------------------------------------------------------*/ +float GetSelValue(pSelVar self, SConnection * pCon) +{ + assert(self); + return self->pDrivInt->GetValue(self, pCon); +} + /*------------------------------------------------------------------------- Syntax: MakeWL name monochromatorname AccesCode */ - int MakeWaveLengthVar(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - int iRet; - char pBueffel[132]; - pSicsSelector pMono = NULL; - pSelVar pNeu = NULL; - CommandList *pCom = NULL; +int MakeWaveLengthVar(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + int iRet; + char pBueffel[132]; + pSicsSelector pMono = NULL; + pSelVar pNeu = NULL; + CommandList *pCom = NULL; + + /* 99.99999999999 % of all code is argument checking! */ + argtolower(argc, argv); + if (argc < 3) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Insufficient number of arguments to %s", + argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* argv[1] == name, argv[2] should be a monochromator, find it */ + pCom = FindCommand(pSics, argv[2]); + if (!pCom) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s not found", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + pMono = (pSicsSelector) pCom->pData; + if (!pMono) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s is no monochromator", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + if (!iHasType(pMono, "CrystalSelector")) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s is no monochromator", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* got everything we need to set things up */ + pNeu = CreateWLVar(argv[1], pMono); + if (!pNeu) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Out of memory creating %s found", argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + iRet = AddCommand(pSics, argv[1], WaveLengthAction, DeleteSelVar, pNeu); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: duplicate command %s not created", argv[1]); + DeleteSelVar((void *) pNeu); + SCWrite(pCon, pBueffel, eError); + return 0; + } + return 1; +} - /* 99.99999999999 % of all code is argument checking! */ - argtolower(argc,argv); - if(argc < 3) - { - sprintf(pBueffel,"ERROR: Insufficient number of arguments to %s", - argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* argv[1] == name, argv[2] should be a monochromator, find it */ - pCom = FindCommand(pSics,argv[2]); - if(!pCom) - { - sprintf(pBueffel,"ERROR: %s not found",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - pMono = (pSicsSelector)pCom->pData; - if(!pMono) - { - sprintf(pBueffel,"ERROR: %s is no monochromator",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - if(!iHasType(pMono, "CrystalSelector")) - { - sprintf(pBueffel,"ERROR: %s is no monochromator",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* got everything we need to set things up */ - pNeu = CreateWLVar(argv[1],pMono); - if(!pNeu) - { - sprintf(pBueffel,"ERROR: Out of memory creating %s found",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - iRet = AddCommand(pSics,argv[1],WaveLengthAction,DeleteSelVar,pNeu); - if(!iRet) - { - sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[1]); - DeleteSelVar((void *)pNeu); - SCWrite(pCon,pBueffel,eError); - return 0; - } - return 1; - } /*--------------------------------------------------------------------------*/ - int MakeEnergyVar(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - int iRet; - char pBueffel[132]; - pSicsSelector pMono = NULL; - pSelVar pNeu = NULL; - CommandList *pCom = NULL; +int MakeEnergyVar(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + int iRet; + char pBueffel[132]; + pSicsSelector pMono = NULL; + pSelVar pNeu = NULL; + CommandList *pCom = NULL; + + /* 99.99999999999 % of all code is argument checking! */ + argtolower(argc, argv); + if (argc < 3) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Insufficient number of arguments to %s", + argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* argv[1] == name, argv[2] should be a monochromator, find it */ + pCom = FindCommand(pSics, argv[2]); + if (!pCom) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s not found", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + pMono = (pSicsSelector) pCom->pData; + if (!pMono) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s is no monochromator", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + if (!iHasType(pMono, "CrystalSelector")) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s is no monochromator", argv[2]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* got everything we need to set things up */ + pNeu = CreateEnergy(argv[1], pMono); + if (!pNeu) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Out of memory creating %s found", argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + iRet = AddCommand(pSics, argv[1], EnergyAction, DeleteSelVar, pNeu); + if (!iRet) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: duplicate command %s not created", argv[1]); + SCWrite(pCon, pBueffel, eError); + DeleteSelVar((void *) pNeu); + return 0; + } + return 1; +} - /* 99.99999999999 % of all code is argument checking! */ - argtolower(argc,argv); - if(argc < 3) - { - sprintf(pBueffel,"ERROR: Insufficient number of arguments to %s", - argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* argv[1] == name, argv[2] should be a monochromator, find it */ - pCom = FindCommand(pSics,argv[2]); - if(!pCom) - { - sprintf(pBueffel,"ERROR: %s not found",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - pMono = (pSicsSelector)pCom->pData; - if(!pMono) - { - sprintf(pBueffel,"ERROR: %s is no monochromator",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - if(!iHasType(pMono,"CrystalSelector")) - { - sprintf(pBueffel,"ERROR: %s is no monochromator",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* got everything we need to set things up */ - pNeu = CreateEnergy(argv[1],pMono); - if(!pNeu) - { - sprintf(pBueffel,"ERROR: Out of memory creating %s found",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - iRet = AddCommand(pSics,argv[1],EnergyAction,DeleteSelVar,pNeu); - if(!iRet) - { - sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[1]); - SCWrite(pCon,pBueffel,eError); - DeleteSelVar((void *)pNeu); - return 0; - } - return 1; - } /*------------------------------------------------------------------------*/ - static int WaveLengthCallBack(int iEvent, void *pEvent, void *pUser, - commandContext cc) - { - SConnection *pCon = NULL; - pSelVar self = NULL; - float fVal; - char pBueffel[512]; - - pCon = (SConnection *)pUser; - self = (pSelVar)pEvent; - assert(pCon); - assert(self); - - fVal = GetSelValue(self,pCon); - sprintf(pBueffel,"%s.value = %f", self->name, fVal); - SCWriteInContext(pCon,pBueffel,eValue,cc); - return 1; - } +static int WaveLengthCallBack(int iEvent, void *pEvent, void *pUser) +{ + SConnection *pCon = NULL; + pSelVar self = NULL; + float fVal; + char pBueffel[512]; + + pCon = (SConnection *) pUser; + self = (pSelVar) pEvent; + assert(pCon); + assert(self); + + if (pCon == NULL || !SCisConnected(pCon)) { + return -1; + } + + fVal = GetSelValue(self, pCon); + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.value = %f", self->name, fVal); + SCWrite(pCon, pBueffel, eValue); + return 1; +} + /*-------------------------------------------------------------------------- very simple syntax: name - return current value @@ -505,147 +491,129 @@ no new code is needed to do that interest - enables automatic printing when changes. uninterest - disables printing of value changes -*/ - int WaveLengthAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - char pBueffel[132]; - float fWave; - pSelVar self; - int iRet; - double dVal; - long lID; - - assert(pCon); - assert(pSics); - assert(pData); - self = (pSelVar)pData; - assert(self->pSel); - - if(argc > 1) /* set case or interest handling*/ - { - strtolower(argv[1]); - if(strcmp(argv[1],"interest") == 0) - { - lID = RegisterCallback(self->pCall, SCGetContext(pCon), - WLCHANGE, WaveLengthCallBack, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); - SCSendOK(pCon); - return 1; - } - else if(strcmp(argv[1],"uninterest") == 0) - { - RemoveCallback2(self->pCall,pCon); - SCSendOK(pCon); - return 1; - } - - /* verify that argv[1] is a valid number */ - iRet = Tcl_GetDouble(pSics->pTcl,argv[1],&dVal); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: %s is NO valid number ",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - if(dVal < 0) - { - sprintf(pBueffel,"ERROR: %s cannnot be a valid wavelength",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } +*/ +int WaveLengthAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + char pBueffel[132]; + float fWave; + pSelVar self; + int iRet; + double dVal; + long lID; - /* - Removed, on demand of Lukas Keller, DMC - sprintf(pBueffel,"%s %s %s",DRIVE,argv[0],argv[1]); + assert(pCon); + assert(pSics); + assert(pData); + self = (pSelVar) pData; + assert(self->pSel); + + if (argc > 1) { /* set case or interest handling */ + strtolower(argv[1]); + if (strcmp(argv[1], "interest") == 0) { + lID = RegisterCallback(self->pCall, + WLCHANGE, WaveLengthCallBack, + SCCopyConnection(pCon), SCDeleteConnection); + SCSendOK(pCon); + return 1; + } else if (strcmp(argv[1], "uninterest") == 0) { + RemoveCallback2(self->pCall, pCon); + SCSendOK(pCon); + return 1; + } + + /* verify that argv[1] is a valid number */ + iRet = Tcl_GetDouble(pSics->pTcl, argv[1], &dVal); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s is NO valid number ", argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + if (dVal < 0) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s cannnot be a valid wavelength", + argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* + Removed, on demand of Lukas Keller, DMC + snprintf(pBueffel,sizeof(pBueffel)-1,"%s %s %s",DRIVE,argv[0],argv[1]); return InterpExecute(pSics,pCon,pBueffel); - */ - snprintf(pBueffel,131,"ERROR: subcommand %s to %s not understood", - argv[1], argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - else /* get case */ - { - fWave = GetMonoPosition(self->pSel,pCon); - sprintf(pBueffel,"%s = %f",argv[0],fWave); - SCWrite(pCon,pBueffel,eStatus); - return 1; - } - return 0; - } -/*------------------------------------------------------------------------*/ - int EnergyAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - char pBueffel[132]; - float fWave; - pSelVar self; - int iRet; - double dVal; - long lID; + */ + snprintf(pBueffel, 131, "ERROR: subcommand %s to %s not understood", + argv[1], argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } else { /* get case */ - assert(pCon); - assert(pSics); - assert(pData); - self = (pSelVar)pData; - assert(self->pSel); - - if(argc > 1) /* set case or interest/uninterest*/ - { - strtolower(argv[1]); - if(strcmp(argv[1],"interest") == 0) - { - lID = RegisterCallback(self->pCall, SCGetContext(pCon), - WLCHANGE, WaveLengthCallBack, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); - SCSendOK(pCon); - return 1; - } - else if(strcmp(argv[1],"uninterest") == 0) - { - RemoveCallback2(self->pCall,pCon); - SCSendOK(pCon); - return 1; - } - - /* verify that argv[1] is a valid number */ - iRet = Tcl_GetDouble(pSics->pTcl,argv[1],&dVal); - if(iRet != TCL_OK) - { - sprintf(pBueffel,"ERROR: %s is NO valid number ",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - if(dVal < 0) - { - sprintf(pBueffel,"ERROR: %s cannnot be a valid energy",argv[1]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - - sprintf(pBueffel,"%s %s %s",DRIVE,argv[0],argv[1]); - return InterpExecute(pSics,pCon,pBueffel); - } - else /* get case */ - { - fWave = GetMonoPosition(self->pSel,pCon); - /* convert to energy */ - if(fWave >0.001) - { - fWave = 0.286/fWave; - fWave = fWave*fWave*1000.; - } - else - { - fWave = 777.77; - } - sprintf(pBueffel,"%s = %f",argv[0],fWave); - SCWrite(pCon,pBueffel,eStatus); - return 1; - } - return 0; + fWave = GetMonoPosition(self->pSel, pCon); + snprintf(pBueffel,sizeof(pBueffel)-1, "%s = %f", argv[0], fWave); + SCWrite(pCon, pBueffel, eValue); + return 1; } + return 0; +} + +/*------------------------------------------------------------------------*/ +int EnergyAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + char pBueffel[132]; + float fWave; + pSelVar self; + int iRet; + double dVal; + long lID; + + assert(pCon); + assert(pSics); + assert(pData); + self = (pSelVar) pData; + assert(self->pSel); + + if (argc > 1) { /* set case or interest/uninterest */ + strtolower(argv[1]); + if (strcmp(argv[1], "interest") == 0) { + lID = RegisterCallback(self->pCall, + WLCHANGE, WaveLengthCallBack, pCon, NULL); + SCSendOK(pCon); + return 1; + } else if (strcmp(argv[1], "uninterest") == 0) { + RemoveCallback2(self->pCall, pCon); + SCSendOK(pCon); + return 1; + } + + /* verify that argv[1] is a valid number */ + iRet = Tcl_GetDouble(pSics->pTcl, argv[1], &dVal); + if (iRet != TCL_OK) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s is NO valid number ", argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + if (dVal < 0) { + snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s cannnot be a valid energy", argv[1]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + + snprintf(pBueffel,sizeof(pBueffel)-1, "%s %s %s", DRIVE, argv[0], argv[1]); + return InterpExecute(pSics, pCon, pBueffel); + } else { /* get case */ + + fWave = GetMonoPosition(self->pSel, pCon); + /* convert to energy */ + if (fWave > 0.001) { + fWave = 0.286 / fWave; + fWave = fWave * fWave * 1000.; + } else { + fWave = 777.77; + } + snprintf(pBueffel,sizeof(pBueffel)-1, "%s = %f", argv[0], fWave); + SCWrite(pCon, pBueffel, eValue); + return 1; + } + return 0; +} diff --git a/selvar.h b/selvar.h index 3386b69b..47ddb78f 100644 --- a/selvar.h +++ b/selvar.h @@ -16,23 +16,22 @@ #ifndef SICSSELVAR #define SICSSELVAR - typedef struct __SelVar *pSelVar; - -/*------------------------ birth and death --------------------------------*/ - pSelVar CreateWLVar(char *name, pSicsSelector pSel); - pSelVar CreateEnergy(char *name, pSicsSelector pSel); - void DeleteSelVar(void *pSelf); -/* ----------------------- Factory functions for initialization -----------*/ - int MakeWaveLengthVar(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - int MakeEnergyVar(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); -/*-------------------------------------------------------------------------*/ - float GetSelValue(pSelVar self, SConnection *pCon); -/*------------------------ Action functions -------------------------------*/ - int WaveLengthAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); - int EnergyAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); -#endif +typedef struct __SelVar *pSelVar; +/*------------------------ birth and death --------------------------------*/ +pSelVar CreateWLVar(char *name, pSicsSelector pSel); +pSelVar CreateEnergy(char *name, pSicsSelector pSel); +void DeleteSelVar(void *pSelf); +/* ----------------------- Factory functions for initialization -----------*/ +int MakeWaveLengthVar(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); +int MakeEnergyVar(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); +/*-------------------------------------------------------------------------*/ +float GetSelValue(pSelVar self, SConnection * pCon); +/*------------------------ Action functions -------------------------------*/ +int WaveLengthAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); +int EnergyAction(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); +#endif diff --git a/serialsinq.h b/serialsinq.h index 4261d88f..bd7ba68f 100644 --- a/serialsinq.h +++ b/serialsinq.h @@ -22,20 +22,20 @@ #line 10 "serialsinq.w" - int SerialOpen(void **pData, char *pHost, int iPort, int iChannel); - int SerialForceOpen(void **pData, char *pHost, int iPort, int iChannel); - int SerialConfig(void **pData, int iTmo); - int SerialGetTmo(void **pData); - int SerialATerm(void **pData, char *pTerm); - int SerialAGetTerm(void **pData, char *pTerm, int iTermLen); - int SerialSendTerm(void **pData, char *pTerm); - int SerialGetSocket(void **pData); - int SerialClose(void **pData); - int SerialSend(void **pData, char *pCommand); - int SerialReceive(void **pData, char *pBuffer, int iBufLen); - int SerialError(int iError, char *pError, int iErrLen); - int SerialWriteRead(void **pData, char *pCommand, - char *pBuffer, int iBufLen); +int SerialOpen(void **pData, char *pHost, int iPort, int iChannel); +int SerialForceOpen(void **pData, char *pHost, int iPort, int iChannel); +int SerialConfig(void **pData, int iTmo); +int SerialGetTmo(void **pData); +int SerialATerm(void **pData, char *pTerm); +int SerialAGetTerm(void **pData, char *pTerm, int iTermLen); +int SerialSendTerm(void **pData, char *pTerm); +int SerialGetSocket(void **pData); +int SerialClose(void **pData); +int SerialSend(void **pData, char *pCommand); +int SerialReceive(void **pData, char *pBuffer, int iBufLen); +int SerialError(int iError, char *pError, int iErrLen); +int SerialWriteRead(void **pData, char *pCommand, + char *pBuffer, int iBufLen); #line 131 "serialsinq.w" @@ -43,8 +43,8 @@ #line 96 "serialsinq.w" - typedef int (*SerialSleep)(void *pData, int iTime); - void SetSerialSleep(void **pData, SerialSleep pFunc, void *pUserData); +typedef int (*SerialSleep) (void *pData, int iTime); +void SetSerialSleep(void **pData, SerialSleep pFunc, void *pUserData); #line 133 "serialsinq.w" diff --git a/serialwait.c b/serialwait.c index 8eb3aed9..b03f02a3 100644 --- a/serialwait.c +++ b/serialwait.c @@ -23,221 +23,196 @@ #define SDEBUG 1 */ /*--------------- The wait data structure --------------------------------*/ - typedef struct { - int iEnd; /* end signal flag */ - int iError; /* error returns */ - int iFirst; /* first call, receive only */ - time_t tEnd; /* not more then a minute! */ - pDynString data; /* reply data read */ - void **pData; /* the serial IO data structure */ - } SW, *pSW; - +typedef struct { + int iEnd; /* end signal flag */ + int iError; /* error returns */ + int iFirst; /* first call, receive only */ + time_t tEnd; /* not more then a minute! */ + pDynString data; /* reply data read */ + void **pData; /* the serial IO data structure */ +} SW, *pSW; + /*---------------- The signal function --------------------------------*/ - static void SWSignal(void *pUser, int iSignal, void *pSigData) - { - pSW self = NULL; - int *iInt; - - self = (pSW)pUser; - iInt = (int *)pSigData; - - if(iSignal == SICSINT) - { - if(*iInt > eContinue) - { - self->iEnd = 2; - } - } +static void SWSignal(void *pUser, int iSignal, void *pSigData) +{ + pSW self = NULL; + int *iInt; + + self = (pSW) pUser; + iInt = (int *) pSigData; + + if (iSignal == SICSINT) { + if (*iInt > eContinue) { + self->iEnd = 2; + } } +} + /*---------------------- The task function ------------------------------*/ - static int SWTask(void *pData) - { - pSW self = NULL; - char pReply[1024]; - int iRet, iCount; - char *pPtr; - - self = (pSW)pData; - assert(self); +static int SWTask(void *pData) +{ + pSW self = NULL; + char pReply[1024]; + int iRet, iCount; + char *pPtr; - - /* check for interrupt end */ - if(self->iEnd > 0) - { - return 0; - } - - /* check for timeout */ - if(time(NULL) >= self->tEnd) - { - self->iError = TIMEOUT; - self->iEnd = 3; - return 0; - } + self = (pSW) pData; + assert(self); - /* wait for a second */ - SicsWait(1); - - /* send a null command and read reply */ - if(!self->iFirst) - { - iRet = SerialSend(self->pData,""); - } - else - { - self->iFirst = 0; - } + /* check for interrupt end */ + if (self->iEnd > 0) { + return 0; + } + /* check for timeout */ + if (time(NULL) >= self->tEnd) { + self->iError = TIMEOUT; + self->iEnd = 3; + return 0; + } + + + /* wait for a second */ + SicsWait(1); + + /* send a null command and read reply */ + if (!self->iFirst) { + iRet = SerialSend(self->pData, ""); + } else { + self->iFirst = 0; + } + + pReply[0] = '\0'; + iRet = SerialReceive(self->pData, pReply, 1023); +#ifdef SDEBUG + printf("Primary answer: %s\n", pReply); +#endif + if ((iRet == TIMEOUT) || (iRet == SELECTFAIL)) { +#ifdef SDEBUG + printf("Return 1 on timeout\n"); +#endif + return 1; + } else if (iRet < 0) { + self->iError = iRet; + self->iEnd = 3; +#ifdef SDEBUG + printf("Error %d return Receive 0\n", iRet); +#endif + return 0; + } + + /* is there data ? */ + iCount = strlen(pReply); + if (iCount <= 0) { +#ifdef SDEBUG + printf("No data in Reply, return 1\n"); +#endif + return 1; + } + + /* do we have a tmo message ? */ + if (strncmp("?TMO", pReply, 4) == 0) { + /* is there additional data appended ? */ + if (iCount > 4) { + /* store what we have */ + pPtr = pReply + 4; + DynStringConcat(self->data, pPtr); + + /* set tmo high, read rest of reply */ + SerialConfig(self->pData, 90000); pReply[0] = '\0'; - iRet = SerialReceive(self->pData,pReply,1023); + iRet = SerialWriteRead(self->pData, "", pReply, 1023); #ifdef SDEBUG - printf("Primary answer: %s\n",pReply); -#endif - if((iRet == TIMEOUT) || (iRet == SELECTFAIL) ) - { -#ifdef SDEBUG - printf("Return 1 on timeout\n"); -#endif - return 1; - } - else if(iRet < 0) - { - self->iError = iRet; - self->iEnd = 3; -#ifdef SDEBUG - printf("Error %d return Receive 0\n", iRet); -#endif - return 0; - } - - /* is there data ? */ - iCount = strlen(pReply); - if(iCount <= 0) - { + printf(" sec rep: %s\n", pReply); +#endif + if (iRet != 1) { + self->iError = iRet; + self->iEnd = 3; #ifdef SDEBUG - printf("No data in Reply, return 1\n"); -#endif - return 1; + printf("return 0, on secondary read error\n"); +#endif + return 0; } - - /* do we have a tmo message ? */ - if(strncmp("?TMO",pReply,4) == 0) - { - /* is there additional data appended ? */ - if(iCount > 4) - { - /* store what we have */ - pPtr = pReply + 4; - DynStringConcat(self->data, pPtr); - - /* set tmo high, read rest of reply */ - SerialConfig(self->pData, 90000); - pReply[0] = '\0'; - iRet = SerialWriteRead(self->pData,"",pReply,1023); -#ifdef SDEBUG - printf(" sec rep: %s\n",pReply); -#endif - if(iRet != 1) - { - self->iError = iRet; - self->iEnd = 3; -#ifdef SDEBUG - printf("return 0, on secondary read error\n"); -#endif - return 0; - } - DynStringConcat(self->data,pReply); - self->iEnd = 1; -#ifdef SDEBUG - printf("Complete read on second try, return 0\n"); -#endif - return 0; - } - else /* schnuuuueeeeeffffff! no data, poll again */ - { + DynStringConcat(self->data, pReply); + self->iEnd = 1; #ifdef SDEBUG - printf("Do agaian, got a TMO \n"); + printf("Complete read on second try, return 0\n"); +#endif + return 0; + } else { /* schnuuuueeeeeffffff! no data, poll again */ + +#ifdef SDEBUG + printf("Do agaian, got a TMO \n"); #endif - return 1; - } - } - else /* we obtained all the data right away */ - { - DynStringConcat(self->data,pReply); - self->iEnd = 1; -#ifdef SDEBUG - printf("Return 0, received all data in one go \n"); -#endif - return 0; - } - /* should not get here */ -#ifdef SDEBUG - printf("Should not get here return 1\n"); -#endif return 1; + } + } else { /* we obtained all the data right away */ + + DynStringConcat(self->data, pReply); + self->iEnd = 1; +#ifdef SDEBUG + printf("Return 0, received all data in one go \n"); +#endif + return 0; + } + /* should not get here */ +#ifdef SDEBUG + printf("Should not get here return 1\n"); +#endif + return 1; +} + +/*-------------------------- The actual working function ------------------*/ +int SerialSicsExecute(void **pData, char *pCommand, + char *pReply, int iBufLen) +{ + int iOldTmo, iRet, iResult; + long lTask; + SW control; + char *pPtr; + + /* set timeout to 0 */ + iOldTmo = SerialGetTmo(pData); + SerialConfig(pData, 200); + + /* send the command to execute */ + iRet = SerialSend(pData, pCommand); + if (iRet != 1) { + SerialConfig(pData, iOldTmo); + return iRet; } -/*-------------------------- The actual working function ------------------*/ - int SerialSicsExecute(void **pData, char *pCommand, - char *pReply, int iBufLen) - { - int iOldTmo, iRet, iResult; - long lTask; - SW control; - char *pPtr; - - /* set timeout to 0 */ - iOldTmo = SerialGetTmo(pData); - SerialConfig(pData,200); - - /* send the command to execute */ - iRet = SerialSend(pData,pCommand); - if(iRet != 1) - { - SerialConfig(pData,iOldTmo); - return iRet; - } - - /* initialize task data structure */ - control.iEnd = 0; - control.iError = 0; - control.iFirst = 1; - control.pData = pData; - /* do a timeout after a minute without a reply */ - control.tEnd = time(NULL) + 60; - control.data = CreateDynString(1024,1024); - - /* start task */ - lTask = TaskRegister(pServ->pTasker, - SWTask, - SWSignal, - NULL, - &control, - 1); - /* wait for it to end */ - TaskWait(pServ->pTasker,lTask); - - /* analyse what we have got, success first */ - if(control.iEnd == 1) - { - iResult = 1; - pPtr = GetCharArray(control.data); - strncpy(pReply,pPtr,iBufLen); - } - else if(control.iEnd == 2) /* interrupted */ - { - iResult = INTERRUPTED; - } - else - { - iResult = control.iError; - } - control.iEnd = 10; - - /* clear up and go */ - DeleteDynString(control.data); - SerialConfig(pData,iOldTmo); - return iResult; + /* initialize task data structure */ + control.iEnd = 0; + control.iError = 0; + control.iFirst = 1; + control.pData = pData; + /* do a timeout after a minute without a reply */ + control.tEnd = time(NULL) + 60; + control.data = CreateDynString(1024, 1024); + + /* start task */ + lTask = TaskRegister(pServ->pTasker, + SWTask, SWSignal, NULL, &control, 1); + /* wait for it to end */ + TaskWait(pServ->pTasker, lTask); + + /* analyse what we have got, success first */ + if (control.iEnd == 1) { + iResult = 1; + pPtr = GetCharArray(control.data); + strlcpy(pReply, pPtr, iBufLen); + } else if (control.iEnd == 2) { /* interrupted */ + iResult = INTERRUPTED; + } else { + iResult = control.iError; } + control.iEnd = 10; + + /* clear up and go */ + DeleteDynString(control.data); + SerialConfig(pData, iOldTmo); + return iResult; +} diff --git a/serialwait.h b/serialwait.h index d7193f9a..d750a61c 100644 --- a/serialwait.h +++ b/serialwait.h @@ -13,7 +13,7 @@ #define SERIALSICSWAIT #include "sics.h" #include "psi/hardsup/serialsinq.h" - int SerialSicsExecute(void **pData, char *pCommand, char *pReply, - int iBufLen); +int SerialSicsExecute(void **pData, char *pCommand, char *pReply, + int iBufLen); #endif diff --git a/servlog.c b/servlog.c index 14f167b7..29faad49 100644 --- a/servlog.c +++ b/servlog.c @@ -47,15 +47,14 @@ - NETWrites log message (if enabled) before attempt to write to file - uses OpenVerifyLogFile helper function (removed duplicate code) -----------------------------------------------------------------------------*/ -#include #include "fortify.h" #include #include #include #include #include -#include -#include +#include + #include "ifile.h" #include "conman.h" #include "servlog.h" @@ -69,54 +68,46 @@ The server log output can be captured by a client. In order to implement this the following code is necessary. */ - typedef struct __LogLog{ - SConnection *pCon; - OutCode iOut; - int iAllFlag; - struct __LogLog *pNext; - struct __LogLog *pPrevious; - } CaptureEntry, *pCaptureEntry; +typedef struct __LogLog { + SConnection *pCon; + OutCode iOut; + int iAllFlag; + struct __LogLog *pNext; + struct __LogLog *pPrevious; +} CaptureEntry, *pCaptureEntry; - static pCaptureEntry pCapture = NULL; +static pCaptureEntry pCapture = NULL; /*------------------------------------------------------------------------*/ - int KillCapture(SConnection *pCon) - { - pCaptureEntry pCurrent, pTemp; - - /* find first */ - pCurrent = pCapture; - while(pCurrent != NULL) - { - if(pCon == pCurrent->pCon) - { - /* relink */ - if(pCurrent->pPrevious) - { - pCurrent->pPrevious->pNext = pCurrent->pNext; - } - else - { - pCapture = pCurrent->pNext; - } - if(pCurrent->pNext) - { - pCurrent->pNext->pPrevious = pCurrent->pPrevious; - } - pTemp = pCurrent->pNext; - /* get rid of pCurrent */ - free(pCurrent); - pCurrent = pTemp; - } - else - { - pCurrent = pCurrent->pNext; - } - } - return 1; - } - - +int KillCapture(SConnection * pCon) +{ + pCaptureEntry pCurrent, pTemp; + + /* find first */ + pCurrent = pCapture; + while (pCurrent != NULL) { + if (pCon == pCurrent->pCon) { + /* relink */ + if (pCurrent->pPrevious) { + pCurrent->pPrevious->pNext = pCurrent->pNext; + } else { + pCapture = pCurrent->pNext; + } + if (pCurrent->pNext) { + pCurrent->pNext->pPrevious = pCurrent->pPrevious; + } + pTemp = pCurrent->pNext; + /* get rid of pCurrent */ + free(pCurrent); + pCurrent = pTemp; + } else { + pCurrent = pCurrent->pNext; + } + } + return 1; +} + + /* ------------------------------------------------------------------------ the command function: Syntax: @@ -124,485 +115,181 @@ Log OutCode starts loggin OutCode events All starts logging all events -------------------------------------------------------------------------- */ -#include "outcode.c" /* for pCode */ - - int LogCapture(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - pCaptureEntry pNew = NULL; - char pBueffel[512]; - int i; - - /* check no af args */ - if(argc < 2) - { - sprintf(pBueffel,"Insufficient number of argumenst to %s",argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - argtolower(argc,argv); - - /* Branch according to argv[1] */ - if(strcmp(argv[1],"kill") == 0 ) - { - KillCapture(pCon); - return 1; - } - else if(strcmp(argv[1],"all") == 0) - { - pNew = (pCaptureEntry)malloc(sizeof(CaptureEntry)); - if(!pNew) - { - SICSLogWrite("Out of memory in LogCapture",eInternal); - return 0; - } - if(pCapture) - { - pCapture->pPrevious = pNew; - } - pNew->pPrevious = NULL; - pNew->pNext = pCapture; - pCapture = pNew; - pNew->iAllFlag = 1; - pNew->pCon = pCon; - return 1; - } - else - { - /* must be outcode, try find it */ - i = 0; - while(pCode[i] != NULL) - { - if(strcmp(argv[1],pCode[i]) == 0) - { - break; - } - i++; - } - if(i > iNoCodes) - { - sprintf(pBueffel,"OutPutCode %s not recognized in %s",argv[1], - argv[0]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - /* create a new one */ - pNew = (pCaptureEntry)malloc(sizeof(CaptureEntry)); - if(!pNew) - { - SICSLogWrite("Out of memory in LogCapture",eInternal); - return 0; - } - if(pCapture) - { - pCapture->pPrevious = pNew; - } - pNew->pPrevious = NULL; - pNew->pNext = pCapture; - pCapture = pNew; - pNew->iAllFlag = 0; - pNew->pCon = pCon; - pNew->iOut = i; - return 1; - } +#include "outcode.c" /* for pCode */ + +int LogCapture(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pCaptureEntry pNew = NULL; + char pBueffel[512]; + int i; + + /* check no af args */ + if (argc < 2) { + snprintf(pBueffel,sizeof(pBueffel)-1, "Insufficient number of argumenst to %s", argv[0]); + SCWrite(pCon, pBueffel, eError); return 0; } -/*--------------------------------------------------------------------------*/ - static int HasLineFeed(char *pText) - { - int i; - - for(i = strlen(pText); i > 0; i--) - { - if(pText[i] == '\n') - { - return 1; - } - if(isalpha(pText[i])) - { - return 0; - } - } - return 1; - } + argtolower(argc, argv); -static const char* timestamp(struct timeval *tp) { - static char ts[80]; - int year, month, day; - int hour, min, sec, usec; - struct timeval tv; - struct tm *time; - if (tp) - tv = *tp; - else - gettimeofday(&tv, NULL); - time = localtime(&tv.tv_sec); - year = 1900 + time->tm_year; - month = time->tm_mon + 1; - day = time->tm_mday; - hour = time->tm_hour; - min = time->tm_min; - sec = time->tm_sec; - usec = (int) tv.tv_usec; - snprintf(ts, 80, "%04d-%02d-%02dT%02d:%02d:%02d.%06d", - year, month, day, hour, min, sec, usec); - return ts; + /* Branch according to argv[1] */ + if (strcmp(argv[1], "kill") == 0) { + KillCapture(pCon); + return 1; + } else if (strcmp(argv[1], "all") == 0) { + pNew = (pCaptureEntry) malloc(sizeof(CaptureEntry)); + if (!pNew) { + SICSLogWrite("Out of memory in LogCapture", eInternal); + return 0; + } + if (pCapture) { + pCapture->pPrevious = pNew; + } + pNew->pPrevious = NULL; + pNew->pNext = pCapture; + pCapture = pNew; + pNew->iAllFlag = 1; + pNew->pCon = pCon; + return 1; + } else { + /* must be outcode, try find it */ + i = 0; + while (pCode[i] != NULL) { + if (strcmp(argv[1], pCode[i]) == 0) { + break; + } + i++; + } + if (i > iNoCodes) { + snprintf(pBueffel,sizeof(pBueffel)-1, "OutPutCode %s not recognized in %s", argv[1], + argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + /* create a new one */ + pNew = (pCaptureEntry) malloc(sizeof(CaptureEntry)); + if (!pNew) { + SICSLogWrite("Out of memory in LogCapture", eInternal); + return 0; + } + if (pCapture) { + pCapture->pPrevious = pNew; + } + pNew->pPrevious = NULL; + pNew->pNext = pCapture; + pCapture = pNew; + pNew->iAllFlag = 0; + pNew->pCon = pCon; + pNew->iOut = i; + return 1; + } + return 0; } +/*--------------------------------------------------------------------------*/ +static int HasLineFeed(char *pText) +{ + int i; -/*---------------------------------------------------------------------------*/ -#define MAXLOG 100000 -#define MAXFILES 100 - - static FILE *fLogFile = NULL; - static int iFile = -1; - static int iLineCount = 0; - static int iLogUsable = 1; - -/*---------------------------------------------------------------------------*/ - int OpenVerifyLogFile() - { - char pFile[256]; - char filnam[512]; - char *pChar = NULL; - char fPath[1024]; - -/* snprintf(fPath, 1023, "%s/", getenv("SICS_INIT_LOGPATH")); */ -snprintf(fPath, 1023, "%s/", "../log"); - - pChar = IFindOption(pSICSOptions,"LogFileBaseName"); - if(!pChar) - { /* Try to write to file "server" in*/ - strcpy(pFile,"server"); + for (i = strlen(pText); i > 0; i--) { + if (pText[i] == '\n') { + return 1; } - else - { - strncpy(pFile,pChar,255); - } - - // Jing added here to add timestamp info for the server00.log file name as server00_hh:mm:sec-daymonyear.log - int hh, mm, ss, day, mon, year; - struct timeval tv; - struct tm *time; - - gettimeofday(&tv, NULL); - time = localtime(&tv.tv_sec); - hh = time->tm_hour; - mm = time->tm_min; - ss = time->tm_sec; - day = time->tm_mday; - mon = time->tm_mon+1; - year = time->tm_year + 1900; - - if(iFile==-1){ - snprintf(filnam,511,"%s%s_%04d-%02d-%02dT%02d:%02d:%02d.000.log", fPath, pFile, year, mon, day, hh, mm, ss); - iFile = 0; - }else - snprintf(filnam,511,"%s%s_%04d-%02d-%02dT%02d:%02d:%02d.%2.2d.log", fPath, pFile, year, mon, day, hh, mm, ss, iFile); - - fLogFile = fopen(filnam,"w"); - if(!fLogFile) - { - fprintf(stderr,"ERROR: Cannot open logfile %s for writing\n",pFile); - fLogFile = NULL; - return 0; - } - else - { - return 1; + if (isalpha(pText[i])) { + return 0; } } - + return 1; +} + /*---------------------------------------------------------------------------*/ - void SICSLogEnable(int flag) { - iLogUsable=flag; +#define MAXLOG 10000 +#define MAXFILES 20 + +static FILE *fLogFile = NULL; +static int iFile = 0; +static int iLineCount = 0; +static int iLogUsable = 1; + +/*---------------------------------------------------------------------------*/ +int OpenVerifyLogFile() +{ + char pFile[256]; + char filnam[512]; + char *pChar = NULL; + + pChar = IFindOption(pSICSOptions, "LogFileBaseName"); + if (!pChar) { /* Try to write to file "server" in */ + strcpy(pFile, "server"); + } else { + strlcpy(pFile, pChar, 255); } + snprintf(filnam, 511, "%s%2.2d.log", pFile, iFile); + fLogFile = fopen(filnam, "w"); + if (!fLogFile) { + fprintf(stderr, "ERROR: Cannot open logfile %s for writing\n", pFile); + fLogFile = NULL; + return 0; + } else { + return 1; + } +} + /*---------------------------------------------------------------------------*/ - static void SICSLogWriteFile(char *pText, OutCode eOut, struct timeval *tp) - { - pCaptureEntry pCurrent; - int text_len; +void SICSLogEnable(int flag) +{ + iLogUsable = flag; +} + +/*---------------------------------------------------------------------------*/ +void SICSLogWrite(char *pText, OutCode eOut) +{ + char pFile[256]; + char *pChar = NULL; + pCaptureEntry pCurrent; + char pBueffel[256]; #ifdef NOLOG - return ; -#endif - - text_len = strlen(pText); - /* do all captured */ - pCurrent = pCapture; - while(pCurrent) - { - if( (pCurrent->iOut == eOut) || (pCurrent->iAllFlag == 1) ) - { - NETWrite(pCurrent->pCon->pSock,pText,strlen(pText)); - if (pText[text_len - 1] != '\n') - NETWrite(pCurrent->pCon->pSock, "\n", 1); - } - pCurrent = pCurrent->pNext; - } - - if(0 == iLogUsable) return; - - if(fLogFile == NULL) /* first time of use*/ - { - /* no options: startup or serious trouble, print to stdout*/ - if(!pSICSOptions) - { - printf("WARNING: Cannot log(%s)\n",pText); - return; - } - iLogUsable = OpenVerifyLogFile(); - } - - /* switch file if too many lines */ - if(iLineCount >= MAXLOG) - { - fprintf(fLogFile,"%s: <<>>\n", timestamp(NULL)); - fclose(fLogFile); - fLogFile = NULL; - iFile++; - iLineCount = 0; - if(iFile >= MAXFILES) - { - iFile = 0; - } - iLogUsable = OpenVerifyLogFile(); - } - - if(1 == iLogUsable) - { - - if (iLineCount == 0) - fprintf(fLogFile,"%s: <<>>\n", timestamp(NULL)); - fprintf(fLogFile,"%s: ", timestamp(tp)); - fprintf(fLogFile,"%s", pText); - if (text_len < 1 || pText[text_len - 1] != '\n') - fprintf(fLogFile,"\n"); - fflush(fLogFile); - iLineCount++; - -#if 0 /* Already done above */ - /* do all captured as well */ - pCurrent = pCapture; - while(pCurrent) - { - if( (pCurrent->iOut == eOut) || (pCurrent->iAllFlag == 1) ) - { - NETWrite(pCurrent->pCon->pSock,pText,strlen(pText)); - if (pText[text_len - 1] != '\n') - NETWrite(pCurrent->pCon->pSock, "\n", 1); - } - pCurrent = pCurrent->pNext; - } + return; #endif + + /* do all captured */ + pCurrent = pCapture; + while (pCurrent) { + if ((pCurrent->iOut == eOut) || (pCurrent->iAllFlag == 1)) { + ANETwrite(pCurrent->pCon->sockHandle, pText, strlen(pText)); + ANETwrite(pCurrent->pCon->sockHandle, "\n", 1); } + pCurrent = pCurrent->pNext; } - void SICSLogWriteTime(char *pText, OutCode eOut, struct timeval *tp) { - char buf[200]; - const char *cp = pText; - int idx = 0; - struct timeval tv; - - if (tp == NULL) { - gettimeofday(&tv, NULL); - tp = &tv; - } - while (*cp) { - if (*cp == '\n') { - buf[idx++] = '\n'; - buf[idx++] = '\0'; - SICSLogWriteFile(buf, eOut, tp); - idx = 0; - } - else if (*cp == '\r') { - buf[idx++] = '\\'; - buf[idx++] = 'r'; - } - else if (*cp == '\t') { - buf[idx++] = '\\'; - buf[idx++] = 't'; - } - else if (*cp < ' ' || *cp > '~') { - const char hex[] = "0123456789ABCDEF"; - buf[idx++] = '<'; - buf[idx++] = hex[(*cp >> 4) & 0xF]; - buf[idx++] = hex[(*cp) & 0xF]; - buf[idx++] = '>'; - } - else { - buf[idx++] = *cp; - } - cp++; - if (idx > 132) { - buf[idx++] = '\n'; - buf[idx++] = '\0'; - SICSLogWriteFile(buf, eOut, tp); - idx = 0; - } - } - if (idx > 0) { - buf[idx++] = '\n'; - buf[idx++] = '\0'; - SICSLogWriteFile(buf, eOut, tp); - } - } - - void SICSLogWrite(char *pText, OutCode eOut) { - struct timeval tv; - gettimeofday(&tv, NULL); - SICSLogWriteTime(pText, eOut, &tv); - } - - void SICSLogWriteHexTime(const char* text, int count, OutCode eOut, struct timeval *tp) { - const char hex[] = "0123456789ABCDEF"; - char addr[20], left[80], right[80]; - char *lp = left; - char *rp = right; - int i; - int duplicates; - /* Limit the output */ - if (count > 1024) - count = 1024; - duplicates = 0; - for (i = 0; i < count; ++i) { - if ((i & 0xF) == 0) { - if (i > 0) { - char line[132]; - snprintf(line, sizeof(line)-1, "%-6s: %-49s | %-17s |", addr, left, right); - SICSLogWriteTime(line, eOut, tp); - } - snprintf(addr, sizeof(addr)-1, "0x%04X", i); - while (i >= 16 && i + 16 < count) { - if (memcmp(&text[i-16], &text[i], 16) != 0) - break; - ++duplicates; - i += 16; - } - if (duplicates > 0) { - if (duplicates > 1) { - char line[132]; - snprintf(line, sizeof(line)-1, "%-6s: ... (%d duplicates)", addr, duplicates); - SICSLogWriteTime(line, eOut, tp); - } - else { - char line[132]; - snprintf(line, sizeof(line)-1, "%-6s: %-49s | %-17s |", addr, left, right); - SICSLogWriteTime(line, eOut, tp); - } - duplicates = 0; - } - snprintf(addr, sizeof(addr)-1, "0x%04X", i); - lp = left; - rp = right; - } - *lp++ = hex[(text[i] >> 4) & 0xF]; - *lp++ = hex[(text[i]) & 0xF]; - *lp++ = ' '; - if (text[i]>= ' ' && text[i] <= '~') - *rp++ = text[i]; - else - *rp++ = '.'; - /* if we just did slot 7, insert an extra space */ - if ((i & 0xF) == 7) { - *lp++ = ' '; - *rp++ = ' '; - } - *lp = *rp = '\0'; - } - if (i > 0) { - char line[132]; - snprintf(line, sizeof(line)-1, "%-6s: %-49s | %-17s |", addr, left, right); - SICSLogWriteTime(line, eOut, tp); - } - } - - void SICSLogWriteHex(const char* text, int count, OutCode eOut) { - struct timeval tv; - gettimeofday(&tv, NULL); - SICSLogWriteHexTime(text, count, eOut, &tv); - } - - void SICSLogTimePrintf(OutCode eOut, struct timeval *tp, const char *fmt, ...) - { - va_list ap; - char buf[256]; - char *dyn; - unsigned 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); - vsnprintf(dyn, l+1, fmt, ap); - va_end(ap); - SICSLogWriteTime(dyn, eOut, tp); - free(dyn); - return; - } - } - SICSLogWriteTime(buf, eOut, tp); + if (0 == iLogUsable) return; - } - void SICSLogPrintf(OutCode eOut, const char *fmt, ...) - { - va_list ap; - char buf[256]; - char *dyn; - unsigned 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); - vsnprintf(dyn, l+1, fmt, ap); - va_end(ap); - SICSLogWrite(dyn, eOut); - free(dyn); - return; - } + if (fLogFile == NULL) { /* first time of use */ + /* no options: startup or serious trouble, print to stdout */ + if (!pSICSOptions) { + printf("WARNING: Cannot log(%s)\n", pText); + return; } - SICSLogWrite(buf, eOut); - return; + iLogUsable = OpenVerifyLogFile(); } -/* Test of the logging facilities */ -int testLogCmd(SConnection *pCon, SicsInterp *pInter, void *pData, int argc, char *argv[]) { - char lbuf[2048]; - char sbuf[1000]; - int i; - SICSLogWrite("Multiline:\nLine 1\r\nLine 2\r\nLine 3\r\n", eStatus); - memset(lbuf, 0, sizeof(lbuf)); - memset(sbuf, ' ', sizeof(sbuf)); - SICSLogPrintf(eStatus, "Hexlog %d all zero bytes", sizeof(lbuf)); - SICSLogWriteHex(lbuf, sizeof(lbuf), eStatus); - for (i = 0; i <= 128; ++i) - sbuf[i] = sbuf[sizeof(sbuf)-1 - i] = i; - sbuf[sizeof(sbuf)/2] = '!'; - SICSLogPrintf(eStatus, "Hexlog %d mid space bytes", sizeof(sbuf)); - SICSLogWriteHex(sbuf, sizeof(sbuf), eStatus); - for (i = 0; i < 1000; ++i) - sbuf[i] = ' ' + (i % 96); - sbuf[sizeof(sbuf)-1] = '\0'; - SICSLogWrite("Very long line 1000 bytes", eStatus); - SICSLogWrite(sbuf, eStatus); - SCSendOK(pCon); - return OKOK; + /* switch file if too many lines */ + if (iLineCount >= MAXLOG) { + fclose(fLogFile); + fLogFile = NULL; + iFile++; + iLineCount = 0; + if (iFile >= MAXFILES) { + iFile = 0; + } + iLogUsable = OpenVerifyLogFile(); + } + + if (1 == iLogUsable) { + fprintf(fLogFile, "%s\n", pText); + fflush(fLogFile); + iLineCount++; + } } - - diff --git a/servlog.h b/servlog.h index 00f4bca4..c61615f5 100644 --- a/servlog.h +++ b/servlog.h @@ -15,15 +15,10 @@ #ifndef SICSLOG #define SICSLOG #include "Scommon.h" - void SICSLogWrite(char *ptext, OutCode eOut ); - void SICSLogWriteTime(char *ptext, OutCode eOut, struct timeval *tp ); - void SICSLogWriteHex(const char* text, int count, OutCode eOut); - void SICSLogWriteHexTime(const char* text, int count, OutCode eOut, struct timeval *tp); - void SICSLogPrintf(OutCode eOut, const char*fmt, ...); - void SICSLogTimePrintf(OutCode eOut, struct timeval *tp, const char *fmt, ...); - void SICSLogEnable(int flag); - int KillCapture(SConnection *pCon); - - int LogCapture(SConnection *pCon, SicsInterp *pInter, void *pData, - int argc, char *argv[]); +void SICSLogWrite(char *ptext, OutCode eOut); +void SICSLogEnable(int flag); +int KillCapture(SConnection * pCon); + +int LogCapture(SConnection * pCon, SicsInterp * pInter, void *pData, + int argc, char *argv[]); #endif diff --git a/sgclib.c b/sgclib.c new file mode 100644 index 00000000..7be51869 --- /dev/null +++ b/sgclib.c @@ -0,0 +1,2664 @@ +/* + Space Group Info's (c) 1994-96 Ralf W. Grosse-Kunstleve + */ + +#include +#include +#include + + +#define SGCLIB_C__ +#include "sginfo.h" + + +static const char *Err_Ill_SMx_in_List = "Error: Illegal SeitzMx in list"; + + +void SetSgError(const char *msg) +{ + if (SgError == NULL) + SgError = msg; +} + + +int iModPositive(int ix, int iy) +{ + if (iy > 0) { + ix %= iy; + if (ix < 0) + ix += iy; + } + + return ix; +} + + +static void SwapRTMx(T_RTMx * Mx_a, T_RTMx * Mx_b) +{ + int i; + T_RTMx BufMx; + + + for (i = 0; i < 12; i++) + BufMx.a[i] = Mx_a->a[i]; + for (i = 0; i < 12; i++) + Mx_a->a[i] = Mx_b->a[i]; + for (i = 0; i < 12; i++) + Mx_b->a[i] = BufMx.a[i]; +} + + +static void CopyRotMxInfo(T_RotMxInfo * target, const T_RotMxInfo * source) +{ + memcpy(target, source, sizeof(*target)); +} + + +static void SwapRotMxInfo(T_RotMxInfo * RMx_a, T_RotMxInfo * RMx_b) +{ + T_RotMxInfo Buffer; + + memcpy(&Buffer, RMx_a, sizeof(Buffer)); + memcpy(RMx_a, RMx_b, sizeof(Buffer)); + memcpy(RMx_b, &Buffer, sizeof(Buffer)); +} + + +int traceRotMx(const int *RotMx) +{ + return RotMx[0] + RotMx[4] + RotMx[8]; +} + + +int deterRotMx(const int *RotMx) +{ + int det; + + det = RotMx[0] * (RotMx[4] * RotMx[8] - RotMx[5] * RotMx[7]); + det -= RotMx[1] * (RotMx[3] * RotMx[8] - RotMx[5] * RotMx[6]); + det += RotMx[2] * (RotMx[3] * RotMx[7] - RotMx[4] * RotMx[6]); + + return det; +} + + +void RotMx_t_Vector(int *R_t_V, const int *RotMx, const int *Vector, + int FacTr) +{ + const int *vec; + + + if (FacTr > 0) { + vec = Vector; + *R_t_V = *RotMx++ * *vec++; + *R_t_V += *RotMx++ * *vec++; + *R_t_V += *RotMx++ * *vec; + *R_t_V %= FacTr; + if (*R_t_V < 0) + *R_t_V += FacTr; + R_t_V++; + vec = Vector; + *R_t_V = *RotMx++ * *vec++; + *R_t_V += *RotMx++ * *vec++; + *R_t_V += *RotMx++ * *vec; + *R_t_V %= FacTr; + if (*R_t_V < 0) + *R_t_V += FacTr; + R_t_V++; + vec = Vector; + *R_t_V = *RotMx++ * *vec++; + *R_t_V += *RotMx++ * *vec++; + *R_t_V += *RotMx * *vec; + *R_t_V %= FacTr; + if (*R_t_V < 0) + *R_t_V += FacTr; + } else { + vec = Vector; + *R_t_V = *RotMx++ * *vec++; + *R_t_V += *RotMx++ * *vec++; + *R_t_V++ += *RotMx++ * *vec; + vec = Vector; + *R_t_V = *RotMx++ * *vec++; + *R_t_V += *RotMx++ * *vec++; + *R_t_V++ += *RotMx++ * *vec; + vec = Vector; + *R_t_V = *RotMx++ * *vec++; + *R_t_V += *RotMx++ * *vec++; + *R_t_V += *RotMx * *vec; + } +} + + +void RotMxMultiply(int *rmxab, const int *rmxa, const int *rmxb) +{ + const int *a, *b; + + /* no loops to be as fast as posslible */ + + a = rmxa; + b = rmxb; + *rmxab = *a++ * *b; + b += 3; /* r11 */ + *rmxab += *a++ * *b; + b += 3; + *rmxab += *a * *b; + b -= 5; + rmxab++; + + a = rmxa; + *rmxab = *a++ * *b; + b += 3; /* r12 */ + *rmxab += *a++ * *b; + b += 3; + *rmxab += *a * *b; + b -= 5; + rmxab++; + + a = rmxa; + *rmxab = *a++ * *b; + b += 3; /* r13 */ + *rmxab += *a++ * *b; + b += 3; + *rmxab += *a++ * *b; + b = rmxb; + rmxab++; + + rmxa = a; + *rmxab = *a++ * *b; + b += 3; /* r21 */ + *rmxab += *a++ * *b; + b += 3; + *rmxab += *a * *b; + b -= 5; + rmxab++; + + a = rmxa; + *rmxab = *a++ * *b; + b += 3; /* r22 */ + *rmxab += *a++ * *b; + b += 3; + *rmxab += *a * *b; + b -= 5; + rmxab++; + + a = rmxa; + *rmxab = *a++ * *b; + b += 3; /* r23 */ + *rmxab += *a++ * *b; + b += 3; + *rmxab += *a++ * *b; + b = rmxb; + rmxab++; + + rmxa = a; + *rmxab = *a++ * *b; + b += 3; /* r31 */ + *rmxab += *a++ * *b; + b += 3; + *rmxab += *a * *b; + b -= 5; + rmxab++; + + a = rmxa; + *rmxab = *a++ * *b; + b += 3; /* r32 */ + *rmxab += *a++ * *b; + b += 3; + *rmxab += *a * *b; + b -= 5; + rmxab++; + + a = rmxa; + *rmxab = *a++ * *b; + b += 3; /* r33 */ + *rmxab += *a++ * *b; + b += 3; + *rmxab += *a * *b; +} + + +void RotateRotMx(int *RotMx, const int *RMx, const int *InvRMx) +{ + int BufMx[9]; + + + RotMxMultiply(BufMx, RotMx, InvRMx); + RotMxMultiply(RotMx, RMx, BufMx); +} + + +void SeitzMxMultiply(T_RTMx * smxab, const T_RTMx * smxa, + const T_RTMx * smxb) +{ + const int *ar, *a, *b, *bt; + int *ab; + + /* no loops to be as fast as posslible */ + + ar = smxa->a; + a = smxa->a; + b = smxb->a; + ab = smxab->a; + + *ab = *a++ * *b; + b += 3; /* r11 */ + *ab += *a++ * *b; + b += 3; + *ab += *a * *b; + b -= 5; + ab++; + + a = ar; + *ab = *a++ * *b; + b += 3; /* r12 */ + *ab += *a++ * *b; + b += 3; + *ab += *a * *b; + b -= 5; + ab++; + + a = ar; + *ab = *a++ * *b; + b += 3; /* r13 */ + *ab += *a++ * *b; + b += 3; + *ab += *a++ * *b; + b = smxb->a; + ab++; + + ar = a; + *ab = *a++ * *b; + b += 3; /* r21 */ + *ab += *a++ * *b; + b += 3; + *ab += *a * *b; + b -= 5; + ab++; + + a = ar; + *ab = *a++ * *b; + b += 3; /* r22 */ + *ab += *a++ * *b; + b += 3; + *ab += *a * *b; + b -= 5; + ab++; + + a = ar; + *ab = *a++ * *b; + b += 3; /* r23 */ + *ab += *a++ * *b; + b += 3; + *ab += *a++ * *b; + b = smxb->a; + ab++; + + ar = a; + *ab = *a++ * *b; + b += 3; /* r31 */ + *ab += *a++ * *b; + b += 3; + *ab += *a * *b; + b -= 5; + ab++; + + a = ar; + *ab = *a++ * *b; + b += 3; /* r32 */ + *ab += *a++ * *b; + b += 3; + *ab += *a * *b; + b -= 5; + ab++; + + a = ar; + *ab = *a++ * *b; + b += 3; /* r33 */ + *ab += *a++ * *b; + b += 3; + *ab += *a++ * *b++; + bt = b; + ab++; + + ar = smxa->a; + *ab = *ar++ * *b++; /* t1 */ + *ab += *ar++ * *b++; + *ab += *ar++ * *b; + b = bt; + *ab += *a++; + *ab %= STBF; + if (*ab < 0) + *ab += STBF; + ab++; + + *ab = *ar++ * *b++; /* t2 */ + *ab += *ar++ * *b++; + *ab += *ar++ * *b; + b = bt; + *ab += *a++; + *ab %= STBF; + if (*ab < 0) + *ab += STBF; + ab++; + + *ab = *ar++ * *b++; /* t3 */ + *ab += *ar++ * *b++; + *ab += *ar * *b; + *ab += *a; + *ab %= STBF; + if (*ab < 0) + *ab += STBF; +} + + +void RTMxMultiply(T_RTMx * rtmxab, const T_RTMx * rtmxa, + const T_RTMx * rtmxb, int FacAug, int FacTr) +{ + const int *ar, *a, *b, *bt; + int *ab; + + /* no loops to be as fast as posslible */ + + ar = rtmxa->a; + a = rtmxa->a; + b = rtmxb->a; + ab = rtmxab->a; + + *ab = *a++ * *b; + b += 3; /* r11 */ + *ab += *a++ * *b; + b += 3; + *ab += *a * *b; + b -= 5; + ab++; + + a = ar; + *ab = *a++ * *b; + b += 3; /* r12 */ + *ab += *a++ * *b; + b += 3; + *ab += *a * *b; + b -= 5; + ab++; + + a = ar; + *ab = *a++ * *b; + b += 3; /* r13 */ + *ab += *a++ * *b; + b += 3; + *ab += *a++ * *b; + b = rtmxb->a; + ab++; + + ar = a; + *ab = *a++ * *b; + b += 3; /* r21 */ + *ab += *a++ * *b; + b += 3; + *ab += *a * *b; + b -= 5; + ab++; + + a = ar; + *ab = *a++ * *b; + b += 3; /* r22 */ + *ab += *a++ * *b; + b += 3; + *ab += *a * *b; + b -= 5; + ab++; + + a = ar; + *ab = *a++ * *b; + b += 3; /* r23 */ + *ab += *a++ * *b; + b += 3; + *ab += *a++ * *b; + b = rtmxb->a; + ab++; + + ar = a; + *ab = *a++ * *b; + b += 3; /* r31 */ + *ab += *a++ * *b; + b += 3; + *ab += *a * *b; + b -= 5; + ab++; + + a = ar; + *ab = *a++ * *b; + b += 3; /* r32 */ + *ab += *a++ * *b; + b += 3; + *ab += *a * *b; + b -= 5; + ab++; + + a = ar; + *ab = *a++ * *b; + b += 3; /* r33 */ + *ab += *a++ * *b; + b += 3; + *ab += *a++ * *b++; + bt = b; + ab++; + + if (FacTr > 0) { + ar = rtmxa->a; + *ab = *ar++ * *b++; /* t1 */ + *ab += *ar++ * *b++; + *ab += *ar++ * *b; + b = bt; + *ab += *a++ * FacAug; + *ab %= FacTr; + if (*ab < 0) + *ab += FacTr; + ab++; + + *ab = *ar++ * *b++; /* t2 */ + *ab += *ar++ * *b++; + *ab += *ar++ * *b; + b = bt; + *ab += *a++ * FacAug; + *ab %= FacTr; + if (*ab < 0) + *ab += FacTr; + ab++; + + *ab = *ar++ * *b++; /* t3 */ + *ab += *ar++ * *b++; + *ab += *ar * *b; + *ab += *a * FacAug; + *ab %= FacTr; + if (*ab < 0) + *ab += FacTr; + } else { + ar = rtmxa->a; + *ab = *ar++ * *b++; /* t1 */ + *ab += *ar++ * *b++; + *ab += *ar++ * *b; + b = bt; + *ab += *a++ * FacAug; + ab++; + + *ab = *ar++ * *b++; /* t2 */ + *ab += *ar++ * *b++; + *ab += *ar++ * *b; + b = bt; + *ab += *a++ * FacAug; + ab++; + + *ab = *ar++ * *b++; /* t3 */ + *ab += *ar++ * *b++; + *ab += *ar * *b; + *ab += *a * FacAug; + } +} + + +void InverseRotMx(const int *RotMx, int *InvRotMx) +{ + InvRotMx[0] = RotMx[4] * RotMx[8] - RotMx[5] * RotMx[7]; + InvRotMx[1] = -RotMx[1] * RotMx[8] + RotMx[2] * RotMx[7]; + InvRotMx[2] = RotMx[1] * RotMx[5] - RotMx[2] * RotMx[4]; + InvRotMx[3] = -RotMx[3] * RotMx[8] + RotMx[5] * RotMx[6]; + InvRotMx[4] = RotMx[0] * RotMx[8] - RotMx[2] * RotMx[6]; + InvRotMx[5] = -RotMx[0] * RotMx[5] + RotMx[2] * RotMx[3]; + InvRotMx[6] = RotMx[3] * RotMx[7] - RotMx[4] * RotMx[6]; + InvRotMx[7] = -RotMx[0] * RotMx[7] + RotMx[1] * RotMx[6]; + InvRotMx[8] = RotMx[0] * RotMx[4] - RotMx[1] * RotMx[3]; +} + + +void InverseRTMx(const T_RTMx * RTMx, T_RTMx * InvRTMx) +{ + int *iR; + const int *T; + + + iR = InvRTMx->s.R; + + InverseRotMx(RTMx->s.R, iR); + + T = RTMx->s.T; + + InvRTMx->s.T[0] = -iR[0] * T[0] - iR[1] * T[1] - iR[2] * T[2]; + InvRTMx->s.T[1] = -iR[3] * T[0] - iR[4] * T[1] - iR[5] * T[2]; + InvRTMx->s.T[2] = -iR[6] * T[0] - iR[7] * T[1] - iR[8] * T[2]; +} + + +int IsSMxTransl0(const T_LatticeInfo * LatticeInfo, const int *SeitzMxT) +{ + int iTrV, nTrV, t; + const int *TrV; + + + nTrV = LatticeInfo->nTrVector; + TrV = LatticeInfo->TrVector; + + for (iTrV = 0; iTrV < nTrV; iTrV++) { + t = (SeitzMxT[0] + TrV[0]) % STBF; + if (t == 0) { + t = (SeitzMxT[1] + TrV[1]) % STBF; + if (t == 0) { + t = (SeitzMxT[2] + TrV[2]) % STBF; + if (t == 0) + return 1; + } + } + + TrV += 3; + } + + return 0; +} + + +static int IsSpecialSeitzMx(T_SgInfo * SgInfo, const T_RTMx * SMx, + int ExpandLT) +{ + int i, special, smx11; + const T_LatticeInfo *ExpLT; + + + /* check rotation part for identity or inversion operation */ + + smx11 = SMx->s.R[0]; + if (smx11 != 1 && smx11 != -1) + return 0; + + for (i = 1; i < 9; i++) { + if (i % 4) { + if (SMx->s.R[i] != 0) + return 0; + } else { + if (SMx->s.R[i] != smx11) + return 0; + } + } + + if (smx11 == 1) + special = SpecialSMx_Identity; + else + special = SpecialSMx_Inversion; + + /* rotation part is identity or inversion + check translation part now + */ + + if (IsSMxTransl0(SgInfo->LatticeInfo, SMx->s.T) == 1) + return (special | SpecialSMx_Transl0); + + if (ExpandLT && (smx11 == 1 || SgInfo->Centric)) { + /* try to expand lattice type */ + + ExpLT = NULL; + + switch (SgInfo->LatticeInfo->Code) { + case 'P': + if (IsSMxTransl0(LI_A, SMx->s.T) == 1) { + ExpLT = LI_A; + break; + } + if (IsSMxTransl0(LI_B, SMx->s.T) == 1) { + ExpLT = LI_B; + break; + } + if (IsSMxTransl0(LI_C, SMx->s.T) == 1) { + ExpLT = LI_C; + break; + } + if (IsSMxTransl0(LI_I, SMx->s.T) == 1) { + ExpLT = LI_I; + break; + } + if (IsSMxTransl0(LI_R, SMx->s.T) == 1) { + ExpLT = LI_R; + break; + } + if (IsSMxTransl0(LI_S, SMx->s.T) == 1) { + ExpLT = LI_S; + break; + } + if (IsSMxTransl0(LI_T, SMx->s.T) == 1) { + ExpLT = LI_T; + break; + } + case 'A': + case 'B': + case 'C': + if (IsSMxTransl0(LI_F, SMx->s.T) == 1) + ExpLT = LI_F; + } + + if (ExpLT != NULL) { + SgInfo->LatticeInfo = ExpLT; + SgInfo->StatusLatticeTr = -1; + return (special | SpecialSMx_Transl0); + } + } + + return special; +} + + +int CompareSeitzMx(const T_LatticeInfo * LatticeInfo, + const T_RTMx * SeitzMxA, const T_RTMx * SeitzMxB) +{ + int i, iTrV, nTrV, t; + const int *TrV; + + + /* compare rotation part */ + + for (i = 0; i < 9; i++) + if (SeitzMxA->s.R[i] != SeitzMxB->s.R[i]) + return 1; + + /* rotation part is same + check translation + */ + + nTrV = LatticeInfo->nTrVector; + TrV = LatticeInfo->TrVector; + + for (iTrV = 0; iTrV < nTrV; iTrV++, TrV += 3) { + t = (SeitzMxA->s.T[0] + TrV[0]) % STBF; + if (t == SeitzMxB->s.T[0]) { + t = (SeitzMxA->s.T[1] + TrV[1]) % STBF; + if (t == SeitzMxB->s.T[1]) { + t = (SeitzMxA->s.T[2] + TrV[2]) % STBF; + if (t == SeitzMxB->s.T[2]) + return 0; + } + } + } + + return -1; +} + + +int GetRotMxOrder(const int *RotMx) +{ + int deter = deterRotMx(RotMx); + + if (deter == -1 || deter == 1) { + switch (traceRotMx(RotMx)) { + case -3: + return -1; + case -2: + return -6; + case -1: + if (deter == -1) + return -4; + else + return 2; + case 0: + if (deter == -1) + return -3; + else + return 3; + case 1: + if (deter == -1) + return -2; + else + return 4; + case 2: + return 6; + case 3: + return 1; + } + } + + return 0; +} + + +static int nNextBasis_of_DirCode(const int DirCode, + const int **RMx, const int **InvRMx) +{ + switch (DirCode) { + case '.': + *RMx = *InvRMx = NULL; + return 1; + case '=': + case '"': + case '\'': + case '|': + case '\\': + *RMx = RMx_3_111; + *InvRMx = RMx_3i111; + return 3; + case '*': + *RMx = RMx_4_001; + *InvRMx = RMx_4i001; + return 4; + default: + break; + } + + SetSgError("Internal Error: Corrupt DirCode"); + return -1; +} + + +int GetRotMxInfo(const int *RotMx, T_RotMxInfo * RotMxInfo) +{ + int i; + int nNextBasis, iNextBasis; + int nLoopInv, iLoopInv; + int Order, AbsOrder; + int RMxCopy[9], MatchMx[9], InvMatchMx[9], REV[3]; + int *mmx; + const int *NBRMx, *InvNBRMx; + + const T_TabXtalRotMx *txrmx; + + + Order = GetRotMxOrder(RotMx); + + if (RotMxInfo) + RotMxInfo->Order = Order; + + if (Order) { + AbsOrder = abs(Order); + + if (Order > 0) + for (i = 0; i < 9; i++) + RMxCopy[i] = RotMx[i]; + else + for (i = 0; i < 9; i++) + RMxCopy[i] = -RotMx[i]; + + for (txrmx = TabXtalRotMx; txrmx->Order; txrmx++) + if (txrmx->Order == AbsOrder) + break; + + while (txrmx->Order == AbsOrder) { + nNextBasis = + nNextBasis_of_DirCode(txrmx->DirCode, &NBRMx, &InvNBRMx); + + if (nNextBasis < 0) + return 0; + + if (AbsOrder > 2) + nLoopInv = 2; + else + nLoopInv = 1; + + for (i = 0; i < 9; i++) + MatchMx[i] = txrmx->RMx[i]; + + for (iNextBasis = 0; iNextBasis < nNextBasis; iNextBasis++) { + if (iNextBasis) + RotateRotMx(MatchMx, NBRMx, InvNBRMx); + + mmx = MatchMx; + + for (iLoopInv = 0; iLoopInv < nLoopInv; iLoopInv++) { + if (iLoopInv) { + InverseRotMx(MatchMx, InvMatchMx); + mmx = InvMatchMx; + } + + for (i = 0; i < 9; i++) + if (mmx[i] != RMxCopy[i]) + break; + + if (i == 9) { /* matrix has been found */ + if (RotMxInfo) { + RotMxInfo->Inverse = iLoopInv; + + if (nNextBasis == 3) { + switch (iNextBasis) { + case 0: + RotMxInfo->RefAxis = 'z'; + break; + case 1: + RotMxInfo->RefAxis = 'x'; + break; + case 2: + RotMxInfo->RefAxis = 'y'; + break; + } + } else + RotMxInfo->RefAxis = 'o'; + + RotMxInfo->DirCode = txrmx->DirCode; + + for (i = 0; i < 3; i++) + RotMxInfo->EigenVector[i] = txrmx->EigenVector[i]; + + for (; iNextBasis--;) { + RotMx_t_Vector(REV, NBRMx, RotMxInfo->EigenVector, 0); + + if (iNextBasis-- == 0) { + for (i = 0; i < 3; i++) + RotMxInfo->EigenVector[i] = REV[i]; + + break; + } + + RotMx_t_Vector(RotMxInfo->EigenVector, NBRMx, REV, 0); + } + } + + return Order; + } + } + } + + txrmx++; + } + } + + return 0; +} + + +const T_RotMxInfo *ListOrBufRotMxInfo(const T_SgInfo * SgInfo, int iList, + T_RotMxInfo * BufRotMxInfo) +{ + T_RotMxInfo *RMxI; + + + RMxI = SgInfo->ListRotMxInfo; + if (RMxI) + RMxI += iList; + else { + RMxI = BufRotMxInfo; + + if (GetRotMxInfo(SgInfo->ListSeitzMx[iList].s.R, RMxI) == 0) { + SetSgError(Err_Ill_SMx_in_List); + return NULL; + } + } + + return RMxI; +} + + +static int CoreAdd2ListSeitzMx(T_SgInfo * SgInfo, const T_RTMx * NewSMx) +{ + int i, iList; + T_RTMx *lsmx; + T_RotMxInfo RotMxInfo; + const T_LatticeInfo *LI; + + static const char *Err_NonXtalOp = + "Error: Generators produce non-crystallographic operation"; + + + if (SgInfo->GenOption) + LI = SgInfo->LatticeInfo; + else + LI = LI_P; + + lsmx = SgInfo->ListSeitzMx; + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) + if (CompareSeitzMx(LI, NewSMx, lsmx) == 0) + return 0; /* matrix is not unique */ + + if (GetRotMxInfo(NewSMx->s.R, &RotMxInfo) == 0) { + SetSgError(Err_NonXtalOp); + return -1; + } + + if (SgInfo->nList >= SgInfo->MaxList) { + if (SgInfo->nList >= 192) + SetSgError(Err_NonXtalOp); + else + SetSgError + ("Internal Error: Allocated space for ListSeitzMx too small"); + + return -1; + } + + for (i = 0; i < 12; i++) + lsmx->a[i] = NewSMx->a[i]; + + if (SgInfo->ListRotMxInfo != NULL) + CopyRotMxInfo(&SgInfo->ListRotMxInfo[SgInfo->nList], &RotMxInfo); + + SgInfo->nList++; + + return 1; +} + + +int Add2ListSeitzMx(T_SgInfo * SgInfo, const T_RTMx * NewSMx) +{ + int i, special, Enter; + int iMult, jMult; + T_RTMx TrialSMx, *iMultSMx, *jMultSMx; + + static const char *Err_Ill_lattice_translation = + "Error: Illegal lattice translation"; + + + if (SgInfo->nList == 0) { + /* make sure identity matrix is first in list */ + + InitSeitzMx(&TrialSMx, 1); + + if (CoreAdd2ListSeitzMx(SgInfo, &TrialSMx) < 0) + return -1;; + } + + for (i = 0; i < 9; i++) + TrialSMx.s.R[i] = NewSMx->s.R[i]; + + for (i = 0; i < 3; i++) { + TrialSMx.s.T[i] = NewSMx->s.T[i] % STBF; + if (TrialSMx.s.T[i] < 0) + TrialSMx.s.T[i] += STBF; + } + + iMult = SgInfo->nList; + iMultSMx = &SgInfo->ListSeitzMx[iMult]; + + jMult = 1; + jMultSMx = &SgInfo->ListSeitzMx[1]; /* skip first = identity matrix */ + + for (;;) { + Enter = 1; + + special = IsSpecialSeitzMx(SgInfo, &TrialSMx, 1); + + if (special & SpecialSMx_Identity) { + if (!(special & SpecialSMx_Transl0)) { + SetSgError(Err_Ill_lattice_translation); + return -1; + } + + if (SgInfo->GenOption) + Enter = 0; + } else if (special & SpecialSMx_Inversion) { + if (!(special & SpecialSMx_Transl0)) { + if (SgInfo->Centric) { + SetSgError(Err_Ill_lattice_translation); + return -1; + } + + SgInfo->InversionOffOrigin = 1; + } else { + if (SgInfo->InversionOffOrigin) + SgInfo->Centric = 1; + + SgInfo->InversionOffOrigin = 0; + + if (SgInfo->GenOption) { + if (SgInfo->Centric == 0) + SgInfo->Centric = -1; + + Enter = 0; + } else + SgInfo->Centric = 1; + } + } + + if (Enter && CoreAdd2ListSeitzMx(SgInfo, &TrialSMx) < 0) + return -1; + + if (SgInfo->GenOption < 0) + break; + + if (jMult > iMult) { + iMult++; + iMultSMx++; + + jMult = 1; + jMultSMx = &SgInfo->ListSeitzMx[1]; /* skip first = identity matrix */ + } + + if (iMult == SgInfo->nList) + break; + + SeitzMxMultiply(&TrialSMx, jMultSMx, iMultSMx); + + jMult++; + jMultSMx++; + } + + return 0; +} + + +int AddInversion2ListSeitzMx(T_SgInfo * SgInfo) +{ + T_RTMx SeitzMx; + + InitSeitzMx(&SeitzMx, -1); + return Add2ListSeitzMx(SgInfo, &SeitzMx); +} + + +int AddLatticeTr2ListSeitzMx(T_SgInfo * SgInfo, + const T_LatticeInfo * LatticeInfo) +{ + int iTrV, nTrV; + const int *TrV; + T_RTMx SeitzMx; + + + InitRotMx(SeitzMx.s.R, 1); + + nTrV = LatticeInfo->nTrVector; + TrV = &LatticeInfo->TrVector[3]; /* skip first vector which is always 000 */ + + for (iTrV = 1; iTrV < nTrV; iTrV++) { + SeitzMx.s.T[0] = *TrV++; + SeitzMx.s.T[1] = *TrV++; + SeitzMx.s.T[2] = *TrV++; + + if (Add2ListSeitzMx(SgInfo, &SeitzMx) < 0) + return -1; + } + + if (SgInfo->GenOption) + SgInfo->StatusLatticeTr = 0; + else + SgInfo->StatusLatticeTr = 1; + + return 0; +} + + +static int RemoveLatticeTr(T_SgInfo * SgInfo) +{ + int iList, jList, i; + T_RTMx *smxi, *smxj, *lastsmx; + T_RotMxInfo *lrmxi, *lastrmxi; + + + if (SgInfo->LatticeInfo->Code == 'P') + return 0; + + if (SgInfo->StatusLatticeTr == -1) { + if (AddLatticeTr2ListSeitzMx(SgInfo, SgInfo->LatticeInfo) < 0) + return -1; + } + + iList = 0; + + while (iList < SgInfo->nList) { + smxi = &SgInfo->ListSeitzMx[iList]; + jList = iList + 1; + + while (jList < SgInfo->nList) { + smxj = &SgInfo->ListSeitzMx[jList]; + + if (CompareSeitzMx(SgInfo->LatticeInfo, smxi, smxj) == 0) { + /* copy last element to this place */ + + SgInfo->nList--; + lastsmx = &SgInfo->ListSeitzMx[SgInfo->nList]; + for (i = 0; i < 12; i++) + smxj->a[i] = lastsmx->a[i]; + + if (SgInfo->ListRotMxInfo != NULL) { + lrmxi = &SgInfo->ListRotMxInfo[jList]; + lastrmxi = &SgInfo->ListRotMxInfo[SgInfo->nList]; + CopyRotMxInfo(lrmxi, lastrmxi); + } + } else + jList++; + } + + iList++; + } + + SgInfo->StatusLatticeTr = 0; + + return 0; +} + + +static int RemoveInversion(T_SgInfo * SgInfo) +{ + int i, iList, special, deter, Centric, InversionOffOrigin; + T_RTMx *lsmx, *smx, ProperSMx; + T_RotMxInfo *lrmxi, *rmxi; + + + Centric = 0; + InversionOffOrigin = 0; + + lsmx = SgInfo->ListSeitzMx; + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) { + special = IsSpecialSeitzMx(SgInfo, lsmx, 0); + + if (special & SpecialSMx_Inversion) { + if (special & SpecialSMx_Transl0) + Centric = 1; + else + InversionOffOrigin = 1; + + break; + } + } + + if (InversionOffOrigin && Centric) { + SetSgError("Internal Error: Corrupt SgInfo"); + return -1; + } + + if (Centric == 0) { + if (InversionOffOrigin) { + SgInfo->Centric = 0; + SgInfo->InversionOffOrigin = 1; + } else { + if (SgInfo->Centric) + SgInfo->Centric = -1; + SgInfo->InversionOffOrigin = 0; + } + } else { + SgInfo->InversionOffOrigin = 0; + + lsmx = SgInfo->ListSeitzMx; + lrmxi = SgInfo->ListRotMxInfo; + iList = 0; + + while (iList < SgInfo->nList) { + deter = deterRotMx(lsmx->s.R); + + if (deter == -1 && SgInfo->Centric == -1) { + for (i = 0; i < 9; i++) + ProperSMx.s.R[i] = -lsmx->s.R[i]; + + for (i = 0; i < 3; i++) { + ProperSMx.s.T[i] = -lsmx->s.T[i] % STBF; + if (ProperSMx.s.T[i] < 0) + ProperSMx.s.T[i] += STBF; + } + + smx = SgInfo->ListSeitzMx; + + for (i = 0; i < SgInfo->nList; i++, smx++) + if (CompareSeitzMx(LI_P, &ProperSMx, smx) == 0) + break; + + if (i == SgInfo->nList) { + for (i = 0; i < 12; i++) + lsmx->a[i] = ProperSMx.a[i]; + + deter = deterRotMx(lsmx->s.R); + + if (deter != 1 || (lrmxi && GetRotMxInfo(lsmx->s.R, lrmxi) == 0)) { + SetSgError(Err_Ill_SMx_in_List); + return -1; + } + } + } + + if (deter == -1) { + /* copy last element to this place */ + + SgInfo->nList--; + if (SgInfo->nList != iList) { + smx = &SgInfo->ListSeitzMx[SgInfo->nList]; + for (i = 0; i < 12; i++) + lsmx->a[i] = smx->a[i]; + + if (lrmxi) { + rmxi = &SgInfo->ListRotMxInfo[SgInfo->nList]; + CopyRotMxInfo(lrmxi, rmxi); + } + } + } else if (deter == 1) { + lsmx++; + if (lrmxi != NULL) + lrmxi++; + iList++; + } else { + SetSgError(Err_Ill_SMx_in_List); + return -1; + } + } + + SgInfo->Centric = -1; + } + + return 0; +} + + +int ApplyOriginShift(T_SgInfo * SgInfo) +{ + int HaveOrSh, iList, i; + T_RTMx *lsmx, SMx; + int OrSh[3], lo[3]; + + + HaveOrSh = 0; + + for (i = 0; i < 3; i++) { + OrSh[i] = SgInfo->OriginShift[i] * (STBF / 12); + if (OrSh[i]) + HaveOrSh = 1; + } + + if (HaveOrSh == 0) + return 0; + + lsmx = SgInfo->ListSeitzMx; + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) { + RotMx_t_Vector(lo, lsmx->s.R, OrSh, STBF); + + for (i = 0; i < 3; i++) + lsmx->s.T[i] = iModPositive(lsmx->s.T[i] - lo[i] + OrSh[i], STBF); + } + + if (SgInfo->Centric == -1) { + lsmx = &SMx; + + InitSeitzMx(lsmx, -1); + + RotMx_t_Vector(lo, lsmx->s.R, OrSh, STBF); + + for (i = 0; i < 3; i++) + lsmx->s.T[i] = iModPositive(lsmx->s.T[i] - lo[i] + OrSh[i], STBF); + + if (CoreAdd2ListSeitzMx(SgInfo, lsmx) < 0) + return -1; + + SgInfo->Centric = 0; + SgInfo->InversionOffOrigin = 1; + } + + return 1; +} + + +static void TidyTranslation(T_SgInfo * SgInfo) +{ + int iList; + int iTrV, nTrV; + const int *TrV; + T_RTMx *lsmx; + int t1, t2, t3, *lt1, *lt2, *lt3, mint1, mint2, mint3; + int n0t, n0mint; + + + nTrV = SgInfo->LatticeInfo->nTrVector; + + lsmx = SgInfo->ListSeitzMx; + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) { + mint1 = *(lt1 = &lsmx->s.T[0]); + mint2 = *(lt2 = &lsmx->s.T[1]); + mint3 = *(lt3 = &lsmx->s.T[2]); + + TrV = SgInfo->LatticeInfo->TrVector; + + for (iTrV = 0; iTrV < nTrV; iTrV++) { + t1 = ((*lt1) + *TrV++) % STBF; + t2 = ((*lt2) + *TrV++) % STBF; + t3 = ((*lt3) + *TrV++) % STBF; + + n0t = (t1 == 0) + (t2 == 0) + (t3 == 0); + n0mint = (mint1 == 0) + (mint2 == 0) + (mint3 == 0); + + if (n0t > n0mint + || (n0t == n0mint + && (t1 + t2 + t3 < mint1 + mint2 + mint3 + || (t1 + t2 + t3 == mint1 + mint2 + mint3 + && (t1 < mint1 || (t1 == mint1 && t2 < mint2)))))) { + mint1 = t1; + mint2 = t2; + mint3 = t3; + } + } + + *lt1 = mint1; + *lt2 = mint2; + *lt3 = mint3; + } +} + + +static T_SgInfo *Pt_SgInfo_ListSortFunction = NULL; + +static int SgInfoListSortFunction(const int *iList_a, const int *iList_b) +{ + int val_a, val_b, n0_a, n0_b, i; + T_RTMx *smx_a, *smx_b; + T_RotMxInfo RotMxInfo_a, RotMxInfo_b, *rmxi_a, *rmxi_b; + T_SgInfo *SgInfo = Pt_SgInfo_ListSortFunction; + + + if (SgError != NULL) + return 0; + + if (SgInfo->ListRotMxInfo == NULL) { + rmxi_a = &RotMxInfo_a; + rmxi_b = &RotMxInfo_b; + + smx_a = &SgInfo->ListSeitzMx[*iList_a]; + smx_b = &SgInfo->ListSeitzMx[*iList_b]; + + if (GetRotMxInfo(smx_a->s.R, rmxi_a) == 0 + || GetRotMxInfo(smx_b->s.R, rmxi_b) == 0) { + SetSgError(Err_Ill_SMx_in_List); + return 0; + } + } else { + rmxi_a = &SgInfo->ListRotMxInfo[*iList_a]; + rmxi_b = &SgInfo->ListRotMxInfo[*iList_b]; + } + + val_a = abs(rmxi_a->Order); + val_b = abs(rmxi_b->Order); + + if (val_a == 1 && val_b != 1) + return -1; + if (val_a != 1 && val_b == 1) + return 1; + if (rmxi_a->Order == 1 && rmxi_b->Order != 1) + return -1; + if (rmxi_a->Order != 1 && rmxi_b->Order == 1) + return 1; + + if (val_a != 1) { + if (val_a > val_b) + return -1; + if (val_a < val_b) + return 1; + if (rmxi_a->Order > rmxi_b->Order) + return -1; + if (rmxi_a->Order < rmxi_b->Order) + return 1; + } + + n0_a = n0_b = 0; + + for (i = 0; i < 3; i++) { + if (rmxi_a->EigenVector[i] == 0) + n0_a++; + if (rmxi_b->EigenVector[i] == 0) + n0_b++; + } + if (n0_a > n0_b) + return -1; + if (n0_a < n0_b) + return 1; + + val_a = val_b = 0; + + for (i = 0; i < 3; i++) { + if (val_a < abs(rmxi_a->EigenVector[i])) + val_a = abs(rmxi_a->EigenVector[i]); + if (val_b < abs(rmxi_b->EigenVector[i])) + val_b = abs(rmxi_b->EigenVector[i]); + } + if (val_a < val_b) + return -1; + if (val_a > val_b) + return 1; + + val_a = 100 * abs(rmxi_a->EigenVector[2]); + val_a += 10 * abs(rmxi_a->EigenVector[0]); + val_a += abs(rmxi_a->EigenVector[1]); + val_b = 100 * abs(rmxi_b->EigenVector[2]); + val_b += 10 * abs(rmxi_b->EigenVector[0]); + val_b += abs(rmxi_b->EigenVector[1]); + + if (n0_a < 2) { + if (val_a < val_b) + return -1; + if (val_a > val_b) + return 1; + } else { + if (val_a > val_b) + return -1; + if (val_a < val_b) + return 1; + } + + for (i = 0; i < 3; i++) { + if (rmxi_a->EigenVector[i] > rmxi_b->EigenVector[i]) + return -1; + if (rmxi_a->EigenVector[i] < rmxi_b->EigenVector[i]) + return 1; + } + + if (rmxi_a->Inverse < rmxi_b->Inverse) + return -1; + if (rmxi_a->Inverse > rmxi_b->Inverse) + return 1; + + smx_a = &SgInfo->ListSeitzMx[*iList_a]; + smx_b = &SgInfo->ListSeitzMx[*iList_b]; + + for (i = 0; i < 3; i++) { + if (smx_a->s.T[i] < smx_b->s.T[i]) + return -1; + if (smx_a->s.T[i] > smx_b->s.T[i]) + return 1; + } + + return 0; +} + + +static int PostSortSgInfoList(const T_SgInfo * SgInfo, int *List_iList) +{ + int nList, iL_iL, jL_iL; + T_RTMx BufMx1, BufMx2, *smxab; + const T_RTMx *lsmx, *smxb; + T_RotMxInfo RotMxInfo; + const T_RotMxInfo *rmxi; + int nO_1, iO, save, i, i_; + + + nList = SgInfo->nList; + + iL_iL = 0; + + while (iL_iL < nList) { + lsmx = &SgInfo->ListSeitzMx[List_iList[iL_iL]]; + + rmxi = ListOrBufRotMxInfo(SgInfo, List_iList[iL_iL], &RotMxInfo); + if (rmxi == NULL) + return -1; + + iL_iL++; + + iO = rmxi->Order; + if (iO < 0 && iO % 2) + iO *= 2; + nO_1 = abs(iO) - 1; + + smxab = &BufMx2; + smxb = lsmx; + + for (iO = 1; iO < nO_1; iO++) { + SeitzMxMultiply(smxab, lsmx, smxb); + + for (jL_iL = iL_iL; jL_iL < nList; jL_iL++) { + smxb = &SgInfo->ListSeitzMx[List_iList[jL_iL]]; + if (CompareSeitzMx(SgInfo->LatticeInfo, smxab, smxb) == 0) + break; + } + + if (jL_iL < nList) { + save = List_iList[jL_iL]; + + for (i = i_ = jL_iL; i > iL_iL; i = i_) + List_iList[i] = List_iList[--i_]; + + List_iList[iL_iL++] = save; + } + + smxb = smxab; + if (iO % 2) + smxab = &BufMx1; + else + smxab = &BufMx2; + } + } + + return 0; +} + + +static void SortSgInfoList(T_SgInfo * SgInfo, int *List_iList) +{ + int i, j, refi; + int nList; + T_RTMx *lsmx; + T_RotMxInfo *lrmxi; + + + if (SgError != NULL) + return; + + nList = SgInfo->nList; + lsmx = SgInfo->ListSeitzMx; + lrmxi = SgInfo->ListRotMxInfo; + Pt_SgInfo_ListSortFunction = SgInfo; + + for (i = 0; i < nList; i++) + List_iList[i] = i; + + qsort((void *) List_iList, nList, sizeof(*List_iList), + (int (*)(const void *, const void *)) SgInfoListSortFunction); + + Pt_SgInfo_ListSortFunction = NULL; + if (SgError != NULL) + return; + + if (PostSortSgInfoList(SgInfo, List_iList) != 0) + return; + + for (i = 0; i < nList; i++) { + j = List_iList[i]; + + if (j != i) { + for (refi = i + 1; refi < nList; refi++) + if (List_iList[refi] == i) + break; + + if (refi >= nList) { + SetSgError("Internal Error: SortSgInfoList(): Corrupt List_iList"); + return; + } + + SwapRTMx(&lsmx[i], &lsmx[j]); + if (lrmxi != NULL) + SwapRotMxInfo(&lrmxi[i], &lrmxi[j]); + + List_iList[refi] = j; + } + } +} + + +int FindSeitzMx(const T_SgInfo * SgInfo, + int Order, int HonorSign, int RefAxis, int DirCode) +{ + int iList; + int MatchingOrder; + T_RTMx *lsmx; + T_RotMxInfo *lrmxi, RotMxInfo; + + + lsmx = SgInfo->ListSeitzMx; + lrmxi = SgInfo->ListRotMxInfo; + + if (lrmxi == NULL) + lrmxi = &RotMxInfo; + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) { + if (lrmxi == &RotMxInfo) { + if (GetRotMxInfo(lsmx->s.R, lrmxi) == 0) { + SetSgError(Err_Ill_SMx_in_List); + return -1; + } + } + + if (HonorSign == 0) + MatchingOrder = (abs(Order) == abs(lrmxi->Order)); + else + MatchingOrder = (Order == lrmxi->Order); + + if (MatchingOrder + && lrmxi->Inverse == 0 + && (RefAxis == 0 || RefAxis == lrmxi->RefAxis) + && (DirCode == 0 || DirCode == lrmxi->DirCode)) { + if (DirCode != '*') + return iList; + + if (lrmxi->EigenVector[0] == 1 + && lrmxi->EigenVector[1] == 1 && lrmxi->EigenVector[2] == 1) + return iList; + } + + if (lrmxi != &RotMxInfo) + lrmxi++; + } + + return -1; +} + + +static int FindXtalSystem(T_SgInfo * SgInfo) +{ + int iList, i; + int HonorSign = 0, CheckEnantiomorph; + const T_RTMx *lsmx; + T_RotMxInfo RotMxInfo; + const T_RotMxInfo *lrmxi; + + enum Axis { N1 = 0, N2, N3, N4, N6, EndOfAxis }; + int N_count[EndOfAxis]; + + + SgInfo->XtalSystem = XS_Unknown; + SgInfo->UniqueRefAxis = 0; + SgInfo->UniqueDirCode = 0; + SgInfo->ExtraInfo = EI_Unknown; + + CheckEnantiomorph = 0; + + for (i = 0; i < EndOfAxis; i++) + N_count[i] = 0; + + lsmx = SgInfo->ListSeitzMx; + lrmxi = SgInfo->ListRotMxInfo; + + if (lrmxi == NULL) + lrmxi = &RotMxInfo; + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) { + if (lrmxi == &RotMxInfo) { + if (GetRotMxInfo(lsmx->s.R, &RotMxInfo) == 0) { + SetSgError(Err_Ill_SMx_in_List); + return XS_Unknown; + } + } + + switch (abs(lrmxi->Order)) { + case 1: + i = N1; + break; + case 2: + i = N2; + break; + case 3: + i = N3; + break; + case 4: + i = N4; + break; + case 6: + i = N6; + break; + default: + SetSgError + ("Internal Error: FindXtalSystem(): Corrupt ListRotMxInfo"); + return XS_Unknown; + } + + if (lrmxi->Inverse == 0) /* skip N^-1 */ + N_count[i]++; + + if (lrmxi != &RotMxInfo) + lrmxi++; + } + + i = EndOfAxis; + + if (SgInfo->InversionOffOrigin == 1) { + for (i = 0; i < EndOfAxis; i++) { + if (N_count[i] % 2) + break; + N_count[i] /= 2; + } + } + + if (i == EndOfAxis) { + if (N_count[N3] == 4) + SgInfo->XtalSystem = XS_Cubic; + else if (N_count[N3] > 1) + SgInfo->XtalSystem = XS_Unknown; + else if (N_count[N6] == 1) + SgInfo->XtalSystem = XS_Hexagonal; + else if (N_count[N6] > 0) + SgInfo->XtalSystem = XS_Unknown; + else if (N_count[N3] == 1) + SgInfo->XtalSystem = XS_Trigonal; + else if (N_count[N4] == 1) + SgInfo->XtalSystem = XS_Tetragonal; + else if (N_count[N4] > 0) + SgInfo->XtalSystem = XS_Unknown; + else if (N_count[N2] > 2) + SgInfo->XtalSystem = XS_Orthorhombic; + else if (N_count[N2] > 0) + SgInfo->XtalSystem = XS_Monoclinic; + else if (N_count[N1] > 0) + SgInfo->XtalSystem = XS_Triclinic; + + HonorSign = 1; + iList = FindSeitzMx(SgInfo, -1, HonorSign, 'o', '.'); + if (iList < 0) + HonorSign = 0; + + switch (SgInfo->XtalSystem) { + case XS_Monoclinic: + iList = FindSeitzMx(SgInfo, 2, HonorSign, 0, '='); + if (iList < 0) + SgInfo->XtalSystem = XS_Unknown; + break; + case XS_Tetragonal: + CheckEnantiomorph = 1; + iList = FindSeitzMx(SgInfo, 4, HonorSign, 0, '='); + if (iList < 0) + SgInfo->XtalSystem = XS_Unknown; + break; + case XS_Trigonal: + CheckEnantiomorph = 1; + iList = FindSeitzMx(SgInfo, 3, HonorSign, 0, '='); + if (iList < 0) + iList = FindSeitzMx(SgInfo, 3, HonorSign, 0, '*'); + if (iList < 0) + SgInfo->XtalSystem = XS_Unknown; + break; + case XS_Hexagonal: + CheckEnantiomorph = 1; + iList = FindSeitzMx(SgInfo, 6, HonorSign, 0, '='); + if (iList < 0) + SgInfo->XtalSystem = XS_Unknown; + break; + case XS_Cubic: + iList = FindSeitzMx(SgInfo, 4, HonorSign, 0, '='); + if (iList >= 0) + CheckEnantiomorph = 1; + break; + default: + iList = -1; + break; + } + } + + if (SgInfo->XtalSystem == XS_Unknown) { + SetSgError("Error: Can't determine crystal system"); + } else if (iList >= 0) { + lrmxi = ListOrBufRotMxInfo(SgInfo, iList, &RotMxInfo); + if (lrmxi == NULL) { + SgInfo->XtalSystem = XS_Unknown; + return XS_Unknown; + } + + if (SgInfo->XtalSystem != XS_Cubic) { + SgInfo->UniqueRefAxis = lrmxi->RefAxis; + SgInfo->UniqueDirCode = lrmxi->DirCode; + + if (SgInfo->XtalSystem == XS_Trigonal && lrmxi->DirCode == '=') { + switch (lrmxi->RefAxis) { + case 'z': + switch (SgInfo->LatticeInfo->Code) { + case 'R': + SgInfo->ExtraInfo = EI_Obverse; + break; + case 'T': + SgInfo->ExtraInfo = EI_Reverse; + break; + } + break; + case 'y': + switch (SgInfo->LatticeInfo->Code) { + case 'S': + SgInfo->ExtraInfo = EI_Obverse; + break; + case 'R': + SgInfo->ExtraInfo = EI_Reverse; + break; + } + break; + case 'x': + switch (SgInfo->LatticeInfo->Code) { + case 'T': + SgInfo->ExtraInfo = EI_Obverse; + break; + case 'S': + SgInfo->ExtraInfo = EI_Reverse; + break; + } + break; + } + } + } + + if (HonorSign == 0 /* no inversion matrix */ + && SgInfo->LatticeInfo->Code == 'P' && CheckEnantiomorph == 1) { + lsmx = &SgInfo->ListSeitzMx[iList]; + + if (GetRotMxOrder(lsmx->s.R) > 1) { + i = lsmx->s.T[0] * lrmxi->EigenVector[0]; + i += lsmx->s.T[1] * lrmxi->EigenVector[1]; + i += lsmx->s.T[2] * lrmxi->EigenVector[2]; + + if (i % (STBF / 2)) + SgInfo->ExtraInfo = EI_Enantiomorphic; + } + } + } + + return SgInfo->XtalSystem; +} + + +static int BuildGenerator_iList(T_SgInfo * SgInfo) +{ + int iList, iList_1, nG; + int SgInfo_CI, HonorSign, Flag3asterisk, FlagPG; + + + SgInfo_CI = (SgInfo->Centric || SgInfo->InversionOffOrigin); + + SgInfo->PointGroup = PG_Unknown; + + nG = SgInfo->nGenerator = 0; +#define G_iL SgInfo->Generator_iList + + HonorSign = 1; + iList_1 = FindSeitzMx(SgInfo, -1, HonorSign, 'o', '.'); + if (iList_1 < 0) + HonorSign = 0; + + if (SgInfo->XtalSystem == XS_Unknown) + FindXtalSystem(SgInfo); + + switch (SgInfo->XtalSystem) { + case XS_Triclinic: + if (iList_1 < 0) + iList_1 = FindSeitzMx(SgInfo, 1, HonorSign, 'o', '.'); + if (iList_1 >= 0) + G_iL[nG++] = iList_1; + + if (SgInfo_CI) + SgInfo->PointGroup = PG_1b; + else + SgInfo->PointGroup = PG_1; + + SgInfo->nGenerator = nG; + return 0; + + case XS_Monoclinic: + iList = FindSeitzMx(SgInfo, 2, HonorSign, 0, '='); + if (iList < 0) + break; + G_iL[nG++] = iList; + + if (SgInfo_CI) + SgInfo->PointGroup = PG_2_m; + else if (deterRotMx(SgInfo->ListSeitzMx[iList].s.R) == -1) + SgInfo->PointGroup = PG_m; + else + SgInfo->PointGroup = PG_2; + + if (iList_1 >= 0) + G_iL[nG++] = iList_1; + + SgInfo->nGenerator = nG; + return 0; + + case XS_Orthorhombic: + iList = FindSeitzMx(SgInfo, 2, HonorSign, 'z', '='); + if (iList >= 0) + G_iL[nG++] = iList; + + iList = FindSeitzMx(SgInfo, 2, HonorSign, 'x', '='); + if (iList >= 0) + G_iL[nG++] = iList; + + if (nG < 2) { + iList = FindSeitzMx(SgInfo, 2, HonorSign, 'y', '='); + if (iList >= 0) + G_iL[nG++] = iList; + } + + if (nG != 2) + break; + + if (SgInfo_CI) + SgInfo->PointGroup = PG_mmm; + else if (deterRotMx(SgInfo->ListSeitzMx[G_iL[0]].s.R) == -1 + || deterRotMx(SgInfo->ListSeitzMx[G_iL[1]].s.R) == -1) + SgInfo->PointGroup = PG_mm2; + else + SgInfo->PointGroup = PG_222; + + if (iList_1 >= 0) + G_iL[nG++] = iList_1; + + SgInfo->nGenerator = nG; + return 0; + + case XS_Tetragonal: + iList = FindSeitzMx(SgInfo, 4, HonorSign, 0, '='); + if (iList < 0) + break; + G_iL[nG++] = iList; + + if (SgInfo->UniqueRefAxis != 'x') { + iList = FindSeitzMx(SgInfo, 2, HonorSign, 'x', '='); + if (iList >= 0) + G_iL[nG++] = iList; + } + if (nG < 2 && SgInfo->UniqueRefAxis != 'z') { + iList = FindSeitzMx(SgInfo, 2, HonorSign, 'z', '='); + if (iList >= 0) + G_iL[nG++] = iList; + } + if (nG < 2 && SgInfo->UniqueRefAxis != 'y') { + iList = FindSeitzMx(SgInfo, 2, HonorSign, 'y', '='); + if (iList >= 0) + G_iL[nG++] = iList; + } + + if (nG < 2) { + if (SgInfo_CI) + SgInfo->PointGroup = PG_4_m; + else if (deterRotMx(SgInfo->ListSeitzMx[G_iL[0]].s.R) == -1) + SgInfo->PointGroup = PG_4b; + else + SgInfo->PointGroup = PG_4; + } else { + if (SgInfo_CI) + SgInfo->PointGroup = PG_4_mmm; + else if (deterRotMx(SgInfo->ListSeitzMx[G_iL[0]].s.R) == -1) { + if (deterRotMx(SgInfo->ListSeitzMx[G_iL[1]].s.R) == -1) + SgInfo->PointGroup = PG_4bm2; + else + SgInfo->PointGroup = PG_4b2m; + } else { + if (deterRotMx(SgInfo->ListSeitzMx[G_iL[1]].s.R) == -1) + SgInfo->PointGroup = PG_4mm; + else + SgInfo->PointGroup = PG_422; + } + } + + if (iList_1 >= 0) + G_iL[nG++] = iList_1; + + SgInfo->nGenerator = nG; + return 0; + + case XS_Trigonal: + case XS_Hexagonal: + Flag3asterisk = 0; + + if (SgInfo->XtalSystem == XS_Trigonal) { + iList = FindSeitzMx(SgInfo, 3, HonorSign, 0, '='); + if (iList < 0) { + iList = FindSeitzMx(SgInfo, 3, HonorSign, 0, '*'); + Flag3asterisk = 1; + } + } else + iList = FindSeitzMx(SgInfo, 6, HonorSign, 0, '='); + + if (iList < 0) + break; + G_iL[nG++] = iList; + + iList = FindSeitzMx(SgInfo, 2, HonorSign, 0, '\''); + if (iList >= 0) + G_iL[nG++] = iList; + + FlagPG = -1; + + if (nG < 2) { + iList = FindSeitzMx(SgInfo, 2, HonorSign, 0, '"'); + if (iList >= 0) + G_iL[nG++] = iList; + FlagPG = 1; + } + + if (SgInfo->XtalSystem == XS_Trigonal) { + if (nG < 2) { + if (SgInfo_CI) + SgInfo->PointGroup = PG_3b; + else + SgInfo->PointGroup = PG_3; + } else { + if (Flag3asterisk == 1) { + if (SgInfo_CI) + SgInfo->PointGroup = PG_3bm; + else { + FlagPG = deterRotMx(SgInfo->ListSeitzMx[G_iL[1]].s.R); + if (FlagPG == -1) + SgInfo->PointGroup = PG_3m; + else + SgInfo->PointGroup = PG_32; + } + } else if (FlagPG == -1) { + if (SgInfo_CI) + SgInfo->PointGroup = PG_3b1m; + else { + FlagPG = deterRotMx(SgInfo->ListSeitzMx[G_iL[1]].s.R); + if (FlagPG == -1) + SgInfo->PointGroup = PG_31m; + else + SgInfo->PointGroup = PG_312; + } + } else { + if (SgInfo_CI) + SgInfo->PointGroup = PG_3bm1; + else { + FlagPG = deterRotMx(SgInfo->ListSeitzMx[G_iL[1]].s.R); + if (FlagPG == -1) + SgInfo->PointGroup = PG_3m1; + else + SgInfo->PointGroup = PG_321; + } + } + } + } else { + if (nG < 2) { + if (SgInfo_CI) + SgInfo->PointGroup = PG_6_m; + else if (deterRotMx(SgInfo->ListSeitzMx[G_iL[0]].s.R) == -1) + SgInfo->PointGroup = PG_6b; + else + SgInfo->PointGroup = PG_6; + } else { + if (SgInfo_CI) + SgInfo->PointGroup = PG_6_mmm; + else if (deterRotMx(SgInfo->ListSeitzMx[G_iL[0]].s.R) == -1) { + if (deterRotMx(SgInfo->ListSeitzMx[G_iL[1]].s.R) == FlagPG) + SgInfo->PointGroup = PG_6b2m; + else + SgInfo->PointGroup = PG_6bm2; + } else if (deterRotMx(SgInfo->ListSeitzMx[G_iL[1]].s.R) == -1) + SgInfo->PointGroup = PG_6mm; + else + SgInfo->PointGroup = PG_622; + } + } + + if (iList_1 >= 0) + G_iL[nG++] = iList_1; + + SgInfo->nGenerator = nG; + return 0; + + case XS_Cubic: + FlagPG = 0; + + iList = FindSeitzMx(SgInfo, 4, HonorSign, 'z', '='); + if (iList < 0) { + iList = FindSeitzMx(SgInfo, 2, HonorSign, 'z', '='); + FlagPG = 1; + } + if (iList < 0) + break; + G_iL[nG++] = iList; + + iList = FindSeitzMx(SgInfo, 2, HonorSign, 'x', '='); + if (iList < 0) + break; + G_iL[nG++] = iList; + + iList = FindSeitzMx(SgInfo, 3, HonorSign, 'o', '*'); + if (iList < 0) + break; + G_iL[nG++] = iList; + + if (FlagPG) { + if (SgInfo_CI) + SgInfo->PointGroup = PG_m3b; + else + SgInfo->PointGroup = PG_23; + } else { + if (SgInfo_CI) + SgInfo->PointGroup = PG_m3bm; + else if (deterRotMx(SgInfo->ListSeitzMx[G_iL[0]].s.R) == -1) + SgInfo->PointGroup = PG_4b3m; + else + SgInfo->PointGroup = PG_432; + } + + if (iList_1 >= 0) + G_iL[nG++] = iList_1; + + SgInfo->nGenerator = nG; + return 0; + + default: + break; + } + +#undef G_iL + + return -1; +} + + +static int BuildHSym(T_SgInfo * SgInfo) +{ + int NeedDash, HaveOrSh, nGRT, iList, iG, ip, os, i; + int AbsOrder, RefAxis, DirCode, ScrewPrimitive, Screw; + int PreviousRotation, PreviousRefAxis, PreviousDirCode; + int nTrV, iTrV, OrSh[3], RO[3], Transl[3]; + const int *TrV, *ht; + T_RTMx SMx_1; + const T_RTMx *SMx; + const T_RotMxInfo *rmxi; + char *hsym, *hsym_mark; + + struct { + T_RotMxInfo RMxI_Buf; + const T_RotMxInfo *RMxI; + int Transl[3]; + } GRT[sizeof SgInfo->Generator_iList / sizeof(*SgInfo->Generator_iList) + + 1]; + + const char *Digits = "0123456"; + + + if (SgInfo->nGenerator == 0) { + SetSgError("Internal Error: BuildHSym(): Empty generator list"); + return -1; + } + + HaveOrSh = 0; + + for (i = 0; i < 3; i++) { + OrSh[i] = SgInfo->OriginShift[i] * (STBF / 12); + if (OrSh[i]) + HaveOrSh = 1; + } + + NeedDash = 0; + nGRT = 0; + + for (iG = 0; iG < SgInfo->nGenerator; iG++) { + iList = SgInfo->Generator_iList[iG]; + + GRT[nGRT].RMxI = + ListOrBufRotMxInfo(SgInfo, iList, &GRT[nGRT].RMxI_Buf); + if (GRT[nGRT].RMxI == NULL) + return -1; + + SMx = &SgInfo->ListSeitzMx[iList]; + + RotMx_t_Vector(RO, SMx->s.R, OrSh, STBF); + + for (i = 0; i < 3; i++) + GRT[nGRT].Transl[i] = + iModPositive(SMx->s.T[i] + RO[i] - OrSh[i], STBF); + + if (GRT[nGRT].RMxI->Order == -1) { + for (i = 0; i < 3; i++) + if (GRT[nGRT].Transl[i] != 0) + break; + + if (i == 3) + NeedDash = 1; + else + nGRT++; + } else + nGRT++; + } + + if (SgInfo->Centric) { + if (HaveOrSh == 0) + NeedDash = 1; + else { + for (iG = 0; iG < nGRT; iG++) + if (GRT[iG].RMxI->Order == 1) + break; + + InitSeitzMx(&SMx_1, -1); + + if (GetRotMxInfo(SMx_1.s.R, &GRT[iG].RMxI_Buf) != -1) { + SetSgError("Internal Error: BuildHSym(): Corrupt GetRotMxInfo()"); + return -1; + } + + GRT[iG].RMxI = &GRT[iG].RMxI_Buf; + + for (i = 0; i < 3; i++) + GRT[iG].Transl[i] = iModPositive(-2 * OrSh[i], STBF); + + if (iG == nGRT) + nGRT++; + } + } + + hsym = SgInfo->HallSymbol; + + for (i = 0; i <= MaxLenHallSymbol; i++) + *hsym++ = '\0'; + + PreviousRotation = 0; + PreviousRefAxis = 0; + PreviousDirCode = 0; + + hsym = SgInfo->HallSymbol; + + if (NeedDash) + *hsym++ = '-'; + else + *hsym++ = ' '; + + *hsym++ = SgInfo->LatticeInfo->Code; + + nTrV = SgInfo->LatticeInfo->nTrVector; + + for (iG = 0; iG < nGRT; iG++) { + rmxi = GRT[iG].RMxI; + + AbsOrder = abs(rmxi->Order); + RefAxis = rmxi->RefAxis; + DirCode = rmxi->DirCode; + if (RefAxis == 'o') + RefAxis = 0; + if (DirCode == '=' || DirCode == '.') + DirCode = 0; + + if (iG == 0) { + if (RefAxis == 'z') + RefAxis = 0; + } else { + if (AbsOrder == 2) { + if (PreviousRotation == 2 || PreviousRotation == 4) { + if (RefAxis == 'x') + RefAxis = 0; + } else if (PreviousRotation == 3 || PreviousRotation == 6) { + if (PreviousDirCode == '*' || RefAxis == PreviousRefAxis) + RefAxis = 0; + if (DirCode == '\'') + DirCode = 0; + } + } else if (AbsOrder == 3) { + if (DirCode == '*') + DirCode = 0; + } + } + + PreviousRotation = AbsOrder; + PreviousRefAxis = rmxi->RefAxis; + PreviousDirCode = rmxi->DirCode; + + *hsym++ = ' '; + if (rmxi->Order < 0) + *hsym++ = '-'; + *hsym++ = Digits[AbsOrder]; + if (RefAxis) + *hsym++ = RefAxis; + if (DirCode) + *hsym++ = DirCode; + + TrV = SgInfo->LatticeInfo->TrVector; + + for (iTrV = 0; iTrV < nTrV; iTrV++, TrV += 3) { + for (i = 0; i < 3; i++) + if ((GRT[iG].Transl[i] + TrV[i]) % STBF != 0) + break; + + if (i == 3) + break; + } + + if (iTrV < nTrV) + continue; /* next iG */ + + hsym_mark = hsym; + + TrV = SgInfo->LatticeInfo->TrVector; + + for (iTrV = 0; iTrV < nTrV; iTrV++, TrV += 3, hsym = hsym_mark) { + for (i = 0; i < 3; i++) + Transl[i] = iModPositive(GRT[iG].Transl[i] + TrV[i], STBF); + + Screw = 0; + + for (ip = 0; ip < 3; ip++) + if (rmxi->EigenVector[ip] != 0) + break; + + if (ip < 3 && rmxi->EigenVector[ip] == 1) { + for (i = ip + 1; i < 3; i++) + if (rmxi->EigenVector[i] != 0) + break; + + if (i == 3) { + ScrewPrimitive = STBF / AbsOrder; + Screw = Transl[ip] / ScrewPrimitive; + i = Screw * ScrewPrimitive; + if (i % 3) { + *hsym++ = Digits[Screw]; + Transl[ip] -= i; + } + } + } + + ht = HallTranslations; + + while (*ht) { + for (i = 0; i < 3; i++) + if (Transl[i] < ht[i + 1]) + break; + + if (i == 3) { + for (i = 0; i < 3; i++) + Transl[i] -= ht[i + 1]; + + *hsym++ = (char) *ht; + } + + ht += 4; + } + + for (i = 0; i < 3; i++) + if (Transl[i] != 0) + break; + + if (i == 3) + break; + } + + if (iTrV == nTrV) + return 0; + } + + if (nGRT == 0) { + *hsym++ = ' '; + *hsym++ = '1'; + } + + if (HaveOrSh) { + *hsym++ = ' '; + *hsym++ = '('; + + for (i = 0; i < 3; i++) { + if (i) + *hsym++ = ' '; + + os = iModPositive(SgInfo->OriginShift[i], 12); + if (os > 6) { + *hsym++ = '-'; + os = 12 - os; + } + + *hsym++ = Digits[os]; + } + + *hsym++ = ')'; + } + + *hsym = '\0'; + + if (SgInfo->HallSymbol[MaxLenHallSymbol] != '\0') { + SetSgError("Internal Error: BuildHSym(): MaxLenHallSymbol too small"); + return -1; + } + + return 1; +} + + +static int BuildHallSymbol(T_SgInfo * SgInfo, int FixedOriginShift) +{ + int ix, iy, iz; + int status; + + static const int ShiftTable[] = { 0, 1, -1, 2, -2, 3 }; + + + if (SgError != NULL) + return -1; + + if (SgInfo->nGenerator == 0) { + if (BuildGenerator_iList(SgInfo) != 0) { + SetSgError("Error: Can't build generator list"); + return -1; + } + } + + if (FixedOriginShift) { + status = BuildHSym(SgInfo); + if (status == 1) + return 0; + } else { + for (ix = 0; ix < 6; ix++) { + SgInfo->OriginShift[0] = ShiftTable[ix]; + + for (iy = 0; iy < 6; iy++) { + SgInfo->OriginShift[1] = ShiftTable[iy]; + + for (iz = 0; iz < 6; iz++) { + SgInfo->OriginShift[2] = ShiftTable[iz]; + + status = BuildHSym(SgInfo); + if (status < 0) + return -1; + + if (status == 1) + return 0; + } + } + } + } + + SetSgError("Error: Can't build Hall Symbol"); + return -1; +} + + +void InitSgInfo(T_SgInfo * SgInfo) +{ + int i; + + + SgInfo->GenOption = 0; + SgInfo->Centric = 0; + SgInfo->InversionOffOrigin = 0; + SgInfo->LatticeInfo = LI_P; + SgInfo->StatusLatticeTr = 0; + for (i = 0; i < 3; i++) + SgInfo->OriginShift[i] = 0; + SgInfo->nList = 0; + + SgInfo->OrderL = 0; + SgInfo->OrderP = 0; + SgInfo->XtalSystem = XS_Unknown; + SgInfo->UniqueRefAxis = 0; + SgInfo->UniqueDirCode = 0; + SgInfo->ExtraInfo = EI_Unknown; + SgInfo->PointGroup = PG_Unknown; + SgInfo->nGenerator = 0; + SgInfo->HallSymbol[0] = '\0'; + SgInfo->TabSgName = NULL; + SgInfo->CCMx_LP = NULL; + SgInfo->n_si_Vector = -1; +} + + +int CompleteSgInfo(T_SgInfo * SgInfo) +{ + int List_iList[192]; + const T_TabSgName *tsgn; + + + if (SgInfo->StatusLatticeTr == -1) { + if (AddLatticeTr2ListSeitzMx(SgInfo, SgInfo->LatticeInfo) < 0) + return -1; + } + + if (ApplyOriginShift(SgInfo) < 0) + return -1; + + if (SgInfo->nList > sizeof List_iList / sizeof(*List_iList)) { + SetSgError("Internal Error: CompleteSgInfo()"); + return -1; + } + + if (SgInfo->nList > 1) { + SortSgInfoList(SgInfo, List_iList); + if (SgError != NULL) + return -1; + } + + if (RemoveLatticeTr(SgInfo) != 0) + return -1; + + if (RemoveInversion(SgInfo) != 0) + return -1; + + TidyTranslation(SgInfo); + + if (SgInfo->nList > 1) { + SortSgInfoList(SgInfo, List_iList); + if (SgError != NULL) + return -1; + } + SgInfo->OrderP = SgInfo->nList; + if (SgInfo->Centric == -1) + SgInfo->OrderP *= 2; + + SgInfo->OrderL = SgInfo->OrderP * SgInfo->LatticeInfo->nTrVector; + + if (BuildHallSymbol(SgInfo, 0) != 0) + return -1; + + for (tsgn = TabSgName; tsgn->HallSymbol; tsgn++) + if (strcmp(tsgn->HallSymbol, SgInfo->HallSymbol) == 0 + && (SgInfo->TabSgName == NULL || SgInfo->TabSgName == tsgn)) + break; + + if (SgInfo->TabSgName != NULL && tsgn->HallSymbol == NULL) { + if (SgError) + return -1; + + sprintf(SgErrorBuffer, + "Internal Error: Input/Output HallSymbol mismatch: %s <> %s", + SgInfo->TabSgName->HallSymbol, SgInfo->HallSymbol); + + SetSgError(SgErrorBuffer); + return -1; + } + + if (tsgn->HallSymbol) + SgInfo->TabSgName = tsgn; + + SgInfo->CCMx_LP = NULL; + + switch (SgInfo->LatticeInfo->Code) { + case 'P': + SgInfo->CCMx_LP = CCMx_PP; + break; + case 'A': + SgInfo->CCMx_LP = CCMx_AP; + break; + case 'B': + SgInfo->CCMx_LP = CCMx_BP; + break; + case 'C': + SgInfo->CCMx_LP = CCMx_CP; + break; + case 'I': + SgInfo->CCMx_LP = CCMx_IP; + break; + case 'R': + switch (SgInfo->UniqueRefAxis) { + case 0: + case 'z': + SgInfo->CCMx_LP = CCMx_RP_z; + break; + case 'y': + SgInfo->CCMx_LP = CCMx_RP_y; + break; + default: + break; + } + break; + case 'S': + switch (SgInfo->UniqueRefAxis) { + case 0: + case 'y': + SgInfo->CCMx_LP = CCMx_SP_y; + break; + case 'x': + SgInfo->CCMx_LP = CCMx_SP_x; + break; + default: + break; + } + break; + case 'T': + switch (SgInfo->UniqueRefAxis) { + case 0: + case 'x': + SgInfo->CCMx_LP = CCMx_TP_x; + break; + case 'z': + SgInfo->CCMx_LP = CCMx_TP_z; + break; + default: + break; + } + break; + case 'F': + SgInfo->CCMx_LP = CCMx_FP; + break; + default: + break; + } + + if (SgInfo->CCMx_LP == NULL) { + SetSgError("Internal Error: Illegal lattice code"); + return -1; + } + + return 0; +} + + +int CB_SMx(T_RTMx * CSiC, + const T_RTMx * CBMx, const T_RTMx * SMx, const T_RTMx * InvCBMx) +{ + int i; + T_RTMx BufMx; + + + RTMxMultiply(&BufMx, SMx, InvCBMx, CTBF / STBF, CTBF); + RTMxMultiply(CSiC, CBMx, &BufMx, CRBF, CRBF * CTBF); + + for (i = 0; i < 9; i++) { + if (CSiC->s.R[i] % (CRBF * CRBF)) { + SetSgError("Internal Error: Corrupt CBMx/SMx/InvCBMx"); + return -1; + } + + CSiC->s.R[i] /= (CRBF * CRBF); + } + + for (i = 0; i < 3; i++) { + if (CSiC->s.T[i] % (CRBF * (CTBF / STBF))) { + SetSgError("Internal Error: Out of STBF range"); + return -1; + } + + CSiC->s.T[i] /= (CRBF * (CTBF / STBF)); + } + + return 0; +} + + +int TransformSgInfo(const T_SgInfo * SgInfo, + const T_RTMx * CBMx, const T_RTMx * InvCBMx, + T_SgInfo * BC_SgInfo) +{ + int iList, f, i; + int nTrV, iTrV, nLoopInv, iLoopInv; + const int *TrV; + T_RTMx SMx, BC_SMx; + const T_RTMx *lsmx; + + + nLoopInv = Sg_nLoopInv(SgInfo); + + nTrV = SgInfo->LatticeInfo->nTrVector; + TrV = SgInfo->LatticeInfo->TrVector; + + for (iTrV = 0; iTrV < nTrV; iTrV++, TrV += 3) { + for (iLoopInv = 0; iLoopInv < nLoopInv; iLoopInv++) { + if (iLoopInv == 0) + f = 1; + else + f = -1; + + lsmx = SgInfo->ListSeitzMx; + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) { + for (i = 0; i < 9; i++) + SMx.s.R[i] = f * lsmx->s.R[i]; + + for (i = 0; i < 3; i++) + SMx.s.T[i] = f * lsmx->s.T[i] + TrV[i]; + + if (CB_SMx(&BC_SMx, CBMx, &SMx, InvCBMx) != 0) + return -1; + + if (Add2ListSeitzMx(BC_SgInfo, &BC_SMx) < 0) + return -1; + } + } + } + + return 0; +} + + +#undef SGCLIB_C__ diff --git a/sgfind.c b/sgfind.c new file mode 100644 index 00000000..0cc9fdfa --- /dev/null +++ b/sgfind.c @@ -0,0 +1,1180 @@ +/* + Space Group Info's (c) 1994-96 Ralf W. Grosse-Kunstleve + */ + +#include +#include + + +#define SGCOREDEF__ +#include "sginfo.h" + + +static int InitialCBMxR(T_SgInfo * SgInfo, + const T_LatticeInfo ** NewLatticeInfo, + int *NewPointGroup, + int *IniCBMxR, int *IniInvCBMxR) +{ + int Code, NewPG, deterCCMx, fac, i; + const T_LatticeInfo *NewLI; + const int *CCMx; + + + Code = SgInfo->LatticeInfo->Code; + NewLI = SgInfo->LatticeInfo; + NewPG = SgInfo->PointGroup; + CCMx = CCMx_PP; + + switch (SgInfo->XtalSystem) { + case XS_Triclinic: + NewLI = LI_P; + CCMx = SgInfo->CCMx_LP; + break; + + case XS_Monoclinic: + case XS_Tetragonal: + switch (SgInfo->UniqueRefAxis) { + case 'z': + if (Code == 'C') { + NewLI = LI_P; + CCMx = SgInfo->CCMx_LP; + } else if (Code == 'F') { + NewLI = LI_I; + CCMx = CCMx_FI_z; + } + break; + case 'y': + if (Code == 'B') { + NewLI = LI_P; + CCMx = SgInfo->CCMx_LP; + } else if (Code == 'F') { + NewLI = LI_I; + CCMx = CCMx_FI_y; + } + break; + case 'x': + if (Code == 'A') { + NewLI = LI_P; + CCMx = SgInfo->CCMx_LP; + } else if (Code == 'F') { + NewLI = LI_I; + CCMx = CCMx_FI_x; + } + break; + default: + goto ReturnError; + } + + if (SgInfo->XtalSystem == XS_Tetragonal + && SgInfo->LatticeInfo != NewLI) { + if (NewPG == PG_4b2m) + NewPG = PG_4bm2; + else if (NewPG == PG_4bm2) + NewPG = PG_4b2m; + } + + break; + + case XS_Orthorhombic: + break; + + case XS_Trigonal: + NewLI = LI_P; + CCMx = SgInfo->CCMx_LP; + + if (Code == 'R' || Code == 'S' || Code == 'T') { + if (NewPG == PG_321) + NewPG = PG_32; + else if (NewPG == PG_3m1) + NewPG = PG_3m; + else if (NewPG == PG_3bm1) + NewPG = PG_3bm; + } + + break; + + case XS_Hexagonal: + break; + + case XS_Cubic: + break; + + default: + goto ReturnError; + } + + deterCCMx = deterRotMx(CCMx); + if (deterCCMx < 1 || CRBF % deterCCMx) + goto ReturnError; + + fac = CRBF / deterCCMx; + + InverseRotMx(CCMx, IniInvCBMxR); + + for (i = 0; i < 9; i++) { + IniCBMxR[i] = CRBF * CCMx[i]; + IniInvCBMxR[i] *= fac; + } + + *NewLatticeInfo = NewLI; + *NewPointGroup = NewPG; + + return deterCCMx; + +ReturnError: + + SetSgError("Internal Error: InitialCBMxR()"); + return -1; +} + + +static int CBR_RMx(int *RRMx, + const int *CBMxR, const int *RMx, const int *InvCBMxR) +{ + int i, BufMx[9]; + + + RotMxMultiply(BufMx, RMx, InvCBMxR); + RotMxMultiply(RRMx, CBMxR, BufMx); + + for (i = 0; i < 9; i++) { + if (RRMx[i] % (CRBF * CRBF)) { + SetSgError("Internal Error: CBR_SMx()"); + return -1; + } + + RRMx[i] /= (CRBF * CRBF); + } + + return 0; +} + + +static void RotateCBMxR(const int *RMx, const int *InvRMx, + int *CBMxR, int *InvCBMxR) +{ + int i, BufMx[9]; + + + RotMxMultiply(BufMx, RMx, CBMxR); + for (i = 0; i < 9; i++) + CBMxR[i] = BufMx[i]; + + /* matrix algebra: (A * B)^-1 = B^-1 * A^-1 */ + + RotMxMultiply(BufMx, InvCBMxR, InvRMx); + for (i = 0; i < 9; i++) + InvCBMxR[i] = BufMx[i]; +} + + +static int AlignUniqueAxis(const T_SgInfo * SgInfo, + const T_SgInfo * GenSgI, + int *CBMxR, int *InvCBMxR, const int **AlignRMx) +{ + int i, iListS, DirCode; + int UAMx[9], RotEV[3]; + const int *RMx, *InvRMx, *lsmxR; + T_RotMxInfo RMxI_S, *RMxI_G; + + + if (GenSgI->nList < 2) + goto ReturnError; + + RMxI_G = &GenSgI->ListRotMxInfo[1]; + + if (abs(RMxI_G->Order) == 3) + DirCode = 0; + else + DirCode = '='; + + iListS = FindSeitzMx(SgInfo, RMxI_G->Order, 1, 0, DirCode); + if (iListS < 0) { + if (SgInfo->Centric == 0) + return 0; + + iListS = FindSeitzMx(SgInfo, -RMxI_G->Order, 1, 0, DirCode); + if (iListS < 0) + goto ReturnError; + + for (i = 0; i < 9; i++) + UAMx[i] = -SgInfo->ListSeitzMx[iListS].s.R[i]; + + lsmxR = UAMx; + } else + lsmxR = SgInfo->ListSeitzMx[iListS].s.R; + + if (CBR_RMx(UAMx, CBMxR, lsmxR, InvCBMxR) != 0) + goto ReturnError; + + if (GetRotMxInfo(UAMx, &RMxI_S) != RMxI_G->Order) + goto ReturnError; + + if (RMxI_S.DirCode != RMxI_G->DirCode) + return 0; + + RMx = InvRMx = RMx_1_000; + + for (;;) { + RotMx_t_Vector(RotEV, RMx, RMxI_S.EigenVector, 0); + + for (i = 0; i < 3; i++) + if (RotEV[i] != RMxI_G->EigenVector[i]) + break; + + if (i == 3) + break; + + if (RMxI_S.DirCode == '=') { + if (RMx == RMx_1_000) { + RMx = RMx_3_111; + InvRMx = RMx_3i111; + } else if (RMx == RMx_3_111) { + RMx = RMx_3i111; + InvRMx = RMx_3_111; + } else + goto ReturnError; + } else if (RMxI_S.DirCode == '*') { + if (RMx == RMx_1_000) { + RMx = RMx_4_001; + InvRMx = RMx_4i001; + } else if (RMx == RMx_4_001) { + RMx = RMx_2_001; + InvRMx = RMx_2_001; + } else if (RMx == RMx_2_001) { + RMx = RMx_4i001; + InvRMx = RMx_4_001; + } else + goto ReturnError; + } else + goto ReturnError; + } + + if (RMx != RMx_1_000) + RotateCBMxR(RMx, InvRMx, CBMxR, InvCBMxR); + + if (AlignRMx) + *AlignRMx = RMx; + + return 1; + +ReturnError: + + SetSgError("Internal Error: AlignUniqueAxis()"); + return -1; +} + + +static const T_RTMx *GetSMxWithSameRot(const int *WtdRotMx, + const T_SgInfo * SgInfo, + T_RTMx * BufMx) +{ + int iList, i; + const T_RTMx *lsmx; + + + lsmx = SgInfo->ListSeitzMx; + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) { + for (i = 0; i < 9; i++) + if (WtdRotMx[i] != lsmx->s.R[i]) + break; + + if (i == 9) + return lsmx; + + if (SgInfo->Centric != -1) + continue; + + for (i = 0; i < 9; i++) + if (WtdRotMx[i] != -lsmx->s.R[i]) + break; + + if (i == 9) { + for (i = 0; i < 9; i++) + BufMx->s.R[i] = -lsmx->s.R[i]; + + for (i = 0; i < 3; i++) { + BufMx->s.T[i] = -lsmx->s.T[i] % STBF; + if (BufMx->s.T[i] < 0) + BufMx->s.T[i] += STBF; + } + + return BufMx; + } + } + + return NULL; +} + + +static int BuildFreeMx(const int *EigenVector, int Order, int *FreeMx) +{ + static const int GeneratorEigenVectors[] = { + 001, 0, 0, 1, + 010, 0, 1, 0, + 100, 1, 0, 0, + 110, 1, 1, 0, + -110, 1, -1, 0, + 111, 1, 1, 1, + 0 + }; + + int i; + const int *gev; + + + for (i = 0; i < 9; i++) + FreeMx[i] = 0; + + if (Order == -1 || Order == -3 || Order == -4 || Order == -6) + return 0; + + for (gev = GeneratorEigenVectors; *gev++ != 0; gev += 3) { + for (i = 0; i < 3; i++) + if (EigenVector[i] != gev[i]) + break; + + if (i == 3) + break; + } + + gev--; + + if (Order == -2) { + switch (*gev) { + case 001: + FreeMx[0] = 1; + FreeMx[4] = 1; + return 0; + case 010: + FreeMx[8] = 1; + FreeMx[0] = 1; + return 0; + case 100: + FreeMx[4] = 1; + FreeMx[8] = 1; + return 0; + case 110: + FreeMx[1] = 1; + FreeMx[4] = -1; + FreeMx[8] = 1; + return 1; + case -110: + FreeMx[1] = 1; + FreeMx[4] = 1; + FreeMx[8] = 1; + return 1; + default: + break; + } + } else if (Order > 1) { + switch (*gev) { + case 001: + FreeMx[8] = 1; + return 0; + case 010: + FreeMx[4] = 1; + return 0; + case 100: + FreeMx[0] = 1; + return 0; + case 110: + FreeMx[0] = 1; + FreeMx[3] = 1; + return 1; + case -110: + FreeMx[0] = 1; + FreeMx[3] = -1; + return 1; + case 111: + FreeMx[0] = 1; + FreeMx[3] = 1; + FreeMx[6] = 1; + return 1; + default: + break; + } + } + + SetSgError("Internal Error: BuildFreeMx()"); + return -1; +} + + +static int StartFixAxes(const T_SgInfo * SgInfo, + const T_SgInfo * GenSgI, const int *iGen, + T_RTMx * CBMx, T_RTMx * InvCBMx, + T_RTMx * SMxG, T_RTMx * SMxS_G, + int *FreeMx, int *TryAgain) +{ + int iG, Order, i; + const int *EV; + T_RTMx SMxG_S, BufMx; + const T_RTMx *SMx; + const T_RotMxInfo *RMxI_G; + + + if (*iGen == -3) + iG = 1; + else + iG = *iGen; + + if (iG == -1) { + Order = -1; + EV = NULL; + } else { + if (iG < 1 || iG >= GenSgI->nList) + goto ReturnError; + + RMxI_G = &GenSgI->ListRotMxInfo[iG]; + Order = RMxI_G->Order; + EV = RMxI_G->EigenVector; + + if (iG != *iGen) { + Order *= -1; + if (Order != *iGen) + goto ReturnError; + } + } + + if (Order == -1) { + if (GenSgI->Centric == -1) { + InitSeitzMx(SMxG, -1); + } else { + for (iG = 1; iG < GenSgI->nList; iG++) + if (GenSgI->ListRotMxInfo[iG].Order == -1) + break; + + if (iG == GenSgI->nList) + goto ReturnError; + + SMx = &GenSgI->ListSeitzMx[iG]; + + for (i = 0; i < 12; i++) + SMxG->a[i] = SMx->a[i]; + } + } else { + SMx = &GenSgI->ListSeitzMx[iG]; + + if (iG == *iGen) + for (i = 0; i < 12; i++) + SMxG->a[i] = SMx->a[i]; + else { + for (i = 0; i < 9; i++) + SMxG->s.R[i] = -SMx->s.R[i]; + + for (i = 0; i < 3; i++) { + SMxG->s.T[i] = -SMx->s.T[i] % STBF; + if (SMxG->s.T[i] < 0) + SMxG->s.T[i] += STBF; + } + } + } + + if (CB_SMx(&SMxG_S, InvCBMx, SMxG, CBMx) != 0) + return -1; + + SMx = GetSMxWithSameRot(SMxG_S.s.R, SgInfo, &BufMx); + if (SMx == NULL) + return 0; + + if (CB_SMx(SMxS_G, CBMx, SMx, InvCBMx) != 0) + return -1; + + for (i = 0; i < 9; i++) + if (SMxS_G->s.R[i] != SMxG->s.R[i]) + goto ReturnError; + + *TryAgain = BuildFreeMx(EV, Order, FreeMx); + if (*TryAgain < 0) + return -1; + + return 1; + +ReturnError: + + SetSgError("Internal Error: StartFixAxes()"); + return -1; +} + + +static int FindInvertableMx(const int *Mx, int *InvMx, + int *nActive, int *irActive, int *icActive) +{ + int Init, deterMx, i; + + + if (*nActive == 0 || *nActive == 3) + return 0; + + if (*nActive == -1) { + Init = 1; + + deterMx = deterRotMx(Mx); + if (deterMx) { + InverseRotMx(Mx, InvMx); + + *nActive = 3; + return deterMx; + } + } else + Init = 0; + + if (Init || *nActive == 2) { + for (;;) { + if (Init) { + irActive[0] = 0; + irActive[1] = 1; + icActive[0] = 0; + icActive[1] = 1; + Init = 0; + } else { + if (++icActive[1] == 3) { + if (++icActive[0] == 2) { + if (++irActive[1] == 3) { + if (++irActive[0] == 2) { + Init = 1; + break; + } else { + irActive[1] = irActive[0] + 1; + icActive[0] = 0; + icActive[1] = 1; + } + } else { + icActive[0] = 0; + icActive[1] = 1; + } + } else { + icActive[1] = icActive[0] + 1; + } + } + } + + InvMx[0] = Mx[irActive[1] * 3 + icActive[1]]; + InvMx[1] = -Mx[irActive[0] * 3 + icActive[1]]; + InvMx[2] = -Mx[irActive[1] * 3 + icActive[0]]; + InvMx[3] = Mx[irActive[0] * 3 + icActive[0]]; + + deterMx = InvMx[3] * InvMx[0] - InvMx[1] * InvMx[2]; + if (deterMx) { + *nActive = 2; + return deterMx; + } + } + } + + if (*nActive == 2) + return 0; + + if (Init) + i = 0; + else + i = irActive[0] * 3 + icActive[0] + 1; + + for (; i < 9; i++) { + if (Mx[i]) { + irActive[0] = i / 3; + icActive[0] = i % 3; + *nActive = 1; + return Mx[i]; + } + } + + if (*nActive == 1) + return 0; + + *nActive = 0; + return 1; +} + + +static int SetInvCBMxT(const int *CBMxT, const int *InvCBMxR, + int *InvCBMxT) +{ + int i; + + + RotMx_t_Vector(InvCBMxT, InvCBMxR, CBMxT, CRBF * CTBF); + + for (i = 0; i < 3; i++) { + if (InvCBMxT[i] % CRBF) { + SetSgError("Internal Error: SetInvCBMxT()"); + return -1; + } + + if (InvCBMxT[i]) + InvCBMxT[i] = CTBF - InvCBMxT[i] / CRBF; + } + + return 0; +} + + +static int FixAxes(const T_SgInfo * SgInfo, + const T_SgInfo * GenSgI, const int *iGen, + T_RTMx * CBMx, T_RTMx * InvCBMx, + int *FreeMx, int TryAgain) +{ + int i, NextTryAgain; + int IniCBMxT[3], SingleFreeMx[9]; + T_RTMx SMxG, SMxS_G; + int NextFreeMxBuf[9], R_I_FMxBuf[9]; + int R_I[9], *R_I_FMx, InvR_I_FMx[9], deterR_I_FMx; + int S_G[3], CmpS_G[3], RedSh[3], Sh[3], *NextFreeMx; + int nActive, irActive[3], icActive[3]; + int nTrV, iTrV; + const int *TrV; + + + if (FreeMx == NULL) { + for (i = 0; i < 3; i++) { + CBMx->s.T[i] = 0; + InvCBMx->s.T[i] = 0; + } + } + + i = StartFixAxes(SgInfo, GenSgI, iGen, CBMx, InvCBMx, + &SMxG, &SMxS_G, SingleFreeMx, &NextTryAgain); + if (i != 1) + return i; + + if (FreeMx) { + RotMxMultiply(NextFreeMxBuf, SingleFreeMx, FreeMx); + NextFreeMx = NextFreeMxBuf; + } else + NextFreeMx = SingleFreeMx; + + for (i = 0; i < 9; i++) + R_I[i] = SMxG.s.R[i]; + + for (i = 0; i < 9; i += 4) + R_I[i] -= 1; + + if (FreeMx) { + RotMxMultiply(R_I_FMxBuf, R_I, FreeMx); + R_I_FMx = R_I_FMxBuf; + } else + R_I_FMx = R_I; + + for (i = 0; i < 3; i++) + IniCBMxT[i] = CBMx->s.T[i]; + + nActive = -1; + + for (;;) { + deterR_I_FMx = FindInvertableMx(R_I_FMx, InvR_I_FMx, + &nActive, irActive, icActive); + if (deterR_I_FMx == 0) + break; + + nTrV = GenSgI->LatticeInfo->nTrVector; + TrV = GenSgI->LatticeInfo->TrVector; + + for (iTrV = 0; iTrV < nTrV; iTrV++, TrV += 3) { + for (i = 0; i < 3; i++) { + S_G[i] = (CTBF / STBF) + * ((SMxS_G.s.T[i] - SMxG.s.T[i] - TrV[i]) % STBF); + RedSh[i] = 0; + } + + switch (nActive) { + case 1: + RedSh[icActive[0]] = S_G[irActive[0]]; + break; + case 2: + RedSh[icActive[0]] = InvR_I_FMx[0] * S_G[irActive[0]] + + InvR_I_FMx[1] * S_G[irActive[1]]; + RedSh[icActive[1]] = InvR_I_FMx[2] * S_G[irActive[0]] + + InvR_I_FMx[3] * S_G[irActive[1]]; + break; + case 3: + RotMx_t_Vector(RedSh, InvR_I_FMx, S_G, 0); + break; + default: + break; + } + + if (FreeMx) { + RotMx_t_Vector(Sh, FreeMx, RedSh, 0); + + for (i = 0; i < 3; i++) + Sh[i] %= (CTBF * abs(deterR_I_FMx)); + } else { + for (i = 0; i < 3; i++) + Sh[i] = RedSh[i] % (CTBF * abs(deterR_I_FMx)); + } + + RotMx_t_Vector(CmpS_G, R_I, Sh, 0); + + for (i = 0; i < 3; i++) + if ((CmpS_G[i] - + S_G[i] * deterR_I_FMx) % (CTBF * abs(deterR_I_FMx))) + break; + + if (i < 3) + continue; + + if (deterR_I_FMx != 1) { + for (i = 0; i < 3; i++) { + if (Sh[i] % abs(deterR_I_FMx)) + goto ReturnError; + + Sh[i] /= deterR_I_FMx; + } + } + + for (i = 0; i < 3; i++) { + CBMx->s.T[i] = IniCBMxT[i] + Sh[i] % CTBF; + if (CBMx->s.T[i] < 0) + CBMx->s.T[i] += CTBF; + } + + if (SetInvCBMxT(CBMx->s.T, InvCBMx->s.R, InvCBMx->s.T) != 0) + return -1; + + if (iGen[1] == 0) + return 1; + + i = FixAxes(SgInfo, GenSgI, &iGen[1], CBMx, InvCBMx, + NextFreeMx, NextTryAgain); + if (i != 0) + return i; + } + + if (TryAgain == 0) + break; + } + + return 0; + +ReturnError: + + SetSgError("Internal Error: FixAxes()"); + return -1; +} + + +static int CompleteCBMx(const T_SgInfo * SgInfo, + const T_LatticeInfo * NewLI, + const T_SgInfo * GenSgI, const int *IniCBMxR, + const int *IniInvCBMxR, T_RTMx * CBMx, + T_RTMx * InvCBMx) +{ + int iGen[5], i; + + + if (SgInfo->XtalSystem == XS_Triclinic) { + for (i = 0; i < 9; i++) { + CBMx->s.R[i] = IniCBMxR[i]; + InvCBMx->s.R[i] = IniInvCBMxR[i]; + } + + if (GenSgI->PointGroup == PG_1) { + for (i = 0; i < 3; i++) { + CBMx->s.T[i] = 0; + InvCBMx->s.T[i] = 0; + } + return 1; + } + + iGen[0] = -1; + iGen[1] = 0; + + return FixAxes(SgInfo, GenSgI, iGen, CBMx, InvCBMx, NULL, 0); + } + + if (SgInfo->XtalSystem == XS_Monoclinic) { + int iCCs, BufRMx[9]; + int RMxCCs_Buf[9], RMxCCn_Buf[9], InvRMxCCn_Buf[9], RotLTrV[3]; + const int *RMxAA, *RMxCCs, *RMxCCn, *InvRMxCCn, *TrV; + T_RTMx BufCBMx, BufInvCBMx; + + + if (NewLI->nTrVector != 1 && NewLI->nTrVector != 2) + goto ReturnError; + + for (i = 0; i < 9; i++) { + BufCBMx.s.R[i] = IniCBMxR[i]; + BufInvCBMx.s.R[i] = IniInvCBMxR[i]; + } + + i = AlignUniqueAxis(SgInfo, GenSgI, + BufCBMx.s.R, BufInvCBMx.s.R, &RMxAA); + if (i != 1) + return i; + + if (GenSgI->nList < 2) + goto ReturnError; + + for (i = 0; i < 9; i++) { + RMxCCs_Buf[i] = RMx_2_110[i]; + RMxCCn_Buf[i] = RMx_3_001[i]; + } + + switch (GenSgI->ListRotMxInfo[1].RefAxis) { + case 'z': + break; + case 'x': + RotateRotMx(RMxCCs_Buf, RMx_3_111, RMx_3i111); + RotateRotMx(RMxCCn_Buf, RMx_3_111, RMx_3i111); + break; + case 'y': + RotateRotMx(RMxCCs_Buf, RMx_3i111, RMx_3_111); + RotateRotMx(RMxCCn_Buf, RMx_3i111, RMx_3_111); + break; + default: + goto ReturnError; + } + + InverseRotMx(RMxCCn_Buf, InvRMxCCn_Buf); + + i = 0; + iGen[i++] = 1; + if (GenSgI->PointGroup == PG_2_m) + iGen[i++] = -1; + iGen[i] = 0; + + RMxCCs = RMx_1_000; + + for (iCCs = 0; iCCs < 2; iCCs++, RMxCCs = RMxCCs_Buf) { + RMxCCn = InvRMxCCn = RMx_1_000; + + for (;;) { + if (NewLI->nTrVector == 2) { + RotMx_t_Vector(RotLTrV, RMxAA, &NewLI->TrVector[3], STBF); + RotMx_t_Vector(BufRMx, RMxCCn, RotLTrV, STBF); + RotMx_t_Vector(RotLTrV, RMxCCs, BufRMx, STBF); + + TrV = &GenSgI->LatticeInfo->TrVector[3]; + + for (i = 0; i < 3; i++) + if (RotLTrV[i] != TrV[i]) + break; + } + + if (NewLI->nTrVector == 1 || i == 3) { + RotMxMultiply(BufRMx, RMxCCn, BufCBMx.s.R); + RotMxMultiply(CBMx->s.R, RMxCCs, BufRMx); + + RotMxMultiply(BufRMx, BufInvCBMx.s.R, InvRMxCCn); + RotMxMultiply(InvCBMx->s.R, BufRMx, RMxCCs); + + i = FixAxes(SgInfo, GenSgI, iGen, CBMx, InvCBMx, NULL, 0); + if (i != 0) + return i; + } + + if (RMxCCn == RMx_1_000) { + RMxCCn = RMxCCn_Buf; + InvRMxCCn = InvRMxCCn_Buf; + } else if (RMxCCn == RMxCCn_Buf) { + RMxCCn = InvRMxCCn_Buf; + InvRMxCCn = RMxCCn_Buf; + } else { + RMxCCn = NULL; + break; + } + } + } + + return 0; + } + + for (i = 0; i < 9; i++) { + CBMx->s.R[i] = IniCBMxR[i]; + InvCBMx->s.R[i] = IniInvCBMxR[i]; + } + + if (SgInfo->XtalSystem == XS_Orthorhombic) { + int iNextBasis; + int BufCBMxR[9], BufInvCBMxR[9]; + int NLTrV_Buf1[3], NLTrV_Buf2[3]; + const int *NLTrV, *GLTrV; + + + if ((GenSgI->LatticeInfo->Code == 'I') != (NewLI->Code == 'I')) + return 0; + + if (NewLI->Code == 'A' || NewLI->Code == 'B' || NewLI->Code == 'C') { + NLTrV = &NewLI->TrVector[3]; + GLTrV = &GenSgI->LatticeInfo->TrVector[3]; + } else { + NLTrV = NULL; + GLTrV = NULL; + } + i = 0; + iGen[i++] = 1; + iGen[i++] = 2; + if (GenSgI->PointGroup == PG_mmm) + iGen[i++] = -1; + iGen[i] = 0; + + for (iNextBasis = 0; iNextBasis < 6; iNextBasis++) { + if (iNextBasis % 2) { + RotMxMultiply(BufCBMxR, RMx_2_110, CBMx->s.R); + RotMxMultiply(BufInvCBMxR, InvCBMx->s.R, RMx_2_110); + + for (i = 0; i < 9; i++) { + CBMx->s.R[i] = BufCBMxR[i]; + InvCBMx->s.R[i] = BufInvCBMxR[i]; + } + } else if (iNextBasis == 2) { + RotMxMultiply(CBMx->s.R, RMx_3_111, IniCBMxR); + RotMxMultiply(InvCBMx->s.R, IniInvCBMxR, RMx_3i111); + } else if (iNextBasis) { + RotMxMultiply(CBMx->s.R, RMx_3i111, IniCBMxR); + RotMxMultiply(InvCBMx->s.R, IniInvCBMxR, RMx_3_111); + } + + if (NLTrV) { + if (iNextBasis % 2) { + RotMx_t_Vector(NLTrV_Buf1, RMx_2_110, NLTrV, STBF); + NLTrV = NLTrV_Buf1; + } else if (iNextBasis == 2) { + RotMx_t_Vector(NLTrV_Buf2, RMx_3_111, &NewLI->TrVector[3], STBF); + NLTrV = NLTrV_Buf2; + } else if (iNextBasis) { + RotMx_t_Vector(NLTrV_Buf2, RMx_3i111, &NewLI->TrVector[3], STBF); + NLTrV = NLTrV_Buf2; + } + + for (i = 0; i < 3; i++) + if (NLTrV[i] != GLTrV[i]) + break; + + if (i < 3) + continue; + } + + i = FixAxes(SgInfo, GenSgI, iGen, CBMx, InvCBMx, NULL, 0); + if (i != 0) + return i; + } + } + + if (SgInfo->XtalSystem == XS_Tetragonal) { + i = AlignUniqueAxis(SgInfo, GenSgI, CBMx->s.R, InvCBMx->s.R, NULL); + if (i != 1) + return -1; + i = 0; + iGen[i++] = 1; + + switch (GenSgI->PointGroup) { + case PG_422: + case PG_4mm: + case PG_4b2m: + case PG_4bm2: + case PG_4_mmm: + iGen[i++] = 2; + } + + switch (GenSgI->PointGroup) { + case PG_4_m: + case PG_4_mmm: + iGen[i++] = -1; + } + iGen[i] = 0; + + return FixAxes(SgInfo, GenSgI, iGen, CBMx, InvCBMx, NULL, 0); + } + + if (SgInfo->XtalSystem == XS_Trigonal) { + i = AlignUniqueAxis(SgInfo, GenSgI, CBMx->s.R, InvCBMx->s.R, NULL); + if (i != 1) + return i; + i = 0; + + switch (GenSgI->PointGroup) { + case PG_3: + case PG_312: + case PG_32: + case PG_3m1: + case PG_3m: + iGen[i++] = 1; + break; + case PG_3b: + case PG_3bm1: + case PG_3b1m: + case PG_3bm: + iGen[i++] = -3; + } + + switch (GenSgI->PointGroup) { + case PG_321: + case PG_312: + case PG_32: + case PG_3m1: + case PG_31m: + case PG_3m: + case PG_3bm1: + case PG_3b1m: + case PG_3bm: + iGen[i++] = 2; + } + + switch (GenSgI->PointGroup) { + case PG_321: + case PG_31m: + iGen[i++] = 1; + } + iGen[i] = 0; + + return FixAxes(SgInfo, GenSgI, iGen, CBMx, InvCBMx, NULL, 0); + } + + if (SgInfo->XtalSystem == XS_Hexagonal) { + i = AlignUniqueAxis(SgInfo, GenSgI, CBMx->s.R, InvCBMx->s.R, NULL); + if (i != 1) + return -1; + i = 0; + + switch (GenSgI->PointGroup) { + case PG_6bm2: + case PG_6b2m: + iGen[i++] = 2; + } + iGen[i++] = 1; + + switch (GenSgI->PointGroup) { + case PG_622: + case PG_6mm: + case PG_6_mmm: + iGen[i++] = 2; + } + + switch (GenSgI->PointGroup) { + case PG_6_m: + case PG_6_mmm: + iGen[i++] = -1; + } + iGen[i] = 0; + + return FixAxes(SgInfo, GenSgI, iGen, CBMx, InvCBMx, NULL, 0); + } + + if (SgInfo->XtalSystem == XS_Cubic) { + i = 0; + iGen[i++] = 3; + iGen[i++] = 1; + iGen[i++] = 2; + if (GenSgI->PointGroup == PG_m3b || GenSgI->PointGroup == PG_m3bm) + iGen[i++] = -1; + iGen[i] = 0; + + return FixAxes(SgInfo, GenSgI, iGen, CBMx, InvCBMx, NULL, 0); + } + + return 0; + +ReturnError: + + SetSgError("Internal Error: CompleteCBMx()"); + return -1; +} + + +const T_TabSgName *FindReferenceSpaceGroup(T_SgInfo * SgInfo, + T_RTMx * CBMx, T_RTMx * InvCBMx) +{ + int stat, NewPG, SgInfo_CI, OL_SgInfo, OL_GenSgI; + const T_TabSgName *tsgn; + T_SgInfo GenSgI; + T_RTMx GenSgI_ListSeitzMx[5]; + T_RotMxInfo GenSgI_ListRotMxInfo[5]; + int iList, PrevSgNumber; + int FacIniCBMxR; + T_RotMxInfo *lrmxi; + const T_LatticeInfo *NewLI; + int IniCBMxR[9], IniInvCBMxR[9]; + + + GenSgI.MaxList = 5; + GenSgI.ListSeitzMx = GenSgI_ListSeitzMx; + GenSgI.ListRotMxInfo = GenSgI_ListRotMxInfo; + + FacIniCBMxR = + InitialCBMxR(SgInfo, &NewLI, &NewPG, IniCBMxR, IniInvCBMxR); + if (FacIniCBMxR < 0) + return NULL; + + OL_SgInfo = SgInfo->OrderL; + if (OL_SgInfo % FacIniCBMxR) + goto ReturnError; + + OL_SgInfo /= FacIniCBMxR; + + SgInfo_CI = (SgInfo->Centric || SgInfo->InversionOffOrigin); + + PrevSgNumber = 0; + + for (tsgn = TabSgName; tsgn->HallSymbol; tsgn++) { + if (tsgn->HallSymbol[1] == 'R') + continue; + + if (VolAPointGroups[tsgn->SgNumber] != NewPG) + continue; + + if (tsgn->SgNumber == PrevSgNumber) + continue; + + PrevSgNumber = tsgn->SgNumber; + + InitSgInfo(&GenSgI); + GenSgI.GenOption = -1; + + ParseHallSymbol(tsgn->HallSymbol, &GenSgI); + + if (SgError != NULL) + return NULL; + + if (ApplyOriginShift(&GenSgI) < 0) + return NULL; + + if (SgInfo_CI != (GenSgI.Centric || GenSgI.InversionOffOrigin)) + goto ReturnError; + + OL_GenSgI = GenSgI.LatticeInfo->nTrVector; + + if (SgInfo_CI) + OL_GenSgI *= 2; + + lrmxi = &GenSgI.ListRotMxInfo[1]; + + for (iList = 1; iList < GenSgI.nList; iList++, lrmxi++) { + OL_GenSgI *= abs(lrmxi->Order); + + if ((lrmxi->Order == -1 || lrmxi->Order == -3) + && GenSgI.Centric == 0 && GenSgI.InversionOffOrigin == 0) + goto ReturnError; + } + + if (OL_GenSgI == OL_SgInfo) { + if (NewLI->nTrVector != GenSgI.LatticeInfo->nTrVector) + goto ReturnError; + + GenSgI.PointGroup = NewPG; + +#if DEBUG_FindConventionalSetting + fprintf(stdout, "%s ?= %s (%d)\n", + SgInfo->HallSymbol, tsgn->HallSymbol, tsgn->SgNumber); +#endif + + stat = CompleteCBMx(SgInfo, NewLI, &GenSgI, + IniCBMxR, IniInvCBMxR, CBMx, InvCBMx); + if (stat < 0) + return NULL; + + if (stat) + return tsgn; + } + } + + SetSgError("Internal Error: Space Group not found"); + return NULL; + +ReturnError: + + SetSgError("Internal Error: FindReferenceSpaceGroup()"); + return NULL; +} diff --git a/sghkl.c b/sghkl.c new file mode 100644 index 00000000..ba04b74e --- /dev/null +++ b/sghkl.c @@ -0,0 +1,268 @@ +/* + Space Group Info's (c) 1994-96 Ralf W. Grosse-Kunstleve + */ + +#include +#include + + +#include "sginfo.h" + + +static const char *IErr_Inc_SymMx = + "Internal Error: Inconsistent symmetry matrices"; + + +int IsSysAbsent_hkl(const T_SgInfo * SgInfo, + int h, int k, int l, int *TH_Restriction) +{ + int iTrV, nTrV; + const int *TrV; + int iList, mh, mk, ml, hm, km, lm; + int TH, THr, FlagMismatch; + const T_RTMx *lsmx; + + + mh = -h; + mk = -k; + ml = -l; + + /* check list of symmetry operations + take care of lattice type and "centric" flag */ + + THr = -1; + if (TH_Restriction != NULL) + *TH_Restriction = THr; + FlagMismatch = 0; + + nTrV = SgInfo->LatticeInfo->nTrVector; + lsmx = SgInfo->ListSeitzMx; + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) { + hm = lsmx->s.R[0] * h + lsmx->s.R[3] * k + lsmx->s.R[6] * l; + km = lsmx->s.R[1] * h + lsmx->s.R[4] * k + lsmx->s.R[7] * l; + lm = lsmx->s.R[2] * h + lsmx->s.R[5] * k + lsmx->s.R[8] * l; + + TrV = SgInfo->LatticeInfo->TrVector; + + for (iTrV = 0; iTrV < nTrV; iTrV++) { + TH = (lsmx->s.T[0] + *TrV++) * h; + TH += (lsmx->s.T[1] + *TrV++) * k; + TH += (lsmx->s.T[2] + *TrV++) * l; + TH %= STBF; + if (TH < 0) + TH += STBF; + + if (mh == hm && mk == km && ml == lm) { + if (TH != 0 && SgInfo->Centric == -1) + return -(iList + 1 + iTrV * SgInfo->nList); + + if (THr < 0) + THr = TH; + else if (THr != TH) + FlagMismatch = 1; /* must be systematic absent */ + /* will check later ... */ + } else if (h == hm && k == km && l == lm) { + if (TH != 0) + return (iList + 1 + iTrV * SgInfo->nList); + } else + break; + } + } + + if (THr >= 0 && FlagMismatch) /* ... consistency check */ + SetSgError(IErr_Inc_SymMx); + + if (TH_Restriction != NULL) { + if (SgInfo->Centric == -1) + *TH_Restriction = 0; + else + *TH_Restriction = THr; + } + + return 0; +} + + +int BuildEq_hkl(const T_SgInfo * SgInfo, T_Eq_hkl * Eq_hkl, int h, int k, + int l) +{ + int iList, hm, km, lm, i; + T_RTMx *lsmx; + T_Eq_hkl BufEq_hkl; + + + if (Eq_hkl == NULL) + Eq_hkl = &BufEq_hkl; + + Eq_hkl->M = 1; + Eq_hkl->N = 1; + Eq_hkl->h[0] = h; + Eq_hkl->k[0] = k; + Eq_hkl->l[0] = l; + Eq_hkl->TH[0] = 0; + + if (!(h || k || l)) + return Eq_hkl->M; /* this is 000 */ + + Eq_hkl->M++; + + /* check list of symmetry operations */ + + lsmx = &SgInfo->ListSeitzMx[1]; /* skip first = identity matrix */ + + for (iList = 1; iList < SgInfo->nList; iList++, lsmx++) { + hm = lsmx->s.R[0] * h + lsmx->s.R[3] * k + lsmx->s.R[6] * l; + km = lsmx->s.R[1] * h + lsmx->s.R[4] * k + lsmx->s.R[7] * l; + lm = lsmx->s.R[2] * h + lsmx->s.R[5] * k + lsmx->s.R[8] * l; + + for (i = 0; i < Eq_hkl->N; i++) { + if ((hm == Eq_hkl->h[i] && km == Eq_hkl->k[i] && lm == Eq_hkl->l[i]) + || (-hm == Eq_hkl->h[i] && -km == Eq_hkl->k[i] + && -lm == Eq_hkl->l[i])) + break; + } + + if (i == Eq_hkl->N) { + if (Eq_hkl->N >= 24) { + SetSgError(IErr_Inc_SymMx); + return 0; + } + + Eq_hkl->h[i] = hm; + Eq_hkl->k[i] = km; + Eq_hkl->l[i] = lm; + + Eq_hkl->TH[i] = (lsmx->s.T[0] * h + + lsmx->s.T[1] * k + lsmx->s.T[2] * l) % STBF; + if (Eq_hkl->TH[i] < 0) + Eq_hkl->TH[i] += STBF; + + Eq_hkl->M += 2; + Eq_hkl->N++; + } + } + + if (SgInfo->nList % Eq_hkl->N) { /* another error trap */ + SetSgError(IErr_Inc_SymMx); + return 0; + } + + return Eq_hkl->M; +} + + +int AreSymEquivalent_hkl(const T_SgInfo * SgInfo, int h1, int k1, int l1, + int h2, int k2, int l2) +{ + int iList, mh2, mk2, ml2, hm, km, lm; + T_RTMx *lsmx; + + + mh2 = -h2; + mk2 = -k2; + ml2 = -l2; + + /* check list of symmetry operations */ + + lsmx = SgInfo->ListSeitzMx; + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) { + hm = lsmx->s.R[0] * h1 + lsmx->s.R[3] * k1 + lsmx->s.R[6] * l1; + km = lsmx->s.R[1] * h1 + lsmx->s.R[4] * k1 + lsmx->s.R[7] * l1; + lm = lsmx->s.R[2] * h1 + lsmx->s.R[5] * k1 + lsmx->s.R[8] * l1; + + if (h2 == hm && k2 == km && l2 == lm) + return (iList + 1); + + else if (mh2 == hm && mk2 == km && ml2 == lm) + return -(iList + 1); + } + + return 0; +} + + +void SetListMin_hkl(const T_SgInfo * SgInfo, int Maxk, int Maxl, + int *Minh, int *Mink, int *Minl) +{ + *Minh = 0; + + switch (SgInfo->XtalSystem) { + case XS_Triclinic: + *Mink = -Maxk; + *Minl = -Maxl; + break; + case XS_Monoclinic: + if (SgInfo->UniqueRefAxis == 'z') { + *Mink = -Maxk; + *Minl = 0; + } else { + *Mink = 0; + *Minl = -Maxl; + } + break; + default: + if (SgInfo->XtalSystem == XS_Trigonal && SgInfo->UniqueDirCode == '*') + *Mink = -Maxk; + else + *Mink = 0; + *Minl = 0; + break; + } +} + + +int IsSuppressed_hkl(const T_SgInfo * SgInfo, int Minh, int Mink, int Minl, + int Maxk, int Maxl, int h, int k, int l) +{ + int iList, mate, hm, km, lm; + T_RTMx *lsmx; + + + /* check for Friedel mate first */ + + hm = -h, km = -k, lm = -l; + + if ((Minh <= hm && hm <= h) + && (Mink <= km && km <= Maxk) + && (Minl <= lm && lm <= Maxl)) { + if (hm < h) + return -1; + else /* if (h == 0) */ if (km < k) + return -1; + else if (k == 0) + if (lm < l) + return -1; + } + + lsmx = &SgInfo->ListSeitzMx[1]; /* skip first = identity matrix */ + + for (iList = 1; iList < SgInfo->nList; iList++, lsmx++) { + /* check if equivalent hm, km, lm are inside loop range ... */ + + hm = lsmx->s.R[0] * h + lsmx->s.R[3] * k + lsmx->s.R[6] * l; + km = lsmx->s.R[1] * h + lsmx->s.R[4] * k + lsmx->s.R[7] * l; + lm = lsmx->s.R[2] * h + lsmx->s.R[5] * k + lsmx->s.R[8] * l; + + for (mate = 0; mate < 2; mate++) { + if (mate) + hm = -hm, km = -km, lm = -lm; /* ... or friedel mate */ + + if (Minh <= hm && hm <= h + && Mink <= km && km <= Maxk && Minl <= lm && lm <= Maxl) { + /* ... and were processed before */ + + if (hm < h) + return (mate ? -(iList + 1) : iList + 1); + else /* if (hm == h) */ if (km < k) + return (mate ? -(iList + 1) : iList + 1); + else if (km == k) + if (lm < l) + return (mate ? -(iList + 1) : iList + 1); + } + } + } + + return 0; +} diff --git a/sginfo.c b/sginfo.c new file mode 100644 index 00000000..3e638576 --- /dev/null +++ b/sginfo.c @@ -0,0 +1,1943 @@ +/* + Space Group Info's (c) 1994-96 Ralf W. Grosse-Kunstleve + */ + +#include +#include +#include +#include + + +/* + Macintosh extras (Courtesy Jon Tischler ) + */ +#if defined(__THINK__) || defined(__MWERKS__) +#include +#define CONSOLE_LINES 36 /* number of lines to use for console */ +#define CONSOLE_COLUMNS 90 /* number of columns to use for console */ +#ifdef __MWERKS__ +#include +#endif +#endif + + +#define AppMalloc(ptr, n) (ptr) = malloc((n) * sizeof (*(ptr))) +#define AppFree(ptr, n) free(ptr) + + +#define SGCOREDEF__ +#include "sginfo.h" + + +#if USE_GS_SI + +static int PrimitiveRotMx(const int *CCMx_LP, int *RotMx, + const int *CCMx_PL, int deterCCMx_LP) +{ + int i; + int BufMx[9]; + + + /* Mp = Tlp . Mz . Tpl */ + + RotMxMultiply(BufMx, RotMx, CCMx_PL); + RotMxMultiply(RotMx, CCMx_LP, BufMx); + + for (i = 0; i < 9; i++) { + if (RotMx[i] % deterCCMx_LP) { + SetSgError("Internal Error: PrimitiveRotMx()"); + return -1; + } + } + + for (i = 0; i < 9; i++) + RotMx[i] /= deterCCMx_LP; + + return 0; +} + + +static int Find_si(T_SgInfo * SgInfo) +{ + static const int Tab_si_Vector[] = { + 1, 0, 0, 0, /* h */ + 0, 1, 0, 1, /* k */ + 0, 0, 1, 2, /* l */ + 1, 1, 0, 0, /* h+k */ + 1, -1, 0, 0, /* h-k */ + 0, 1, 1, 1, /* k+l */ + 0, 1, -1, 1, /* k-l */ + 1, 0, 1, 1, /* h+l */ + 1, 0, -1, 1, /* h-l */ + 1, 1, 1, 0, /* h+k+l */ + 1, 1, -1, 0, /* h+k-l */ + 1, -1, 1, 0, /* h-k+l */ + -1, 1, 1, 0, /* -h+k+l */ + 2, 1, -1, 0, /* 2h+k-l */ + 2, -1, 1, 0, /* 2h-k+l */ + -1, 2, 1, 0, /* -h+2k+l */ + 1, 2, -1, 0, /* h+2k-l */ + -1, 1, 2, 0, /* -h+k+2l */ + 1, -1, 2, 0 /* h-k+2l */ + }; + + static int nTab_si_Vector + = sizeof Tab_si_Vector / sizeof(*Tab_si_Vector) / 4; + + int deterCCMx_LP, CCMx_PL[9]; + int i, itabsiv; + int nLoopInv, iLoopInv, n_si_v, i_si_v; + int n, m, l; + int IsFine; + int item[3]; + int R_I[9], si_Buf[9]; + int iList; + T_RTMx *lsmx; + const int *tabsiv; + + + if (SgInfo->LatticeInfo->Code != 'P') { + deterCCMx_LP = deterRotMx(SgInfo->CCMx_LP); + InverseRotMx(SgInfo->CCMx_LP, CCMx_PL); + + if (deterCCMx_LP < 1) + goto ReturnError; + } + + nLoopInv = Sg_nLoopInv(SgInfo); + + SgInfo->n_si_Vector = n_si_v = 0; + + for (i = 0; i < 9; i++) + SgInfo->si_Vector[i] = 0; + + for (i = 0; i < 3; i++) { + SgInfo->si_Modulus[i] = 1; + item[i] = 1; + } + + tabsiv = Tab_si_Vector; + + for (itabsiv = 0; itabsiv < nTab_si_Vector; itabsiv++, tabsiv += 4) { + IsFine = 1; + m = -1; + + for (iList = 0; IsFine && iList < SgInfo->nList; iList++) { + lsmx = &SgInfo->ListSeitzMx[iList]; + + for (iLoopInv = 0; IsFine && iLoopInv < nLoopInv; iLoopInv++) { + if (iLoopInv == 0) + for (i = 0; i < 9; i++) { + if (i % 4) + R_I[i] = lsmx->s.R[i]; + else + R_I[i] = lsmx->s.R[i] - 1; + } else + for (i = 0; i < 9; i++) { + if (i % 4) + R_I[i] = -lsmx->s.R[i]; + else + R_I[i] = -lsmx->s.R[i] - 1; + } + + if (SgInfo->LatticeInfo->Code != 'P') { + if (PrimitiveRotMx(SgInfo->CCMx_LP, R_I, CCMx_PL, + deterCCMx_LP) < 0) + return -1; + } + + for (i = 0; IsFine && i < 3; i++) { + n = tabsiv[0] * R_I[i * 3 + 0]; + n += tabsiv[1] * R_I[i * 3 + 1]; + n += tabsiv[2] * R_I[i * 3 + 2]; + n = abs(n); + + if (n == 1) + IsFine = 0; + else if (m < 2) + m = n; + else if (n > 0 && n != m) + IsFine = 0; + } + } + } + + if (IsFine) { +#if DEBUG_Find_si + fprintf(stdout, "H-Kt %2d %2d %2d %d\n", + tabsiv[0], tabsiv[1], tabsiv[2], m); +#endif + + l = tabsiv[3]; + + while (item[l] > 1) { /* just "if", see break's */ + if (m == item[l]) + break; + + if (m == 3 && (SgInfo->XtalSystem != XS_Trigonal + || SgInfo->UniqueDirCode != '=')) + break; + + if (m == 4 && (SgInfo->XtalSystem == XS_Triclinic + || SgInfo->XtalSystem == XS_Monoclinic)) + break; + + if (m == 2) + break; + + /* if (m > 1 || m != 4) break; */ + + n_si_v--; + item[l] = 1; + break; + } + + if (item[l] == 1) { + if (itabsiv > 12) + n_si_v = 0; + + item[l] = m; + SgInfo->si_Modulus[n_si_v] = m; + + n = n_si_v * 3; + for (i = 0; i < 3; i++) + SgInfo->si_Vector[n++] = tabsiv[i]; + + n_si_v++; + } + } + } + +#if DEBUG_Find_si + fprintf(stdout, "H-Kt\n"); +#endif + + if (SgInfo->LatticeInfo->Code != 'P') { +#if DEBUG_Find_si + for (i = 0; i < n_si_v; i++) + fprintf(stdout, "H-Kp %2d %2d %2d %d\n", + SgInfo->si_Vector[i * 3 + 0], + SgInfo->si_Vector[i * 3 + 1], + SgInfo->si_Vector[i * 3 + 2], SgInfo->si_Modulus[i]); + fprintf(stdout, "H-Kp\n"); +#endif + + for (i_si_v = 0; i_si_v < n_si_v; i_si_v++) { + for (i = 0; i < 3; i++) { + si_Buf[i_si_v * 3 + i] + = SgInfo->si_Vector[i_si_v * 3 + 0] * CCMx_PL[i * 3 + 0] + + SgInfo->si_Vector[i_si_v * 3 + 1] * CCMx_PL[i * 3 + 1] + + SgInfo->si_Vector[i_si_v * 3 + 2] * CCMx_PL[i * 3 + 2]; + } + } + + for (i = 0; i < i_si_v * 3; i++) { + if (si_Buf[i] % deterCCMx_LP) { + n = i / 3; + n *= 3; + fprintf(stdout, " %3d %3d %3d\n", + si_Buf[n + 0], si_Buf[n + 1], si_Buf[n + 2]); + goto ReturnError; + } + + SgInfo->si_Vector[i] = si_Buf[i] / deterCCMx_LP; + } + } + + SgInfo->n_si_Vector = n_si_v; + return n_si_v; + +ReturnError: + + SetSgError("Internal Error: Find_si()"); + return -1; +} + + +static int Try_GS_si(T_SgInfo * SgInfo) +{ + int h, k, l, iList; + int Maxh, Maxk, Maxl; + int Minh, Mink, Minl; + int nTestField, *TestField; + int nProperty, *Property, *pp; + int IsFine, would_be, is; + + + SgInfo->n_si_Vector = -1; + + nTestField = 12 * 12 * 12; + AppMalloc(TestField, nTestField); + if (TestField == NULL) { + SetSgError("Not enough core"); + return -1; + } + + MarkLegalOrigins(SgInfo, TestField); + + Maxh = Maxk = Maxl = 7; + SetListMin_hkl(SgInfo, Maxk, Maxl, &Minh, &Mink, &Minl); + + nProperty = (Maxh - Minh + 1) + * (Maxk - Mink + 1) + * (Maxl - Minl + 1); + + AppMalloc(Property, nProperty); + if (Property == NULL) { + SetSgError("Not enough core"); + AppFree(TestField, nTestField); + return -1; + } + + pp = Property; + for (h = Minh; h <= Maxh; h++) + for (k = Mink; k <= Maxk; k++) + for (l = Minl; l <= Maxl; l++) { + iList = IsSysAbsent_hkl(SgInfo, h, k, l, NULL); + if (SgError != NULL) { + AppFree(Property, nProperty); + AppFree(TestField, nTestField); + return -1; + } + + if (iList == 0) + *pp++ = Verify_si(h, k, l, TestField); + else + *pp++ = -1; + } + + if (Find_si(SgInfo) >= 0) { + IsFine = 1; + + pp = Property; + for (h = Minh; IsFine && h <= Maxh; h++) + for (k = Mink; IsFine && k <= Maxk; k++) + for (l = Minl; IsFine && l <= Maxl; l++) { + is = *pp++; + + if (is >= 0) { + would_be = Is_si(SgInfo, h, k, l); + if (is != would_be) + IsFine = 0; + } + } + + if (IsFine) { + AppFree(Property, nProperty); + AppFree(TestField, nTestField); + return 0; + } + } + + SetSgError("Internal Error: Can't determine s.i. vectors and moduli"); + + AppFree(Property, nProperty); + AppFree(TestField, nTestField); + + return -1; +} + +#endif /* USE_GS_SI */ + + +static const char *progn = "sginfo"; + + +static void progerror(const char *message) +{ + fflush(stdout); + fprintf(stderr, "%s: %s\n", progn, message); + exit(1); +} + + +static void NotEnoughCore(void) +{ + progerror("Not enough core"); +} + + +static void PrintClearSgError(int ClearError, int CertainSgError) +{ + if (CertainSgError && SgError == NULL) + SetSgError("Internal Error: SgError not set but should be"); + + if (SgError) { + fprintf(stdout, "%s: %s\n", progn, SgError); + if (ClearError == 0) + exit(1); + SgError = NULL; + } +} + + +static int str_icmp(const char *s, const char *t) +{ + char cs, ct; + + while (*s || *t) { + cs = toupper(*s++); + ct = toupper(*t++); + if (cs < ct) + return -1; + if (cs > ct) + return 1; + } + return 0; +} + + +static int str_ibegin(const char *s1, const char *s2) +{ /* string ignore-case *//* begin */ + char u1, u2; + + while (*s1 && *s2) { + u1 = toupper(*s1++); + u2 = toupper(*s2++); + if (u1 < u2) + return -1; + else if (u1 > u2) + return 1; + } + if (*s2) + return -1; + return 0; +} + + +static const char *LegendTabSgName[] = { + "", + " Extensions", + " ----------", + " Monoclinic unique axis b unique axis c unique axis a", + " abc c-ba abc ba-c abc -acb", + " ------------ ------------ ------------", + " cell choice 1 :b1 :-b1 :c1 :-c1 :a1 :-a1", + " 2 :b2 :-b2 :c2 :-c2 :a2 :-a2", + " 3 :b3 :-b3 :c3 :-c3 :a3 :-a3", + "", + " Orthorhombic :ba-c change of basis abc -> ba-c", + " :1 origin choice 1", + " :2ba-c origin choice 2, change of basis abc -> ba-c", + "", + " Tetragonal :1 origin choice 1", + " Cubic :2 origin choice 2", + "", + " Trigonal :H hexagonal axes", + " :R rhombohedral axes", + "", + " Number Schoenflies Hermann-Mauguin Hall", + " ------ ----------- --------------- ----", + NULL, +}; + + +static void ListTabSgName(int WantedSgNumber, int VolLetter, FILE * fpout) +{ + int i; + const char *sgl, *ext, **ltsgn; + const T_TabSgName *tsgn, *show, *show_later; + + + if (WantedSgNumber == -1) + for (ltsgn = LegendTabSgName; *ltsgn; ltsgn++) + fprintf(fpout, "%s\n", *ltsgn); + + if (VolLetter == '1') + VolLetter = 'I'; + else + VolLetter = toupper(VolLetter); + + show = show_later = NULL; + + for (tsgn = TabSgName; tsgn->HallSymbol; tsgn++) { + if (WantedSgNumber == -1 || WantedSgNumber == tsgn->SgNumber) { + if (tsgn->SgNumber >= 3 && tsgn->SgNumber < 16) { + if (VolLetter == 'I') { + ext = tsgn->Extension; + if (*ext == '-') + ext++; + + if (tsgn->Extension[0] == 'b' + && (tsgn->Extension[1] == '\0' || tsgn->Extension[1] == '1')) + show_later = tsgn; + else if (ext[0] == 'c') { + if (ext[1] == '\0') + show = tsgn; + else { + i = 0; + for (sgl = tsgn->SgLabels; *sgl; sgl++) + if (*sgl == '=') + i++; + + if (i == 2) + show = tsgn; + } + } + } else if (VolLetter == 'A') { + if (tsgn->Extension[0] != '-' && tsgn->Extension[0] != 'a') + show = tsgn; + } else + show = tsgn; + } else if (tsgn->Extension[0] == 'H' && VolLetter == 'I') + show_later = tsgn; + else if (VolLetter == 'A' || VolLetter == 'I') { + if (tsgn->Extension[0] == '\0' || tsgn->Extension[1] == '\0') + show = tsgn; + } else + show = tsgn; + + if (show) { + putc(' ', fpout); + PrintTabSgNameEntry(show, 1, 0, fpout); + putc('\n', fpout); + show = NULL; + + if (show_later) { + putc(' ', fpout); + PrintTabSgNameEntry(show_later, 1, 0, fpout); + putc('\n', fpout); + show_later = NULL; + } + } + } + } +} + + +static void ListCIF(FILE * fpout) +{ + int n; + const char **loop, *lbl; + const T_TabSgName *tsgn; + + static const char *loop_monoclinic_extensions[] = { + "_monoclinic_extension # cf. _symmetry_space_group_id", + "_monoclinic_axis # cf. IT Vol. A 1983 sec. 2.16.", + "_monoclinic_setting # cf. IT Vol. A 1983 tab. 2.16.1.", + "_monoclinic_cellchoice # cf. IT Vol. A 1983 sec. 2.16.(i) & fig. 2.6.4.", + "", + " b b abc 1", + " b1 b abc 1", + " b2 b abc 2", + " b3 b abc 3", + "-b b c-ba 1", + "-b1 b c-ba 1", + "-b2 b c-ba 2", + "-b3 b c-ba 3", + " c c abc 1", + " c1 c abc 1", + " c2 c abc 2", + " c3 c abc 3", + "-c c ba-c 1", + "-c1 c ba-c 1", + "-c2 c ba-c 2", + "-c3 c ba-c 3", + " a a abc 1", + " a1 a abc 1", + " a2 a abc 2", + " a3 a abc 3", + "-a a -acb 1", + "-a1 a -acb 1", + "-a2 a -acb 2", + "-a3 a -acb 3", + NULL + }; + + static const char *loop_symmetry_space_group[] = { + "_symmetry_space_group_id", + "_symmetry_space_group_name_sch", + "_symmetry_space_group_name_h-m # recognised IUCr CIF data names", + "_symmetry_space_group_name_hall # recognised IUCr CIF data names", + NULL + }; + + + fprintf(fpout, "data_ notation\n\n"); + + fprintf(fpout, "loop_\n"); + + for (loop = loop_monoclinic_extensions; *loop; loop++) { + if ((*loop)[0]) + fprintf(fpout, " %s", *loop); + putc('\n', fpout); + } + + putc('\n', fpout); + putc('\n', fpout); + + fprintf(fpout, "loop_\n"); + + for (loop = loop_symmetry_space_group; *loop; loop++) { + if ((*loop)[0]) + fprintf(fpout, " %s", *loop); + putc('\n', fpout); + } + + putc('\n', fpout); + + for (tsgn = TabSgName; tsgn->HallSymbol; tsgn++) { + n = fprintf(fpout, " %3d", tsgn->SgNumber); + + if (tsgn->Extension[0]) + n += fprintf(fpout, ":%s", tsgn->Extension); + + if (tsgn->SgNumber < 1 || tsgn->SgNumber > 230) { + SetSgError("Internal Error: ListCIF()"); + return; + } + + while (n < 14) { + putc(' ', fpout); + n++; + } + putc(' ', fpout); + n++; + + n += fprintf(fpout, "%s", SchoenfliesSymbols[tsgn->SgNumber]); + + while (n < 22) { + putc(' ', fpout); + n++; + } + putc(' ', fpout); + n++; + + n += PrintFullHM_SgName(tsgn, '_', fpout); + + while (n < 36) { + putc(' ', fpout); + n++; + } + putc(' ', fpout); + + for (lbl = tsgn->HallSymbol; *lbl; lbl++) { + if (*lbl == ' ' && lbl != tsgn->HallSymbol) + putc('_', fpout); + else + putc(*lbl, fpout); + } + + putc('\n', fpout); + } +} + + +static void PutAllXYZ(const T_SgInfo * SgInfo, FILE * fpout) +{ + int iList, f, i; + int nTrV, iTrV, nLoopInv, iLoopInv; + const int *TrV; + T_RTMx SMx; + const T_RTMx *lsmx; + const char *xyz; + char buf0[8], buf1[8], buf2[8]; + + + nLoopInv = Sg_nLoopInv(SgInfo); + + nTrV = SgInfo->LatticeInfo->nTrVector; + TrV = SgInfo->LatticeInfo->TrVector; + + for (iTrV = 0; iTrV < nTrV; iTrV++, TrV += 3) { + for (iLoopInv = 0; iLoopInv < nLoopInv; iLoopInv++) { + if (iLoopInv == 0) + f = 1; + else + f = -1; + + lsmx = SgInfo->ListSeitzMx; + + if (nLoopInv > 1 || nTrV > 1) + putc('#', fpout); + + if (nTrV > 1) + fprintf(fpout, " +(%s %s %s)", + FormatFraction(TrV[0], STBF, 0, buf0, + sizeof buf0 / sizeof(*buf0)), + FormatFraction(TrV[1], STBF, 0, buf1, + sizeof buf1 / sizeof(*buf1)), + FormatFraction(TrV[2], STBF, 0, buf2, + sizeof buf2 / sizeof(*buf2))); + + if (nLoopInv > 1) + fprintf(fpout, " Inversion-Flag = %d", iLoopInv); + + if (nLoopInv > 1 || nTrV > 1) + putc('\n', fpout); + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) { + for (i = 0; i < 9; i++) + SMx.s.R[i] = f * lsmx->s.R[i]; + + for (i = 0; i < 3; i++) + SMx.s.T[i] = iModPositive(f * lsmx->s.T[i] + TrV[i], STBF); + + xyz = RTMx2XYZ(&SMx, 1, STBF, 0, 0, 1, ", ", NULL, 0); + if (xyz) + fprintf(fpout, "%s\n", xyz); + else { + SetSgError("Internal Error: PutAllXYZ()"); + return; + } + } + } + } + + putc('\n', fpout); +} + + +static void PutMaple(const T_SgInfo * SgInfo, FILE * fpout) +{ + int iList, f, i; + int nTrV, iTrV, nLoopInv, iLoopInv; + const int *TrV; + T_RTMx SMx; + const T_RTMx *lsmx; + int iMatrix; + char buf0[8], buf1[8], buf2[8]; + + + iMatrix = 0; + + nLoopInv = Sg_nLoopInv(SgInfo); + + nTrV = SgInfo->LatticeInfo->nTrVector; + TrV = SgInfo->LatticeInfo->TrVector; + + for (iTrV = 0; iTrV < nTrV; iTrV++, TrV += 3) { + for (iLoopInv = 0; iLoopInv < nLoopInv; iLoopInv++) { + if (iLoopInv == 0) + f = 1; + else + f = -1; + + lsmx = SgInfo->ListSeitzMx; + + if (nLoopInv > 1 || nTrV > 1) + putc('#', fpout); + + if (nTrV > 1) + fprintf(fpout, " +(%s %s %s)", + FormatFraction(TrV[0], STBF, 0, buf0, + sizeof buf0 / sizeof(*buf0)), + FormatFraction(TrV[1], STBF, 0, buf1, + sizeof buf1 / sizeof(*buf1)), + FormatFraction(TrV[2], STBF, 0, buf2, + sizeof buf2 / sizeof(*buf2))); + + if (nLoopInv > 1) + fprintf(fpout, " Inversion-Flag = %d", iLoopInv); + + if (nLoopInv > 1 || nTrV > 1) + putc('\n', fpout); + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) { + for (i = 0; i < 9; i++) + SMx.s.R[i] = f * lsmx->s.R[i]; + + for (i = 0; i < 3; i++) + SMx.s.T[i] = iModPositive(f * lsmx->s.T[i] + TrV[i], STBF); + + fprintf(fpout, "m%d", ++iMatrix); + PrintMapleRTMx(&SMx, 1, STBF, NULL, fpout); + } + } + } + + putc('\n', fpout); +} + + +static void PutSpaceSymFile(const T_SgInfo * SgInfo, FILE * fpout) +{ + unsigned int SgID; + int iList, SuppressMx, f, i; + int nTrV, iTrV, nLoopInv, iLoopInv; + const int *TrV; + const T_RTMx *lsmx; + const T_TabSgName *tsgn; + + + tsgn = SgInfo->TabSgName; + if (tsgn && tsgn->SgLabels == NULL) + tsgn = NULL; + + SgID = 0; + + if (tsgn != NULL) + SgID = SgID_Number(tsgn); + + fprintf(fpout, "%u '", SgID); + + if (tsgn != NULL) + PrintFullHM_SgName(tsgn, 0, fpout); + else if (SgInfo->HallSymbol[0]) + fprintf(fpout, "%s", SgInfo->HallSymbol); + else + fprintf(fpout, "Unknown"); + + putc('\'', fpout); + putc('\n', fpout); + + nLoopInv = Sg_nLoopInv(SgInfo); + + nTrV = SgInfo->LatticeInfo->nTrVector; + TrV = SgInfo->LatticeInfo->TrVector; + + iList = SgInfo->OrderL; + if (iList > 1) { + iList--; + SuppressMx = 1; + } else + SuppressMx = 0; + + fprintf(fpout, "%d\n", iList); + + for (iTrV = 0; iTrV < nTrV; iTrV++, TrV += 3) { + for (iLoopInv = 0; iLoopInv < nLoopInv; iLoopInv++) { + if (iLoopInv == 0) + f = 1; + else + f = -1; + + lsmx = SgInfo->ListSeitzMx; + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) { + if (SuppressMx == 0) { + for (i = 0; i < 3; i++) + fprintf(fpout, " %12.8f %12.8f %12.8f %12.8f\n", + (double) f * lsmx->s.R[3 * i + 0], + (double) f * lsmx->s.R[3 * i + 1], + (double) f * lsmx->s.R[3 * i + 2], + (double) iModPositive(f * lsmx->s.T[i] + TrV[i], + STBF) / STBF); + + putc(':', fpout); + putc('\n', fpout); + } + + SuppressMx = 0; + } + } + } +} + + +static void PutShelx(const T_SgInfo * SgInfo, FILE * fpout) +{ + int Latt_N = 0, iList; + const T_RTMx *lsmx; + const char *xyz; + + + if (SgInfo->InversionOffOrigin != 0) + fprintf(fpout, "***WARNING***: %s\n", + "Shelx manual: the origin MUST lie on a center of symmetry"); + + switch (SgInfo->LatticeInfo->Code) { + case 'P': + Latt_N = 1; + break; + case 'A': + Latt_N = 5; + break; + case 'B': + Latt_N = 6; + break; + case 'C': + Latt_N = 7; + break; + case 'I': + Latt_N = 2; + break; + case 'R': + if (SgInfo->ExtraInfo == EI_Obverse) + Latt_N = 3; + break; + case 'S': + case 'T': + SetSgError("Shelx supports R-obverse only"); + return; + case 'F': + Latt_N = 4; + break; + default: + goto ReturnError; + } + + /* N must be made negative if the structure is non-centrosymmetric + */ + if (SgInfo->Centric != -1) + Latt_N = -Latt_N; + + fprintf(fpout, "LATT %2d\n", Latt_N); + + lsmx = &SgInfo->ListSeitzMx[1]; /* skip first = identity matrix */ + + for (iList = 1; iList < SgInfo->nList; iList++, lsmx++) { + xyz = RTMx2XYZ(lsmx, 1, STBF, 1, 1, 0, ", ", NULL, 0); + if (xyz) + fprintf(fpout, "SYMM %s\n", xyz); + else + goto ReturnError; + } + + putc('\n', fpout); + + return; + +ReturnError: + + SetSgError("Internal Error: PutShelx()"); + return; +} + + +static void PutSchakal(const T_SgInfo * SgInfo, FILE * fpout) +{ + int iList, nMx, i; + int nTrV, iTrV; + const int *TrV; + T_RTMx SMx; + const T_RTMx *lsmx; + const char *xyz; + + + if (Sg_nLoopInv(SgInfo) == 2) + fprintf(fpout, "DU -x,-y,-z\n"); + + nTrV = SgInfo->LatticeInfo->nTrVector; + TrV = SgInfo->LatticeInfo->TrVector; + + if (nTrV > 1) { + fprintf(fpout, "DU"); + + InitRotMx(SMx.s.R, 1); + + TrV += 3; + + for (iTrV = 1; iTrV < nTrV; iTrV++, TrV += 3) { + for (i = 0; i < 3; i++) + SMx.s.T[i] = TrV[i]; + + xyz = RTMx2XYZ(&SMx, 1, STBF, 0, 0, 1, ",", NULL, 0); + if (xyz) { + if (iTrV > 1) + fprintf(fpout, " ;"); + + fprintf(fpout, " %s", xyz); + } else { + putc('\n', fpout); + goto ReturnError; + } + } + + putc('\n', fpout); + } + + nMx = 0; + + lsmx = &SgInfo->ListSeitzMx[1]; + + for (iList = 1; iList < SgInfo->nList; iList++, lsmx++) { + xyz = RTMx2XYZ(lsmx, 1, STBF, 0, 0, 1, ",", NULL, 0); + if (xyz) { + if (nMx % 4 == 0) { + if (nMx) + putc('\n', fpout); + fprintf(fpout, "SY %s", xyz); + } else + fprintf(fpout, " ; %s", xyz); + } else { + putc('\n', fpout); + goto ReturnError; + } + + nMx++; + } + + if (nMx) + putc('\n', fpout); + + putc('\n', fpout); + + return; + +ReturnError: + + SetSgError("Internal Error: PutSchakal()"); + return; +} + + +static void Simple_hklList(T_SgInfo * SgInfo, int Maxh, int Maxk, int Maxl, + int ListSysAbsent) +{ + int h, k, l, iList, restriction, M, n, i; + int Minh, Mink, Minl; + int uvw[3]; + int CCMx_PL[9], deterCCMx_LP = 0, hP, kP, lP; + + + if (SgInfo->LatticeInfo->Code != 'P') { + deterCCMx_LP = deterRotMx(SgInfo->CCMx_LP); + InverseRotMx(SgInfo->CCMx_LP, CCMx_PL); + + if (deterCCMx_LP < 1) + goto ReturnError; + } + + SetListMin_hkl(SgInfo, Maxk, Maxl, &Minh, &Mink, &Minl); + + fprintf(stdout, ">Begin hklList\n"); + + for (h = Minh; h <= Maxh; h++) + for (k = Mink; k <= Maxk; k++) + for (l = Minl; l <= Maxl; l++) { + iList = IsSysAbsent_hkl(SgInfo, h, k, l, &restriction); + if (SgError != NULL) + return; + + M = BuildEq_hkl(SgInfo, NULL, h, k, l); + if (SgError != NULL) + return; + + if (iList == 0) { + if ((iList = IsSuppressed_hkl(SgInfo, Minh, Mink, Minl, + Maxk, Maxl, h, k, l)) != 0) + n = fprintf(stdout, "# %3d %3d %3d %3d [%d]", + h, k, l, M, iList); + else + n = fprintf(stdout, " %3d %3d %3d %3d", h, k, l, M); + + if (restriction >= 0) { + while (n < 27) { + n++; + putc(' ', stdout); + } + n += fprintf(stdout, " %2d/%d", restriction, STBF); + } + + while (n < 34) { + n++; + putc(' ', stdout); + } + if (Is_si(SgInfo, h, k, l) == 1) + n += fprintf(stdout, " s.i."); + + while (n < 41) { + n++; + putc(' ', stdout); + } + Set_uvw(SgInfo, h, k, l, uvw); + for (i = 0; i < SgInfo->n_si_Vector; i++) + n += fprintf(stdout, " %3d", uvw[i]); + + if (SgInfo->LatticeInfo->Code != 'P') { + hP = h * CCMx_PL[0] + k * CCMx_PL[3] + l * CCMx_PL[6]; + kP = h * CCMx_PL[1] + k * CCMx_PL[4] + l * CCMx_PL[7]; + lP = h * CCMx_PL[2] + k * CCMx_PL[5] + l * CCMx_PL[8]; + + if (hP % deterCCMx_LP || kP % deterCCMx_LP + || lP % deterCCMx_LP) + goto ReturnError; + + hP /= deterCCMx_LP; + kP /= deterCCMx_LP; + lP /= deterCCMx_LP; + + while (n < 55) { + n++; + putc(' ', stdout); + } + n += fprintf(stdout, " P %3d %3d %3d", hP, kP, lP); + } + + putc('\n', stdout); + } else if (ListSysAbsent) + fprintf(stdout, "# %3d %3d %3d %3d (%d)\n", h, k, l, M, iList); + } + + fprintf(stdout, ">End hklList\n"); + + return; + +ReturnError: + + SetSgError("Internal Error: Simple_hklList()"); + return; +} + + +/* **************************************************************************** + some code for the handling of lattice constants + */ + + +#include + + +typedef struct { + double a, b, c; + double alpha, beta, gamma; + double sa, sb, sg; + double ca, cb, cg; + double v; + char calcs, calcc; +} T_LatticeConstants; + + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_PI_2 +#define M_PI_2 1.57079632679489661923 +#endif + +#define PIover180 (M_PI / 180.) + +#define EpsPI (1.e-6) /* ARBITRARY */ + + +static double sinC(double arg) +{ + if (M_PI_2 - EpsPI <= arg && arg <= M_PI_2 + EpsPI) + return 1.; + else + return sin(arg); +} + + +static double cosC(double arg) +{ + if (M_PI_2 - EpsPI <= arg && arg <= M_PI_2 + EpsPI) + return 0.; + else + return cos(arg); +} + + +static int Lc2RLc(T_LatticeConstants * lc, T_LatticeConstants * rlc) +{ + /* Transformation Lattice Constants -> Reciprocal Lattice Constants + after Kleber, W., 17. Aufl., Verlag Technik GmbH Berlin 1990, P.352 + */ + + double D; + + + if (lc->calcs) { + lc->sa = sinC(lc->alpha); + lc->sb = sinC(lc->beta); + lc->sg = sinC(lc->gamma); + lc->calcs = 0; + } + + if (lc->calcc) { + lc->ca = cosC(lc->alpha); + lc->cb = cosC(lc->beta); + lc->cg = cosC(lc->gamma); + lc->calcc = 0; + } + + D = 1. - lc->ca * lc->ca - lc->cb * lc->cb - lc->cg * lc->cg + + 2. * lc->ca * lc->cb * lc->cg; + if (D < 0.) + return -1; + + lc->v = lc->a * lc->b * lc->c * sqrt(D); + if (lc->v == 0.) + return -1; + + if (lc->sa == 0. || lc->sb == 0. || lc->sg == 0.) + return -1; + + if (rlc != NULL) { + rlc->a = lc->b * lc->c * lc->sa / lc->v; + rlc->b = lc->c * lc->a * lc->sb / lc->v; + rlc->c = lc->a * lc->b * lc->sg / lc->v; + rlc->ca = (lc->cb * lc->cg - lc->ca) / (lc->sb * lc->sg); + rlc->cb = (lc->cg * lc->ca - lc->cb) / (lc->sg * lc->sa); + rlc->cg = (lc->ca * lc->cb - lc->cg) / (lc->sa * lc->sb); + rlc->alpha = acos(rlc->ca); + rlc->beta = acos(rlc->cb); + rlc->gamma = acos(rlc->cg); + rlc->sa = sinC(rlc->alpha); + rlc->sb = sinC(rlc->beta); + rlc->sg = sinC(rlc->gamma); + rlc->v = 1. / lc->v; + rlc->calcs = 0; + rlc->calcc = 0; + } + + return 0; +} + + +static void Lc2MetricalMx(T_LatticeConstants * lc, double *G) +{ + G[0] = lc->a * lc->a; + G[1] = G[3] = lc->a * lc->b * lc->cg; + G[2] = G[6] = lc->a * lc->c * lc->cb; + + G[4] = lc->b * lc->b; + G[5] = G[7] = lc->b * lc->c * lc->ca; + + G[8] = lc->c * lc->c; +} + + +static int HarmonizeSgLatCon(T_SgInfo * SgInfo, T_LatticeConstants * lc, + int np) +{ + switch (SgInfo->XtalSystem) { + case XS_Triclinic: + if (np != 6) + goto IllUnitCell; + break; + case XS_Monoclinic: + if (np != 4 && np != 6) + goto IllUnitCell; + switch (SgInfo->UniqueRefAxis) { + case 'x': + lc->beta = lc->gamma = 90. * PIover180; + break; + case 'y': + if (np != 6) + lc->beta = lc->alpha; + lc->alpha = lc->gamma = 90. * PIover180; + break; + case 'z': + if (np != 6) + lc->gamma = lc->alpha; + lc->alpha = lc->beta = 90. * PIover180; + break; + default: + goto IntErr; + } + break; + case XS_Orthorhombic: + if (np != 3 && np != 6) + goto IllUnitCell; + lc->alpha = lc->beta = lc->gamma = 90. * PIover180; + break; + case XS_Tetragonal: + if (np != 2 && np != 6) + goto IllUnitCell; + switch (SgInfo->UniqueRefAxis) { + case 'x': + lc->c = lc->b; + break; + case 'y': + lc->c = lc->a; + break; + case 'z': + if (np != 6) + lc->c = lc->b; + lc->b = lc->a; + break; + default: + goto IntErr; + } + lc->alpha = lc->beta = lc->gamma = 90. * PIover180; + break; + case XS_Trigonal: + if (np != 2 && np != 6) + goto IllUnitCell; + if (SgInfo->UniqueDirCode == '*') { + if (np != 6) + lc->alpha = lc->b * PIover180; + lc->c = lc->b = lc->a; + lc->gamma = lc->beta = lc->alpha; + break; + } + case XS_Hexagonal: + if (np != 2 && np != 6) + goto IllUnitCell; + switch (SgInfo->UniqueRefAxis) { + case 'x': + lc->c = lc->b; + lc->alpha = 120. * PIover180; + lc->beta = lc->gamma = 90. * PIover180; + break; + case 'y': + lc->c = lc->a; + lc->beta = 120. * PIover180; + lc->alpha = lc->gamma = 90. * PIover180; + break; + case 'z': + if (np != 6) + lc->c = lc->b; + lc->b = lc->a; + lc->gamma = 120. * PIover180; + lc->alpha = lc->beta = 90. * PIover180; + break; + default: + goto IntErr; + } + break; + case XS_Cubic: + if (np != 1 && np != 6) + goto IllUnitCell; + lc->c = lc->b = lc->a; + lc->alpha = lc->beta = lc->gamma = 90. * PIover180; + break; + default: + goto IntErr; + } + + return 0; + +IntErr:SetSgError("Internal Error: HarmonizeSgLatCon()"); + return -1; + +IllUnitCell:SetSgError("Error: Illegal UnitCell or SpaceGroup"); + return -1; +} + + +static void MxMultiply(double *ab, double *a, double *b, int ma, int na, + int nb) +{ + int i, j, k; + double *ai, *aij, *bk, *bkj; + + ai = a; + + for (i = 0; i < ma; i++) { + bk = b; + + for (k = 0; k < nb; k++) { + aij = ai; + bkj = bk; + + *ab = 0.; + + for (j = 0; j < na; j++) { + *ab += (*aij) * (*bkj); + + aij++; + bkj += nb; + } + + ab++; + bk++; + } + + ai += na; + } +} + + +static int TransformLatticeConstants(T_LatticeConstants * LatConA, + int np, + T_LatticeConstants * LatConB, + T_SgInfo * SgInfo, int *InvCBMxR) +{ + int i, j; + double GA[9], GB[9], GAR[9], R[9], Rt[9]; + + + if (HarmonizeSgLatCon(SgInfo, LatConA, np) != 0) + return -1; + + LatConA->calcs = 1; + LatConA->calcc = 1; + + /* just to check LatConA and to compute sin and cos of angles + */ + if (Lc2RLc(LatConA, LatConB) != 0) { + SetSgError("Error: Illegal UnitCell"); + return -1; + } + + Lc2MetricalMx(LatConA, GA); + + for (i = 0; i < 3; i++) + for (j = 0; j < 3; j++) { + R[i * 3 + j] = InvCBMxR[i * 3 + j] / (double) CRBF; + Rt[i * 3 + j] = InvCBMxR[j * 3 + i] / (double) CRBF; + } + + MxMultiply(GAR, GA, R, 3, 3, 3); + MxMultiply(GB, Rt, GAR, 3, 3, 3); + + if (GB[0] < 0. || GB[4] < 0. || GB[8] < 0.) + goto ReturnError; + + LatConB->a = sqrt(GB[0]); + LatConB->b = sqrt(GB[4]); + LatConB->c = sqrt(GB[8]); + + LatConB->alpha = GB[5] / LatConB->b / LatConB->c; + LatConB->beta = GB[2] / LatConB->c / LatConB->a; + LatConB->gamma = GB[1] / LatConB->a / LatConB->b; + + if (LatConB->alpha < -1. || LatConB->alpha > 1. + || LatConB->beta < -1. || LatConB->beta > 1. + || LatConB->gamma < -1. || LatConB->gamma > 1.) + goto ReturnError; + + LatConB->alpha = acos(LatConB->alpha); + LatConB->beta = acos(LatConB->beta); + LatConB->gamma = acos(LatConB->gamma); + + LatConB->calcs = 1; + LatConB->calcc = 1; + + return 0; + +ReturnError: + + SetSgError("InternalError: Corrupt InvCBMxR"); + return -1; +} + + +/* **************************************************************************** + */ + + +static void usage(void) +{ + static const char *quick_help[] = { + "-Hall|VolA|VolI select conventions", + "-ListTable[=#] print [parts of] internal table", + "-CIF print internal table in CIF format", + "-XYZ print something like \"-x, y+1/2, z\"", + "-AllXYZ print all symmetry operations", + "-Maple print symmetry matrices in Maple format", + "-Space print symmetry file for AVS SpaceModule", + "-Shelx print Shelx LATT & SYMM cards", + "-Schakal print Schakal DU & SY cards", + "-hklList print simple hkl listing", + "-Standard compute transformation to \"standard\" setting", + "-UnitCell=\"a..g\" unit cell constants a, b, c, alpha, beta, gamma", + "-v be more verbose", + "-Verify debug option: verify transformations", + "-ClearError debug option: clear errors and continue", + NULL + }; + + const char **qh; + + + fprintf(stderr, + "usage: %s [options] [SpaceGroupName_or_# [SpaceGroupName_or_#]]\n", + progn); + + for (qh = quick_help; *qh; qh++) + fprintf(stderr, " %s\n", *qh); + + putc('\n', stderr); + + fprintf(stderr, "examples: %s 68\n", progn); + fprintf(stderr, " %s C2/m:c2 -XYZ\n", progn); + fprintf(stderr, " %s \"Oh^3\" -Shelx\n", progn); + fprintf(stderr, " %s -Hall \"-F 4y 2\" -Standard\n", progn); + fprintf(stderr, " %s -VolI 15 -VolA 15\n", progn); + fprintf(stderr, " %s -ListTable=68\n", progn); + + exit(1); +} + + +static void ShowCBMx(T_RTMx * CBMx, T_RTMx * InvCBMx, int F_Maple) +{ + if (F_Maple) { + PrintMapleRTMx(CBMx, CRBF, CTBF, " CBMx", stdout); + PrintMapleRTMx(InvCBMx, CRBF, CTBF, "InvCBMx", stdout); + } else { + fprintf(stdout, " CBMx = %s\n", + RTMx2XYZ(CBMx, CRBF, CTBF, 0, 0, 1, ", ", NULL, 0)); + fprintf(stdout, "InvCBMx = %s\n", + RTMx2XYZ(InvCBMx, CRBF, CTBF, 0, 0, 1, ", ", NULL, 0)); + } +} + + +typedef struct { + int Convention; + const char *SgName; + const T_TabSgName *InpTSgN; + const T_TabSgName *RefTSgN; + T_RTMx CBMx, InvCBMx; +} T_SgList; + + +int main(int argc, char *argv[]) +{ + int i, n, HaveSpace, pos_hsym; + int F_Convention, Last_F_Convention; + int F_ListTable, F_CIF; + int F_XYZ, F_AllXYZ, F_Maple; + int F_Space, F_Shelx, F_Schakal; + int F_hklList; + int F_Standard, F_UnitCell; + int F_Verbose, F_Verify, F_ClearError; + T_LatticeConstants LatConA, LatConB; + char *cp, xtrac; + const char *SgName; + const T_TabSgName *tsgn; + T_SgInfo SpgrInfo[2], BC_SgInfo, *SgInfo; + int nSgList, iSgList; + T_SgList SgList[2]; + T_RTMx *CBMx, *InvCBMx; + T_RTMx CCBMx, CInvCBMx; + + +/* + Macintosh extras (Courtesy Jon Tischler ) + */ +#ifdef __THINK__ + console_options.nrows = CONSOLE_LINES; + console_options.ncols = CONSOLE_COLUMNS; + console_options.title = "\psgInfo version 1.0.1"; +#endif +#ifdef __MWERKS__ + SIOUXSettings.autocloseonquit = FALSE; + SIOUXSettings.asktosaveonclose = TRUE; + SIOUXSettings.columns = CONSOLE_COLUMNS; + SIOUXSettings.rows = CONSOLE_LINES; +#endif +#if defined(__THINK__) || defined(__MWERKS__) + argc = ccommand(&argv); +#endif + + + nSgList = 0; + + F_Convention = 'A'; + Last_F_Convention = 0; + F_ListTable = 0; + F_CIF = 0; + F_XYZ = 0; + F_AllXYZ = 0; + F_Maple = 0; + F_Space = 0; + F_Shelx = 0; + F_Schakal = 0; + F_hklList = 0; + F_Standard = 0; + F_UnitCell = 0; + F_Verbose = 0; + F_Verify = 0; + F_ClearError = 0; + + for (i = 1; i < argc; i++) { + if (str_icmp(argv[i], "-Hall") == 0) { + F_Convention = 'H'; + Last_F_Convention = 0; + } else if (str_icmp(argv[i], "-VolA") == 0) { + F_Convention = 'A'; + Last_F_Convention = 'A'; + } else if (str_icmp(argv[i], "-VolI") == 0 + || str_icmp(argv[i], "-Vol1") == 0) { + F_Convention = 'I'; + Last_F_Convention = 'I'; + } else if (str_ibegin(argv[i], "-ListTable") == 0) { + cp = argv[i] + 10; + if (*cp == '\0') + F_ListTable = -1; + else if (*cp++ == '=') { + n = sscanf(cp, "%d%c", &F_ListTable, &xtrac); + if (n != 1 || F_ListTable < 1 || F_ListTable > 230) + usage(); + } else + usage(); + } else if (str_icmp(argv[i], "-CIF") == 0) + F_CIF = 1; + + else if (str_icmp(argv[i], "-XYZ") == 0) + F_XYZ = 1; + + else if (str_icmp(argv[i], "-AllXYZ") == 0) + F_AllXYZ = 1; + + else if (str_icmp(argv[i], "-Maple") == 0) + F_Maple = 1; + + else if (str_icmp(argv[i], "-Space") == 0) + F_Space = 1; + + else if (str_icmp(argv[i], "-Shelx") == 0) + F_Shelx = 1; + + else if (str_icmp(argv[i], "-Schakal") == 0) + F_Schakal = 1; + + else if (str_icmp(argv[i], "-hklList") == 0) + F_hklList = 1; + + else if (str_icmp(argv[i], "-Standard") == 0) + F_Standard = 1; + + else if (str_ibegin(argv[i], "-UnitCell=") == 0) { + F_UnitCell = sscanf(&argv[i][10], "%lf%lf%lf%lf%lf%lf", + &LatConA.a, &LatConA.b, &LatConA.c, + &LatConA.alpha, &LatConA.beta, &LatConA.gamma); + + if (F_UnitCell < 1) + usage(); + + if (F_UnitCell > 3) + LatConA.alpha *= PIover180; + if (F_UnitCell > 4) + LatConA.beta *= PIover180; + if (F_UnitCell > 5) + LatConA.gamma *= PIover180; + } else if (str_icmp(argv[i], "-v") == 0) + F_Verbose = 1; + + else if (str_icmp(argv[i], "-Verify") == 0) + F_Verify = 1; + + else if (str_icmp(argv[i], "-ClearError") == 0) + F_ClearError = 1; + + else if (nSgList < 2) { + SgName = argv[i]; + + while (*SgName == ' ' || *SgName == '\t') + SgName++; + + if (F_Convention == 'H' && isdigit(*SgName)) + SgList[nSgList].Convention = 'A'; + else + SgList[nSgList].Convention = F_Convention; + + SgList[nSgList].SgName = SgName; + SgList[nSgList].InpTSgN = NULL; + SgList[nSgList].RefTSgN = NULL; + + nSgList++; + } else + usage(); + } + + if (F_ListTable) { + ListTabSgName(F_ListTable, Last_F_Convention, stdout); + PrintClearSgError(1, 0); + putc('\n', stdout); + } + + if (F_CIF) { + ListCIF(stdout); + PrintClearSgError(1, 0); + putc('\n', stdout); + } + + if (nSgList == 0) { + if (F_ListTable == 0 && F_CIF == 0) + usage(); + else + exit(0); + } + + if (F_Space == 0) { + putc('#', stdout); + + for (i = 0; i < argc; i++) { + putc(' ', stdout); + + HaveSpace = 0; + + if (i) { + for (n = 0; argv[i][n]; n++) { + if (isspace(argv[i][n])) { + HaveSpace = 1; + break; + } + } + } + + if (HaveSpace == 0) + fprintf(stdout, "%s", argv[i]); + else { + putc('"', stdout); + + for (n = 0; argv[i][n]; n++) + if (argv[i][n] == '"') + putc('+', stdout); + else + putc(argv[i][n], stdout); + + putc('"', stdout); + } + } + + putc('\n', stdout); + } + + BC_SgInfo.MaxList = 0; + BC_SgInfo.ListSeitzMx = NULL; + BC_SgInfo.ListRotMxInfo = NULL; + + for (iSgList = 0; iSgList < nSgList; iSgList++) { + if (iSgList) + putc('\n', stdout); + + if (nSgList > 1 || F_Standard) + fprintf(stdout, "Setting %c:\n\n", "AB"[iSgList]); + + SgInfo = &SpgrInfo[iSgList]; + + SgInfo->MaxList = 192; + + SgInfo->ListSeitzMx + = malloc(SgInfo->MaxList * sizeof(*SgInfo->ListSeitzMx)); + if (SgInfo->ListSeitzMx == NULL) + NotEnoughCore(); + +#ifndef No_ListRotMxInfo + SgInfo->ListRotMxInfo + = malloc(SgInfo->MaxList * sizeof(*SgInfo->ListRotMxInfo)); + if (SgInfo->ListRotMxInfo == NULL) + NotEnoughCore(); +#else + SgInfo->ListRotMxInfo = NULL; +#endif + + F_Convention = SgList[iSgList].Convention; + SgName = SgList[iSgList].SgName; + + tsgn = NULL; + + if (F_Convention == 'A' || F_Convention == 'I') { + tsgn = FindTabSgNameEntry(SgName, F_Convention); + if (tsgn == NULL) { + PrintClearSgError(1, 0); + progerror("Error: Unknown Space Group Symbol"); + } + + if (F_Space == 0) { + fprintf(stdout, "Space Group "); + PrintTabSgNameEntry(tsgn, 0, 0, stdout); + putc('\n', stdout); + } + + SgName = tsgn->HallSymbol; + } + + SgList[iSgList].InpTSgN = tsgn; + + InitSgInfo(SgInfo); + + SgInfo->TabSgName = tsgn; + if (tsgn) + SgInfo->GenOption = 1; + + pos_hsym = ParseHallSymbol(SgName, SgInfo); + + if (SgError != NULL) { + fprintf(stdout, " %s\n", SgName); + for (i = 0; i < pos_hsym; i++) + putc('-', stdout); + fprintf(stdout, "---^\n"); + fprintf(stdout, "%s\n", SgError); + exit(1); + } + + if (CompleteSgInfo(SgInfo) != 0) + PrintClearSgError(F_ClearError, 1); + + if (tsgn == NULL && F_Space == 0) { + if (SgInfo->TabSgName) { + fprintf(stdout, "Space Group "); + PrintTabSgNameEntry(SgInfo->TabSgName, 0, 0, stdout); + putc('\n', stdout); + } else + fprintf(stdout, "Hall Symbol %s\n", SgInfo->HallSymbol); + } + + PrintClearSgError(F_ClearError, 0); + +#if USE_GS_SI + if (Try_GS_si(SgInfo) < 0) +#else + if (Set_si(SgInfo) < 0) +#endif + PrintClearSgError(F_ClearError, 1); + + if (F_Space == 0) { + ListSgInfo(SgInfo, F_XYZ, F_Verbose, stdout); + PrintClearSgError(F_ClearError, 0); + } + + if (F_AllXYZ) { + PutAllXYZ(SgInfo, stdout); + PrintClearSgError(F_ClearError, 0); + } + + if (F_Maple) { + PutMaple(SgInfo, stdout); + PrintClearSgError(F_ClearError, 0); + } + + if (F_Space) { + PutSpaceSymFile(SgInfo, stdout); + PrintClearSgError(F_ClearError, 0); + } + + if (F_Shelx) { + PutShelx(SgInfo, stdout); + PrintClearSgError(F_ClearError, 0); + } + + if (F_Schakal) { + PutSchakal(SgInfo, stdout); + PrintClearSgError(F_ClearError, 0); + } + + if (F_hklList) { + Simple_hklList(SgInfo, 4, 4, 4, F_Verbose); + PrintClearSgError(F_ClearError, 0); + } + + if (nSgList > 1 || F_Standard) { + CBMx = &SgList[iSgList].CBMx; + InvCBMx = &SgList[iSgList].InvCBMx; + + SgList[iSgList].RefTSgN = FindReferenceSpaceGroup(SgInfo, + CBMx, InvCBMx); + PrintClearSgError(F_ClearError, 0); + + if (SgList[iSgList].RefTSgN) { + if (F_Verbose || F_Verify) { + fprintf(stdout, "Change of Basis => Reference Setting "); + PrintTabSgNameEntry(SgList[iSgList].RefTSgN, 0, 0, stdout); + putc('\n', stdout); + + ShowCBMx(CBMx, InvCBMx, F_Maple); + PrintClearSgError(F_ClearError, 0); + } + + if (F_Verify) { + if (BC_SgInfo.MaxList == 0) { + BC_SgInfo.MaxList = 192; + + BC_SgInfo.ListSeitzMx + = + malloc(BC_SgInfo.MaxList * sizeof(*BC_SgInfo.ListSeitzMx)); + if (BC_SgInfo.ListSeitzMx == NULL) + NotEnoughCore(); + + BC_SgInfo.ListRotMxInfo + = + malloc(BC_SgInfo.MaxList * + sizeof(*BC_SgInfo.ListRotMxInfo)); + if (BC_SgInfo.ListRotMxInfo == NULL) + NotEnoughCore(); + } + + InitSgInfo(&BC_SgInfo); + + if (TransformSgInfo(SgInfo, CBMx, InvCBMx, &BC_SgInfo) == 0) + CompleteSgInfo(&BC_SgInfo); + + if (SgError) { + PrintClearSgError(F_ClearError, 0); + SgList[iSgList].RefTSgN = NULL; + } else if (BC_SgInfo.TabSgName != SgList[iSgList].RefTSgN) { + fprintf(stdout, "Hall Symbol %s\n", BC_SgInfo.HallSymbol); + SetSgError("Verify Error: Wrong CBMx/InvCBMx"); + PrintClearSgError(F_ClearError, 0); + SgList[iSgList].RefTSgN = NULL; + } else + fprintf(stdout, "Verify O.K.\n\n"); + } + } + + tsgn = SgList[iSgList].RefTSgN; + if (tsgn && F_Standard && nSgList == 1) { + if (Last_F_Convention == 'A' || Last_F_Convention == 'I') + SgList[nSgList].Convention = Last_F_Convention; + else + SgList[nSgList].Convention = 'A'; + + SgList[nSgList].SgName = SchoenfliesSymbols[tsgn->SgNumber]; + SgList[nSgList].InpTSgN = NULL; + SgList[nSgList].RefTSgN = NULL; + + nSgList++; + } + } + } + + if (nSgList == 2 + && SgList[0].RefTSgN && SgList[1].RefTSgN + && SgList[0].RefTSgN->SgNumber == SgList[1].RefTSgN->SgNumber) { + putc('\n', stdout); + fprintf(stdout, "Change of Basis Setting A -> Setting B:\n"); + + RTMxMultiply(&CCBMx, &SgList[1].InvCBMx, &SgList[0].CBMx, + CRBF, CRBF * CTBF); + RTMxMultiply(&CInvCBMx, &SgList[0].InvCBMx, &SgList[1].CBMx, + CRBF, CRBF * CTBF); + + for (i = 0; i < 12; i++) { + if (CCBMx.a[i] % CRBF) + break; + if (CInvCBMx.a[i] % CRBF) + break; + + CCBMx.a[i] /= CRBF; + CInvCBMx.a[i] /= CRBF; + } + + if (i < 12) { + SetSgError("Internal Error: Can't combine CBMx's"); + PrintClearSgError(1, 1); + } else { + ShowCBMx(&CCBMx, &CInvCBMx, F_Maple); + PrintClearSgError(F_ClearError, 0); + + if (F_Verify) { + InitSgInfo(&BC_SgInfo); + + if (TransformSgInfo(&SpgrInfo[0], &CCBMx, &CInvCBMx, &BC_SgInfo) == + 0) + CompleteSgInfo(&BC_SgInfo); + + if (SgError) + PrintClearSgError(F_ClearError, 1); + + else if (strcmp(SpgrInfo[1].HallSymbol, BC_SgInfo.HallSymbol) != 0) { + fprintf(stdout, "Hall Symbol %s\n", SpgrInfo[1].HallSymbol); + fprintf(stdout, "Hall Symbol %s\n", BC_SgInfo.HallSymbol); + SetSgError("Verify Error: Wrong CBMx/InvCBMx"); + PrintClearSgError(F_ClearError, 1); + } else + fprintf(stdout, "Verify O.K.\n"); + } + + if (F_UnitCell) { + putc('\n', stdout); + + if (TransformLatticeConstants(&LatConA, F_UnitCell, + &LatConB, &SpgrInfo[0], + CInvCBMx.s.R) != 0) + PrintClearSgError(0, 1); + + fprintf(stdout, + "Setting A UnitCell %.6g %.6g %.6g %.6g %.6g %.6g\n", + LatConA.a, LatConA.b, LatConA.c, + LatConA.alpha / PIover180, + LatConA.beta / PIover180, LatConA.gamma / PIover180); + + fprintf(stdout, + "Setting B UnitCell %.6g %.6g %.6g %.6g %.6g %.6g\n", + LatConB.a, LatConB.b, LatConB.c, + LatConB.alpha / PIover180, + LatConB.beta / PIover180, LatConB.gamma / PIover180); + } + } + + putc('\n', stdout); + } + + exit(0); /* old VAX didn't like "return 0;" */ + return 0; +} diff --git a/sginfo.h b/sginfo.h new file mode 100644 index 00000000..adb23c1f --- /dev/null +++ b/sginfo.h @@ -0,0 +1,1773 @@ +/* + Space Group Info's (c) 1994-96 Ralf W. Grosse-Kunstleve + */ + +#ifndef SGINFO_H__ +#define SGINFO_H__ + + +#ifndef SGCLIB_C__ +extern +const char *SgError; +#ifdef SGCOREDEF__ +extern +char SgErrorBuffer[128]; +#endif +#else +const char *SgError = NULL; +char SgErrorBuffer[128]; +#endif + + +#define STBF 12 /* Seitz Matrix Translation Base Factor */ + +#define CRBF 12 /* Change of Basis Matrix Rotation Base Factor */ +#define CTBF 72 /* Change of Basis Matrix Translation Base Factor */ + +/* CAUTION: (CTBF / STBF) has to be an INTEGER */ + + +typedef struct { + int Code; + int nTrVector; + int *TrVector; +} T_LatticeInfo; + + +typedef union { + struct { + int R[9], T[3]; + } s; + int a[12]; +} T_RTMx; + + +typedef struct { + int EigenVector[3]; + int Order; + int Inverse; + int RefAxis; + int DirCode; +} T_RotMxInfo; + + +typedef struct { + const char *HallSymbol; + int SgNumber; + const char *Extension; + const char *SgLabels; +} T_TabSgName; + + +#define MaxLenHallSymbol 39 + + +typedef struct { + int GenOption; + int Centric; + int InversionOffOrigin; + const T_LatticeInfo *LatticeInfo; + int StatusLatticeTr; + int OriginShift[3]; + int nList; + int MaxList; + T_RTMx *ListSeitzMx; + T_RotMxInfo *ListRotMxInfo; + int OrderL; + int OrderP; + int XtalSystem; + int UniqueRefAxis; + int UniqueDirCode; + int ExtraInfo; + int PointGroup; + int nGenerator; + int Generator_iList[4]; + char HallSymbol[MaxLenHallSymbol + 1]; + const T_TabSgName *TabSgName; + const int *CCMx_LP; + int n_si_Vector; + int si_Vector[9]; + int si_Modulus[3]; +} T_SgInfo; + +/* T_Sginfo.GenOption: 0 = full group generation + 1 = trusted: + set Centric/InversionOffOrigin/LatticeInfo only + -1 = no group generation + + T_Sginfo.Centric: 0 = acentric + 1 = inversion in list + -1 = inversion removed from list + + T_Sginfo.StatusLatticeTr: 0 = removed from list + 1 = all translation vectors in list + -1 = some translation vectors could be + missing in list + */ + + +typedef struct { + int M; /* Multiplicity */ + int N; /* Number of equivalent hkl to follow */ + int h[24]; /* If hkl == 000 M = N = 1 */ + int k[24]; /* If hkl != 000 M = 2 * N */ + int l[24]; /* List of hkl does not contain friedel mates */ + int TH[24]; /* Phase shift relative to h[0], k[0], l[0] */ +} T_Eq_hkl; + + +#define EI_Unknown 0 +#define EI_Enantiomorphic 1 +#define EI_Obverse 2 +#define EI_Reverse 3 + +#ifndef SGCLIB_C__ +extern +const char *EI_Name[]; +#else +const char *EI_Name[] = { + "Unknown", + "Enantiomorphic", + "Obverse", + "Reverse" +}; +#endif + + +#define XS_Unknown 0 +#define XS_Triclinic 1 +#define XS_Monoclinic 2 +#define XS_Orthorhombic 3 +#define XS_Tetragonal 4 +#define XS_Trigonal 5 +#define XS_Hexagonal 6 +#define XS_Cubic 7 + +#ifndef SGCLIB_C__ +extern +const char *XS_Name[]; +#else +const char *XS_Name[] = { + "Unknown", + "Triclinic", + "Monoclinic", + "Orthorhombic", + "Tetragonal", + "Trigonal", + "Hexagonal", + "Cubic" +}; +#endif + + +#define Make_PG_Code( i, p, l) (((i) * 33 + (p)) * 12 + (l)) +#define PG_Unknown Make_PG_Code( 0, 0, 0) +#define PG_1 Make_PG_Code( 1, 1, 1) +#define PG_1b Make_PG_Code( 2, 2, 1) +#define PG_2 Make_PG_Code( 3, 3, 2) +#define PG_m Make_PG_Code( 4, 4, 2) +#define PG_2_m Make_PG_Code( 5, 5, 2) +#define PG_222 Make_PG_Code( 6, 6, 3) +#define PG_mm2 Make_PG_Code( 7, 7, 3) +#define PG_mmm Make_PG_Code( 8, 8, 3) +#define PG_4 Make_PG_Code( 9, 9, 4) +#define PG_4b Make_PG_Code(10, 10, 4) +#define PG_4_m Make_PG_Code(11, 11, 4) +#define PG_422 Make_PG_Code(12, 12, 5) +#define PG_4mm Make_PG_Code(13, 13, 5) +#define PG_4b2m Make_PG_Code(14, 14, 5) +#define PG_4bm2 Make_PG_Code(15, 14, 5) +#define PG_4_mmm Make_PG_Code(16, 15, 5) +#define PG_3 Make_PG_Code(17, 16, 6) +#define PG_3b Make_PG_Code(18, 17, 6) +#define PG_321 Make_PG_Code(19, 18, 7) +#define PG_312 Make_PG_Code(20, 18, 7) +#define PG_32 Make_PG_Code(21, 18, 7) +#define PG_3m1 Make_PG_Code(22, 19, 7) +#define PG_31m Make_PG_Code(23, 19, 7) +#define PG_3m Make_PG_Code(24, 19, 7) +#define PG_3bm1 Make_PG_Code(25, 20, 7) +#define PG_3b1m Make_PG_Code(26, 20, 7) +#define PG_3bm Make_PG_Code(27, 20, 7) +#define PG_6 Make_PG_Code(28, 21, 8) +#define PG_6b Make_PG_Code(29, 22, 8) +#define PG_6_m Make_PG_Code(30, 23, 8) +#define PG_622 Make_PG_Code(31, 24, 9) +#define PG_6mm Make_PG_Code(32, 25, 9) +#define PG_6bm2 Make_PG_Code(33, 26, 9) +#define PG_6b2m Make_PG_Code(34, 26, 9) +#define PG_6_mmm Make_PG_Code(35, 27, 9) +#define PG_23 Make_PG_Code(36, 28, 10) +#define PG_m3b Make_PG_Code(37, 29, 10) +#define PG_432 Make_PG_Code(38, 30, 11) +#define PG_4b3m Make_PG_Code(39, 31, 11) +#define PG_m3bm Make_PG_Code(40, 32, 11) + +#define PG_Index(PG_Code) ((PG_Code) / (33 * 12)) +#define PG_Number(PG_Code) (((PG_Code) / 12) % 33) +#define LG_Number(PG_Code) ((PG_Code) % (33 * 12)) + +#ifndef SGCLIB_C__ +extern +const int LG_Code_of_PG_Index[]; +#else +const int LG_Code_of_PG_Index[] = { + PG_Unknown, + PG_1b, + PG_1b, + PG_2_m, + PG_2_m, + PG_2_m, + PG_mmm, + PG_mmm, + PG_mmm, + PG_4_m, + PG_4_m, + PG_4_m, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_3b, + PG_3b, + PG_3bm1, + PG_3b1m, + PG_3bm, + PG_3bm1, + PG_3b1m, + PG_3bm, + PG_3bm1, + PG_3b1m, + PG_3bm, + PG_6_m, + PG_6_m, + PG_6_m, + PG_6_mmm, + PG_6_mmm, + PG_6_mmm, + PG_6_mmm, + PG_6_mmm, + PG_m3b, + PG_m3b, + PG_m3bm, + PG_m3bm, + PG_m3bm +}; +#endif /* SGCLIB_C__ */ + +#ifndef SGCLIB_C__ +extern +const char *PG_Names[]; +#else +const char *PG_Names[] = { + "Unknown", + "1", + "-1", + "2", + "m", + "2/m", + "222", + "mm2", + "mmm", + "4", + "-4", + "4/m", + "422", + "4mm", + "-42m", + "-4m2", + "4/mmm", + "3", + "-3", + "321", + "312", + "32", + "3m1", + "31m", + "3m", + "-3m1", + "-31m", + "-3m", + "6", + "-6", + "6/m", + "622", + "6mm", + "-6m2", + "-62m", + "6/mmm", + "23", + "m-3", + "432", + "-43m", + "m-3m" +}; +#endif /* SGCLIB_C__ */ + + +#ifndef SGCLIB_C__ +#ifdef SGCOREDEF__ +extern const T_LatticeInfo LI_P[]; +extern const T_LatticeInfo LI_A[]; +extern const T_LatticeInfo LI_B[]; +extern const T_LatticeInfo LI_C[]; +extern const T_LatticeInfo LI_I[]; +extern const T_LatticeInfo LI_R[]; +extern const T_LatticeInfo LI_S[]; +extern const T_LatticeInfo LI_T[]; +extern const T_LatticeInfo LI_F[]; +#endif +#else +#define T(i) ((i) * (STBF / 12)) +static int LTr_P[] = { T(0), T(0), T(0) +}; +const T_LatticeInfo LI_P[] = { {'P', 1, LTr_P} +}; +static int LTr_A[] = { T(0), T(0), T(0), + T(0), T(6), T(6) +}; +const T_LatticeInfo LI_A[] = { {'A', 2, LTr_A} +}; +static int LTr_B[] = { T(0), T(0), T(0), + T(6), T(0), T(6) +}; +const T_LatticeInfo LI_B[] = { {'B', 2, LTr_B} +}; +static int LTr_C[] = { T(0), T(0), T(0), + T(6), T(6), T(0) +}; +const T_LatticeInfo LI_C[] = { {'C', 2, LTr_C} +}; +static int LTr_I[] = { T(0), T(0), T(0), + T(6), T(6), T(6) +}; +const T_LatticeInfo LI_I[] = { {'I', 2, LTr_I} +}; +static int LTr_R[] = { T(0), T(0), T(0), + T(8), T(4), T(4), + T(4), T(8), T(8) +}; +const T_LatticeInfo LI_R[] = { {'R', 3, LTr_R} +}; +static int LTr_S[] = { T(0), T(0), T(0), + T(4), T(4), T(8), + T(8), T(8), T(4) +}; +const T_LatticeInfo LI_S[] = { {'S', 3, LTr_S} +}; +static int LTr_T[] = { T(0), T(0), T(0), + T(4), T(8), T(4), + T(8), T(4), T(8) +}; +const T_LatticeInfo LI_T[] = { {'T', 3, LTr_T} +}; +static int LTr_F[] = { T(0), T(0), T(0), + T(0), T(6), T(6), + T(6), T(0), T(6), + T(6), T(6), T(0) +}; +const T_LatticeInfo LI_F[] = { {'F', 4, LTr_F} +}; + +#undef T +#endif /* SGCLIB_C__ */ + +/* + lattice code + R S T + unique axis + 3z obv - rev + 3y rev obv - + 3x - rev obv + */ + + +#ifndef SGCLIB_C__ +#ifdef SGCOREDEF__ +extern +const int CCMx_PP[]; +extern +const int CCMx_AP[]; +extern +const int CCMx_BP[]; +extern +const int CCMx_CP[]; +extern +const int CCMx_IP[]; +extern +const int CCMx_RP_z[]; +extern +const int CCMx_SP_y[]; +extern +const int CCMx_TP_x[]; +extern +const int CCMx_TP_z[]; +extern +const int CCMx_RP_y[]; +extern +const int CCMx_SP_x[]; +extern +const int CCMx_FI_z[]; +extern +const int CCMx_FI_y[]; +extern +const int CCMx_FI_x[]; +extern +const int CCMx_FP[]; +#endif +#else +const int CCMx_PP[] = { 1, 0, 0, /* Change of Basis Matrices */ + 0, 1, 0, /* (coordinate transformations) */ + 0, 0, 1 +}; +const int CCMx_AP[] = { -1, 0, 0, + 0, -1, 1, + 0, 1, 1 +}; +const int CCMx_BP[] = { -1, 0, 1, + 0, -1, 0, + 1, 0, 1 +}; +const int CCMx_CP[] = { 1, 1, 0, + 1, -1, 0, + 0, 0, -1 +}; +const int CCMx_IP[] = { 0, 1, 1, + 1, 0, 1, + 1, 1, 0 +}; +const int CCMx_RP_z[] = { 1, 0, 1, + -1, 1, 1, + 0, -1, 1 +}; +const int CCMx_SP_y[] = { 1, 1, -1, + -1, 1, 0, + 0, 1, 1 +}; +const int CCMx_TP_x[] = { 1, 0, -1, + 1, 1, 0, + 1, -1, 1 +}; +const int CCMx_TP_z[] = { -1, 0, 1, + 1, -1, 1, + 0, 1, 1 +}; +const int CCMx_RP_y[] = { -1, 1, 1, + 1, 1, 0, + 0, 1, -1 +}; +const int CCMx_SP_x[] = { 1, 0, 1, + 1, -1, 0, + 1, 1, -1 +}; +const int CCMx_FI_z[] = { 1, 1, 0, + -1, 1, 0, + 0, 0, 1 +}; +const int CCMx_FI_y[] = { 1, 0, -1, + 0, 1, 0, + 1, 0, 1 +}; +const int CCMx_FI_x[] = { 1, 0, 0, + 0, 1, 1, + 0, -1, 1 +}; +const int CCMx_FP[] = { -1, 1, 1, + 1, -1, 1, + 1, 1, -1 +}; +#endif /* SGCLIB_C__ */ + + +#if defined(SGCLIB_C__) || defined(SGCOREDEF__) +typedef struct { + int Order; + int EigenVector[3]; + int DirCode; + int RMx[9]; +} T_TabXtalRotMx; +#endif + + +#ifndef SGCLIB_C__ +#ifdef SGCOREDEF__ +extern +const T_TabXtalRotMx TabXtalRotMx[]; +#endif +#else +const T_TabXtalRotMx TabXtalRotMx[] = { + /* # EigenVector DirCode */ + + { /* [ 0] */ 1, {0, 0, 0}, '.', /* CAUTION: */ + {1, 0, 0, /* Reorganizing this table */ + 0, 1, 0, /* affects RMx_????? below. */ + 0, 0, 1} + }, + { /* [ 1] */ 2, {0, 0, 1}, '=', + {-1, 0, 0, + 0, -1, 0, + 0, 0, 1} + }, + { /* [ 2] */ 2, {1, 0, 0}, '=', /* hexagonal */ + {1, -1, 0, + 0, -1, 0, + 0, 0, -1} + }, + { /* [ 3] */ 2, {0, 1, 0}, '=', /* hexagonal */ + {-1, 0, 0, + -1, 1, 0, + 0, 0, -1} + }, + { /* [ 4] */ 2, {1, 1, 0}, '"', + {0, 1, 0, + 1, 0, 0, + 0, 0, -1} + }, + { /* [ 5] */ 2, {1, -1, 0}, '\'', + {0, -1, 0, + -1, 0, 0, + 0, 0, -1} + }, + { /* [ 6] */ 2, {2, 1, 0}, '|', /* hexagonal */ + {1, 0, 0, + 1, -1, 0, + 0, 0, -1} + }, + { /* [ 7] */ 2, {1, 2, 0}, '\\', /* hexagonal */ + {-1, 1, 0, + 0, 1, 0, + 0, 0, -1} + }, + { /* [ 8] */ 3, {0, 0, 1}, '=', + {0, -1, 0, + 1, -1, 0, + 0, 0, 1} + }, + { /* [ 9] */ 3, {1, 1, 1}, '*', + {0, 0, 1, + 1, 0, 0, + 0, 1, 0} + }, + { /* [10] */ 4, {0, 0, 1}, '=', + {0, -1, 0, + 1, 0, 0, + 0, 0, 1} + }, + { /* [11] */ 6, {0, 0, 1}, '=', + {1, -1, 0, + 1, 0, 0, + 0, 0, 1} + }, + {0, {0, 0, 0}, 0, + {0, 0, 0, + 0, 0, 0, + 0, 0, 0} + } +}; +#endif /* SGCLIB_C__ */ + + +#ifndef SGCLIB_C__ +#ifdef SGCOREDEF__ +extern +const int *RMx_1_000; +extern +const int *RMx_2_001; +extern +const int *RMx_2_110; +extern +const int *RMx_3_001; +extern +const int *RMx_3_111; +extern +const int RMx_3i111[]; +extern +const int *RMx_4_001; +extern +const int RMx_4i001[]; +#endif +#else +const int *RMx_1_000 = TabXtalRotMx[0].RMx; +const int *RMx_2_001 = TabXtalRotMx[1].RMx; +const int *RMx_2_110 = TabXtalRotMx[4].RMx; +const int *RMx_3_001 = TabXtalRotMx[8].RMx; +const int *RMx_3_111 = TabXtalRotMx[9].RMx; +const int RMx_3i111[] = { + 0, 1, 0, + 0, 0, 1, + 1, 0, 0 +}; +const int *RMx_4_001 = TabXtalRotMx[10].RMx; +const int RMx_4i001[] = { + 0, 1, 0, + -1, 0, 0, + 0, 0, 1 +}; +#endif /* SGCLIB_C__ */ + + +#ifndef SGCLIB_C__ +#ifdef SGCOREDEF__ +extern +const int HallTranslations[]; +#endif +#else +#define T(i) ((i) * (STBF / 12)) +const int HallTranslations[] = { + 'n', T(6), T(6), T(6), + 'a', T(6), T(0), T(0), + 'b', T(0), T(6), T(0), + 'c', T(0), T(0), T(6), + 'd', T(3), T(3), T(3), + 'u', T(3), T(0), T(0), + 'v', T(0), T(3), T(0), + 'w', T(0), T(0), T(3), + 0 +}; + +#undef T +#endif + + +#ifndef SGCLIB_C__ +#ifdef SGCOREDEF__ +extern +const int VolAPointGroups[]; +#endif +#else +const int VolAPointGroups[] = { + PG_Unknown, + PG_1, + PG_1b, + PG_2, + PG_2, + PG_2, + PG_m, + PG_m, + PG_m, + PG_m, + PG_2_m, + PG_2_m, + PG_2_m, + PG_2_m, + PG_2_m, + PG_2_m, + PG_222, + PG_222, + PG_222, + PG_222, + PG_222, + PG_222, + PG_222, + PG_222, + PG_222, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_4, + PG_4, + PG_4, + PG_4, + PG_4, + PG_4, + PG_4b, + PG_4b, + PG_4_m, + PG_4_m, + PG_4_m, + PG_4_m, + PG_4_m, + PG_4_m, + PG_422, + PG_422, + PG_422, + PG_422, + PG_422, + PG_422, + PG_422, + PG_422, + PG_422, + PG_422, + PG_4mm, + PG_4mm, + PG_4mm, + PG_4mm, + PG_4mm, + PG_4mm, + PG_4mm, + PG_4mm, + PG_4mm, + PG_4mm, + PG_4mm, + PG_4mm, + PG_4b2m, + PG_4b2m, + PG_4b2m, + PG_4b2m, + PG_4bm2, + PG_4bm2, + PG_4bm2, + PG_4bm2, + PG_4bm2, + PG_4bm2, + PG_4b2m, + PG_4b2m, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_3, + PG_3, + PG_3, + PG_3, + PG_3b, + PG_3b, + PG_312, + PG_321, + PG_312, + PG_321, + PG_312, + PG_321, + PG_32, + PG_3m1, + PG_31m, + PG_3m1, + PG_31m, + PG_3m, + PG_3m, + PG_3b1m, + PG_3b1m, + PG_3bm1, + PG_3bm1, + PG_3bm, + PG_3bm, + PG_6, + PG_6, + PG_6, + PG_6, + PG_6, + PG_6, + PG_6b, + PG_6_m, + PG_6_m, + PG_622, + PG_622, + PG_622, + PG_622, + PG_622, + PG_622, + PG_6mm, + PG_6mm, + PG_6mm, + PG_6mm, + PG_6bm2, + PG_6bm2, + PG_6b2m, + PG_6b2m, + PG_6_mmm, + PG_6_mmm, + PG_6_mmm, + PG_6_mmm, + PG_23, + PG_23, + PG_23, + PG_23, + PG_23, + PG_m3b, + PG_m3b, + PG_m3b, + PG_m3b, + PG_m3b, + PG_m3b, + PG_m3b, + PG_432, + PG_432, + PG_432, + PG_432, + PG_432, + PG_432, + PG_432, + PG_432, + PG_4b3m, + PG_4b3m, + PG_4b3m, + PG_4b3m, + PG_4b3m, + PG_4b3m, + PG_m3bm, + PG_m3bm, + PG_m3bm, + PG_m3bm, + PG_m3bm, + PG_m3bm, + PG_m3bm, + PG_m3bm, + PG_m3bm, + PG_m3bm +}; +#endif /* SGCLIB_C__ */ + + +#ifndef SGCLIB_C__ +#ifdef SGCOREDEF__ +extern +const char *SchoenfliesSymbols[]; +#endif +#else +const char *SchoenfliesSymbols[] = { + NULL, + "C1^1", + "Ci^1", + "C2^1", + "C2^2", + "C2^3", + "Cs^1", + "Cs^2", + "Cs^3", + "Cs^4", + "C2h^1", + "C2h^2", + "C2h^3", + "C2h^4", + "C2h^5", + "C2h^6", + "D2^1", + "D2^2", + "D2^3", + "D2^4", + "D2^5", + "D2^6", + "D2^7", + "D2^8", + "D2^9", + "C2v^1", + "C2v^2", + "C2v^3", + "C2v^4", + "C2v^5", + "C2v^6", + "C2v^7", + "C2v^8", + "C2v^9", + "C2v^10", + "C2v^11", + "C2v^12", + "C2v^13", + "C2v^14", + "C2v^15", + "C2v^16", + "C2v^17", + "C2v^18", + "C2v^19", + "C2v^20", + "C2v^21", + "C2v^22", + "D2h^1", + "D2h^2", + "D2h^3", + "D2h^4", + "D2h^5", + "D2h^6", + "D2h^7", + "D2h^8", + "D2h^9", + "D2h^10", + "D2h^11", + "D2h^12", + "D2h^13", + "D2h^14", + "D2h^15", + "D2h^16", + "D2h^17", + "D2h^18", + "D2h^19", + "D2h^20", + "D2h^21", + "D2h^22", + "D2h^23", + "D2h^24", + "D2h^25", + "D2h^26", + "D2h^27", + "D2h^28", + "C4^1", + "C4^2", + "C4^3", + "C4^4", + "C4^5", + "C4^6", + "S4^1", + "S4^2", + "C4h^1", + "C4h^2", + "C4h^3", + "C4h^4", + "C4h^5", + "C4h^6", + "D4^1", + "D4^2", + "D4^3", + "D4^4", + "D4^5", + "D4^6", + "D4^7", + "D4^8", + "D4^9", + "D4^10", + "C4v^1", + "C4v^2", + "C4v^3", + "C4v^4", + "C4v^5", + "C4v^6", + "C4v^7", + "C4v^8", + "C4v^9", + "C4v^10", + "C4v^11", + "C4v^12", + "D2d^1", + "D2d^2", + "D2d^3", + "D2d^4", + "D2d^5", + "D2d^6", + "D2d^7", + "D2d^8", + "D2d^9", + "D2d^10", + "D2d^11", + "D2d^12", + "D4h^1", + "D4h^2", + "D4h^3", + "D4h^4", + "D4h^5", + "D4h^6", + "D4h^7", + "D4h^8", + "D4h^9", + "D4h^10", + "D4h^11", + "D4h^12", + "D4h^13", + "D4h^14", + "D4h^15", + "D4h^16", + "D4h^17", + "D4h^18", + "D4h^19", + "D4h^20", + "C3^1", + "C3^2", + "C3^3", + "C3^4", + "C3i^1", + "C3i^2", + "D3^1", + "D3^2", + "D3^3", + "D3^4", + "D3^5", + "D3^6", + "D3^7", + "C3v^1", + "C3v^2", + "C3v^3", + "C3v^4", + "C3v^5", + "C3v^6", + "D3d^1", + "D3d^2", + "D3d^3", + "D3d^4", + "D3d^5", + "D3d^6", + "C6^1", + "C6^2", + "C6^3", + "C6^4", + "C6^5", + "C6^6", + "C3h^1", + "C6h^1", + "C6h^2", + "D6^1", + "D6^2", + "D6^3", + "D6^4", + "D6^5", + "D6^6", + "C6v^1", + "C6v^2", + "C6v^3", + "C6v^4", + "D3h^1", + "D3h^2", + "D3h^3", + "D3h^4", + "D6h^1", + "D6h^2", + "D6h^3", + "D6h^4", + "T^1", + "T^2", + "T^3", + "T^4", + "T^5", + "Th^1", + "Th^2", + "Th^3", + "Th^4", + "Th^5", + "Th^6", + "Th^7", + "O^1", + "O^2", + "O^3", + "O^4", + "O^5", + "O^6", + "O^7", + "O^8", + "Td^1", + "Td^2", + "Td^3", + "Td^4", + "Td^5", + "Td^6", + "Oh^1", + "Oh^2", + "Oh^3", + "Oh^4", + "Oh^5", + "Oh^6", + "Oh^7", + "Oh^8", + "Oh^9", + "Oh^10" +}; +#endif /* SGCLIB_C__ */ + + +#ifndef SGCLIB_C__ +#ifdef SGCOREDEF__ +extern +const T_TabSgName TabSgName[]; +#endif +#else +const T_TabSgName TabSgName[] = { + {" P 1", 1, "", "P_1"}, + {"-P 1", 2, "", "P_-1"}, + {" P 2y", 3, "b", "P_2 = P_1_2_1"}, + {" P 2", 3, "c", "P_2 = P_1_1_2"}, + {" P 2x", 3, "a", "P_2 = P_2_1_1"}, + {" P 2yb", 4, "b", "P_21 = P_1_21_1"}, + {" P 2c", 4, "c", "P_21 = P_1_1_21"}, + {" P 2xa", 4, "a", "P_21 = P_21_1_1"}, + {" C 2y", 5, "b1", "C_2 = C_1_2_1"}, + {" A 2y", 5, "b2", "C_2 = A_1_2_1"}, + {" I 2y", 5, "b3", "C_2 = I_1_2_1"}, + {" A 2", 5, "c1", "C_2 = A_1_1_2"}, + {" B 2", 5, "c2", "C_2 = B_1_1_2 = B_2"}, + {" I 2", 5, "c3", "C_2 = I_1_1_2"}, + {" B 2x", 5, "a1", "C_2 = B_2_1_1"}, + {" C 2x", 5, "a2", "C_2 = C_2_1_1"}, + {" I 2x", 5, "a3", "C_2 = I_2_1_1"}, + {" P -2y", 6, "b", "P_m = P_1_m_1"}, + {" P -2", 6, "c", "P_m = P_1_1_m"}, + {" P -2x", 6, "a", "P_m = P_m_1_1"}, + {" P -2yc", 7, "b1", "P_c = P_1_c_1"}, + {" P -2yac", 7, "b2", "P_c = P_1_n_1"}, + {" P -2ya", 7, "b3", "P_c = P_1_a_1"}, + {" P -2a", 7, "c1", "P_c = P_1_1_a"}, + {" P -2ab", 7, "c2", "P_c = P_1_1_n"}, + {" P -2b", 7, "c3", "P_c = P_1_1_b = P_b"}, + {" P -2xb", 7, "a1", "P_c = P_b_1_1"}, + {" P -2xbc", 7, "a2", "P_c = P_n_1_1"}, + {" P -2xc", 7, "a3", "P_c = P_c_1_1"}, + {" C -2y", 8, "b1", "C_m = C_1_m_1"}, + {" A -2y", 8, "b2", "C_m = A_1_m_1"}, + {" I -2y", 8, "b3", "C_m = I_1_m_1"}, + {" A -2", 8, "c1", "C_m = A_1_1_m"}, + {" B -2", 8, "c2", "C_m = B_1_1_m = B_m"}, + {" I -2", 8, "c3", "C_m = I_1_1_m"}, + {" B -2x", 8, "a1", "C_m = B_m_1_1"}, + {" C -2x", 8, "a2", "C_m = C_m_1_1"}, + {" I -2x", 8, "a3", "C_m = I_m_1_1"}, + {" C -2yc", 9, "b1", "C_c = C_1_c_1"}, + {" A -2yac", 9, "b2", "C_c = A_1_n_1"}, + {" I -2ya", 9, "b3", "C_c = I_1_a_1"}, + {" A -2ya", 9, "-b1", "C_c = A_1_a_1"}, + {" C -2ybc", 9, "-b2", "C_c = C_1_n_1"}, + {" I -2yc", 9, "-b3", "C_c = I_1_c_1"}, + {" A -2a", 9, "c1", "C_c = A_1_1_a"}, + {" B -2bc", 9, "c2", "C_c = B_1_1_n"}, + {" I -2b", 9, "c3", "C_c = I_1_1_b"}, + {" B -2b", 9, "-c1", "C_c = B_1_1_b = B_b"}, + {" A -2ac", 9, "-c2", "C_c = A_1_1_n"}, + {" I -2a", 9, "-c3", "C_c = I_1_1_a"}, + {" B -2xb", 9, "a1", "C_c = B_b_1_1"}, + {" C -2xbc", 9, "a2", "C_c = C_n_1_1"}, + {" I -2xc", 9, "a3", "C_c = I_c_1_1"}, + {" C -2xc", 9, "-a1", "C_c = C_c_1_1"}, + {" B -2xbc", 9, "-a2", "C_c = B_n_1_1"}, + {" I -2xb", 9, "-a3", "C_c = I_b_1_1"}, + {"-P 2y", 10, "b", "P_2/m = P_1_2/m_1"}, + {"-P 2", 10, "c", "P_2/m = P_1_1_2/m"}, + {"-P 2x", 10, "a", "P_2/m = P_2/m_1_1"}, + {"-P 2yb", 11, "b", "P_21/m = P_1_21/m_1"}, + {"-P 2c", 11, "c", "P_21/m = P_1_1_21/m"}, + {"-P 2xa", 11, "a", "P_21/m = P_21/m_1_1"}, + {"-C 2y", 12, "b1", "C_2/m = C_1_2/m_1"}, + {"-A 2y", 12, "b2", "C_2/m = A_1_2/m_1"}, + {"-I 2y", 12, "b3", "C_2/m = I_1_2/m_1"}, + {"-A 2", 12, "c1", "C_2/m = A_1_1_2/m"}, + {"-B 2", 12, "c2", "C_2/m = B_1_1_2/m = B_2/m"}, + {"-I 2", 12, "c3", "C_2/m = I_1_1_2/m"}, + {"-B 2x", 12, "a1", "C_2/m = B_2/m_1_1"}, + {"-C 2x", 12, "a2", "C_2/m = C_2/m_1_1"}, + {"-I 2x", 12, "a3", "C_2/m = I_2/m_1_1"}, + {"-P 2yc", 13, "b1", "P_2/c = P_1_2/c_1"}, + {"-P 2yac", 13, "b2", "P_2/c = P_1_2/n_1"}, + {"-P 2ya", 13, "b3", "P_2/c = P_1_2/a_1"}, + {"-P 2a", 13, "c1", "P_2/c = P_1_1_2/a"}, + {"-P 2ab", 13, "c2", "P_2/c = P_1_1_2/n"}, + {"-P 2b", 13, "c3", "P_2/c = P_1_1_2/b = P_2/b"}, + {"-P 2xb", 13, "a1", "P_2/c = P_2/b_1_1"}, + {"-P 2xbc", 13, "a2", "P_2/c = P_2/n_1_1"}, + {"-P 2xc", 13, "a3", "P_2/c = P_2/c_1_1"}, + {"-P 2ybc", 14, "b1", "P_21/c = P_1_21/c_1"}, + {"-P 2yn", 14, "b2", "P_21/c = P_1_21/n_1"}, + {"-P 2yab", 14, "b3", "P_21/c = P_1_21/a_1"}, + {"-P 2ac", 14, "c1", "P_21/c = P_1_1_21/a"}, + {"-P 2n", 14, "c2", "P_21/c = P_1_1_21/n"}, + {"-P 2bc", 14, "c3", "P_21/c = P_1_1_21/b = P_21/b"}, + {"-P 2xab", 14, "a1", "P_21/c = P_21/b_1_1"}, + {"-P 2xn", 14, "a2", "P_21/c = P_21/n_1_1"}, + {"-P 2xac", 14, "a3", "P_21/c = P_21/c_1_1"}, + {"-C 2yc", 15, "b1", "C_2/c = C_1_2/c_1"}, + {"-A 2yac", 15, "b2", "C_2/c = A_1_2/n_1"}, + {"-I 2ya", 15, "b3", "C_2/c = I_1_2/a_1"}, + {"-A 2ya", 15, "-b1", "C_2/c = A_1_2/a_1"}, + {"-C 2ybc", 15, "-b2", "C_2/c = C_1_2/n_1"}, + {"-I 2yc", 15, "-b3", "C_2/c = I_1_2/c_1"}, + {"-A 2a", 15, "c1", "C_2/c = A_1_1_2/a"}, + {"-B 2bc", 15, "c2", "C_2/c = B_1_1_2/n"}, + {"-I 2b", 15, "c3", "C_2/c = I_1_1_2/b"}, + {"-B 2b", 15, "-c1", "C_2/c = B_1_1_2/b = B_2/b"}, + {"-A 2ac", 15, "-c2", "C_2/c = A_1_1_2/n"}, + {"-I 2a", 15, "-c3", "C_2/c = I_1_1_2/a"}, + {"-B 2xb", 15, "a1", "C_2/c = B_2/b_1_1"}, + {"-C 2xbc", 15, "a2", "C_2/c = C_2/n_1_1"}, + {"-I 2xc", 15, "a3", "C_2/c = I_2/c_1_1"}, + {"-C 2xc", 15, "-a1", "C_2/c = C_2/c_1_1"}, + {"-B 2xbc", 15, "-a2", "C_2/c = B_2/n_1_1"}, + {"-I 2xb", 15, "-a3", "C_2/c = I_2/b_1_1"}, + {" P 2 2", 16, "", "P_2_2_2"}, + {" P 2c 2", 17, "", "P_2_2_21"}, + {" P 2a 2a", 17, "cab", "P_21_2_2"}, + {" P 2 2b", 17, "bca", "P_2_21_2"}, + {" P 2 2ab", 18, "", "P_21_21_2"}, + {" P 2bc 2", 18, "cab", "P_2_21_21"}, + {" P 2ac 2ac", 18, "bca", "P_21_2_21"}, + {" P 2ac 2ab", 19, "", "P_21_21_21"}, + {" C 2c 2", 20, "", "C_2_2_21"}, + {" A 2a 2a", 20, "cab", "A_21_2_2"}, + {" B 2 2b", 20, "bca", "B_2_21_2"}, + {" C 2 2", 21, "", "C_2_2_2"}, + {" A 2 2", 21, "cab", "A_2_2_2"}, + {" B 2 2", 21, "bca", "B_2_2_2"}, + {" F 2 2", 22, "", "F_2_2_2"}, + {" I 2 2", 23, "", "I_2_2_2"}, + {" I 2b 2c", 24, "", "I_21_21_21"}, + {" P 2 -2", 25, "", "P_m_m_2"}, + {" P -2 2", 25, "cab", "P_2_m_m"}, + {" P -2 -2", 25, "bca", "P_m_2_m"}, + {" P 2c -2", 26, "", "P_m_c_21"}, + {" P 2c -2c", 26, "ba-c", "P_c_m_21"}, + {" P -2a 2a", 26, "cab", "P_21_m_a"}, + {" P -2 2a", 26, "-cba", "P_21_a_m"}, + {" P -2 -2b", 26, "bca", "P_b_21_m"}, + {" P -2b -2", 26, "a-cb", "P_m_21_b"}, + {" P 2 -2c", 27, "", "P_c_c_2"}, + {" P -2a 2", 27, "cab", "P_2_a_a"}, + {" P -2b -2b", 27, "bca", "P_b_2_b"}, + {" P 2 -2a", 28, "", "P_m_a_2"}, + {" P 2 -2b", 28, "ba-c", "P_b_m_2"}, + {" P -2b 2", 28, "cab", "P_2_m_b"}, + {" P -2c 2", 28, "-cba", "P_2_c_m"}, + {" P -2c -2c", 28, "bca", "P_c_2_m"}, + {" P -2a -2a", 28, "a-cb", "P_m_2_a"}, + {" P 2c -2ac", 29, "", "P_c_a_21"}, + {" P 2c -2b", 29, "ba-c", "P_b_c_21"}, + {" P -2b 2a", 29, "cab", "P_21_a_b"}, + {" P -2ac 2a", 29, "-cba", "P_21_c_a"}, + {" P -2bc -2c", 29, "bca", "P_c_21_b"}, + {" P -2a -2ab", 29, "a-cb", "P_b_21_a"}, + {" P 2 -2bc", 30, "", "P_n_c_2"}, + {" P 2 -2ac", 30, "ba-c", "P_c_n_2"}, + {" P -2ac 2", 30, "cab", "P_2_n_a"}, + {" P -2ab 2", 30, "-cba", "P_2_a_n"}, + {" P -2ab -2ab", 30, "bca", "P_b_2_n"}, + {" P -2bc -2bc", 30, "a-cb", "P_n_2_b"}, + {" P 2ac -2", 31, "", "P_m_n_21"}, + {" P 2bc -2bc", 31, "ba-c", "P_n_m_21"}, + {" P -2ab 2ab", 31, "cab", "P_21_m_n"}, + {" P -2 2ac", 31, "-cba", "P_21_n_m"}, + {" P -2 -2bc", 31, "bca", "P_n_21_m"}, + {" P -2ab -2", 31, "a-cb", "P_m_21_n"}, + {" P 2 -2ab", 32, "", "P_b_a_2"}, + {" P -2bc 2", 32, "cab", "P_2_c_b"}, + {" P -2ac -2ac", 32, "bca", "P_c_2_a"}, + {" P 2c -2n", 33, "", "P_n_a_21"}, + {" P 2c -2ab", 33, "ba-c", "P_b_n_21"}, + {" P -2bc 2a", 33, "cab", "P_21_n_b"}, + {" P -2n 2a", 33, "-cba", "P_21_c_n"}, + {" P -2n -2ac", 33, "bca", "P_c_21_n"}, + {" P -2ac -2n", 33, "a-cb", "P_n_21_a"}, + {" P 2 -2n", 34, "", "P_n_n_2"}, + {" P -2n 2", 34, "cab", "P_2_n_n"}, + {" P -2n -2n", 34, "bca", "P_n_2_n"}, + {" C 2 -2", 35, "", "C_m_m_2"}, + {" A -2 2", 35, "cab", "A_2_m_m"}, + {" B -2 -2", 35, "bca", "B_m_2_m"}, + {" C 2c -2", 36, "", "C_m_c_21"}, + {" C 2c -2c", 36, "ba-c", "C_c_m_21"}, + {" A -2a 2a", 36, "cab", "A_21_m_a"}, + {" A -2 2a", 36, "-cba", "A_21_a_m"}, + {" B -2 -2b", 36, "bca", "B_b_21_m"}, + {" B -2b -2", 36, "a-cb", "B_m_21_b"}, + {" C 2 -2c", 37, "", "C_c_c_2"}, + {" A -2a 2", 37, "cab", "A_2_a_a"}, + {" B -2b -2b", 37, "bca", "B_b_2_b"}, + {" A 2 -2", 38, "", "A_m_m_2"}, + {" B 2 -2", 38, "ba-c", "B_m_m_2"}, + {" B -2 2", 38, "cab", "B_2_m_m"}, + {" C -2 2", 38, "-cba", "C_2_m_m"}, + {" C -2 -2", 38, "bca", "C_m_2_m"}, + {" A -2 -2", 38, "a-cb", "A_m_2_m"}, + {" A 2 -2c", 39, "", "A_b_m_2"}, + {" B 2 -2c", 39, "ba-c", "B_m_a_2"}, + {" B -2c 2", 39, "cab", "B_2_c_m"}, + {" C -2b 2", 39, "-cba", "C_2_m_b"}, + {" C -2b -2b", 39, "bca", "C_m_2_a"}, + {" A -2c -2c", 39, "a-cb", "A_c_2_m"}, + {" A 2 -2a", 40, "", "A_m_a_2"}, + {" B 2 -2b", 40, "ba-c", "B_b_m_2"}, + {" B -2b 2", 40, "cab", "B_2_m_b"}, + {" C -2c 2", 40, "-cba", "C_2_c_m"}, + {" C -2c -2c", 40, "bca", "C_c_2_m"}, + {" A -2a -2a", 40, "a-cb", "A_m_2_a"}, + {" A 2 -2ac", 41, "", "A_b_a_2"}, + {" B 2 -2bc", 41, "ba-c", "B_b_a_2"}, + {" B -2bc 2", 41, "cab", "B_2_c_b"}, + {" C -2bc 2", 41, "-cba", "C_2_c_b"}, + {" C -2bc -2bc", 41, "bca", "C_c_2_a"}, + {" A -2ac -2ac", 41, "a-cb", "A_c_2_a"}, + {" F 2 -2", 42, "", "F_m_m_2"}, + {" F -2 2", 42, "cab", "F_2_m_m"}, + {" F -2 -2", 42, "bca", "F_m_2_m"}, + {" F 2 -2d", 43, "", "F_d_d_2"}, + {" F -2d 2", 43, "cab", "F_2_d_d"}, + {" F -2d -2d", 43, "bca", "F_d_2_d"}, + {" I 2 -2", 44, "", "I_m_m_2"}, + {" I -2 2", 44, "cab", "I_2_m_m"}, + {" I -2 -2", 44, "bca", "I_m_2_m"}, + {" I 2 -2c", 45, "", "I_b_a_2"}, + {" I -2a 2", 45, "cab", "I_2_c_b"}, + {" I -2b -2b", 45, "bca", "I_c_2_a"}, + {" I 2 -2a", 46, "", "I_m_a_2"}, + {" I 2 -2b", 46, "ba-c", "I_b_m_2"}, + {" I -2b 2", 46, "cab", "I_2_m_b"}, + {" I -2c 2", 46, "-cba", "I_2_c_m"}, + {" I -2c -2c", 46, "bca", "I_c_2_m"}, + {" I -2a -2a", 46, "a-cb", "I_m_2_a"}, + {"-P 2 2", 47, "", "P_m_m_m"}, + {" P 2 2 -1n", 48, "1", "P_n_n_n"}, + {"-P 2ab 2bc", 48, "2", "P_n_n_n"}, + {"-P 2 2c", 49, "", "P_c_c_m"}, + {"-P 2a 2", 49, "cab", "P_m_a_a"}, + {"-P 2b 2b", 49, "bca", "P_b_m_b"}, + {" P 2 2 -1ab", 50, "1", "P_b_a_n"}, + {"-P 2ab 2b", 50, "2", "P_b_a_n"}, + {" P 2 2 -1bc", 50, "1cab", "P_n_c_b"}, + {"-P 2b 2bc", 50, "2cab", "P_n_c_b"}, + {" P 2 2 -1ac", 50, "1bca", "P_c_n_a"}, + {"-P 2a 2c", 50, "2bca", "P_c_n_a"}, + {"-P 2a 2a", 51, "", "P_m_m_a"}, + {"-P 2b 2", 51, "ba-c", "P_m_m_b"}, + {"-P 2 2b", 51, "cab", "P_b_m_m"}, + {"-P 2c 2c", 51, "-cba", "P_c_m_m"}, + {"-P 2c 2", 51, "bca", "P_m_c_m"}, + {"-P 2 2a", 51, "a-cb", "P_m_a_m"}, + {"-P 2a 2bc", 52, "", "P_n_n_a"}, + {"-P 2b 2n", 52, "ba-c", "P_n_n_b"}, + {"-P 2n 2b", 52, "cab", "P_b_n_n"}, + {"-P 2ab 2c", 52, "-cba", "P_c_n_n"}, + {"-P 2ab 2n", 52, "bca", "P_n_c_n"}, + {"-P 2n 2bc", 52, "a-cb", "P_n_a_n"}, + {"-P 2ac 2", 53, "", "P_m_n_a"}, + {"-P 2bc 2bc", 53, "ba-c", "P_n_m_b"}, + {"-P 2ab 2ab", 53, "cab", "P_b_m_n"}, + {"-P 2 2ac", 53, "-cba", "P_c_n_m"}, + {"-P 2 2bc", 53, "bca", "P_n_c_m"}, + {"-P 2ab 2", 53, "a-cb", "P_m_a_n"}, + {"-P 2a 2ac", 54, "", "P_c_c_a"}, + {"-P 2b 2c", 54, "ba-c", "P_c_c_b"}, + {"-P 2a 2b", 54, "cab", "P_b_a_a"}, + {"-P 2ac 2c", 54, "-cba", "P_c_a_a"}, + {"-P 2bc 2b", 54, "bca", "P_b_c_b"}, + {"-P 2b 2ab", 54, "a-cb", "P_b_a_b"}, + {"-P 2 2ab", 55, "", "P_b_a_m"}, + {"-P 2bc 2", 55, "cab", "P_m_c_b"}, + {"-P 2ac 2ac", 55, "bca", "P_c_m_a"}, + {"-P 2ab 2ac", 56, "", "P_c_c_n"}, + {"-P 2ac 2bc", 56, "cab", "P_n_a_a"}, + {"-P 2bc 2ab", 56, "bca", "P_b_n_b"}, + {"-P 2c 2b", 57, "", "P_b_c_m"}, + {"-P 2c 2ac", 57, "ba-c", "P_c_a_m"}, + {"-P 2ac 2a", 57, "cab", "P_m_c_a"}, + {"-P 2b 2a", 57, "-cba", "P_m_a_b"}, + {"-P 2a 2ab", 57, "bca", "P_b_m_a"}, + {"-P 2bc 2c", 57, "a-cb", "P_c_m_b"}, + {"-P 2 2n", 58, "", "P_n_n_m"}, + {"-P 2n 2", 58, "cab", "P_m_n_n"}, + {"-P 2n 2n", 58, "bca", "P_n_m_n"}, + {" P 2 2ab -1ab", 59, "1", "P_m_m_n"}, + {"-P 2ab 2a", 59, "2", "P_m_m_n"}, + {" P 2bc 2 -1bc", 59, "1cab", "P_n_m_m"}, + {"-P 2c 2bc", 59, "2cab", "P_n_m_m"}, + {" P 2ac 2ac -1ac", 59, "1bca", "P_m_n_m"}, + {"-P 2c 2a", 59, "2bca", "P_m_n_m"}, + {"-P 2n 2ab", 60, "", "P_b_c_n"}, + {"-P 2n 2c", 60, "ba-c", "P_c_a_n"}, + {"-P 2a 2n", 60, "cab", "P_n_c_a"}, + {"-P 2bc 2n", 60, "-cba", "P_n_a_b"}, + {"-P 2ac 2b", 60, "bca", "P_b_n_a"}, + {"-P 2b 2ac", 60, "a-cb", "P_c_n_b"}, + {"-P 2ac 2ab", 61, "", "P_b_c_a"}, + {"-P 2bc 2ac", 61, "ba-c", "P_c_a_b"}, + {"-P 2ac 2n", 62, "", "P_n_m_a"}, + {"-P 2bc 2a", 62, "ba-c", "P_m_n_b"}, + {"-P 2c 2ab", 62, "cab", "P_b_n_m"}, + {"-P 2n 2ac", 62, "-cba", "P_c_m_n"}, + {"-P 2n 2a", 62, "bca", "P_m_c_n"}, + {"-P 2c 2n", 62, "a-cb", "P_n_a_m"}, + {"-C 2c 2", 63, "", "C_m_c_m"}, + {"-C 2c 2c", 63, "ba-c", "C_c_m_m"}, + {"-A 2a 2a", 63, "cab", "A_m_m_a"}, + {"-A 2 2a", 63, "-cba", "A_m_a_m"}, + {"-B 2 2b", 63, "bca", "B_b_m_m"}, + {"-B 2b 2", 63, "a-cb", "B_m_m_b"}, + {"-C 2bc 2", 64, "", "C_m_c_a"}, + {"-C 2bc 2bc", 64, "ba-c", "C_c_m_b"}, + {"-A 2ac 2ac", 64, "cab", "A_b_m_a"}, + {"-A 2 2ac", 64, "-cba", "A_c_a_m"}, + {"-B 2 2bc", 64, "bca", "B_b_c_m"}, + {"-B 2bc 2", 64, "a-cb", "B_m_a_b"}, + {"-C 2 2", 65, "", "C_m_m_m"}, + {"-A 2 2", 65, "cab", "A_m_m_m"}, + {"-B 2 2", 65, "bca", "B_m_m_m"}, + {"-C 2 2c", 66, "", "C_c_c_m"}, + {"-A 2a 2", 66, "cab", "A_m_a_a"}, + {"-B 2b 2b", 66, "bca", "B_b_m_b"}, + {"-C 2b 2", 67, "", "C_m_m_a"}, + {"-C 2b 2b", 67, "ba-c", "C_m_m_b"}, + {"-A 2c 2c", 67, "cab", "A_b_m_m"}, + {"-A 2 2c", 67, "-cba", "A_c_m_m"}, + {"-B 2 2c", 67, "bca", "B_m_c_m"}, + {"-B 2c 2", 67, "a-cb", "B_m_a_m"}, + {" C 2 2 -1bc", 68, "1", "C_c_c_a"}, + {"-C 2b 2bc", 68, "2", "C_c_c_a"}, + {" C 2 2 -1bc", 68, "1ba-c", "C_c_c_b"}, + {"-C 2b 2c", 68, "2ba-c", "C_c_c_b"}, + {" A 2 2 -1ac", 68, "1cab", "A_b_a_a"}, + {"-A 2a 2c", 68, "2cab", "A_b_a_a"}, + {" A 2 2 -1ac", 68, "1-cba", "A_c_a_a"}, + {"-A 2ac 2c", 68, "2-cba", "A_c_a_a"}, + {" B 2 2 -1bc", 68, "1bca", "B_b_c_b"}, + {"-B 2bc 2b", 68, "2bca", "B_b_c_b"}, + {" B 2 2 -1bc", 68, "1a-cb", "B_b_a_b"}, + {"-B 2b 2bc", 68, "2a-cb", "B_b_a_b"}, + {"-F 2 2", 69, "", "F_m_m_m"}, + {" F 2 2 -1d", 70, "1", "F_d_d_d"}, + {"-F 2uv 2vw", 70, "2", "F_d_d_d"}, + {"-I 2 2", 71, "", "I_m_m_m"}, + {"-I 2 2c", 72, "", "I_b_a_m"}, + {"-I 2a 2", 72, "cab", "I_m_c_b"}, + {"-I 2b 2b", 72, "bca", "I_c_m_a"}, + {"-I 2b 2c", 73, "", "I_b_c_a"}, + {"-I 2a 2b", 73, "ba-c", "I_c_a_b"}, + {"-I 2b 2", 74, "", "I_m_m_a"}, + {"-I 2a 2a", 74, "ba-c", "I_m_m_b"}, + {"-I 2c 2c", 74, "cab", "I_b_m_m"}, + {"-I 2 2b", 74, "-cba", "I_c_m_m"}, + {"-I 2 2a", 74, "bca", "I_m_c_m"}, + {"-I 2c 2", 74, "a-cb", "I_m_a_m"}, + {" P 4", 75, "", "P_4"}, + {" P 4w", 76, "", "P_41"}, + {" P 4c", 77, "", "P_42"}, + {" P 4cw", 78, "", "P_43"}, + {" I 4", 79, "", "I_4"}, + {" I 4bw", 80, "", "I_41"}, + {" P -4", 81, "", "P_-4"}, + {" I -4", 82, "", "I_-4"}, + {"-P 4", 83, "", "P_4/m"}, + {"-P 4c", 84, "", "P_42/m"}, + {" P 4ab -1ab", 85, "1", "P_4/n"}, + {"-P 4a", 85, "2", "P_4/n"}, + {" P 4n -1n", 86, "1", "P_42/n"}, + {"-P 4bc", 86, "2", "P_42/n"}, + {"-I 4", 87, "", "I_4/m"}, + {" I 4bw -1bw", 88, "1", "I_41/a"}, + {"-I 4ad", 88, "2", "I_41/a"}, + {" P 4 2", 89, "", "P_4_2_2"}, + {" P 4ab 2ab", 90, "", "P_42_1_2"}, + {" P 4w 2c", 91, "", "P_41_2_2"}, + {" P 4abw 2nw", 92, "", "P_41_21_2"}, + {" P 4c 2", 93, "", "P_42_2_2"}, + {" P 4n 2n", 94, "", "P_42_21_2"}, + {" P 4cw 2c", 95, "", "P_43_2_2"}, + {" P 4nw 2abw", 96, "", "P_43_21_2"}, + {" I 4 2", 97, "", "I_4_2_2"}, + {" I 4bw 2bw", 98, "", "I_41_2_2"}, + {" P 4 -2", 99, "", "P_4_m_m"}, + {" P 4 -2ab", 100, "", "P_4_b_m"}, + {" P 4c -2c", 101, "", "P_42_c_m"}, + {" P 4n -2n", 102, "", "P_42_n_m"}, + {" P 4 -2c", 103, "", "P_4_c_c"}, + {" P 4 -2n", 104, "", "P_4_n_c"}, + {" P 4c -2", 105, "", "P_42_m_c"}, + {" P 4c -2ab", 106, "", "P_42_b_c"}, + {" I 4 -2", 107, "", "I_4_m_m"}, + {" I 4 -2c", 108, "", "I_4_c_m"}, + {" I 4bw -2", 109, "", "I_41_m_d"}, + {" I 4bw -2c", 110, "", "I_41_c_d"}, + {" P -4 2", 111, "", "P_-4_2_m"}, + {" P -4 2c", 112, "", "P_-4_2_c"}, + {" P -4 2ab", 113, "", "P_-4_21_m"}, + {" P -4 2n", 114, "", "P_-4_21_c"}, + {" P -4 -2", 115, "", "P_-4_m_2"}, + {" P -4 -2c", 116, "", "P_-4_c_2"}, + {" P -4 -2ab", 117, "", "P_-4_b_2"}, + {" P -4 -2n", 118, "", "P_-4_n_2"}, + {" I -4 -2", 119, "", "I_-4_m_2"}, + {" I -4 -2c", 120, "", "I_-4_c_2"}, + {" I -4 2", 121, "", "I_-4_2_m"}, + {" I -4 2bw", 122, "", "I_-4_2_d"}, + {"-P 4 2", 123, "", "P_4/m_m_m"}, + {"-P 4 2c", 124, "", "P_4/m_c_c"}, + {" P 4 2 -1ab", 125, "1", "P_4/n_b_m"}, + {"-P 4a 2b", 125, "2", "P_4/n_b_m"}, + {" P 4 2 -1n", 126, "1", "P_4/n_n_c"}, + {"-P 4a 2bc", 126, "2", "P_4/n_n_c"}, + {"-P 4 2ab", 127, "", "P_4/m_b_m"}, + {"-P 4 2n", 128, "", "P_4/m_n_c"}, + {" P 4ab 2ab -1ab", 129, "1", "P_4/n_m_m"}, + {"-P 4a 2a", 129, "2", "P_4/n_m_m"}, + {" P 4ab 2n -1ab", 130, "1", "P_4/n_c_c"}, + {"-P 4a 2ac", 130, "2", "P_4/n_c_c"}, + {"-P 4c 2", 131, "", "P_42/m_m_c"}, + {"-P 4c 2c", 132, "", "P_42/m_c_m"}, + {" P 4n 2c -1n", 133, "1", "P_42/n_b_c"}, + {"-P 4ac 2b", 133, "2", "P_42/n_b_c"}, + {" P 4n 2 -1n", 134, "1", "P_42/n_n_m"}, + {"-P 4ac 2bc", 134, "2", "P_42/n_n_m"}, + {"-P 4c 2ab", 135, "", "P_42/m_b_c"}, + {"-P 4n 2n", 136, "", "P_42/m_n_m"}, + {" P 4n 2n -1n", 137, "1", "P_42/n_m_c"}, + {"-P 4ac 2a", 137, "2", "P_42/n_m_c"}, + {" P 4n 2ab -1n", 138, "1", "P_42/n_c_m"}, + {"-P 4ac 2ac", 138, "2", "P_42/n_c_m"}, + {"-I 4 2", 139, "", "I_4/m_m_m"}, + {"-I 4 2c", 140, "", "I_4/m_c_m"}, + {" I 4bw 2bw -1bw", 141, "1", "I_41/a_m_d"}, + {"-I 4bd 2", 141, "2", "I_41/a_m_d"}, + {" I 4bw 2aw -1bw", 142, "1", "I_41/a_c_d"}, + {"-I 4bd 2c", 142, "2", "I_41/a_c_d"}, + {" P 3", 143, "", "P_3"}, + {" P 31", 144, "", "P_31"}, + {" P 32", 145, "", "P_32"}, + {" R 3", 146, "H", "R_3"}, + {" P 3*", 146, "R", "R_3"}, + {"-P 3", 147, "", "P_-3"}, + {"-R 3", 148, "H", "R_-3"}, + {"-P 3*", 148, "R", "R_-3"}, + {" P 3 2", 149, "", "P_3_1_2"}, + {" P 3 2\"", 150, "", "P_3_2_1"}, + {" P 31 2c (0 0 1)", 151, "", "P_31_1_2"}, + {" P 31 2\"", 152, "", "P_31_2_1"}, + {" P 32 2c (0 0 -1)", 153, "", "P_32_1_2"}, + {" P 32 2\"", 154, "", "P_32_2_1"}, + {" R 3 2\"", 155, "H", "R_32"}, + {" P 3* 2", 155, "R", "R_32"}, + {" P 3 -2\"", 156, "", "P_3_m_1"}, + {" P 3 -2", 157, "", "P_3_1_m"}, + {" P 3 -2\"c", 158, "", "P_3_c_1"}, + {" P 3 -2c", 159, "", "P_3_1_c"}, + {" R 3 -2\"", 160, "H", "R_3_m"}, + {" P 3* -2", 160, "R", "R_3_m"}, + {" R 3 -2\"c", 161, "H", "R_3_c"}, + {" P 3* -2n", 161, "R", "R_3_c"}, + {"-P 3 2", 162, "", "P_-3_1_m"}, + {"-P 3 2c", 163, "", "P_-3_1_c"}, + {"-P 3 2\"", 164, "", "P_-3_m_1"}, + {"-P 3 2\"c", 165, "", "P_-3_c_1"}, + {"-R 3 2\"", 166, "H", "R_-3_m"}, + {"-P 3* 2", 166, "R", "R_-3_m"}, + {"-R 3 2\"c", 167, "H", "R_-3_c"}, + {"-P 3* 2n", 167, "R", "R_-3_c"}, + {" P 6", 168, "", "P_6"}, + {" P 61", 169, "", "P_61"}, + {" P 65", 170, "", "P_65"}, + {" P 62", 171, "", "P_62"}, + {" P 64", 172, "", "P_64"}, + {" P 6c", 173, "", "P_63"}, + {" P -6", 174, "", "P_-6"}, + {"-P 6", 175, "", "P_6/m"}, + {"-P 6c", 176, "", "P_63/m"}, + {" P 6 2", 177, "", "P_6_2_2"}, + {" P 61 2 (0 0 -1)", 178, "", "P_61_2_2"}, + {" P 65 2 (0 0 1)", 179, "", "P_65_2_2"}, + {" P 62 2c (0 0 1)", 180, "", "P_62_2_2"}, + {" P 64 2c (0 0 -1)", 181, "", "P_64_2_2"}, + {" P 6c 2c", 182, "", "P_63_2_2"}, + {" P 6 -2", 183, "", "P_6_m_m"}, + {" P 6 -2c", 184, "", "P_6_c_c"}, + {" P 6c -2", 185, "", "P_63_c_m"}, + {" P 6c -2c", 186, "", "P_63_m_c"}, + {" P -6 2", 187, "", "P_-6_m_2"}, + {" P -6c 2", 188, "", "P_-6_c_2"}, + {" P -6 -2", 189, "", "P_-6_2_m"}, + {" P -6c -2c", 190, "", "P_-6_2_c"}, + {"-P 6 2", 191, "", "P_6/m_m_m"}, + {"-P 6 2c", 192, "", "P_6/m_c_c"}, + {"-P 6c 2", 193, "", "P_63/m_c_m"}, + {"-P 6c 2c", 194, "", "P_63/m_m_c"}, + {" P 2 2 3", 195, "", "P_2_3"}, + {" F 2 2 3", 196, "", "F_2_3"}, + {" I 2 2 3", 197, "", "I_2_3"}, + {" P 2ac 2ab 3", 198, "", "P_21_3"}, + {" I 2b 2c 3", 199, "", "I_21_3"}, + {"-P 2 2 3", 200, "", "P_m_-3"}, + {" P 2 2 3 -1n", 201, "1", "P_n_-3"}, + {"-P 2ab 2bc 3", 201, "2", "P_n_-3"}, + {"-F 2 2 3", 202, "", "F_m_-3"}, + {" F 2 2 3 -1d", 203, "1", "F_d_-3"}, + {"-F 2uv 2vw 3", 203, "2", "F_d_-3"}, + {"-I 2 2 3", 204, "", "I_m_-3"}, + {"-P 2ac 2ab 3", 205, "", "P_a_-3"}, + {"-I 2b 2c 3", 206, "", "I_a_-3"}, + {" P 4 2 3", 207, "", "P_4_3_2"}, + {" P 4n 2 3", 208, "", "P_42_3_2"}, + {" F 4 2 3", 209, "", "F_4_3_2"}, + {" F 4d 2 3", 210, "", "F_41_3_2"}, + {" I 4 2 3", 211, "", "I_4_3_2"}, + {" P 4acd 2ab 3", 212, "", "P_43_3_2"}, + {" P 4bd 2ab 3", 213, "", "P_41_3_2"}, + {" I 4bd 2c 3", 214, "", "I_41_3_2"}, + {" P -4 2 3", 215, "", "P_-4_3_m"}, + {" F -4 2 3", 216, "", "F_-4_3_m"}, + {" I -4 2 3", 217, "", "I_-4_3_m"}, + {" P -4n 2 3", 218, "", "P_-4_3_n"}, + {" F -4c 2 3", 219, "", "F_-4_3_c"}, + {" I -4bd 2c 3", 220, "", "I_-4_3_d"}, + {"-P 4 2 3", 221, "", "P_m_-3_m"}, + {" P 4 2 3 -1n", 222, "1", "P_n_-3_n"}, + {"-P 4a 2bc 3", 222, "2", "P_n_-3_n"}, + {"-P 4n 2 3", 223, "", "P_m_-3_n"}, + {" P 4n 2 3 -1n", 224, "1", "P_n_-3_m"}, + {"-P 4bc 2bc 3", 224, "2", "P_n_-3_m"}, + {"-F 4 2 3", 225, "", "F_m_-3_m"}, + {"-F 4c 2 3", 226, "", "F_m_-3_c"}, + {" F 4d 2 3 -1d", 227, "1", "F_d_-3_m"}, + {"-F 4vw 2vw 3", 227, "2", "F_d_-3_m"}, + {" F 4d 2 3 -1cd", 228, "1", "F_d_-3_c"}, + {"-F 4cvw 2vw 3", 228, "2", "F_d_-3_c"}, + {"-I 4 2 3", 229, "", "I_m_-3_m"}, + {"-I 4bd 2c 3", 230, "", "I_a_-3_d"}, + {NULL, 0, NULL, NULL} +}; +#endif /* SGCLIB_C__ */ + + +#define Sg_nLoopInv(SgInfo_)\ + ((SgInfo_)->Centric == -1 ? 2 : 1) + + +#define InitRotMx(RotMx, diagonal)\ + {\ + int private_i_;\ + for (private_i_ = 0; private_i_ < 9; private_i_++)\ + (RotMx)[private_i_] = (private_i_ % 4 ? 0 : diagonal);\ + } + +#define InitSeitzMx(SeitzMx_, diagonal)\ + {\ + int private_i_;\ + for (private_i_ = 0; private_i_ < 12; private_i_++)\ + (SeitzMx_)->a[private_i_] = (private_i_ % 4 ? 0 : diagonal);\ + } + + +#if defined(SGCLIB_C__) || defined(SGCOREDEF__) +#define SpecialSMx_Identity 0x01 +#define SpecialSMx_Inversion 0x02 +#define SpecialSMx_Transl0 0x04 +#endif + + +/* sgclib.c */ + +void SetSgError(const char *msg); +int iModPositive(int ix, int iy); +int traceRotMx(const int *RotMx); +int deterRotMx(const int *RotMx); +void RotMx_t_Vector(int *R_t_V, const int *RotMx, const int *Vector, + int FacTr); +void RotMxMultiply(int *rmxab, const int *rmxa, const int *rmxb); +void RotateRotMx(int *RotMx, const int *RMx, const int *InvRMx); +void SeitzMxMultiply(T_RTMx * smxab, const T_RTMx * smxa, + const T_RTMx * smxb); +void RTMxMultiply(T_RTMx * rtmxab, const T_RTMx * rtmxa, + const T_RTMx * rtmxb, int FacAug, int FacTr); +void InverseRotMx(const int *RotMx, int *InvRotMx); +void InverseRTMx(const T_RTMx * RTMx, T_RTMx * InvRTMx); +int IsSMxTransl0(const T_LatticeInfo * LatticeInfo, const int *SeitzMxT); +int CompareSeitzMx(const T_LatticeInfo * LatticeInfo, + const T_RTMx * SeitzMxA, const T_RTMx * SeitzMxB); +int GetRotMxOrder(const int *RotMx); +int GetRotMxInfo(const int *RotMx, T_RotMxInfo * RotMxInfo); +const T_RotMxInfo *ListOrBufRotMxInfo(const T_SgInfo * SgInfo, int iList, + T_RotMxInfo * BufRotMxInfo); +int Add2ListSeitzMx(T_SgInfo * SgInfo, const T_RTMx * NewSMx); +int AddInversion2ListSeitzMx(T_SgInfo * SgInfo); +int AddLatticeTr2ListSeitzMx(T_SgInfo * SgInfo, + const T_LatticeInfo * LatticeInfo); +int ApplyOriginShift(T_SgInfo * SgInfo); +int FindSeitzMx(const T_SgInfo * SgInfo, + int Order, int HonorSign, int RefAxis, int DirCode); +void InitSgInfo(T_SgInfo * SgInfo); +int CompleteSgInfo(T_SgInfo * SgInfo); +int CB_SMx(T_RTMx * CSiC, + const T_RTMx * CBMx, const T_RTMx * SMx, + const T_RTMx * InvCBMx); +int TransformSgInfo(const T_SgInfo * SgInfo, const T_RTMx * CBMx, + const T_RTMx * InvCBMx, T_SgInfo * BC_SgInfo); + +/* sgio.c */ + +const T_TabSgName *FindTabSgNameEntry(const char *UserSgName, + int VolLetter); +unsigned int SgID_Number(const T_TabSgName * tsgn); +int ParseSymXYZ(const char *SymXYZ, T_RTMx * SeitzMx, int FacTr); +int ParseHallSymbol(const char *hsym, T_SgInfo * SgInfo); +int PrintFullHM_SgName(const T_TabSgName * tsgn, int space, FILE * fpout); +void PrintTabSgNameEntry(const T_TabSgName * tsgn, int Style, int space, + FILE * fpout); +const char *FormatFraction(int nume, int deno, int Decimal, + char *Buffer, int SizeBuffer); +const char *RTMx2XYZ(const T_RTMx * RTMx, int FacRo, int FacTr, + int Decimal, int TrFirst, int Low, + const char *Seperator, + char *BufferXYZ, int SizeBufferXYZ); +void PrintMapleRTMx(const T_RTMx * RTMx, int FacRo, int FacTr, + const char *Label, FILE * fpout); +void ListSgInfo(const T_SgInfo * SgInfo, int F_XYZ, int F_Verbose, + FILE * fpout); + + +/* sgfind.c */ + +const T_TabSgName *FindReferenceSpaceGroup(T_SgInfo * SgInfo, + T_RTMx * CBMx, + T_RTMx * InvCBMx); + +/* sghkl.c */ + +int IsSysAbsent_hkl(const T_SgInfo * SgInfo, + int h, int k, int l, int *TH_Restriction); +int BuildEq_hkl(const T_SgInfo * SgInfo, T_Eq_hkl * Eq_hkl, int h, int k, + int l); +int AreSymEquivalent_hkl(const T_SgInfo * SgInfo, int h1, int k1, int l1, + int h2, int k2, int l2); +void SetListMin_hkl(const T_SgInfo * SgInfo, int Maxk, int Maxl, int *Minh, + int *Mink, int *Minl); +int IsSuppressed_hkl(const T_SgInfo * SgInfo, int Minh, int Mink, int Minl, + int Maxk, int Maxl, int h, int k, int l); + +/* sgsi.c */ + +void MarkLegalOrigins(const T_SgInfo * SgInfo, int *TestField); +int Verify_si(int h, int k, int l, const int *TestField); +int Is_si(const T_SgInfo * SgInfo, int h, int k, int l); +int Set_si(T_SgInfo * SgInfo); +void Set_uvw(const T_SgInfo * SgInfo, int h, int k, int l, int *uvw); + + +#endif /* SGINFO_H__ */ diff --git a/sgio.c b/sgio.c new file mode 100644 index 00000000..2fde8810 --- /dev/null +++ b/sgio.c @@ -0,0 +1,1843 @@ +/* + Space Group Info's (c) 1994-96 Ralf W. Grosse-Kunstleve + */ + +#include +#include +#include +#include + + +#define SGCOREDEF__ +#include "sginfo.h" + + +typedef struct { + int OriginChoice; + int CellChoice; + int BasisChoice; + const char *BT_or_UA; +} T_ExtInfo; + + +static const char *Ext_BT_or_UA[] = { + /* 0 */ "abc", + /* 1 */ "ba-c", + /* 2 */ "cab", + /* 3 */ "-cba", + /* 4 */ "bca", + /* 5 */ "a-cb", + /* 6 */ "bac", + /* 6 -> 1 */ + /* 7 */ "cba", + /* 7 -> 3 */ + /* 8 */ "acb", + /* 8 -> 5 */ + /* 9 */ "-b", "b-", "bb", "bb", + /* 10, 11, 12 -> 9 */ + /* 13 */ "-c", "c-", "bc", "cb", + /* 14, 15, 16 -> 13 */ + /* 17 */ "-a", "a-", "ba", "ab", + /* 18, 19, 20 -> 17 */ + /* 21 */ "b", + /* 22 */ "c", + /* 23 */ "a", + NULL +}; + + +typedef struct { + int Improper, Rotation, RefAxis, DirCode, Screw; + T_RTMx SeitzMx; +} T_HallGenerator; + + +#define SkipWhite(cp) while (*(cp) && (*(cp) == '_' || isspace(*(cp)))) (cp)++ + + +static const char *IErr_Corrupt_TabSgName = + "Internal Error: Corrupt TabSgName"; + + +static int FindSchoenfliesSymbol(const char *SfSymbol) +{ + int SgNumber; + const char **TabSymbol; + const char *s, *t; + + + TabSymbol = SchoenfliesSymbols + 1; + + for (SgNumber = 1; SgNumber <= 230; SgNumber++) { + t = *TabSymbol; + s = SfSymbol; + + while (*t && *s) { + if (toupper(*t) != toupper(*s) + && (*t != '^' || isalpha(*s) || isdigit(*s))) + break; + + t++; + s++; + } + + if (*t == *s) + return SgNumber; + + TabSymbol++; + } + + return -1; +} + + +static int SgLabelCmp(const int SgNumber, + const char *SgLabel, const char *WtdLbl) +{ + const char *sgl, *wl; + + + /* first try: plain strcmp + */ + sgl = SgLabel; + + for (wl = WtdLbl;; wl++) { + SkipWhite(wl); + SkipWhite(sgl); + + if (*sgl == '\0' || *sgl == '=') { + if (*wl == '\0') + return 0; + break; + } + + if (*sgl == '-') { + if (*wl != '-' && toupper(*wl) != 'B') + break; + } else if (toupper(*sgl) != toupper(*wl)) + break; + + sgl++; + } + + /* second try: swap the dash (there should be only one) + */ + sgl = SgLabel; + + for (wl = WtdLbl;; wl++) { + SkipWhite(wl); + SkipWhite(sgl); + + if (*sgl == '-') { + if (wl[1] != '-' && toupper(wl[1]) != 'B') + break; + if (toupper(sgl[1]) != toupper(*wl)) + break; + + sgl++; + wl++; + } else { + if (*sgl == '\0' || *sgl == '=') { + if (*wl == '\0') + return 0; + break; + } + + if (toupper(*sgl) != toupper(*wl)) + break; + } + + sgl++; + } + + if (SgNumber >= 195) { /* cubic space groups only */ + /* third try: ignore the "-3" dash + */ + sgl = SgLabel; + + for (wl = WtdLbl;; wl++) { + SkipWhite(wl); + SkipWhite(sgl); + + if (*sgl == '-' && sgl[1] == '3') + sgl++; + + if (*sgl == '\0' || *sgl == '=') { + if (*wl == '\0') + return 0; + break; + } + + if (toupper(*sgl) != toupper(*wl)) + break; + + sgl++; + } + } + + return -1; +} + + +static int ParseExtension(const char *Ext, T_ExtInfo * ExtInfo) +{ + int i, mode; + const char *e, *t; + + + ExtInfo->OriginChoice = ExtInfo->CellChoice = ExtInfo->BasisChoice = ' '; + ExtInfo->BT_or_UA = ""; + + mode = 0; + + while (*Ext) { + if (strchr("12", *Ext) != NULL) { + ExtInfo->CellChoice = ExtInfo->OriginChoice = *Ext++; + } else if (strchr("3", *Ext) != NULL) { + ExtInfo->CellChoice = *Ext++; + } else if (strchr("Ss", *Ext) != NULL) { + ExtInfo->OriginChoice = '1'; + Ext++; + } else if (strchr("Zz", *Ext) != NULL) { + ExtInfo->OriginChoice = '2'; + Ext++; + } else if (strchr("Hh", *Ext) != NULL) { + ExtInfo->BasisChoice = 'H'; + Ext++; + } else if (strchr("Rr", *Ext) != NULL) { + ExtInfo->BasisChoice = 'R'; + Ext++; + } else if (mode == 0) + mode = 1; + + if (mode == 2) + break; + + for (i = 0; Ext_BT_or_UA[i]; i++) { + for (e = Ext, t = Ext_BT_or_UA[i]; *t; e++, t++) + if (toupper(*e) != toupper(*t)) + break; + + if (*t == '\0') { + if (6 <= i && i <= 8) + i = 2 * i - 11; + else if (9 <= i && i <= 20) + i = 9 + ((i - 9) / 4) * 4; + + ExtInfo->BT_or_UA = Ext_BT_or_UA[i]; + Ext = e; + break; + } + } + + if (mode == 0) + break; + + mode = 2; + } + + if (*Ext) + return -1; + + return 0; +} + + +static void ExpandMonoclinic(int unique_axis, const char *o, char *m) +{ + if (*o) + *m++ = *o++; + + switch (tolower(unique_axis)) { + case 'a': + while (*o) + *m++ = *o++; + *m++ = '1'; + *m++ = '1'; + break; + case 'c': + *m++ = '1'; + *m++ = '1'; + while (*o) + *m++ = *o++; + break; + default: + *m++ = '1'; + while (*o) + *m++ = *o++; + *m++ = '1'; + break; + } + + *m = '\0'; +} + + +const T_TabSgName *FindTabSgNameEntry(const char *UserSgName, + int VolLetter) +{ +#define MaxWtdLbl 20 + char WtdLblOriginal[MaxWtdLbl + 1]; + char WtdLblModified[MaxWtdLbl + 1]; + char *WtdLbl; +#define MaxWtdExt 5 + char WtdExt[MaxWtdExt + 1]; + int WtdSgNumber; + int WtdLblOriginChoice; + int WtdLblBasisChoice; + int iwl, iwe; + char *wl, *we; + + int i, IsExpanded, lbl_match; + const char *sgl; + const T_TabSgName *tsgn; + int WtdCC; + const char *WtdUA; + char WtdUA_Buf[2]; + T_ExtInfo ExtInfo, WtdExtInfo; + + + if (VolLetter == 0 || isspace(VolLetter)) + VolLetter = 'A'; + else if (VolLetter == '1') + VolLetter = 'I'; + else { + VolLetter = toupper(VolLetter); + if (VolLetter != 'I' && VolLetter != 'A') + return NULL; + } + + WtdLbl = WtdLblOriginal; + + wl = WtdLbl; + iwl = 0; + + while (*UserSgName && *UserSgName != ':') { + if (isspace(*UserSgName) == 0 && *UserSgName != '_') { + if (iwl >= MaxWtdLbl) + return NULL; + + *wl++ = *UserSgName; + iwl++; + } + + UserSgName++; + } + + *wl = '\0'; + + if (iwl == 0) + return NULL; + + we = WtdExt; + iwe = 0; + *we = '\0'; + + if (*UserSgName) { + UserSgName++; + + while (*UserSgName) { + if (isspace(*UserSgName) == 0 && *UserSgName != '_') { + if (iwe >= MaxWtdExt) + return NULL; + + *we++ = *UserSgName; + iwe++; + } + + UserSgName++; + } + } + + *we = '\0'; + + WtdLblOriginChoice = ' '; + WtdLblBasisChoice = ' '; + + if (iwl > 1) { + wl = &WtdLbl[iwl - 1]; + + if (*wl == 'S' || *wl == 's') { + WtdLblOriginChoice = '1'; + *wl = '\0'; + iwl--; + } else if (*wl == 'Z' || *wl == 'z') { + WtdLblOriginChoice = '2'; + *wl = '\0'; + iwl--; + } else if (*wl == 'H' || *wl == 'h') { + WtdLblBasisChoice = 'H'; + *wl = '\0'; + iwl--; + } else if (*wl == 'R' || *wl == 'r') { + WtdLblBasisChoice = 'R'; + *wl = '\0'; + iwl--; + } + } + + if (isalpha(WtdLbl[0])) + WtdSgNumber = FindSchoenfliesSymbol(WtdLbl); + else { + for (wl = WtdLbl; *wl; wl++) + if (isdigit(*wl) == 0) + return NULL; + + if (sscanf(WtdLbl, "%d", &WtdSgNumber) != 1 + || WtdSgNumber < 1 || WtdSgNumber > 230) + return NULL; + } + + if (ParseExtension(WtdExt, &WtdExtInfo) != 0) + return NULL; + + if (WtdExtInfo.OriginChoice == ' ') + WtdExtInfo.OriginChoice = WtdLblOriginChoice; + else if (WtdExtInfo.OriginChoice != WtdLblOriginChoice + && WtdLblOriginChoice != ' ') + return NULL; + + if (WtdExtInfo.BasisChoice == ' ') + WtdExtInfo.BasisChoice = WtdLblBasisChoice; + else if (WtdExtInfo.BasisChoice != WtdLblBasisChoice + && WtdLblBasisChoice != ' ') + return NULL; + + if (WtdExtInfo.OriginChoice != ' ' && WtdExtInfo.BasisChoice != ' ') + return NULL; + + for (IsExpanded = 0; IsExpanded < 4; IsExpanded++) { + for (tsgn = TabSgName; tsgn->HallSymbol; tsgn++) { + if (IsExpanded != 0 && tsgn->SgNumber > 15) + break; + + lbl_match = 0; + + if (WtdSgNumber == -1) { + i = 1; + sgl = tsgn->SgLabels; + while (*sgl && i <= 2) { + while (*sgl && strchr(" =\t", *sgl) != NULL) + sgl++; + + if (SgLabelCmp(tsgn->SgNumber, sgl, WtdLbl) == 0) { + lbl_match = i; + break; + } + + while (*sgl && strchr(" =\t", *sgl) == NULL) + sgl++; + + i++; + } + } + + if (ParseExtension(tsgn->Extension, &ExtInfo) != 0) { + SetSgError(IErr_Corrupt_TabSgName); + return NULL; + } + + if (WtdSgNumber == tsgn->SgNumber || lbl_match != 0) { + if (tsgn->SgNumber >= 3 && tsgn->SgNumber < 16) { + if (WtdLblOriginChoice != ' ' + || WtdExtInfo.BasisChoice != ' ' + || (int) strlen(WtdExtInfo.BT_or_UA) > 2) + continue; /* next tsgn */ + + if (WtdSgNumber == tsgn->SgNumber) { + if (WtdExtInfo.BT_or_UA[0]) + WtdUA = WtdExtInfo.BT_or_UA; + else if (VolLetter == 'I') { + if (ExtInfo.BT_or_UA[0] != 'c' && ExtInfo.BT_or_UA[1] != 'c') + continue; /* next tsgn */ + + if (ExtInfo.CellChoice == ' ' + && (WtdExtInfo.CellChoice == ' ' + || WtdExtInfo.CellChoice == '1')) + return tsgn; + + i = 0; + for (sgl = tsgn->SgLabels; *sgl; sgl++) + if (*sgl == '=') + i++; + + if (i == 2 + && (WtdExtInfo.CellChoice == ' ' + || WtdExtInfo.CellChoice == ExtInfo.CellChoice)) + return tsgn; + + continue; /* next tsgn */ + } else + WtdUA = "b"; + } else { /* if (lbl_match != 0) */ + + if (WtdExtInfo.BT_or_UA[0]) + WtdUA = WtdExtInfo.BT_or_UA; + else if (lbl_match > 1) + WtdUA = ExtInfo.BT_or_UA; + else if (VolLetter == 'I' && ExtInfo.CellChoice == ' ') + WtdUA = "c"; + else + WtdUA = "b"; + } + + if (WtdExtInfo.CellChoice != ' ') + WtdCC = WtdExtInfo.CellChoice; + else if (ExtInfo.CellChoice == '1') + WtdCC = ExtInfo.CellChoice; + else + WtdCC = ' '; + + if (strcmp(ExtInfo.BT_or_UA, WtdUA) == 0) { + if (WtdCC == ' ' && lbl_match > 1) + return tsgn; + if (ExtInfo.CellChoice == WtdCC) + return tsgn; + if (ExtInfo.CellChoice == ' ' && WtdCC == '1') + return tsgn; + if (ExtInfo.CellChoice == '1' && WtdCC == ' ') + return tsgn; + } + } else if (ExtInfo.BasisChoice != ' ') { + if (WtdExtInfo.OriginChoice != ' ' + || WtdExtInfo.CellChoice != ' ' + || WtdExtInfo.BT_or_UA[0] != '\0') + continue; /* next tsgn */ + + if (ExtInfo.BasisChoice == WtdExtInfo.BasisChoice) + return tsgn; + + if (WtdExtInfo.BasisChoice == ' ') { + if (ExtInfo.BasisChoice == 'R' && VolLetter == 'I') + return tsgn; + if (ExtInfo.BasisChoice == 'H' && VolLetter != 'I') + return tsgn; + } + } else if (WtdExtInfo.BasisChoice == ' ') { + if ((WtdExtInfo.OriginChoice == ' ' + && ExtInfo.OriginChoice == '1') + || (WtdExtInfo.OriginChoice == '1' + && ExtInfo.OriginChoice == ' ') + || WtdExtInfo.OriginChoice == ExtInfo.OriginChoice) { + if (WtdExtInfo.BT_or_UA[0]) { + if (WtdExtInfo.BT_or_UA == ExtInfo.BT_or_UA) + return tsgn; + if (WtdExtInfo.BT_or_UA == Ext_BT_or_UA[0] + && ExtInfo.BT_or_UA[0] == '\0') + return tsgn; + } else { + if (lbl_match != 0) + return tsgn; + if (ExtInfo.BT_or_UA[0] == '\0') + return tsgn; + } + } + } + } + } + + if (WtdSgNumber != -1) + return NULL; + + if ((int) strlen(WtdExtInfo.BT_or_UA) > 2) + return NULL; + + if (IsExpanded == 0) { + iwl += 2; + + if (iwl > MaxWtdLbl) + IsExpanded = 2; + else { + if (WtdExtInfo.BT_or_UA[0]) + WtdUA = WtdExtInfo.BT_or_UA; + else { + if (VolLetter == 'I') + WtdUA = "c"; + else + WtdUA = "b"; + } + + ExpandMonoclinic(WtdUA[0], WtdLblOriginal, WtdLblModified); + + WtdLbl = WtdLblModified; + } + } else if (IsExpanded == 1) { + if (WtdExtInfo.BT_or_UA[0]) + return NULL; + + if (VolLetter == 'I') + WtdUA = "b"; + else + WtdUA = "c"; + + ExpandMonoclinic(WtdUA[0], WtdLblOriginal, WtdLblModified); + } + + if (IsExpanded == 2) { + if (WtdExtInfo.BT_or_UA[0]) + return NULL; + + iwl -= 2; + + if (iwl < 2) + return NULL; + iwl--; + WtdUA_Buf[0] = tolower(WtdLblOriginal[iwl]); + WtdLblOriginal[iwl] = '\0'; + WtdUA_Buf[1] = '\0'; + + if (strchr("abc", WtdUA_Buf[0]) == NULL) + return NULL; + + WtdUA = WtdUA_Buf; + + iwl += 2; + + if (iwl > MaxWtdLbl) + return NULL; + + ExpandMonoclinic(WtdUA[0], WtdLblOriginal, WtdLblModified); + + WtdLbl = WtdLblModified; + } + } + + return NULL; +} + + +unsigned int SgID_Number(const T_TabSgName * tsgn) +{ + unsigned int ID; + int iBT; + const char *UA; + T_ExtInfo ExtInfo; + + + ID = tsgn->SgNumber; + + if (ParseExtension(tsgn->Extension, &ExtInfo) != 0) + ID = 0; + + if (ID >= 3 && ID < 16) { + UA = ExtInfo.BT_or_UA; + + if (*UA != 'b' + || (ExtInfo.CellChoice != ' ' && ExtInfo.CellChoice != '1')) { + if (*UA == '-') { + ID += 3000; + UA++; + } + + switch (*UA) { + case 'b': + ID += 10000; + break; + case 'c': + ID += 20000; + break; + case 'a': + ID += 30000; + break; + default: + ID = 0; + break; + } + + if (ID != 0) { + switch (ExtInfo.CellChoice) { + case ' ': + break; + case '1': + ID += 1000; + break; + case '2': + ID += 2000; + break; + case '3': + ID += 3000; + break; + default: + ID = 0; + break; + } + } + } + } else { + if (ExtInfo.BasisChoice == 'R') + ID += 20000; + else { + if (ExtInfo.BT_or_UA[0]) { + for (iBT = 0; iBT < 6; iBT++) + if (ExtInfo.BT_or_UA == Ext_BT_or_UA[iBT]) + break; + } else + iBT = 0; + + if (iBT < 6) { + if (ExtInfo.OriginChoice == '2') + ID += 20000; + else if (iBT) + ID += 10000; + + if (iBT) + ID += (iBT + 1) * 1000; + } else + ID = 0; + } + } + + if (ID == 0) + SetSgError(IErr_Corrupt_TabSgName); + + return ID; +} + + +int ParseSymXYZ(const char *SymXYZ, T_RTMx * SeitzMx, int FacTr) +{ + unsigned int P_mode; + int Row, Column, Sign, GotXYZ, i; + double Value, Value1, Value2, Delta; + + + for (i = 0; i < 12; i++) + SeitzMx->a[i] = 0; + +#define P_Blank 0x01u +#define P_Comma 0x02u +#define P_Plus 0x04u +#define P_Dash 0x08u +#define P_Slash 0x10u +#define P_Value1 0x20u +#define P_Value2 0x40u +#define P_XYZ 0x80u + + Value1 = 0.; + + Row = 0; + Sign = 1; + Value = 0.; + GotXYZ = 0; + P_mode = P_Blank | P_Plus | P_Dash | P_Value1 | P_XYZ; + + do { + switch (*SymXYZ) { + case ' ': + case '\t': + case '_': + if ((P_mode & P_Blank) == 0) + return -1; + break; + case ',': + case ';': + if (Row == 2) + return -1; + case '\0': + if ((P_mode & P_Comma) == 0) + return -1; + if (GotXYZ == 0) + return -1; + if (P_mode & P_Slash) + Value += Value1; + Value *= FacTr; + if (Value < 0.) + i = Value - .5; + else + i = Value + .5; + Delta = Value - i; + if (Delta < 0.) + Delta = -Delta; + if (Delta > .01 * FacTr) + return -1; + i %= FacTr; + if (i < 0) + i += FacTr; + SeitzMx->s.T[Row] = i; + Row++; + Sign = 1; + Value = 0.; + P_mode = P_Blank | P_Plus | P_Dash | P_Value1 | P_XYZ; + GotXYZ = 0; + break; + case '+': + if ((P_mode & P_Plus) == 0) + return -1; + if (P_mode & P_Slash) + Value += Value1; + Sign = 1; + if (P_mode & P_Value2) + P_mode = P_Value2; + else + P_mode = P_Blank | P_Value1 | P_XYZ; + break; + case '-': + if ((P_mode & P_Dash) == 0) + return -1; + if (P_mode & P_Slash) + Value += Value1; + Sign = -1; + if (P_mode & P_Value2) + P_mode = P_Value2; + else + P_mode = P_Blank | P_Value1 | P_XYZ; + break; + case '/': + case ':': + if ((P_mode & P_Slash) == 0) + return -1; + Sign = 1; + P_mode = P_Blank | P_Plus | P_Dash | P_Value2; + break; + case '.': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (P_mode & P_Value1) { + if (sscanf(SymXYZ, "%lf%n", &Value1, &i) != 1) + return -1; + if (Sign == -1) + Value1 = -Value1; + P_mode = P_Blank | P_Comma | P_Plus | P_Dash | P_Slash; + } else if (P_mode & P_Value2) { + if (sscanf(SymXYZ, "%lf%n", &Value2, &i) != 1) + return -1; + if (Sign == -1) + Value2 = -Value2; + if (Value1 != 0.) { + if (Value2 == 0.) + return -1; + Value += Value1 / Value2; + } + P_mode = P_Blank | P_Comma | P_Plus | P_Dash; + } else + return -1; + SymXYZ += (i - 1); + break; + case 'X': + case 'x': + Column = 0; + goto Process_XYZ; + case 'Y': + case 'y': + Column = 1; + goto Process_XYZ; + case 'Z': + case 'z': + Column = 2; + Process_XYZ: + if ((P_mode & P_XYZ) == 0) + return -1; + i = Row * 3 + Column; + if (SeitzMx->s.R[i] != 0) + return -1; + SeitzMx->s.R[i] = Sign; + GotXYZ = 1; + P_mode = P_Blank | P_Comma | P_Plus | P_Dash; + break; + } + } + while (*SymXYZ++); + + if (Row != 3) + return -1; + + return 0; + +#undef P_Blank +#undef P_Comma +#undef P_Plus +#undef P_Dash +#undef P_Slash +#undef P_Value1 +#undef P_Value2 +#undef P_XYZ +} + + +static int LookupRotMx(T_HallGenerator * HG) +{ + int i, f, refaxis, dircode; + int iNextBasis, nNextBasis; + const T_TabXtalRotMx *txrmx; + + + if (HG->Rotation <= 0) + return 0; + + refaxis = HG->RefAxis; + dircode = HG->DirCode; + + if (HG->Rotation == 1) { + refaxis = 'o'; + dircode = '.'; + nNextBasis = 0; + } else if (dircode == '*') { + if (refaxis == 0) + refaxis = 'o'; + nNextBasis = 0; + } else { + if (dircode == 0) + dircode = '='; + + switch (refaxis) { + case 'z': + nNextBasis = 0; + break; + case 'x': + nNextBasis = 1; + break; + case 'y': + nNextBasis = 2; + break; + default: + return 0; + } + } + + for (txrmx = TabXtalRotMx; txrmx->Order; txrmx++) + if (txrmx->Order == HG->Rotation) + break; + + while (txrmx->Order == HG->Rotation) { + if (txrmx->DirCode == dircode) { + if (HG->Improper == 0) + f = 1; + else + f = -1; + + for (i = 0; i < 9; i++) + HG->SeitzMx.s.R[i] = txrmx->RMx[i] * f; + + for (iNextBasis = 0; iNextBasis < nNextBasis; iNextBasis++) + RotateRotMx(HG->SeitzMx.s.R, RMx_3_111, RMx_3i111); + + return 1; + } + + txrmx++; + } + + return 0; +} + + +int ParseHallSymbol(const char *hsym, T_SgInfo * SgInfo) +{ + int c, i, pos_hsym; + const int *ht; + int Centric; + const T_LatticeInfo *LatticeInfo; + int FieldType, PreviousFT; + int iOriginShift, SignOriginShift; + int digit, rotation, refaxis, dircode; + const int *translation; + int PreviousRotation, PreviousRefAxis; + int nHG, ClearHG; + T_HallGenerator HG; + + enum ListOfFieldTypes { + FT_Delimiter, + FT_Improper, + FT_Digit, + FT_Rotation, + FT_RefAxis, + FT_DirCode, + FT_Translation, + FT_OriginShift + }; + + static const char *Err_Ill_ori_shi_val = + "Error: Illegal origin shift value"; + + static const char *Err_Too_ori_shi_val = + "Error: Too much origin shift values"; + + + Centric = 0; + LatticeInfo = NULL; + + HG.Rotation = HG.RefAxis = HG.DirCode = HG.Screw = 0; + + nHG = 0; + ClearHG = 1; + FieldType = FT_Delimiter; + PreviousRotation = 0; + PreviousRefAxis = 0; + iOriginShift = 0; + SignOriginShift = 0; + + pos_hsym = 0; + + do { + if (*hsym == '_' || *hsym == '.' || *hsym == '\t' || *hsym == '\0') + c = ' '; + else + c = *hsym; + + pos_hsym++; + + if (LatticeInfo == NULL) { + if (Centric == 0 && c == '-') { + if (AddInversion2ListSeitzMx(SgInfo) < 0) + return pos_hsym; + Centric = 1; + } else if (c != ' ') { + c = toupper(c); + + switch (c) { + case 'P': + LatticeInfo = LI_P; + break; + case 'A': + LatticeInfo = LI_A; + break; + case 'B': + LatticeInfo = LI_B; + break; + case 'C': + LatticeInfo = LI_C; + break; + case 'I': + LatticeInfo = LI_I; + break; + case 'R': + LatticeInfo = LI_R; + break; + case 'S': + LatticeInfo = LI_S; + break; + case 'T': + LatticeInfo = LI_T; + break; + case 'F': + LatticeInfo = LI_F; + break; + default: + SetSgError("Error: Illegal lattice code"); + return pos_hsym; + } + + if (AddLatticeTr2ListSeitzMx(SgInfo, LatticeInfo) < 0) + return pos_hsym; + } + } else if (FieldType != FT_OriginShift) { + c = tolower(c); + if (c == 'q') + c = '\''; + else if (c == '+') + c = '"'; + + PreviousFT = FieldType; + digit = rotation = refaxis = dircode = 0; + translation = NULL; + + ht = HallTranslations; + + while (*ht) { + if (c == *ht) { + translation = ht; + FieldType = FT_Translation; + break; + } + ht += 4; + } + + if (translation == NULL) { + switch (c) { + case ' ': + FieldType = FT_Delimiter; + break; + + case '-': + FieldType = FT_Improper; + break; + + case '1': + digit = 1; + FieldType = FT_Digit; + break; + case '2': + digit = 2; + FieldType = FT_Digit; + break; + case '3': + digit = 3; + FieldType = FT_Digit; + break; + case '4': + digit = 4; + FieldType = FT_Digit; + break; + case '5': + digit = 5; + FieldType = FT_Digit; + break; + case '6': + digit = 6; + FieldType = FT_Digit; + break; + + case 'x': + case 'y': + case 'z': + refaxis = c; + FieldType = FT_RefAxis; + break; + + case '"': + case '\'': + case '*': + dircode = c; + FieldType = FT_DirCode; + break; + + case '(': + FieldType = FT_OriginShift; + break; + + default: + SetSgError("Error: Illegal character in Hall symbol"); + return pos_hsym; + } + + if (FieldType == FT_Digit) { + if (ClearHG == 0 + && HG.Rotation > digit && HG.Screw == 0 && HG.DirCode == 0) { + HG.Screw = digit; + FieldType = FT_Translation; + } else if (digit == 5) { + SetSgError("Error: Illegal 5-fold rotation"); + return pos_hsym; + } else { + rotation = digit; + FieldType = FT_Rotation; + } + } + } + + if (ClearHG == 0 + && (FieldType == FT_Delimiter + || FieldType == FT_OriginShift + || FieldType < PreviousFT + || (FieldType == PreviousFT && FieldType != FT_Translation)) + && !(FieldType == FT_RefAxis && HG.RefAxis == 0 + && PreviousFT == FT_DirCode)) { + if (HG.RefAxis == 0) { + if (nHG == 0) + HG.RefAxis = 'z'; + else { + if (HG.Rotation == 2) { + if (PreviousRotation == 2 || PreviousRotation == 4) + HG.RefAxis = 'x'; + else if (PreviousRotation == 3 || PreviousRotation == 6) { + HG.RefAxis = PreviousRefAxis; + if (HG.DirCode == 0) + HG.DirCode = '\''; + } + } else if (HG.Rotation == 3) { + if (HG.DirCode == 0) + HG.DirCode = '*'; + } + } + } + + PreviousRefAxis = HG.RefAxis; + PreviousRotation = HG.Rotation; + + if (LookupRotMx(&HG) == 0) { + SetSgError + ("Error: Illegal generator or need explicit axis symbol"); + return pos_hsym - 1; + } + + if (HG.Screw) { + switch (HG.RefAxis) { + case 'x': + i = 0; + break; + case 'y': + i = 1; + break; + case 'z': + i = 2; + break; + default: + i = -1; + break; + } + + if (HG.DirCode != 0 || i < 0) { + SetSgError("Error: Screw for non-principal direction"); + return pos_hsym - 1; + } + + HG.SeitzMx.s.T[i] += STBF * HG.Screw / HG.Rotation; + } + + for (i = 0; i < 3; i++) + HG.SeitzMx.s.T[i] %= STBF; + + if (Add2ListSeitzMx(SgInfo, &HG.SeitzMx) < 0) + return pos_hsym - 1; + + if (SgInfo->StatusLatticeTr == -1) { + if (AddLatticeTr2ListSeitzMx(SgInfo, SgInfo->LatticeInfo) < 0) + return pos_hsym - 1; + } + + nHG++; + ClearHG = 1; + } + + if (FieldType != FT_Delimiter && FieldType != FT_OriginShift) { + if (ClearHG) { + HG.Improper = 0; + HG.Rotation = 1; + HG.RefAxis = 0; + HG.DirCode = 0; + HG.Screw = 0; + for (i = 0; i < 12; i++) + HG.SeitzMx.a[i] = 0; + + ClearHG = 0; + } + + switch (FieldType) { + case FT_Improper: + HG.Improper = 1; + break; + case FT_Rotation: + HG.Rotation = rotation; + break; + case FT_RefAxis: + HG.RefAxis = refaxis; + break; + case FT_DirCode: + HG.DirCode = dircode; + break; + case FT_Translation: + if (translation != NULL) { + for (i = 0; i < 3; i++) + HG.SeitzMx.s.T[i] += *(++translation); + } + break; + } + } + } else { /* FieldType == FT_OriginShift */ + + if (iOriginShift > 3) { + SetSgError(Err_Too_ori_shi_val); + return pos_hsym; + } + + if (*hsym == '\0') + c = ')'; + + digit = -1; + + switch (c) { + case ' ': + break; + + case ')': + if (iOriginShift != 3) { + SetSgError("Error: Missing origin shift values"); + return pos_hsym; + } + iOriginShift++; + FieldType = FT_Delimiter; + break; + + case '-': + if (SignOriginShift != 0) { + SetSgError(Err_Ill_ori_shi_val); + return pos_hsym; + } + SignOriginShift = 1; + break; + + case '0': + digit = 0; + break; + case '1': + digit = 1; + break; + case '2': + digit = 2; + break; + case '3': + digit = 3; + break; + case '4': + digit = 4; + break; + case '5': + digit = 5; + break; + case '6': + digit = 6; + break; + + default: + SetSgError(Err_Ill_ori_shi_val); + return pos_hsym; + } + + if (digit >= 0) { + if (iOriginShift >= 3) { + SetSgError(Err_Too_ori_shi_val); + return pos_hsym; + } + if (SignOriginShift) + digit *= -1; + SignOriginShift = 0; + SgInfo->OriginShift[iOriginShift++] = digit; + } + } + } + while (*hsym++ != '\0'); + + if (LatticeInfo == NULL) { + SetSgError("Error: Lattice type not specified"); + return pos_hsym; + } + + return pos_hsym; +} + + +static const char *PrintSgLabel(const char *lbl, int space, int *n, + FILE * fpout) +{ + while (*lbl && *lbl != ' ') { + if (*lbl == '_') { + if (space) { + putc(space, fpout); + if (n) + (*n)++; + } + } else { + putc(*lbl, fpout); + if (n) + (*n)++; + } + + lbl++; + } + + return lbl; +} + + +int PrintFullHM_SgName(const T_TabSgName * tsgn, int space, FILE * fpout) +{ + int n; + const char *lbl; + + + lbl = tsgn->SgLabels; + + if (tsgn->SgNumber >= 3 && tsgn->SgNumber < 16) + while (*lbl) + if (*lbl++ == '=') + break; + + SkipWhite(lbl); + + n = 0; + + PrintSgLabel(lbl, space, &n, fpout); + + lbl = tsgn->Extension; + + if (*lbl && strchr("12HhRr", *lbl)) { + putc(':', fpout); + putc(*lbl, fpout); + n += 2; + } + + return n; +} + + +void PrintTabSgNameEntry(const T_TabSgName * tsgn, int Style, int space, + FILE * fpout) +{ + int n; + const char *lbl, *SfSymbol; + + + if (Style) + n = fprintf(fpout, "%3d", tsgn->SgNumber); + else + n = fprintf(fpout, "%d", tsgn->SgNumber); + + if (tsgn->Extension[0]) + n += fprintf(fpout, ":%s", tsgn->Extension); + + if (Style) + while (n < 9) { + putc(' ', fpout); + n++; + } + + putc(' ', fpout); + n++; + putc(' ', fpout); + n++; + + if (tsgn->SgNumber >= 1 && tsgn->SgNumber <= 230) + SfSymbol = SchoenfliesSymbols[tsgn->SgNumber]; + else + SfSymbol = ""; + + n += fprintf(fpout, "%s", SfSymbol); + + if (Style) + while (n < 23) { + putc(' ', fpout); + n++; + } + + putc(' ', fpout); + n++; + putc(' ', fpout); + n++; + + if (tsgn->SgNumber >= 3 && tsgn->SgNumber < 16) { + lbl = PrintSgLabel(tsgn->SgLabels, space, &n, fpout); + + if (tsgn->Extension[0]) + n += fprintf(fpout, ":%s", tsgn->Extension); + + putc(' ', fpout); + putc('=', fpout); + putc(' ', fpout); + n += 3; + + n += PrintFullHM_SgName(tsgn, space, fpout); + + while (*lbl) + if (*lbl++ == '=') + break; + while (*lbl) + if (*lbl++ == '=') + break; + SkipWhite(lbl); + + if (*lbl) { + putc(' ', fpout); + putc('=', fpout); + putc(' ', fpout); + n += 3; + + PrintSgLabel(lbl, space, &n, fpout); + } + } else + n += PrintFullHM_SgName(tsgn, space, fpout); + + if (Style) + while (n < 51) { + putc(' ', fpout); + n++; + } + + putc(' ', fpout); + putc(' ', fpout); + + fprintf(fpout, "%s", tsgn->HallSymbol); +} + + +static int FindGCD2(int ri, int rj) +{ + int rk; + + + if (ri < 0) + ri = -ri; + + if (rj) { + for (;;) { + rk = ri % rj; + if (rk == 0) { + ri = rj; + break; + } + ri = rj % rk; + if (ri == 0) { + ri = rk; + break; + } + rj = rk % ri; + if (rj == 0) { + break; + } + } + + if (ri < 0) + ri = -ri; + } + + return ri; +} + + +static void SimplifyFraction(int nume, int deno, int *o_nume, int *o_deno) +{ + int gcd = FindGCD2(nume, deno); + if (gcd) { + *o_nume = nume / gcd; + *o_deno = deno / gcd; + + if (*o_deno < 0) { + *o_nume *= -1; + *o_deno *= -1; + } + } +} + + +const char *FormatFraction(int nume, int deno, int Decimal, + char *Buffer, int SizeBuffer) +{ + int n, d; + char *cp, *cpp; + static char StaticBuffer[40]; + + + if (NULL == Buffer) { + Buffer = StaticBuffer; + SizeBuffer = sizeof StaticBuffer / sizeof(*StaticBuffer); + } + + Buffer[SizeBuffer - 1] = '\0'; + + if (nume == 0) { + Buffer[0] = '0'; + Buffer[1] = '\0'; + } + if (Decimal) { + sprintf(Buffer, "%.6g", (double) nume / deno); + + cp = Buffer; + if (*cp == '-') + cp++; + if (*cp == '0') { + cpp = cp + 1; + while (*cp) + *cp++ = *cpp++; + } + } else { + SimplifyFraction(nume, deno, &n, &d); + + if (d == 1) + sprintf(Buffer, "%d", n); + else + sprintf(Buffer, "%d/%d", n, d); + } + + if (Buffer[SizeBuffer - 1] != '\0') { + Buffer[SizeBuffer - 1] = '\0'; + SetSgError("Internal Error: FormatFraction(): Buffer too small"); + return NULL; + } + + return Buffer; +} + + +const char *RTMx2XYZ(const T_RTMx * RTMx, int FacRo, int FacTr, + int Decimal, int TrFirst, int Low, + const char *Seperator, + char *BufferXYZ, int SizeBufferXYZ) +{ + static const char *UpperXYZ = "XYZ"; + static const char *LowerXYZ = "xyz"; + + int i, j, p, iRo, iTr; + char *xyz, buf_tr[32]; + const char *sep, *LetterXYZ, *ro, *tr; + + static char StaticBufferXYZ[80]; + + + if (NULL == BufferXYZ) { + BufferXYZ = StaticBufferXYZ; + SizeBufferXYZ = sizeof StaticBufferXYZ / sizeof(*StaticBufferXYZ); + } + + BufferXYZ[SizeBufferXYZ - 1] = '\0'; + + if (Low) + LetterXYZ = LowerXYZ; + else + LetterXYZ = UpperXYZ; + + if (Seperator == NULL) + Seperator = ","; + + xyz = BufferXYZ; + + for (i = 0; i < 3; i++) { + if (i != 0) + for (sep = Seperator; *sep; sep++) + *xyz++ = *sep; + + iTr = iModPositive(RTMx->s.T[i], FacTr); + if (iTr > FacTr / 2) + iTr -= FacTr; + + tr = FormatFraction(iTr, FacTr, Decimal, + buf_tr, sizeof buf_tr / sizeof(*buf_tr)); + if (tr == NULL) + return NULL; + + p = 0; + + if (TrFirst && iTr) { + if (*tr) + p = 1; + while (*tr) + *xyz++ = *tr++; + } + + for (j = 0; j < 3; j++) { + iRo = RTMx->s.R[i * 3 + j]; + if (iRo) { + ro = FormatFraction(iRo, FacRo, Decimal, NULL, 0); + if (ro == NULL) + return NULL; + + if (*ro == '-') + *xyz++ = *ro++; + else if (*ro && p) + *xyz++ = '+'; + + if (ro[0] != '1' || ro[1] != '\0') { + while (*ro) + *xyz++ = *ro++; + *xyz++ = '*'; + } + + *xyz++ = LetterXYZ[j]; + + p = 1; + } + } + + if (!TrFirst && iTr) { + if (*tr && *tr != '-' && p) + *xyz++ = '+'; + + while (*tr) + *xyz++ = *tr++; + } + } + + *xyz = '\0'; + + if (BufferXYZ[SizeBufferXYZ - 1] != '\0') { + BufferXYZ[SizeBufferXYZ - 1] = '\0'; + SetSgError("Internal Error: RTMx2XYZ(): BufferXYZ too small"); + return NULL; + } + + return BufferXYZ; +} + + +void PrintMapleRTMx(const T_RTMx * RTMx, int FacRo, int FacTr, + const char *Label, FILE * fpout) +{ + int i, j, nt; + const int *r, *t; + const char *ff; + + + if (Label) + fprintf(fpout, "%s", Label); + + fprintf(fpout, " := matrix(4,4, ["); + + r = RTMx->s.R; + t = RTMx->s.T; + + for (i = 0; i < 3; i++, t++) { + putc(' ', fpout); + + for (j = 0; j < 3; j++, r++) { + ff = FormatFraction(*r, FacRo, 0, NULL, 0); + if (ff == NULL) + return; + + fprintf(fpout, "%s,", ff); + } + + nt = iModPositive(*t, FacTr); + if (nt > FacTr / 2) + nt -= FacTr; + + ff = FormatFraction(nt, FacTr, 0, NULL, 0); + if (ff == NULL) + return; + + fprintf(fpout, "%s,", ff); + } + + fprintf(fpout, " 0,0,0,1]);\n"); +} + + +static void PrintSeitzMx(const T_RTMx * SMx, FILE * fpout) +{ + int i, nt; + const char *ff; + const int *r, *t; + + + r = SMx->s.R; + t = SMx->s.T; + + for (i = 0; i < 3; i++) { + fprintf(fpout, " %2d", *r++); + fprintf(fpout, " %2d", *r++); + fprintf(fpout, " %2d", *r++); + + nt = iModPositive(*t++, STBF); + if (nt > STBF / 2) + nt -= STBF; + + ff = FormatFraction(nt, STBF, 0, NULL, 0); + if (ff == NULL) + return; + + fprintf(fpout, " %6s\n", ff); + } + + putc('\n', fpout); +} + + +void ListSgInfo(const T_SgInfo * SgInfo, int F_XYZ, int F_Verbose, + FILE * fpout) +{ + int iList, i_si_v; + char buf[8]; + const char *xyz; + const T_RTMx *lsmx; + T_RotMxInfo *rmxi, RotMxInfo; + + + iList = PG_Index(SgInfo->PointGroup); + + fprintf(fpout, "Point Group %s\n", PG_Names[iList]); + fprintf(fpout, "Laue Group %s\n", + PG_Names[PG_Index(LG_Code_of_PG_Index[iList])]); + + fprintf(fpout, "%s\n", XS_Name[SgInfo->XtalSystem]); + + if (SgInfo->UniqueRefAxis != 0 || SgInfo->UniqueDirCode != 0) { + fprintf(fpout, "Unique Axis "); + if (SgInfo->UniqueRefAxis != 0 && SgInfo->UniqueRefAxis != 'o') + fprintf(fpout, "%c", SgInfo->UniqueRefAxis); + if (SgInfo->UniqueDirCode != 0 && SgInfo->UniqueDirCode != '=') + fprintf(fpout, "%c", SgInfo->UniqueDirCode); + fprintf(fpout, "\n"); + } + + if (SgInfo->ExtraInfo != EI_Unknown) + fprintf(fpout, "%s\n", EI_Name[SgInfo->ExtraInfo]); + + if (SgInfo->InversionOffOrigin) + fprintf(fpout, "Note: Inversion operation off origin\n"); + + putc('\n', fpout); + + fprintf(fpout, "Order %3d\n", SgInfo->OrderL); + fprintf(fpout, "Order P %3d\n", SgInfo->OrderP); + putc('\n', fpout); + + if (SgInfo->n_si_Vector >= 0) { + fprintf(fpout, "s.i.Vector Modulus\n"); + for (i_si_v = 0; i_si_v < SgInfo->n_si_Vector; i_si_v++) + fprintf(fpout, " %2d %2d %2d %d\n", + SgInfo->si_Vector[i_si_v * 3 + 0], + SgInfo->si_Vector[i_si_v * 3 + 1], + SgInfo->si_Vector[i_si_v * 3 + 2], + SgInfo->si_Modulus[i_si_v]); + putc('\n', fpout); + } + + if (F_XYZ || F_Verbose) { + fprintf(fpout, "#List %3d\n", SgInfo->nList); + putc('\n', fpout); + + lsmx = SgInfo->ListSeitzMx; + rmxi = SgInfo->ListRotMxInfo; + + if (rmxi == NULL) + rmxi = &RotMxInfo; + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) { + if (rmxi == &RotMxInfo) { + if (GetRotMxInfo(lsmx->s.R, &RotMxInfo) == 0) { + SetSgError("Error: Illegal SeitzMx in list"); + return; + } + } + + if (F_Verbose) { + sprintf(buf, "(%d)", iList + 1); + fprintf(fpout, "%-4s", buf); + + fprintf(fpout, " %2d", rmxi->Order); + if (rmxi->Inverse) + fprintf(fpout, "^-1"); + else + fprintf(fpout, " "); + + fprintf(fpout, " [%2d %2d %2d]", + rmxi->EigenVector[0], + rmxi->EigenVector[1], rmxi->EigenVector[2]); + + if (rmxi->RefAxis) + fprintf(fpout, " '%c'", rmxi->RefAxis); + else + fprintf(fpout, " "); + if (rmxi->DirCode) + fprintf(fpout, " '%c'", rmxi->DirCode); + else + fprintf(fpout, " "); + + fprintf(fpout, " "); + } + + xyz = RTMx2XYZ(lsmx, 1, STBF, 0, 0, 1, ", ", NULL, 0); + if (xyz) + fprintf(fpout, "%s", xyz); + + putc('\n', fpout); + + if (xyz == NULL) + return; + + if (F_Verbose) + PrintSeitzMx(lsmx, fpout); + + if (rmxi != &RotMxInfo) + rmxi++; + } + + if (iList && F_Verbose == 0) + putc('\n', fpout); + } +} diff --git a/sgsi.c b/sgsi.c new file mode 100644 index 00000000..f9f53ebd --- /dev/null +++ b/sgsi.c @@ -0,0 +1,467 @@ +/* + Space Group Info's (c) 1994-96 Ralf W. Grosse-Kunstleve + */ + +#include +#include + + +#ifdef APP_INCLUDE +#include APP_INCLUDE +#endif + +#ifndef AppMalloc +#define AppMalloc(ptr, n) (ptr) = malloc((n) * sizeof (*(ptr))) +#endif +#ifndef AppFree +#define AppFree(ptr, n) free(ptr) +#endif + + +#include "sginfo.h" + + +/* Non elegant way to get s.i. vectors and moduli: + 1. Build field with legal reference points marked (TestField) + 2. Go through list of possible s.i. vects and mods: + Verify with TestField + */ + + +void MarkLegalOrigins(const T_SgInfo * SgInfo, int *TestField) +{ + int O[3], V[3], lx, ly, lz, mx, my, mz, i; + int IsFine, iList, iLoopInv, nLoopInv; + int BufMx[9]; + const T_RTMx *lsmx; + int nTrV, iTrV; + const int *TrV; + + + nLoopInv = Sg_nLoopInv(SgInfo); + + nTrV = SgInfo->LatticeInfo->nTrVector; + + switch (SgInfo->LatticeInfo->Code) { + default: + case 'P': + lx = ly = lz = 12; + break; + case 'A': + lx = ly = 12; + lz = 6; + break; + case 'B': + ly = lz = 12; + lx = 6; + break; + case 'C': + lz = lx = 12; + ly = 6; + break; + case 'I': + lx = ly = 12; + lz = 6; + break; + case 'R': + lx = ly = 12; + lz = 4; + break; + case 'S': + lz = lx = 12; + ly = 4; + break; + case 'T': + ly = lz = 12; + lx = 4; + break; + case 'F': + lx = 12; + ly = lz = 6; + break; + } + + for (O[0] = 0; O[0] < 12; O[0]++) + for (O[1] = 0; O[1] < 12; O[1]++) + for (O[2] = 0; O[2] < 12; O[2]++) { + IsFine = 1; + + for (iList = 0; IsFine && iList < SgInfo->nList; iList++) { + lsmx = &SgInfo->ListSeitzMx[iList]; + + for (iLoopInv = 0; IsFine && iLoopInv < nLoopInv; iLoopInv++) { + if (iLoopInv == 0) + for (i = 0; i < 9; i++) { + if (i % 4) + BufMx[i] = lsmx->s.R[i]; + else + BufMx[i] = lsmx->s.R[i] - 1; + } else + for (i = 0; i < 9; i++) { + if (i % 4) + BufMx[i] = -lsmx->s.R[i]; + else + BufMx[i] = -lsmx->s.R[i] - 1; + } + + RotMx_t_Vector(V, BufMx, O, 12); + + TrV = SgInfo->LatticeInfo->TrVector; + + for (iTrV = 0; iTrV < nTrV; iTrV++) { + mx = (V[0] * (STBF / 12) + *TrV++) % STBF; + my = (V[1] * (STBF / 12) + *TrV++) % STBF; + mz = (V[2] * (STBF / 12) + *TrV++) % STBF; + + if (mx == 0 && my == 0 && mz == 0) + break; + } + + if (iTrV == nTrV) + IsFine = 0; + } + } + + if (!(O[0] < lx && O[1] < ly && O[2] < lz)) + IsFine = -IsFine; + + *TestField++ = IsFine; + +#if DEBUG_MarkLegalOrigins + if (IsFine == 1) + putc(' ', stdout); + else if (IsFine == -1) + putc('#', stdout); + if (IsFine != 0) + fprintf(stdout, " %2d %2d %2d\n", O[0], O[1], O[2]); +#endif + } +} + + +#define IsArbitraryShift(iShift) \ + ( (iShift) == 1 || (iShift) == 5 \ + || (iShift) == 7 || (iShift) == 11) + + +int Verify_si(int h, int k, int l, const int *TestField) +{ + int O[3], TH; + + + for (O[0] = 0; O[0] < 12; O[0]++) + for (O[1] = 0; O[1] < 12; O[1]++) + for (O[2] = 0; O[2] < 12; O[2]++) { + if (*TestField++) { + TH = h * O[0] + k * O[1] + l * O[2]; + TH %= 12; + if (TH) + return 0; + + if (IsArbitraryShift(O[0])) + TH += h; + if (IsArbitraryShift(O[1])) + TH += k; + if (IsArbitraryShift(O[2])) + TH += l; + if (TH) + return 0; + } + } + + return 1; +} + + +int Is_si(const T_SgInfo * SgInfo, int h, int k, int l) +{ + int i_si_v, u; + const int *si_v, *si_m; + + + si_v = SgInfo->si_Vector; + si_m = SgInfo->si_Modulus; + + for (i_si_v = 0; i_si_v < SgInfo->n_si_Vector; i_si_v++) { + u = *si_v++ * h; + u += *si_v++ * k; + u += *si_v++ * l; + + if (*si_m) { + if (u % (*si_m)) + return 0; + } else { + if (u) + return 0; + } + + si_m++; + } + + return 1; +} + + +int Set_si(T_SgInfo * SgInfo) +{ + static const int TabTrial_si[] = { + 0, + + 1, 0, 2, -1, 4, /* I -4 */ + 1, 2, -1, 0, 4, + 1, -1, 0, 2, 4, + + 1, 2, 4, 3, 6, /* P 3 2 */ + 1, 4, 3, 2, 6, + 1, 3, 2, 4, 6, + + 1, 1, 1, 1, 4, + 1, 1, 1, 1, 2, + 1, 1, 1, 1, 0, + + 1, 0, 0, 1, 2, + 1, 0, 1, 0, 2, + 1, 1, 0, 0, 2, + + 1, 0, 0, 1, 0, + 1, 0, 1, 0, 0, + 1, 1, 0, 0, 0, + + 2, 1, -1, 0, 3, + 0, 0, 1, 0, + 2, -1, 0, 1, 3, + 0, 1, 0, 0, + 2, 0, 1, -1, 3, + 1, 0, 0, 0, + + 2, 0, 1, 1, 4, /* F 2x */ + 1, 0, 0, 0, + 2, 1, 0, 1, 4, /* F 2y */ + 0, 1, 0, 0, + 2, 1, 1, 0, 4, /* F 2z */ + 0, 0, 1, 0, + + 2, 1, 0, 0, 2, + 0, 0, 1, 2, + 2, 0, 1, 0, 2, + 0, 0, 1, 2, + 2, 1, 0, 0, 2, + 0, 1, 0, 2, + + 2, 1, 1, 0, 2, + 0, 0, 1, 2, + 2, 1, 0, 1, 2, + 0, 1, 0, 2, + 2, 0, 1, 1, 2, + 1, 0, 0, 2, + + 2, 1, 0, 0, 2, + 0, 0, 1, 0, + 2, 0, 1, 0, 2, + 0, 0, 1, 0, + 2, 1, 0, 0, 2, + 0, 1, 0, 0, + + 2, 1, 0, 0, 0, + 0, 0, 1, 2, + 2, 0, 1, 0, 0, + 0, 0, 1, 2, + 2, 1, 0, 0, 0, + 0, 1, 0, 2, + + 2, 1, 1, 0, 2, + 0, 0, 1, 0, + 2, 1, 0, 1, 2, + 0, 1, 0, 0, + 2, 0, 1, 1, 2, + 1, 0, 0, 0, + + 2, 1, 0, 0, 0, + 0, 0, 1, 0, + 2, 0, 1, 0, 0, + 0, 0, 1, 0, + 2, 1, 0, 0, 0, + 0, 1, 0, 0, + + 3, 1, 0, 0, 2, + 0, 1, 0, 2, + 0, 0, 1, 2, + + 3, 1, 0, 0, 0, + 0, 1, 0, 2, + 0, 0, 1, 2, + + 3, 1, 0, 0, 2, + 0, 1, 0, 0, + 0, 0, 1, 2, + + 3, 1, 0, 0, 2, + 0, 1, 0, 2, + 0, 0, 1, 0, + + 3, 1, 0, 0, 2, + 0, 1, 0, 0, + 0, 0, 1, 0, + + 3, 1, 0, 0, 0, + 0, 1, 0, 2, + 0, 0, 1, 0, + + 3, 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 2, + + 3, 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + + 3, -1, 0, 0, 2, /* -A 1 */ + 0, -1, 1, 4, + 0, 1, 1, 4, + + 3, -1, 0, 1, 4, /* -B 1 */ + 0, -1, 0, 2, + 1, 0, 1, 4, + + 3, 1, 1, 0, 4, /* -C 1 */ + 1, -1, 0, 4, + 0, 0, -1, 2, + + 3, -1, 1, 1, 4, /* -I 1 */ + 1, -1, 1, 4, + 1, 1, -1, 4, + + 3, 0, 1, 1, 4, /* -F 1 */ + 1, 0, 1, 4, + 1, 1, 0, 4, + + 3, -1, 0, 0, 0, /* A 2x */ + 0, -1, 1, 4, + 0, 1, 1, 4, + + 3, -1, 0, 1, 4, /* B 2y */ + 0, -1, 0, 0, + 1, 0, 1, 4, + + 3, 1, 1, 0, 4, /* C 2z */ + 1, -1, 0, 4, + 0, 0, -1, 0, + + -1 + }; + + int h, k, l, iList; + int Maxh, Maxk, Maxl; + int Minh, Mink, Minl; + int nTestField, *TestField; + int nProperty, *Property, *pp; + int IsFine, would_be, is; + int i_si, *si_v; + const int *trial_si; + + + SgInfo->n_si_Vector = -1; + + nTestField = 12 * 12 * 12; + AppMalloc(TestField, nTestField); + if (TestField == NULL) { + SetSgError("Not enough core"); + return -1; + } + + MarkLegalOrigins(SgInfo, TestField); + + Maxh = Maxk = Maxl = 7; + SetListMin_hkl(SgInfo, Maxk, Maxl, &Minh, &Mink, &Minl); + + nProperty = (Maxh - Minh + 1) + * (Maxk - Mink + 1) + * (Maxl - Minl + 1); + AppMalloc(Property, nProperty); + if (Property == NULL) { + SetSgError("Not enough core"); + AppFree(TestField, nTestField); + return -1; + } + + pp = Property; + for (h = Minh; h <= Maxh; h++) + for (k = Mink; k <= Maxk; k++) + for (l = Minl; l <= Maxl; l++) { + iList = IsSysAbsent_hkl(SgInfo, h, k, l, NULL); + if (SgError != NULL) { + AppFree(Property, nProperty); + AppFree(TestField, nTestField); + return -1; + } + + if (iList == 0) + *pp++ = Verify_si(h, k, l, TestField); + else + *pp++ = -1; + } + + trial_si = TabTrial_si; + while (*trial_si >= 0) { + SgInfo->n_si_Vector = *trial_si++; + si_v = SgInfo->si_Vector; + for (i_si = 0; i_si < SgInfo->n_si_Vector; i_si++) { + *si_v++ = *trial_si++; + *si_v++ = *trial_si++; + *si_v++ = *trial_si++; + SgInfo->si_Modulus[i_si] = *trial_si++; + } + + IsFine = 1; + + pp = Property; + for (h = Minh; IsFine && h <= Maxh; h++) + for (k = Mink; IsFine && k <= Maxk; k++) + for (l = Minl; IsFine && l <= Maxl; l++) { + is = *pp++; + + if (is >= 0) { + would_be = Is_si(SgInfo, h, k, l); + if (is != would_be) + IsFine = 0; + } + } + + if (IsFine) { + AppFree(Property, nProperty); + AppFree(TestField, nTestField); + return 0; + } + } + + SgInfo->n_si_Vector = -1; + SetSgError("Internal Error: Can't determine s.i. vectors and moduli"); + + AppFree(Property, nProperty); + AppFree(TestField, nTestField); + + return -1; +} + + +void Set_uvw(const T_SgInfo * SgInfo, int h, int k, int l, int *uvw) +{ + int i_si_v, u; + const int *si_v, *si_m; + + + si_v = SgInfo->si_Vector; + si_m = SgInfo->si_Modulus; + + for (i_si_v = 0; i_si_v < SgInfo->n_si_Vector; i_si_v++) { + u = *si_v++ * h; + u += *si_v++ * k; + u += *si_v++ * l; + + if (*si_m) + u %= (*si_m); + si_m++; + + uvw[i_si_v] = u; + } +} diff --git a/sics.h b/sics.h index c585831d..9dce3623 100644 --- a/sics.h +++ b/sics.h @@ -10,19 +10,22 @@ #ifndef SICSSICS #define SICSSICS - typedef enum { - eTimer, - ePreset - }CounterMode; +typedef enum { + eTimer, + ePreset +} CounterMode; /* the following line suppresses const declarations in tcl.h. WARNING: including sics.h must always be done before tcl.h -> makes the compiler happy M.Z. */ -#define NO_CONST +#define NO_CONST #include #include #include + +#include + #include "Scommon.h" #include "event.h" #include "obdes.h" @@ -34,15 +37,10 @@ #include "emon.h" #include "nserver.h" #include "servlog.h" +#include "sicsutil.h" +#include "trace.h" + +extern pServer pServ; - extern pServer pServ; -/** - * Decode privilege text. Implemented in access.c - * @param the text to decode - * @return -1 if code invalid, else the privilege code - */ -int decodeSICSPriv(char *privText); - #endif - diff --git a/sicscron.c b/sicscron.c index 38585f38..5697771c 100644 --- a/sicscron.c +++ b/sicscron.c @@ -7,6 +7,8 @@ copyright: see copyright.h Mark Koennecke, November 1999 + + modified to give more error output: Mark Koennecke, December 2010 ------------------------------------------------------------------------*/ #include #include @@ -16,199 +18,196 @@ #include "sics.h" #include "splitter.h" #include "sicscron.h" +#include "commandlog.h" +typedef struct { + int iInterval; + time_t tNext; + char *pCommand; + SConnection *pCon; + int iEnd; + Statistics *stat; +} Cron, *pCron; - typedef struct { - int iInterval; - time_t tNext; - char *pCommand; - SConnection *pCon; - int iEnd; - Statistics *stat; - } Cron, *pCron; +typedef struct { + SConnection *pCon; + int dolater; +} CronListData; - typedef struct { - SConnection *pCon; - int dolater; - } CronListData; - /*------------------------------------------------------------------------*/ - static void KillCron(void *pData) - { - pCron self = (pCron)pData; - - if(!self) - { - return; - } - if(self->pCommand) - { - free(self->pCommand); - } - if(self->pCon) - { - SCDeleteConnection(self->pCon); - } - if (self->stat) { - StatisticsKill(self->stat); - } - free(self); +static void KillCron(void *pData) +{ + pCron self = (pCron) pData; + + if (!self) { + return; } + if (self->pCommand) { + free(self->pCommand); + } + if (self->pCon) { + SCDeleteConnection(self->pCon); + } + if (self->stat) { + StatisticsKill(self->stat); + } + free(self); +} + /*-----------------------------------------------------------------------*/ - static int CronTask(void *pData) - { - Statistics *old; +static int CronTask(void *pData) +{ + Statistics *old; - pCron self = (pCron)pData; - int iRet; - Tcl_Interp *pTcl = pServ->pSics->pTcl; - time_t now; + pCron self = (pCron) pData; + int iRet; + Tcl_Interp *pTcl = pServ->pSics->pTcl; + time_t now; + struct tm *nowtm; + char buffer[1024]; - if(!self) - { - return 0; - } - - now = time(NULL); - if(now >= self->tNext) - { - MacroPush(self->pCon); - old=StatisticsBegin(self->stat); - iRet = Tcl_Eval(pTcl,self->pCommand); - StatisticsEnd(old); - MacroPop(); - if (iRet != TCL_OK) { - SCPrintf(self->pCon, eStatus, - "ERROR in sicscron script: %s", pTcl->result); - self->iEnd = 0; - return 0; - } - if (self->iEnd == 2) { /* dolater command */ - self->iEnd = 0; - return 0; - } - self->tNext += self->iInterval; - if (now > self->tNext) self->tNext = now + 1; - } - return self->iEnd > 0; + if (!self) { + return 0; } + + now = time(NULL); + if (now >= self->tNext) { + MacroPush(self->pCon); + old = StatisticsBegin(self->stat); + iRet = Tcl_Eval(pTcl, self->pCommand); + StatisticsEnd(old); + MacroPop(); + if (iRet != TCL_OK) { + if (strcmp(pTcl->result, "stop") == 0) { + snprintf(buffer,1024,"sicscron script '%s' stopped", + self->pCommand); + SCPrintf(self->pCon, eLogError, buffer); + WriteToCommandLog("SICSCRON:", buffer); + self->iEnd = 0; + return 0; + } + snprintf(buffer,1024,"ERROR in sicscron script '%s': %s", self->pCommand, pTcl->result); + SCPrintf(self->pCon, eLogError,buffer); + WriteToCommandLog("SICSCRON:", buffer); + } + if (self->iEnd == 2) { /* dolater command */ + self->iEnd = 0; + return 0; + } + self->tNext += self->iInterval; + if (now > self->tNext) + self->tNext = now; + } +/* printf("CronTask return: %d\n", self->iEnd > 0);*/ + if(self->iEnd <= 0){ + snprintf(buffer,1024,"crontask terminating at %s on %d", ctime(&now), self->iEnd); + WriteToCommandLog("SICSCRON", buffer); + } + return self->iEnd > 0; +} + /*-----------------------------------------------------------------------*/ - static void CronSignal(void *pData, int iID, void *pSigData) - { - pCron self = (pCron)pData; - int *iInt; - struct tm tm; - char datim[24]; - CronListData *data; - - if(iID == SICSINT) - { - iInt = (int *)pSigData; - if(*iInt >= eEndServer) - { - self->iEnd = 0; - } - } - if(iID == CRONLIST) { - data = pSigData; - if (self->iEnd == 2 && data->dolater) { - tm = *localtime(&self->tNext); - strftime(datim, sizeof datim, "%Y-%m-%d %T", &tm); - SCPrintf(data->pCon, eStatus, "%s %s", datim, - self->pCommand); - } else if (self->iEnd == 1 && !data->dolater) { - tm = *localtime(&self->tNext); - strftime(datim, sizeof datim, "%Y-%m-%d %T", &tm); - SCPrintf(data->pCon, eStatus, "%s %8d %s", datim, - self->iInterval, self->pCommand); - } - } +static void CronSignal(void *pData, int iID, void *pSigData) +{ + pCron self = (pCron) pData; + int *iInt; + struct tm tm; + char datim[24]; + CronListData *data; + + if (iID == SICSINT) { + iInt = (int *) pSigData; + if (*iInt == eEndServer) { + self->iEnd = 0; + } } + if (iID == CRONLIST) { + data = pSigData; + if (self->iEnd == 2 && data->dolater) { + tm = *localtime(&self->tNext); + strftime(datim, sizeof datim, "%Y-%m-%d %T", &tm); + SCPrintf(data->pCon, eLog, "%s %s", datim, self->pCommand); + } else if (self->iEnd == 1 && !data->dolater) { + tm = *localtime(&self->tNext); + strftime(datim, sizeof datim, "%Y-%m-%d %T", &tm); + SCPrintf(data->pCon, eLog, "%s %8d %s", datim, + self->iInterval, self->pCommand); + } + } +} + /*-----------------------------------------------------------------------*/ - int MakeCron(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]) - { - pCron pNew = NULL; - int iVal, iRet, rights; - char *cmd; - CronListData data; - - /* need user priv. */ - if(!SCMatchRights(pCon,usUser)) - { - return 0; - } +int MakeCron(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pCron pNew = NULL; + int iVal, iRet, rights; + char *cmd; + CronListData data; - if (argc == 2 && strcasecmp(argv[1], "list") == 0) { - if (strcasecmp(argv[0], "dolater") == 0) { - data.dolater = 1; - SCPrintf(pCon, eError, "Date Time Command"); - } else { - data.dolater = 0; - SCPrintf(pCon, eError, "Date Time Interval Command"); - } - data.pCon = pCon; - TaskSignal(pServ->pTasker, CRONLIST, &data); - return 1; - } - - /* enough arguments? */ - if(argc < 3) - { - SCPrintf(pCon,eError,"ERROR: not enough arguments to %s", argv[0]); - return 0; - } - - /* interpret first argument as interval in seconds */ - iRet = Tcl_GetInt(pSics->pTcl,argv[1],&iVal); - if(iRet != TCL_OK) - { - SCWrite(pCon,"ERROR: failed to convert interval argument to int", - eError); - return 0; - } - - /* concatenate the rest to the command */ - cmd = Arg2Tcl(argc-2,&argv[2],NULL,0); - - /* create data structure and install task */ - pNew = (pCron)malloc(sizeof(Cron)); - if(!pNew || !cmd) - { - SCWrite(pCon,"ERROR: out of memory in sicscron",eError); - return 0; - } - pNew->pCon = SCCreateDummyConnection(pSics); - if(!pNew->pCon) - { - SCWrite(pCon,"ERROR: out of memory in sicscron",eError); - return 0; - } - rights = SCGetRights(pCon); - if (rights > usMugger) { - /* transfer the rights to the dummy connection */ - SCSetRights(pNew->pCon, rights); - } - pNew->pCommand = cmd; - pNew->tNext = time(NULL) + iVal; - if (strcasecmp(argv[0], "dolater") == 0) { - pNew->iInterval = -1; - pNew->iEnd = 2; - } else { - pNew->iInterval = iVal; - pNew->iEnd = 1; - } - pNew->stat = StatisticsNew(cmd); - - TaskRegister(pServ->pTasker, - CronTask, - CronSignal, - KillCron, - pNew, - 1); - SCSendOK(pCon); - return 1; + /* need user priv. */ + if (!SCMatchRights(pCon, usUser)) { + return 0; } + if (argc == 2 && strcasecmp(argv[1], "list") == 0) { + if (strcasecmp(argv[0], "dolater") == 0) { + data.dolater = 1; + SCPrintf(pCon, eError, "Date Time Command"); + } else { + data.dolater = 0; + SCPrintf(pCon, eError, "Date Time Interval Command"); + } + data.pCon = pCon; + TaskSignal(pServ->pTasker, CRONLIST, &data); + return 1; + } + /* enough arguments? */ + if (argc < 3) { + SCPrintf(pCon, eError, "ERROR: usage: %s