diff --git a/tecs/Makefile b/tecs/Makefile index c6472031..f1037354 100644 --- a/tecs/Makefile +++ b/tecs/Makefile @@ -3,7 +3,7 @@ # # Markus Zolliker, March 2000 #-------------------------------------------------------------------------- -OBJ= tecc.o client.o coc.o buf.o errhdl.o util.o \ +OBJ= tecc.o client.o coc.o errhdl.o str_util.o str_buf.o \ server.o lsc.o serutil.o logfile.o dlog.o \ asynsrv_utility.o strjoin.o geterrno.o diff --git a/tecs/asynsrv_utility.c b/tecs/asynsrv_utility.c index d0256c80..50336a5c 100644 --- a/tecs/asynsrv_utility.c +++ b/tecs/asynsrv_utility.c @@ -4,7 +4,6 @@ #endif #ifdef __DECC #pragma module AsynSrv_Utility ident -#pragma nostandard #endif /* ** +--------------------------------------------------------------+ @@ -419,7 +418,9 @@ #include #ifdef __VMS +#pragma nostandard #include +#pragma standard #include #else #include diff --git a/tecs/client.c b/tecs/client.c index c4bdc0a3..9c1eb22c 100644 --- a/tecs/client.c +++ b/tecs/client.c @@ -1,6 +1,10 @@ +#include +#include +#include #include +#include "errhdl.h" #include "client.h" -#include "util.h" +#include "str_util.h" /*-------------------------------------------------------------------------*/ @@ -35,7 +39,7 @@ int CocOpen(CocConn *conn) tmo=100; /* wait total ca. 10 sec. for 15 tries */ while (try>0) { try--; - util_delay(tmo); tmo=tmo*5/4; + CocDelay(tmo); tmo=tmo*5/4; ERR_I(i=CocConnect(conn, try>0)); if (i==0) return(0); } @@ -48,12 +52,12 @@ int CocOpen(CocConn *conn) int CocInitClient(CocConn *conn, char *host, int port, char *magic, int bufsize, char *startcmd) { assert(conn!=NULL); if (bufsize==0) bufsize=1024; - conn->cmdbuf=buf_create(bufsize); - conn->resbuf=buf_create(bufsize); + ERR_P(conn->cmdbuf=str_create_buf(bufsize, '\0')); + ERR_P(conn->resbuf=str_create_buf(bufsize, '\0')); conn->port=port; - str_copy(conn->host, host); - str_copy(conn->magic, magic); - str_copy(conn->startcmd, startcmd); + ERR_I(str_copy(conn->host, host)); + ERR_I(str_copy(conn->magic, magic)); + ERR_I(str_copy(conn->startcmd, startcmd)); conn->fd=-1; conn->varList=NULL; CocVarList(&conn->varList); @@ -69,15 +73,13 @@ int CocSendMagic(CocConn *conn, char *magic) { char *err; if (magic[0]!='#') ERR_MSG("magic must start with '#'"); - buf_put_start(conn->resbuf); /* use return buffer for command in order to preserve command buffer */ - buf_put_str(conn->resbuf, magic); - buf_put_end(conn->resbuf); - if (conn->resbuf->buf==NULL) ERR_MSG("buffer full"); - ERR_SI(send(conn->fd, conn->resbuf->buf, conn->resbuf->size, 0)); + str_put_start(conn->resbuf); /* use return buffer for command in order to preserve command buffer */ + ERR_I(str_put_str(conn->resbuf, magic)); + ERR_SI(send(conn->fd, conn->resbuf->buf, conn->resbuf->wrpos, 0)); ERR_I(CocRecv(conn->fd, conn->resbuf)); - err=buf_get_str(conn->resbuf); + ERR_P(err=str_get_str(conn->resbuf, NULL)); if (*err!='\0') { ErrMsg(err); ErrTxt(": (response from server)",0); goto OnError; } - if (buf_size(conn->resbuf)!=0) ERR_MSG("syntax error"); + ERR_I(str_get_end(conn->resbuf)); return(0); OnError: return(-1); } @@ -89,7 +91,7 @@ int CocTryCmd(CocConn *conn) ERR_I(CocOpen(conn)); ERR_I(CocSendMagic(conn, conn->magic)); } - ERR_SI(send(conn->fd, conn->cmdbuf->buf, conn->cmdbuf->size, 0)); + ERR_SI(send(conn->fd, conn->cmdbuf->buf, conn->cmdbuf->wrpos, 0)); ERR_I(CocRecv(conn->fd, conn->resbuf)); return(0); OnError: return(-1); @@ -103,16 +105,17 @@ int CocCmd(CocConn *conn, const char *rwList) const char *t, *s; char nam[32]; CocVar *var; + void *adr; assert(conn!=NULL); - buf_put_start(conn->cmdbuf); + str_put_start(conn->cmdbuf); s=rwList; setmode=0; do { t=strchr(s, ','); if (t==NULL) t=s+strlen(s); if (*s=='[') { - if (!setmode) buf_put_str(conn->cmdbuf, "["); + if (!setmode) ERR_I(str_put_str(conn->cmdbuf, "[")); s++; setmode=1; } @@ -121,19 +124,17 @@ int CocCmd(CocConn *conn, const char *rwList) str_ncpy(nam, s, i+1); if (setmode) { if (nam[i-1]==']') { i--; nam[i]='\0'; setmode=0; } - buf_put_str(conn->cmdbuf, nam); - ERR_I(CocPutVar(conn->varList, conn->cmdbuf, nam)); - if (!setmode) buf_put_str(conn->cmdbuf, "]"); + ERR_I(str_put_str(conn->cmdbuf, nam)); + ERR_I(CocPutVar(conn->varList, conn->cmdbuf, nam, 0)); + if (!setmode) ERR_I(str_put_str(conn->cmdbuf, "]")); } else { - var=CocFindVar(conn->varList, nam); + var=CocFindVar(conn->varList, nam, NULL); if (var==NULL) ERR_MSG("variable not found"); - buf_put_str(conn->cmdbuf, nam); + ERR_I(str_put_str(conn->cmdbuf, nam)); } s=t+1; } while (*t!='\0'); - buf_put_end(conn->cmdbuf); - if (conn->cmdbuf->buf==NULL) ERR_MSG("out buffer full"); cnt=3; while (1) { cnt--; @@ -148,7 +149,7 @@ int CocCmd(CocConn *conn, const char *rwList) if (ErrCode!=ECONNRESET && ErrCode!=EPIPE) goto OnError; ErrShow("try again, error was"); } - err=buf_get_str(conn->resbuf); + ERR_P(err=str_get_str(conn->resbuf, NULL)); if (*err!='\0') { ErrMsg(err); ErrTxt(": (response from server)",0 ); goto OnError; } /* read values */ @@ -166,11 +167,11 @@ int CocCmd(CocConn *conn, const char *rwList) if (*(t-1)==']') setmode=0; } else { str_ncpy(nam, s, i+1); - ERR_I(CocGetVar(conn->varList, conn->resbuf, nam)); + ERR_I(CocGetVar(conn->varList, conn->resbuf, nam, 0)); } s=t+1; } while (*t!='\0'); - if (buf_size(conn->resbuf)!=0) ERR_MSG("syntax error"); + ERR_I(str_get_end(conn->resbuf)); return(0); OnError: return(-1); @@ -179,7 +180,7 @@ int CocCmd(CocConn *conn, const char *rwList) void CocCloseClient(CocConn *conn) { assert(conn!=NULL); close(conn->fd); - buf_free(conn->cmdbuf); - buf_free(conn->resbuf); + str_free_buf(conn->cmdbuf); + str_free_buf(conn->resbuf); CocFreeVarList(&conn->varList); } diff --git a/tecs/client.h b/tecs/client.h index 670e81c8..bf39f3e3 100644 --- a/tecs/client.h +++ b/tecs/client.h @@ -1,10 +1,13 @@ +#ifndef _CLIENT_H_ +#define _CLIENT_H_ + #include "coc.h" typedef struct { int fd, port; CocVar *varList; - buf_type *cmdbuf; /* for sending command */ - buf_type *resbuf; /* for response */ + Str_Buf *cmdbuf; /* for sending command */ + Str_Buf *resbuf; /* for response */ char host[64]; char magic[32]; char startcmd[512]; @@ -14,3 +17,5 @@ int CocInitClient(CocConn *conn, char *host, int port, char *magic, int bufsize, int CocSendMagic(CocConn *conn, char *magic); int CocCmd(CocConn *conn, const char *rwList); void CocCloseClient(CocConn *conn); + +#endif /* _CLIENT_H_ */ diff --git a/tecs/coc.c b/tecs/coc.c index 3f52a428..d804ade8 100644 --- a/tecs/coc.c +++ b/tecs/coc.c @@ -1,4 +1,12 @@ +#include +#include +#include +#include +#include +#include #include +#include "errhdl.h" +#include "util.h" #include "coc.h" /*-------------------------------------------------------------------------*/ /* CreateSocketAddress stolen from Tcl. Thanks to John Ousterhout */ @@ -44,7 +52,7 @@ int CocCreateSockAdr( /*-------------------------------------------------------------------------*/ -int CocRecv(int fd, buf_type *buf) +int CocRecv(int fd, Str_Buf *buf) { struct timeval tmo={0,1}; fd_set mask; @@ -57,11 +65,9 @@ int CocRecv(int fd, buf_type *buf) ERR_SI(i=select(fd+1,&mask,NULL,NULL,&tmo)); if (i==0) ERR_MSG("time out"); - buf_put_start(buf); - ERR_SI(ret=recv(fd, buf->buf, buf->isize, 0)); - if (ret==0) { ERR_COD(ECONNRESET); } - buf->usize=ret; - buf_reset(buf); + ERR_SI(buf->wrpos=recv(fd, buf->buf, buf->dsize, 0)); + if (buf->wrpos==0) { ERR_COD(ECONNRESET); } + str_get_start(buf); return(ret); OnError: return(-1); } @@ -71,7 +77,17 @@ void CocVarList(CocVar **varList) { varListHdl=varList; } -CocVar *CocFindVar(CocVar *varList, const char *name) { +void CocList() { + CocVar *p; + + p=*varListHdl; + while (p!=NULL) { + printf("%s %d\n", p->name, p->type); + p=p->next; + } +} + +CocVar *CocFindVar1(CocVar *varList, const char *name) { CocVar *p; p=varList; @@ -79,67 +95,129 @@ CocVar *CocFindVar(CocVar *varList, const char *name) { return(p); } -void CocDefVar(const char *name, void *var, int type, int *flag) { +CocVar *CocFindVar(CocVar *varList, const char *name, void **adr) { + CocVar *p, *t; + const char *f; + void *base; + char nam[32]; + + f=str_split(nam, name, '.'); + if (f==NULL) { + f=str_split(nam, name, '-'); + if (f!=NULL) { + if (f[0]!='>') { + f=NULL; + } else { + f++; + } + } + } + if (f!=NULL) { + if (adr!=NULL) *adr=NULL; + p=CocFindVar1(varList, nam); + if (p==NULL) { return(NULL); } + t=p->strucType; + if (t==NULL) { return(NULL); } + str_copy(nam, t->name); + str_append(nam, ":"); + str_append(nam, f); + if (adr!=NULL) { + base=p->var; + if (p->type==COC_PTR) base=*(void **)base; + *adr=base; + } + } else if (adr!=NULL) { + *adr=NULL; + } + p=CocFindVar1(varList, nam); + if (p!=NULL && p->type==COC_ALIAS) { /* recursive call for alias */ + p=CocFindVar(varList, p->var, adr); + } + return(p); +} + +CocVar *CocDefVar(const char *name, void *var, int type, int *flag) { CocVar *p; + const char *f; + void *adr; assert(varListHdl!=NULL); - p=CocFindVar(*varListHdl, name); + p=CocFindVar1(*varListHdl, name); if (p==NULL) { p=malloc(sizeof(*p)); p->next=*varListHdl; *varListHdl=p; + str_copy(p->name, name); } - str_copy(p->name, name); p->var=var; p->type=type; p->flag=flag; + return(p); } -int CocGetVar(CocVar *varList, buf_type *buf, const char *name) { - CocVar *var; +void CocDefVarS(const char *name, const char *tname, void *var, int type) { + CocVar *p, *t; - var=CocFindVar(varList, name); + assert(type==COC_PTR || type==COC_STRUCT); + p=CocDefVar(name, var, type, &CocRD); + p->strucType=CocDefVar(tname, NULL, COC_TYPE, &CocRD); +} + +int CocGetVar(CocVar *varList, Str_Buf *buf, const char *name, int secure) { + CocVar *var; + void *adr; + + var=CocFindVar(varList, name, &adr); if (var==NULL) ERR_MSG("undefined variable"); - if (varList==serverVarList) { /* we are the server */ + if (adr==NULL) { + adr=var->var; + } else { + adr=(char *)adr + (int)var->var; + } + if (secure) { /* we are the server */ if (var->flag==&CocRD) ERR_MSG("variable is read only"); } if (var->type==-1) { - *(int *)var->var=buf_get_int(buf); + ERR_I(str_get_int(buf, (int *)adr)); } else if (var->type==-2) { - *(float *)var->var=buf_get_float(buf); + ERR_I(str_get_float(buf, (float *)adr)); } else if (var->type>1) { - str_ncpy((char *)var->var, buf_get_str(buf), var->type); + ERR_P(str_nget_str(buf, (char *)adr, var->type)); } else { ERR_MSG("unknown type"); } - if (varList==serverVarList) { /* we are the server */ + if (secure) { /* we are the server */ (*var->flag)++; } return(0); OnError: return(-1); } -int CocPutVar(CocVar *varList, buf_type *buf, const char *name) { +int CocPutVar(CocVar *varList, Str_Buf *buf, const char *name, int secure) { CocVar *var; + void *adr; char *c; - - var=CocFindVar(varList, name); + + var=CocFindVar(varList, name, &adr); if (var==NULL) ERR_MSG("undefined variable"); - if (varList!=serverVarList) { /* we are the client */ + if (adr==NULL) { + adr=var->var; + } else { + adr=(char *)adr + (int)var->var; + } + if (secure) { /* we are the client */ if (var->flag==&CocRD) ERR_MSG("variable is read only"); } if (var->type==-1) { - buf_put_int(buf, *(int *)var->var); + ERR_I(str_put_int(buf, *(int *)adr)); } else if (var->type==-2) { - buf_put_float(buf, *(float *)var->var); + ERR_I(str_put_float(buf, *(float *)adr)); } else if (var->type>1) { - c=var->var; - if (c[0]<=2 && c[0]!=0) { ERR_MSG("illegal string"); } - buf_put_str(buf, c); + ERR_I(str_put_str(buf, adr)); } else { ERR_MSG("unknown type"); } - if (varList!=serverVarList) { /* we are a client */ + if (secure) { /* we are a client */ if (var->flag!=NULL) (*var->flag)++; } return(0); @@ -159,3 +237,11 @@ void CocFreeVarList(CocVar **varList) { } *varList=NULL; } + +void CocDelay(int msec) { + struct timeval tmo; + + tmo.tv_sec=msec / 1000; + tmo.tv_usec=(msec % 1000)*1000+1; + select(1,NULL,NULL,NULL,&tmo); +} diff --git a/tecs/coc.h b/tecs/coc.h index 8c025bcc..6d38b8ad 100644 --- a/tecs/coc.h +++ b/tecs/coc.h @@ -1,40 +1,47 @@ -#include -#include -#include +#ifndef _COC_H_ +#define _COC_H_ + #include -#include -#include -#include -#include -#include -#include -#include -#include -#include "errhdl.h" -#include "buf.h" -#include "util.h" +#include "str_buf.h" int CocCreateSockAdr( struct sockaddr_in *sockaddrPtr, /* Socket address */ const char *host, /* Host. NULL implies INADDR_ANY */ int port); /* Port number */ -int CocRecv(int fd, buf_type *buf); +int CocRecv(int fd, Str_Buf *buf); -typedef struct { void *next; char name[32]; void *var; int *flag; int type; } CocVar; +typedef struct { void *next; char name[32]; void *var; int *flag; int type; void *strucType; } CocVar; extern int CocRD; extern int CocWR; CocVar *serverVarList; -void CocDefVar(const char *name, void *var, int type, int *flag); +CocVar *CocDefVar(const char *name, void *var, int type, int *flag); +void CocDefVarS(const char *name, const char *tname, void *var, int type); void CocVarList(CocVar **varlist); void CocFreeVarList(CocVar **varList); -CocVar *CocFindVar(CocVar *varList, const char *name); -int CocPutVar(CocVar *varList, buf_type *buf, const char *name); -int CocGetVar(CocVar *varList, buf_type *buf, const char *name); +CocVar *CocFindVar(CocVar *varList, const char *name, void **adr); +int CocPutVar(CocVar *varList, Str_Buf *buf, const char *name, int secure); +int CocGetVar(CocVar *varList, Str_Buf *buf, const char *name, int secure); -#define CocDefInt(V,F) CocDefVar(#V,&V,-1,&F) -#define CocDefFlt(V,F) CocDefVar(#V,&V,-2,&F) +#define COC_INT -1 +#define COC_FLT -2 +#define COC_PTR -3 +#define COC_STRUCT -4 +#define COC_TYPE -5 +#define COC_ALIAS -6 +#define CocDefInt(V,F) CocDefVar(#V,&V,COC_INT,&F) +#define CocDefFlt(V,F) CocDefVar(#V,&V,COC_FLT,&F) #define CocDefStr(V,F) CocDefVar(#V,V,sizeof(V),&F) +#define CocDefPtr(V,S) CocDefVarS(#V,#S,&V,COC_PTR*(V!=(S *)NULL)); +#define CocDefStruct(V,S) CocDefVarS(#V,#S,&V,COC_STRUCT*(&V!=(S *)NULL)); +#define CocIntFld(S,V,F) CocDefVar(#S":"#V,&((S *)NULL)->V,COC_INT,&F); +#define CocFltFld(S,V,F) CocDefVar(#S":"#V,&((S *)NULL)->V,COC_FLT,&F); +#define CocStrFld(S,V,F) CocDefVar(#S":"#V,&((S *)NULL)->V,sizeof(((S *)NULL)->V),&F); #define CocDefCmd(V) CocDefVar("$",V,sizeof(V),&CocWR) #define CocDefStrPtr(V,S,F) CocDefVar(#V,V,S,&F) +#define CocAlias(A,V) CocDefVar(#A, #V, COC_ALIAS, &CocRD); + +void CocDelay(int msec); + +#endif /* _COC_H_ */ diff --git a/tecs/dlog.c b/tecs/dlog.c index 3de0fe0d..ae8b67e6 100644 --- a/tecs/dlog.c +++ b/tecs/dlog.c @@ -1,3 +1,4 @@ + /* switch off ANSI_C_SOURCE (allows compiling all sources with cc/stand=ansi) */ #ifdef __VMS #ifdef __HIDE_FORBIDDEN_NAMES @@ -147,19 +148,21 @@ int DlogPut(DlogSet *dset, time_t time, int nset, float val[]) { } int DlogGet(DlogSet *dset, int iset, int nmax, double *starttime, float x[], float y[]) { - int i0, i, n, undef; + int i0, i1, i, n, undef; float f[DLOG_MAX_SET]; if (iset<0) ERR_MSG("illegal iset"); if (iset>=dset->nset) return(0); i = ( dset->last - dset->start ) / dset->period; - i0=0; - if (i0 <= i - dset->nlen) { - i0 = i - dset->nlen + 1; + if (i - dset->nlen > 0) { + i1 = i - dset->nlen + 1; + } else { + i1 = 0; } + i0=i1; - *starttime = dset->start + i0 * dset->period; + *starttime = dset->start + i1 * dset->period; n=0; undef=2; while (i0<=i) { @@ -167,7 +170,7 @@ int DlogGet(DlogSet *dset, int iset, int nmax, double *starttime, float x[], flo ERR_I(DlogRead(dset, i0, f)); i0++; if (DEFINED(f[iset])) { - x[n]=(float)i0*dset->period; + x[n]=(float)(i0-i1)*dset->period; y[n]=f[iset]; n++; undef=0; @@ -205,7 +208,7 @@ int Dlog_Get_(char *name, int *nset, int *nmax, double *starttime, float x[], fl char buf[64]; int ntot; /* for compaq unix */ - str_ntrim(buf, sizeof(buf), name, namlen); + str_trim(buf, name, namlen); ERR_I(DlogOpen(&dset, buf, 0)); ERR_I(ntot=DlogGetMany(&dset, *nset, *nmax, starttime, x, y, index)); DlogClose(&dset); diff --git a/tecs/dlog.h b/tecs/dlog.h index 9a0c4db1..fd662078 100644 --- a/tecs/dlog.h +++ b/tecs/dlog.h @@ -1,3 +1,6 @@ +#ifndef _DLOG_H_ +#define _DLOG_H_ + #include #define DLOG_MAX_SET 32 @@ -47,3 +50,5 @@ int DlogUpd(DlogSet *dset); int DlogClose(DlogSet *dset); /* close dlog set */ + +#endif /* _DLOG_H_ */ diff --git a/tecs/errhdl.c b/tecs/errhdl.c index 5563744e..da3c7248 100644 --- a/tecs/errhdl.c +++ b/tecs/errhdl.c @@ -52,7 +52,7 @@ void ErrWriteGeneral(char *text, void (*outrtn)(), void *arg) } } outrtn(arg, buf); - outrtn(arg, "---"); + outrtn(arg, ""); } void ErrOutFil(void *arg, char *text) { diff --git a/tecs/errhdl.h b/tecs/errhdl.h index 69eab42c..bd97cf9c 100644 --- a/tecs/errhdl.h +++ b/tecs/errhdl.h @@ -1,3 +1,6 @@ +#ifndef _ERRHDL_H_ +#define _ERRHDL_H_ + #include #include #include @@ -79,3 +82,5 @@ void ErrLog(char *text); extern int ErrCode; extern char *ErrMessage; + +#endif /* _ERRHDL_H_ */ diff --git a/tecs/logfile.c b/tecs/logfile.c index 6057766e..2ac4521b 100644 --- a/tecs/logfile.c +++ b/tecs/logfile.c @@ -25,8 +25,8 @@ static int wrtMask=0; int ftime (struct timeb *__timeptr); /* for some reason not defined in timeb.h with flag -std1 */ -int logfileStd=0; -int dirty=0; +static int logfileStd; +static int dirty, writeAll; void logfileOpen(int first) { struct tm *tim; @@ -50,6 +50,8 @@ void logfileOpen(int first) { } else { sprintf(filnam, "%s%04d-%02d-%02d.log", lnam, tim->tm_year+1900, tim->tm_mon+1, tim->tm_mday); } + } else { + assert(filnam[0]!='\0'); } #ifdef __VMS if (first && notDated) { @@ -66,9 +68,11 @@ void logfileOpen(int first) { #endif } -void logfileInit(char *path, int nodate) { +void logfileInit(char *path, int nodate, int use_stdout, int write_all) { str_copy(lnam, path); lastStamp=-1; + logfileStd=use_stdout; + writeAll=write_all; notDated=nodate; logfileOpen(1); } @@ -78,22 +82,31 @@ void logfileOut(int mask, const char *fmt, ...) assert(mask>0 && mask<32); va_start(ap, fmt); - if (eptr!=NULL) { - if (eptr-ebuf > sizeof(ebuf)-512) { - sprintf(eptr, "... buffer full ... \1\1"); - eptr=NULL; - } else { - vsprintf(eptr, fmt, ap); - assert(NULL==strchr(eptr, '\1')); - eptr+=strlen(eptr); - eptr[0]='\1'; /* put \1 as separator between blocks */ - eptr[1]=mask; - eptr[2]='\0'; - eptr+=2; + + if (writeAll) { +#ifdef __VMS + if (fil==NULL) logfileOpen(0); +#endif + vfprintf(fil, fmt, ap); + wrtMask=LOG_ALL; + } else { + if (eptr!=NULL) { + if (eptr-ebuf > sizeof(ebuf)-512) { + sprintf(eptr, "... buffer full ... \1\1"); + eptr=NULL; + } else { + vsprintf(eptr, fmt, ap); + assert(NULL==strchr(eptr, '\1')); + eptr+=strlen(eptr); + eptr[0]='\1'; /* put \1 as separator between blocks */ + eptr[1]=mask; + eptr[2]='\0'; + eptr+=2; + } } + wrtMask=wrtMask | mask; } va_end(ap); - wrtMask=wrtMask | mask; } void logfileMask(int mask) { @@ -111,34 +124,33 @@ void logfileStamp(void) { if (stamp!=lastStamp) { if (stamp new day -> new logfile */ if (fil!=NULL) { fclose(fil); fil=NULL; } - logfileOpen(0); + logfileOpen(1); } +#ifdef __VMS + else if (fil==NULL) logfileOpen(0); +#endif lastStamp=stamp; - logfileOut(LOG_MAIN, "--- %02d:%02d ---\n",tim->tm_hour,tim->tm_min); + fprintf(fil, "--- %02d:%02d:%02d ---\n", tim->tm_hour, tim->tm_min, tim->tm_sec); dirty=0; } } -void logfileWrite(int mask) { +void logfileWrite0(int mask) { char *s, *next; logMask=logMask | mask; - if (dirty) logfileStamp(); + if (dirty) logfileStamp(); /* there was something written since last time */ -#ifdef __VMS - if (fil==NULL) logfileOpen(0); -#endif s=ebuf; - if (*s!='\0' && wrtMask & logMask) { - logfileStamp(); - dirty=1; - + if (writeAll || *s!='\0' && wrtMask & logMask) { + logfileStamp(); /* write stamp before write something */ next=strchr(s, '\1'); while (next!=NULL) { *next='\0'; next++; if (*next & logMask) { fprintf(fil, "%s", s); + dirty=1; } s=next+1; next=strchr(s, '\1'); @@ -148,6 +160,29 @@ void logfileWrite(int mask) { eptr=&ebuf[0]; logMask=0; wrtMask=0; +} + +void logfileWrite(int mask) { + +#ifdef __VMS + if (fil==NULL) logfileOpen(0); +#endif + logfileWrite0(mask); +#ifdef __VMS + if (!logfileStd) { fclose(fil); fil=NULL; } +#else + fflush(fil); +#endif + +} + +void logfileShowErr(char *text) +{ +#ifdef __VMS + if (fil==NULL) logfileOpen(0); +#endif + logfileWrite0(LOG_ALL); /* write all */ + ErrWrite(fil, text); #ifdef __VMS if (!logfileStd) { fclose(fil); fil=NULL; } #else @@ -155,39 +190,43 @@ void logfileWrite(int mask) { #endif } -void logfileShowErr(char *text) -{ - logfileWrite(LOG_ALL); /* write all */ - ErrWrite(fil, text); -} - void logfileClose() -{ logfileWrite(LOG_MAIN); +{ +#ifdef __VMS + if (fil==NULL) logfileOpen(0); +#endif + logfileWrite0(LOG_MAIN+LOG_WARN); + lastStamp-=1; + logfileStamp(); if (fil!=NULL) { fclose(fil); fil=NULL; } + filnam[0]='\0'; } -void logfileOutBuf(int mask, buf_type *buf) -{ char *obuf, *str; - int osiz; +void logfileOutBuf(int mask, Str_Buf *buf) +{ char str[256]; + int rd0, sep; - obuf=buf->buf; - osiz=buf->size; - while (buf->size>0) { - if (buf->buf==NULL) { - logfileOut(mask, " ?"); break; - } else if (buf->buf[0]==1) { - logfileOut(mask, " %d", buf_get_int(buf)); - } else if (buf->buf[0]==2) { - logfileOut(mask, " %f", buf_get_float(buf)); - } else { - str=buf_get_str(buf); + rd0=buf->rdpos; + if (buf->rdpos < 0 || buf->rdpos >= buf->dsize + || buf->wrpos < 0 || buf->wrpos >= buf->dsize) { + logfileOut(mask, ""); return; + } + sep=0; + while (buf->rdpos < buf->wrpos) { + str_get_str(buf, str); + if (buf->sep=='\0') { + if (sep) logfileOut(mask, " "); if (*str=='\0') { - logfileOut(mask, " ."); + logfileOut(mask, "."); } else { - logfileOut(mask, " %s", str); + logfileOut(mask, "%s", str); } + sep=1; + } else { + if (sep) logfileOut(mask, "%c", buf->sep); + logfileOut(mask, "%s", str); + sep=1; } } - buf->size=osiz; - buf->buf=obuf; + buf->rdpos=rd0; } diff --git a/tecs/logfile.h b/tecs/logfile.h index e921f487..334074c4 100644 --- a/tecs/logfile.h +++ b/tecs/logfile.h @@ -1,4 +1,7 @@ -#include "buf.h" +#ifndef _LOGFILE_H_ +#define _LOGFILE_H_ + +#include "str_buf.h" #define LOG_ALL 31 #define LOG_SER 8 @@ -6,12 +9,12 @@ #define LOG_WARN 2 #define LOG_MAIN 1 -void logfileInit(char *path, int nodate); +void logfileInit(char *path, int nodate, int use_stdout, int write_all); void logfileOut(int mask, const char *fmt, ...); -void logfileOutBuf(int mask, buf_type *buf); +void logfileOutBuf(int mask, Str_Buf *buf); void logfileShowErr(char *text); void logfileMask(int mask); void logfileWrite(int mask); void logfileClose(void); -extern int logfileStd; +#endif /* _LOGFILE_H_ */ diff --git a/tecs/lsc.c b/tecs/lsc.c index 58e93e08..bce81a53 100644 --- a/tecs/lsc.c +++ b/tecs/lsc.c @@ -1,37 +1,37 @@ #include - -#include +#include #include #include #include "errhdl.h" #include "logfile.h" +#include "coc.h" #include "lsc.h" #include "util.h" #define MC LSC_MAX_CMDS #define MAX_PAR 16 #define MAX_ARG 9 -/* when changing FBUF_LEN, change also the constant in the fscanf call in subroutine LscExeCmd */ -#define FBUF_LEN 132 int LscEqPar(char *par, char *res) { - char pbuf[SER_BUF_LEN], rbuf[SER_BUF_LEN]; - char *plist[MAX_PAR], *rlist[MAX_PAR]; + char *p, *r, pbuf[SER_BUF_LEN], rbuf[SER_BUF_LEN]; int i,n,i1,i2; float f1, f2; - char ch1, ch2; - strcpy(pbuf, par); - strcpy(rbuf, res); - n=MAX_PAR; - str_split(pbuf, ',', plist, &n); - str_split(rbuf, ',', rlist, &n); - for (i=0; i1e-4+abs(f1)*5e-6) { - logfileOut(LOG_WARN, "%s#%s\n", plist[i], rlist[i]); + logfileOut(LOG_WARN, "%s#%s\n", pbuf, rbuf); return(0); } } @@ -39,11 +39,131 @@ int LscEqPar(char *par, char *res) { return(1); } -int LscCmdChkC(SerChannel *ser, const char *cmds) { - char buf[128]; - assert(strlen(cmds)<128); - strcpy(buf, cmds); - return(LscCmdChk(ser, buf)); +char *LscCmd(SerChannel *ser, const char *cmds) { + va_list ap; + char *blank, *colon, *qu, *res; + const char *p, *this, *next, *cmd_ptr, *retreq; + const char *list[MC*3]; + char seg[SER_BUF_LEN], buf[SER_BUF_LEN], result[SER_BUF_LEN], par[SER_BUF_LEN]; + char cmd[SER_BUF_LEN]; + char varname[32]; + Str_Buf sbuf; + int nres, i, j, response; + + nres=0; + response=0; + str_link_buf(&sbuf, buf, sizeof(buf), STR_NOSEPARATOR); + this=cmds; + while (this!=NULL) { + next=str_split(cmd, this, ';'); + retreq=strchr(cmd, '>'); + if (retreq!=NULL) { /* save pointer to return request */ + i=retreq-cmd; + cmd[i]='\0'; /* cut return request */ + list[nres]=this+i; + nres++; + } + cmd_ptr=sbuf.buf+sbuf.wrpos; /* pointer to command in buffer */ + p=str_split(seg, cmd, '['); + ERR_I(str_put_str(&sbuf, seg)); + while (p!=NULL) { /* substitute variables */ + p=str_split(varname, p, ']'); + if (p==NULL) ERR_MSG("missing '\'"); + ERR_I(CocPutVar(serverVarList, &sbuf, varname, 0)); + p=str_split(seg, p, '['); + ERR_I(str_put_str(&sbuf, seg)); + } + ERR_I(str_copy(cmd, cmd_ptr)); + colon=strchr(cmd_ptr, ':'); + if (colon!=NULL) { /* command with query */ + blank=strchr(cmd_ptr, ' '); + if (blank==NULL || blank>colon) { + *colon=' '; blank=colon; + } else { + *colon=','; + } + list[nres]=colon+1; nres++; /* pointer to parameters */ + list[nres]=cmd_ptr; nres++; /* pointer to command */ + ERR_I(str_put_str(&sbuf, ";")); + cmd[blank-cmd_ptr]='?'; /* build query */ + if (colon==blank) colon++; + cmd[colon-cmd_ptr]='\0'; + ERR_I(str_put_str(&sbuf, cmd)); /* put query */ + ERR_I(str_put_str(&sbuf, ";")); + response=1; + } else { + qu=strchr(cmd, '?'); + ERR_I(str_put_str(&sbuf, ";")); + if (qu!=NULL) { /* command is a query */ + response=1; + if (retreq==NULL) ERR_MSG("missing return format"); + list[nres]=NULL; nres++; + } else { + if (retreq!=NULL) ERR_MSG("no return request allowed after command without query "); + } + } + this=next; + } + + if (!response) { + ERR_I(str_put_str(&sbuf, "busy?")); + } else { + buf[sbuf.wrpos-1]='\0'; /* strip off trailing ";" */ + } + ERR_P(res=SerCmd(ser, buf)); + if (0==strcmp("?TMO", res)) ERR_MSG("timeout"); + /* + list[0..nres-1] contains a now: + for a command with return request: + - a pointer to a the request + then, for a command with query: + - a pointer to the parameters and + - a pointer to the command + this is repeated for every command + */ + + /* check results */ + this=res; + for (i=0; i') { + i++; + } else { + retreq=NULL; + } + } + if (list[i]!=NULL) { + qu=str_split(par, list[i], ';'); /* get parameters */ + i++; + if (!LscEqPar(par, result)) { /* try again with single command */ + qu=strchr(qu, ';'); + assert(list[i]!=NULL); + str_copy(cmd, list[i]); + if (qu!=NULL) cmd[qu-list[i]]='\0'; + ERR_P(qu=SerCmd(ser, cmd)); + if (!LscEqPar(par, qu)) ERR_MSG("result does not match"); + } + } + if (retreq!=NULL) { /* query */ + str_link_buf(&sbuf, result, 0, ','); + str_split(par, retreq+1, ';'); + p=par; + while (p!=NULL) { + p=str_split(varname, p, ','); + if (varname[0]!='\0') { + ERR_I(CocGetVar(serverVarList, &sbuf, varname, 0)); + } else { + ERR_P(str_get_str(&sbuf, NULL)); + } + } + i++; + } + } + return(res); + OnError: return(NULL); } int LscCmdChk(SerChannel *ser, char *cmds) { @@ -58,7 +178,7 @@ int LscCmdChk(SerChannel *ser, char *cmds) { m=MC; do { n=m; - cn=str_split(cn, ';', clist, &n); + cn=str_splitx(cn, ';', clist, &n); for (i=0; iasyn_info.host, hbuf); + p=str_split(ser->asyn_info.host, hbuf, ':'); port=4000; chan=0; if (p!=NULL) { - c=str_split1(p, '/'); + c=str_split(cport, p, '/'); if (c!=NULL) chan=atoi(c); - port=atoi(p); + port=atoi(cport); } ser->asyn_info.port=port; ser->asyn_info.chan=chan; + logfileOut(LOG_MAIN, "open connection to %s:%d/%d\n", ser->asyn_info.host, ser->asyn_info.port, ser->asyn_info.chan); A_CHK(AsynSrv_Open(&ser->asyn_info)); if (msecTmo==0) msecTmo=5000; A_CHK(AsynSrv_Config(&ser->asyn_info, "msecTmo", msecTmo, "idleHdl", idleHdl, NULL)); diff --git a/tecs/serutil.h b/tecs/serutil.h index dfd5d8d6..b1fa5e35 100644 --- a/tecs/serutil.h +++ b/tecs/serutil.h @@ -1,3 +1,6 @@ +#ifndef _SERUTIL_H_ +#define _SERUTIL_H_ + #define SER_BUF_LEN 320 typedef struct { int private; } SerChannel; @@ -6,3 +9,5 @@ SerChannel *SerOpen(const char *host, int msecTmo, void (*idleHdl)(int,int)); char *SerCmdC(SerChannel *ser, const char *cmnd); char *SerCmd(SerChannel *ser, char *cmnd); int SerClose(SerChannel *ser); + +#endif /* _SERUTIL_H_ */ diff --git a/tecs/server.c b/tecs/server.c index b8bf7e34..c22ca771 100644 --- a/tecs/server.c +++ b/tecs/server.c @@ -5,17 +5,24 @@ #include #include +#include +#include +#include +#include +#include #include +#include "errhdl.h" #include "logfile.h" #include "server.h" -#include "util.h" +#include "str_util.h" -static buf_type *buf, *bufo; +static Str_Buf *buf, *bufo; static fd_set mask, rmask; static int maxfd; struct CocClient *cList, *cLastCmd=NULL; static int mainFd; +static int modified; int CocInitServer(int bufsize, int port) { int i; @@ -23,8 +30,8 @@ int CocInitServer(int bufsize, int port) { char *err; if (bufsize==0) bufsize=1024; - buf=buf_create(bufsize); - bufo=buf_create(bufsize); + ERR_P(buf=str_create_buf(bufsize, '\0')); + ERR_P(bufo=str_create_buf(bufsize,'\0')); cList=malloc(sizeof(*cList)); /* empty header */ /* first try to connect to an existing server */ @@ -48,18 +55,18 @@ int CocHandle1Request(int tmo_msec, int fd) { struct hostent *h; struct timeval tmo={0,1}; struct CocClient *cl, *cl0; - int i, newfd, setmode, status; + int i, newfd, setmode; size_t cadrlen; char *err, *varname; - status=3; rmask=mask; if (fd>0) FD_SET(fd, &rmask); tmo.tv_sec=tmo_msec / 1000; tmo.tv_usec=(tmo_msec % 1000)*1000+1; if (fd>=maxfd) maxfd=fd+1; ERR_SI(i=select(maxfd,&rmask,NULL,NULL,&tmo)); - if (fd>0 && FD_ISSET(fd, &rmask)) return(1); + if (fd>0 && FD_ISSET(fd, &rmask)) return(1); /* event on fd */ + if (i==0) return(0); /* timeout */ if (FD_ISSET(mainFd, &rmask)) { ERR_SI(newfd=accept(mainFd, (struct sockaddr *)&cadr, &cadrlen)); @@ -82,8 +89,8 @@ int CocHandle1Request(int tmo_msec, int fd) { cl0=cList; cl=cl0->next; while (cl!=NULL) { if (FD_ISSET(cl->fd, &rmask)) { - buf->usize=recv(cl->fd, buf->start, buf->isize, 0); - if (buf->usize<=0) { + buf->wrpos=recv(cl->fd, buf->buf, buf->dsize, 0); + if (buf->wrpos<=0) { logfileOut(LOG_MAIN, "(%d) disconnected\n",cl->fd); close(cl->fd); FD_CLR(cl->fd, &mask); @@ -91,29 +98,26 @@ int CocHandle1Request(int tmo_msec, int fd) { free(cl); cl=cl0; } else { - if (buf->usize<0) ERR_MSG("usize negative"); - buf_put_start(bufo); - buf_put_str(bufo, ""); /* empty error message */ + str_put_start(bufo); + str_get_start(buf); + ERR_I(str_put_str(bufo, "")); /* empty error message */ setmode=0; - buf_reset(buf); err=NULL; - varname=buf_get_str(buf); + ERR_P(varname=str_get_str(buf, NULL)); logfileOut(LOG_NET, "(%d) ", cl->fd); if (varname[0]=='#') { /* access code */ if (0==strcmp(varname,"#rdacc")) { - logfileOut(LOG_MAIN, " set read mode\n"); + logfileOut(LOG_MAIN, "set read mode\n"); cl->mode=1; } else if (0==strcmp(varname,"#rwacs")) { - logfileOut(LOG_MAIN, " set write mode\n"); + logfileOut(LOG_MAIN, "set write mode\n"); cl->mode=2; } else { err="bad access code"; } - buf_put_end(bufo); } else if (cl->mode==0) { err="no access"; - buf_put_end(bufo); } else { while (1) { if (varname[0]=='[') { @@ -123,52 +127,50 @@ int CocHandle1Request(int tmo_msec, int fd) { setmode=0; } else if (setmode) { if (0==strcmp("$", varname)) { /* special case: command */ - str_copy(cl->cmd, buf_get_str(buf)); + ERR_P(str_get_str(buf, cl->cmd)); cl->res[0]='\0'; } else { - i=CocGetVar(serverVarList, buf, varname); + i=CocGetVar(serverVarList, buf, varname, 1); if (i<0) { err=ErrMessage; break; } } - status=2; + modified=1; } else { if (0==strcmp("$", varname)) { /* special case: response */ - buf_put_str(bufo, cl->res); + ERR_I(str_put_str(bufo, cl->res)); cl->res[0]='\0'; } else { - i=CocPutVar(serverVarList, bufo, varname); + i=CocPutVar(serverVarList, bufo, varname, 0); if (i<0) { err=ErrMessage; break; } } } - i=buf_size(buf); - if (i<=0) { - if (i<0) err="type mismatch"; + if (buf->rdpos>=buf->wrpos) { + ERR_I(str_get_end(buf)); break; } - varname=buf_get_str(buf); - if (buf_size(buf)<0) { err="syntax error"; break; } + ERR_P(varname=str_get_str(buf, NULL)); } - buf_reset(buf); + str_get_start(buf); logfileOutBuf(LOG_NET, buf); - buf_put_end(bufo); + str_get_start(bufo); logfileOut(LOG_NET, " |"); logfileOutBuf(LOG_NET, bufo); } if (err==NULL) { logfileOut(LOG_NET, "\n"); } else { - buf_put_start(bufo); /* reset output */ - buf_put_str(bufo, err); /* put error message */ - buf_put_end(bufo); + str_put_start(bufo); /* reset output */ + str_put_str(bufo, err); /* put error message */ logfileOut(LOG_NET, " (%s)\n", err); logfileMask(LOG_NET); } - ERR_SI(send(cl->fd, bufo->buf, bufo->size, 0)); + ERR_SI(send(cl->fd, bufo->buf, bufo->wrpos, 0)); } } cl0=cl; cl=cl->next; } } - return(status); + if (modified) return(2); + return(3); OnError: return(-1); } @@ -176,12 +178,20 @@ int CocHandleRequests(int tmo_msec, int fd) { struct timeb tim1, tim0; int tdif, iret; + if (modified && fd==0) { /* earlier modification */ + modified=0; + return(2); + } ftime(&tim0); tdif=tmo_msec; while (tdif>=0) { ERR_I(iret=CocHandle1Request(tdif, fd)); - if (iret==2 && fd==0) return(iret); /* a variable was changed */ - if (iret!=3) return(iret); /* event on fd or timeout */ + if (fd==0) { + if (iret==2) return(2); /* modification of a varaible */ + } else { + if (iret==1) return(1); /* event on fd */ + } + if (iret==0) return(0); /* timeout */ ftime(&tim1); tdif=tmo_msec-((tim1.time-tim0.time)*1000+tim1.millitm-tim0.millitm); } @@ -223,6 +233,6 @@ void CocCloseServer() { } free(cList); close(mainFd); - buf_free(buf); buf_free(bufo); + str_free_buf(buf); str_free_buf(bufo); logfileClose(); } diff --git a/tecs/server.h b/tecs/server.h index 38bfb50a..2101aa44 100644 --- a/tecs/server.h +++ b/tecs/server.h @@ -1,3 +1,6 @@ +#ifndef _SERVER_H_ +#define _SERVER_H_ + #include "coc.h" struct CocClient { struct CocClient *next; int fd; int mode; char cmd[80]; char res[80]; }; @@ -10,7 +13,7 @@ int CocHandle1Request(int tmo_msec, int fd); handle hetwork requests. return value: <0: error - =0: error + =0: timeout =1: event on fd =2: variable was changed =3: other network request treated @@ -20,10 +23,10 @@ int CocHandle1Request(int tmo_msec, int fd); For CocHandleRequests: if fd=0: returns when a network request has changed a variable, - or when timeout has expired + or when timeout has expired (result is 0 or 2) if fd>0: returns when an read event is pending on fd - or when timeout has expired + or when timeout has expired (result is 0 or 1) */ @@ -33,3 +36,5 @@ struct CocClient *CocGetNextCmd(void); */ void CocCloseServer(void); + +#endif /* _SERVER_H_ */ diff --git a/tecs/str_buf.h b/tecs/str_buf.h new file mode 100644 index 00000000..24583a49 --- /dev/null +++ b/tecs/str_buf.h @@ -0,0 +1,27 @@ +#ifndef _STR_BUF_H_ +#define _STR_BUF_H_ + +typedef struct { char *buf; int dsize, rdpos, wrpos; char sep; } Str_Buf; + +#define str_get_str(BUF,RES) str_nget_str(BUF,RES,sizeof(RES)) + +/* input */ +void str_get_start(Str_Buf *buf); +char *str_nget_str(Str_Buf *buf, char *result, int reslen); +int str_get_int(Str_Buf *buf, int *res); +int str_get_float(Str_Buf *buf, float *res); +int str_get_end(Str_Buf *buf); + +/* output */ +void str_put_start(Str_Buf *buf); +int str_put_str(Str_Buf *buf, const char *str); +int str_put_int(Str_Buf *buf, int val); +int str_put_float(Str_Buf *buf, float val); + +/* common */ +#define STR_NOSEPARATOR ((char)1) +Str_Buf *str_create_buf(size_t size, char separator); +void str_link_buf(Str_Buf *buf, char *str, int size, char separator); +void str_free_buf(Str_Buf *buf); + +#endif /* _STR_BUF_H_ */ diff --git a/tecs/str_util.h b/tecs/str_util.h new file mode 100644 index 00000000..741fd265 --- /dev/null +++ b/tecs/str_util.h @@ -0,0 +1,108 @@ +#ifndef _UTIL_H_ +#define _UTIL_H_ + +/* + use these macros if DST is a fixed length character array +*/ + +#define str_trim(DST,SRC,L) str_ntrim(DST,SRC,sizeof(DST),L) +#define str_split(DST,SRC,SEP) str_nsplit(DST,SRC,SEP,sizeof(DST)) +#define str_substitute(DST,SRC,OLD,NEW) str_nsubstitute(DST,SRC,OLD,NEW,sizeof(DST)) +#define str_upcase(DST,SRC) str_nupcase(DST,SRC,sizeof(DST)) +#define str_copy(DST,SRC) str_ncpy(DST,SRC,sizeof(DST)) +#define str_append(DST,SRC) str_ncat(DST,SRC,sizeof(DST)) + + +char *str_split1(char *str, char separator); +/* + trims text before separator in *str and returns + a pointer to the first character after separator +*/ + +char *str_splitx(char *str, char sep, char *list[], int *n); +/* + split string into *n strings using separator sep. + spaces at the end of the elements are trimmed + attention: *str is modified ('\0' placed at the end of the elements) + + if *n separators are found, result points to string after *n-th separator + else result is NULL + *n contains number of elements stored in list +*/ + +int str_ntrim(char *dest, const char *src, int ldest, int lsrc); +/* + copy characters 0 to lsrc-1 from src to dest (max ldest chars). +*/ + +char *str_nsplit(char *dst, const char *src, char sep, int dstlen); +/* + returns a pointer to the text after the separator sep in *src + and copies the text before the separator to *dst + when *src does not contain the separator sep + NULL is returned, and *dst is a copy of *src +*/ + +char *str_read_file(char *file); +/* + return one string containing the contents of file *file + comments separated by '!' are omitted. The caller must + free the result after use. +*/ + +void str_replace_char(char *str, char ch, char rep); +/* + replace all occurences of character ch by character rep in string *str +*/ + +int str_nsubstitute(char *result, char *str, char *old, char *new, int reslen); +/* + replace every instance of old in str by new. + the result must not overlap + if the result would be longer than reslen, the result is en empty string + and the return value is -1; + else the return value is the length of the result. + return one string containing the contents of file *file + the contents are treated in the following way: + - #0,#1,...#n is replaced by the corresponding argument *args[n] (n=0..nargs-1, nargs<10) + - at the end of each line spaces and comments separated by ! are trimmed +*/ + +void str_nupcase(char *dst, const char *src, int dstlen); +/* + convert *str to uppercase +*/ + +#ifdef __VMS_VER +#if _VMS_VER<70000000 + +int strcasecmp(const char *str1, const char *str2); +/* + compare *str1 with *str2 + the comparison is not case sensitive + if result=0: strings are equal + else + result>0 <==> *str1>*str2 + first different character is at position abs(result)-1 +*/ + +#else +#include +#endif /* __VMS_VER<70000000 */ +#else +#include +#endif /* __VMS_VER */ + +int str_ncpy(char *dst, const char *src, int maxdest); +/* + copy *src to *dest, maximal maxdest characters, + it is guaranteed, that dst contains '\0' +*/ + +int str_ncat(char *dst, const char *src, int maxdest); +/* + append *src to *dest, maximal maxdest characters, + it is guaranteed, that dst contains '\0' +*/ + +#endif /* _UTIL_H_ */ diff --git a/tecs/tcli.c b/tecs/tcli.c index 2fe56648..af667346 100644 --- a/tecs/tcli.c +++ b/tecs/tcli.c @@ -13,7 +13,7 @@ main(int argc, char *argv[]) char *res; #ifdef __VMS - ERR_P(conn=TeccInit("@start_tecs -p 9753 -l -d [.log]", 9753)); + ERR_P(conn=TeccInit("@start_tecs test -p 9753 -l -d ud0:[zolliker.lsc.log]", 9753)); #else ERR_P(conn=TeccInit("TecsServer -p 9753 -l -d log/ &", 9753)); #endif diff --git a/tecs/tecc.c b/tecs/tecc.c index 6e5d1b7c..47690ddc 100644 --- a/tecs/tecc.c +++ b/tecs/tecc.c @@ -1,4 +1,6 @@ +#include #include "errhdl.h" +#include "util.h" #include "tecc.h" static char device[80], command[80]; @@ -10,9 +12,9 @@ pTecsClient TeccInit(char *startcmd, int port) { ERR_SP(conn=(CocConn *)malloc(sizeof(*conn))); ERR_I(CocInitClient(conn, "", port, "#rwacs", 0, startcmd)); - CocDefFlt(tempX, CocRD); + CocDefFlt(tempC, CocRD); CocDefFlt(tempP, CocRD); - CocDefFlt(tempC, CocWR); + CocDefFlt(tempX, CocRD); CocDefStr(device, CocWR); CocDefInt(quit, CocWR); CocDefCmd(command); @@ -34,19 +36,18 @@ char *TeccGetDev(pTecsClient conn) { OnError: return(NULL); } -int TeccGet3(pTecsClient conn, float temp[3]) { +int TeccGet3(pTecsClient conn, float *tC, float *tX, float *tP) { ERR_I(CocCmd(conn, "tempC,tempX,tempP")); - temp[0]=tempC; - temp[1]=tempX; - temp[2]=tempP; + *tC=tempC; + *tX=tempX; + *tP=tempP; return(0); OnError: return(-1); } int TeccGet(pTecsClient conn, float *temp) { - float t[3]; - ERR_I(TeccGet3(conn, t)); - *temp=t[2]; + ERR_I(CocCmd(conn, "tempP")); + *temp=tempP; return(0); OnError: return(-1); } @@ -65,14 +66,14 @@ int TeccSend(pTecsClient conn, char *cmd, char *reply, int replyLen) { str_copy(command, cmd); ERR_I(CocCmd(conn, "[$]")); cnt=40; - util_delay(100); + CocDelay(100); while (cnt>0) { ERR_I(CocCmd(conn, "$")); if (command[0]!='\0') { str_ncpy(reply, command, replyLen); return(0); } - util_delay(250); + CocDelay(250); cnt--; } str_ncpy(reply, "", replyLen); @@ -82,7 +83,7 @@ int TeccSend(pTecsClient conn, char *cmd, char *reply, int replyLen) { int TeccQuitServer(pTecsClient conn) { quit=1; - ERR_I(CocCmd(conn, "quit")); + ERR_I(CocCmd(conn, "[quit]")); return(0); OnError: return(-1); } diff --git a/tecs/tecc.h b/tecs/tecc.h index 5e41a672..dd0fcf65 100644 --- a/tecs/tecc.h +++ b/tecs/tecc.h @@ -1,3 +1,6 @@ +#ifndef _TECC_H_ +#define _TECC_H_ + #include "client.h" /* tecc.h: tecs client interface routines @@ -41,3 +44,4 @@ int TeccKillServer(pTecsClient conn); /* kill the server process ------------------------------------------------------------------------*/ +#endif /* _TECC_H_ */ diff --git a/tecs/tecs.c b/tecs/tecs.c index 1d8f7ce0..91f6e288 100644 --- a/tecs/tecs.c +++ b/tecs/tecs.c @@ -1,7 +1,9 @@ #include #include #include +#include #include +#include "errhdl.h" #include "server.h" #include "logfile.h" #include "util.h" @@ -17,48 +19,78 @@ static char *binDir=NULL; static char *logDir=NULL; static DlogSet dset; +typedef struct { + float temp, t1, t2; /* calc, high, low temperature */ + int dirty; /* input config to be reloaded */ + int try; /* trial count */ + int manual; /* manual device */ + int code, code1; /* device code, buffer for device code */ + int nSens; /* number of sensors */ + int codChanged; /* code has changed */ + int codDefined; /* code is not yet confirmed */ + char ch1[2], ch2[2]; /* channels for high/low T */ + char device[16]; /* device name */ +} Part; + +Part /* C standard guarantees initialization to zero */ + cryo, /* data for main sensors (on heat exchanger, or the only sensors) */ + samp, /* data for extra sensors of sample stick */ + *parts[2]={&cryo, &samp}, + *part=&cryo; + static float - tempP=0, /* sample T */ - tempX=0, /* heat exch. T */ - tempC=0, /* set T */ - tempH=0, /* set T on heater */ - htr; /* heat power */ + tempC, /* set T */ + tempH, /* set T on heater */ + htr, /* heat power */ + tLimit, power, /* heater parameters */ + tLow=0, tHigh=0, /* lower limit of high-T sensor, upper limit of low-T sensor */ + tShift=0, /* setpoint shift */ + tInt=0; /* integral time (sec.) for setpoint shift */ static int - logPeriod=10, /* logging period (sec.) */ - period=1000, /* default read interval (msec.) */ - logTime=0, /* next logging time */ - setFlag=0, /* temperature to be set */ - remoteFlag=0, /* to be set to remote mode */ - dirtyX=0, /* reload input config for heat exch. */ - dirtyP=0, /* reload input config for sample */ - tryP=0, /* trial count for sample */ - tryX=0, /* trial count for heat exch */ - saveIt=0, /* CRVSAV command */ + logPeriod=10, /* data logging period (sec.) */ + period=5000, /* default read interval (msec.) */ + logTime, /* next logging time */ + setFlag, /* temperature to be set */ + remoteFlag, /* to be set to remote mode */ + saveTime, /* time for a CRVSAV command */ noResp=1, /* no response */ - manualX=0, /* X device was given manually */ - manualP=0, /* P device was given manually */ - quit=0, /* quit server */ + quit, /* quit server */ controlMode=2, /* 0: control on heater, 1: control on sample, 3: 2nd loop for difference heater-sample */ - serialNo=0; + mode, /* 0: local, 2: remote */ + maxfld, /* last used display field */ + busy, /* busy after CRVSAV */ + deviceFlag, /* device given via net */ + num, /* curve number */ + fld, /* field number */ + key, /* key status */ + serialNo, + resist, + cod1, cod2, out1, out2, /* codes read from digital input/output */ + iRange, iAmp, /* max. range and max. current code */ + per; /* effective period */ + +static time_t + auto_remote_time, /* time for automatic reload */ + tim, /* actual time */ + tableTime; /* last time when table was read */ -static int busy, mode=0; -static int nX=0, nP=0; /* number of sensors */ -static int maxfld; /* last used display field */ -static float tLimit, resist=0.0, power; /* heater parameters */ -static float tLow=0, tHigh=0; /* lower limit of high-T sensor, upper limit of low-T sensor */ -static float tShift=0; /* setpoint shift */ -static float tInt=0; /* integral time (sec.) for setpoint shift */ -static time_t auto_remote_time=0; /* time for automatic reload */ -static time_t tim; /* actual time */ -static time_t tableTime; /* last time when table was read */ -static int codX=-1, codP=0; /* codes for heat exchanger and sample */ static int decod[8]={21,20,17,16,5,4,1,0}; /* for code conversion */ -static char channel[5]="ACBD"; /* sensor channels for heater and sample (main, lowT) */ -static char device[32], deviceX[16], deviceP[16]; -static int deviceFlag=0; -static char *table=NULL; /* environment devices table */ -static char *cache=NULL; /* curve list cache */ + +static char + device[32], /* concatenated device names */ + buf1[256], buf2[256], buf3[256], buf4[256], /* buffers for temporary use */ + head[64], /* curve header */ + intype[64], /* input configuration */ + chan[2], /* actual channel */ + xxxx; + +static char + *table=NULL, /* environment devices table */ + *cache=NULL; /* curve list cache */ + +struct timeb tim0; +int logMask; void idleHdl(int tmo, int fd) { int iRet; @@ -68,133 +100,149 @@ void idleHdl(int tmo, int fd) { } void concatDevice() { - str_copy(device, deviceX); - if (0!=strcmp(deviceX, deviceP)) { + str_copy(device, cryo.device); + if (0!=strcmp(cryo.device, samp.device) && (samp.device[0]!='\0' || samp.manual)) { str_append(device, "/"); - str_append(device, deviceP); + str_append(device, samp.device); } } -int instCurve(char *nam, char chan) { +int instCurve(char *nam, char *channel) { /* - install sensor nam on channel chan + install sensor nam on channel */ - char *args[2]; - char buf[256], head[64], nbuf[256], lbuf[16]; - char *crv, *entry, *points, *intype, *start, + char buf[256], chead[64], nbuf[256], lbuf[16]; + char *crv, *entry, *points, *start, *s, /* start of found entry */ *e, /* cache part after found entry */ *res, *t; - int i, num, n, fld; + int i, n; char used[60]; FILE *fil; int retstat; + str_copy(chan, channel); logfileOut(LOG_MAIN, "install curve %s\n", nam); - retstat=-2; /* errors in following section are severe */ + fil=NULL; crv=NULL; - strcpy(buf, ":"); - str_append(buf, nam); - str_append(buf, " "); - str_upcase(buf); - if (cache==NULL) { cache=malloc(1); *cache='\0'; } /* create empty cache if undefined */ - start=strchr(cache, '\n'); /* skip device names */ - if (start==NULL) { start=cache; } else { start++; } - entry=strstr(start, buf); - if (entry==NULL) { /* sensor not found in cache */ - entry=start; - for (i=60;i>20;i--) used[i]=0; - n=40; num=0; - while (entry!=NULL && n>0) { - i=0; - sscanf(entry, "%d", &i); - if (i>20 && i<=60) { num=i; s=entry; used[i]=1; n--; } - entry=strchr(entry, '\n'); - if (entry !=NULL) entry++; - } - if (n>0) { - for (num=60;num>20;num--) { if (used[num]==0) break; } - s=NULL; - e=NULL; - } else { - e=strchr(s, '\n'); - if (e!=NULL) { *e='\0'; e++; } - if (s>start) { s--; *s='\0'; } - } - head[0]='\0'; - } else { - s=entry; entry++; - while (s>start && *s!='\n') s--; - if (s>start) { *s='\0'; s++; } - num=0; - sscanf(s, "%d", &num); - if (num<21 || num>60) ERR_MSG("illegal curve number"); - sprintf(buf, "CRVHDR?%d", num); - retstat=-1; /* errors in following section are not severe */ - ERR_P(res=SerCmd(ser, buf)); - e=strchr(entry, '\n'); - if (e!=NULL) { *e='\0'; e++; } - str_copy(head, res); - } - - /* read and substitute curve file */ - sprintf(buf, "CRVPT %d", num); - args[0]=buf; - retstat=-2; /* errors in following section are severe */ + /* read curve file */ str_copy(nbuf, binDir); str_append(nbuf, nam); - ERR_P(crv=str_read_arg(nbuf, args, 1)); + retstat=-2; /* an error would be severe */ + ERR_P(crv=str_read_file(nbuf)); - intype=str_split1(crv, '\n'); - if (intype==NULL) { + t=str_split(chead, crv, '\n'); + if (t==NULL) { points=NULL; } else { - points=str_split1(intype, '\n'); + points=str_split(intype, t, '\n'); } - if (points==NULL) { - ERR_MSG("illegal curve file"); - } + if (points==NULL) ERR_MSG("illegal curve file"); + if (points[0]=='$') { /* standard curve */ - res=strchr(channel, chan); - if (res!=NULL) { fld=res-channel+1; } else { fld=1; } + points++; num=atoi(points); + if (num>20) ERR_MSG("illegal standard curve number"); + + retstat=-1; /* an error could be fixed */ + ERR_P(LscCmd(ser, "CRVHDR?[num]>head")); + + } else { + + strcpy(buf, ":"); + str_append(buf, nam); + str_append(buf, " "); + str_upcase(buf, buf); + + if (cache==NULL) { cache=malloc(1); *cache='\0'; } /* create empty cache if undefined */ + start=strchr(cache, '\n'); /* skip device names */ + if (start==NULL) { start=cache; } else { start++; } + entry=strstr(start, buf); + if (entry==NULL) { /* sensor not found in cache */ + entry=start; + for (i=60;i>20;i--) used[i]=0; + n=40; num=0; + while (entry!=NULL && n>0) { + i=0; + sscanf(entry, "%d", &i); + if (i>20 && i<=60) { num=i; s=entry; used[i]=1; n--; } + entry=strchr(entry, '\n'); + if (entry !=NULL) entry++; + } + if (n>0) { + for (num=60;num>20;num--) { if (used[num]==0) break; } + s=NULL; + e=NULL; + } else { + e=strchr(s, '\n'); + if (e!=NULL) { *e='\0'; e++; } + if (s>start) { s--; *s='\0'; } + } + head[0]='\0'; + } else { + s=entry; entry++; + while (s>start && *s!='\n') s--; + if (s>start) { *s='\0'; s++; } + num=0; + sscanf(s, "%d", &num); + if (num<21 || num>60) ERR_MSG("illegal curve number"); + + retstat=-1; /* an error could be fixed */ + ERR_P(LscCmd(ser, "CRVHDR?[num]>head")); + + e=strchr(entry, '\n'); + if (e!=NULL) { *e='\0'; e++; } + } + } + fld=chan[0]-'A'+1; if (fld>maxfld) maxfld=fld; - retstat=-1; /* errors in following section are not severe */ - if (LscEqPar(crv, head)) { /* header matches: select sensor type and curve */ - sprintf(buf, "INTYPE %c:%s;INCRV %c:%d;DISPFLD %d:%c,1;DISPLAY:%d" - , chan, intype, chan, num, fld, chan, maxfld); - ERR_I(LscCmdChk(ser, buf)); - logfileOut(LOG_MAIN, "curve %d on channel %c selected\n", num, chan); + + if (LscEqPar(head, chead)) { /* header matches: select sensor type and curve */ + + retstat=-1; /* an error could be fixed */ + ERR_P(LscCmd(ser, "INTYPE [chan]:[intype];INCRV [chan]:[num];DISPFLD [fld],[chan],1;DISPLAY:[maxfld]")); + logfileOut(LOG_MAIN, "curve %d on channel %s selected\n", num, chan); + } else { /* header does not match -> download */ + + retstat=-2; /* an error would be severe */ + if (num<=20) ERR_MSG("standard curve does not match"); + retstat=-1; /* an error could be fixed */ if (busy) ERR_MSG("busy"); logfileOut(LOG_MAIN, "download curve %d\n", num); - sprintf(buf, "INTYPE %c:%s;DISPFLD %d:%c,3;DISPLAY:%d" - , chan, intype, fld, chan, maxfld); /* select sensor type first to display sensor units */ - ERR_I(LscCmdChk(ser, buf)); - sprintf(buf, "CRVDEL %d;CRVHDR?%d", num, num); + /* select sensor type first to display sensor units */ + ERR_P(LscCmd(ser, "INTYPE [chan]:[intype];DISPFLD [fld],[chan],3;DISPLAY:[maxfld]")); + n=3; do { - ERR_P(res=SerCmd(ser, buf)); - res[4]='\0'; - i=strcmp(res, "User"); + ERR_P(LscCmd(ser, "CRVDEL [num];CRVHDR?[num]>buf1")); + buf1[4]='\0'; + i=strcmp(buf1, "User"); n--; } while (i!=0 && n!=0); if (i!=0) ERR_MSG("can not delete curve"); + + sprintf(lbuf, "CRVPT %d", num); do { /* download curve */ - t=str_split1(points, '\n'); - if (*points!='\0') ERR_I(LscCmdChk(ser, points)); + t=str_split(nbuf, points, '\n'); + if (nbuf[0]!='\0') { + ERR_I(str_substitute(buf, nbuf, "#0", lbuf)); + ERR_P(LscCmd(ser, buf)); + } points=t; } while (t!=NULL); - sprintf(buf, "CRVHDR %d:%s;INCRV %c:%d;DISPFLD %d:%c,1", num, crv, chan, num, fld, chan); /* write header, select curve */ - ERR_I(LscCmdChk(ser, buf)); - logfileOut(LOG_MAIN, "curve selected on channel %c\n", chan); - str_copy(head, crv); - str_upcase(head); - saveIt=1; + + /* write header, select curve */ + str_upcase(head, chead); + ERR_P(LscCmd(ser, "CRVHDR [num]:[head];INCRV [chan]:[num];DISPFLD [fld],[chan],1")); + logfileOut(LOG_MAIN, "curve selected on channel %s\n", chan); + saveTime=tim+30; } free(crv); crv=NULL; + if (num<=20) return(0); /* standard curve, do not touch cache */ + /* rewrite cache with actual entry at beginning */ retstat=-2; /* errors in following section are severe */ sprintf(lbuf, "lsc.%d", serialNo); @@ -202,9 +250,9 @@ int instCurve(char *nam, char chan) { str_append(nbuf, lbuf); fil=fopen(nbuf, "r+"); if (fil==NULL) ERR_SP(fil=fopen(nbuf, "w")); - if (manualX) ERR_SI(fputs(deviceX, fil)); + if (cryo.manual) ERR_SI(fputs(cryo.device, fil)); ERR_SI(fputs("/", fil)); - if (manualP) ERR_SI(fputs(deviceP, fil)); + if (samp.manual) ERR_SI(fputs(samp.device, fil)); ERR_SI(fputs("\n", fil)); sprintf(buf, "%d:%s", num, head); ERR_SI(fputs(buf, fil)); /* write actual entry */ @@ -220,7 +268,7 @@ int instCurve(char *nam, char chan) { fil=NULL; free(cache); /* re-read it */ - ERR_P(cache=str_read_arg(nbuf, NULL, 0)); + ERR_P(cache=str_read_file(nbuf)); return(0); OnError: @@ -229,33 +277,25 @@ int instCurve(char *nam, char chan) { return(retstat); } -int configInput(int sampleStick) { +int configInput() { char *t; char buf[80], nam[16], nbuf[256]; - int i, j, n, nn; + int i, n, nn; int retstat; + char *ext; retstat=-2; /* errors in following section are severe */ - if (sampleStick) { - if (manualP) { - sprintf(buf, ".%s.", deviceP); - } else { - sprintf(buf, "%+d ", codP); - if (codP==0) return(0); - } + if (part->manual) { + sprintf(buf, ".%s.", part->device); } else { - if (manualX) { - sprintf(buf, ".%s.", deviceX); - } else { - sprintf(buf, "%+d ", codX); - if (codX==0) return(0); - } + sprintf(buf, "%+d ", part->code); + if (part->code==0) return(0); } if (table!=NULL && tim>tableTime+60) { free(table); table=NULL; }; /* clear old table */ if (table==NULL) { /* read table */ str_copy(nbuf, binDir); str_append(nbuf, TABLE_FILE); - ERR_P(table=str_read_arg(nbuf, NULL, 0)); + ERR_P(table=str_read_file(nbuf)); tableTime=tim; str_replace_char(table, 9, ' '); /* replace TAB (9) by space in order to find codes terminated by tab */ } @@ -266,53 +306,43 @@ int configInput(int sampleStick) { if (t==NULL) ERR_MSG("missing '.' in table file"); t++; n=1; - if (sampleStick) { - nP=0; + if (part==&samp) { + samp.nSens=0; i=sscanf(t, "%12s%d%d", nam, &nn, &n); if (i<1) ERR_MSG("missing sensor name"); - j=1; - if (n<0 || n>2) ERR_MSG("illegal value for nsensor"); - if (n==0) return(0); - if (!manualP) { /* set device name */ - str_copy(deviceP, nam); - deviceP[strlen(deviceP)-1]='\0'; /* strip off '.' */ - concatDevice(); - } - str_append(nam,"s"); + ext="s"; } else { - nX=0; + cryo.nSens=0; tLow=0; tHigh=0; controlMode=0; - i=sscanf(t, "%12s%d%d%d%f%f%f%f%f", nam, &n, &nn, &controlMode, &tLimit, &resist, &power, &tLow, &tHigh); + i=sscanf(t, "%12s%d%d%d%f%d%f%f%f", nam, &n, &nn, &controlMode, &tLimit, &resist, &power, &tLow, &tHigh); if (i<7) ERR_MSG("missing some sensor parameters"); - j=0; - if (n<0 || n>2) ERR_MSG("illegal value for nsensor"); - if (n==0) return(0); - if (!manualX) { /* set device name */ - str_copy(deviceX, nam); - deviceX[strlen(deviceX)-1]='\0'; /* strip off '.' */ - concatDevice(); - } - str_append(nam, "x"); + ext="x"; } - ERR_I(retstat=instCurve(nam, channel[j])); + if (n<0 || n>2) ERR_MSG("illegal value for nsensor"); + if (n==0) return(0); + if (!part->manual) { /* set device name */ + str_copy(part->device, nam); + part->device[strlen(part->device)-1]='\0'; /* strip off '.' */ + concatDevice(); + } + str_append(nam, ext); + + ERR_I(retstat=instCurve(nam, part->ch1)); if (n==2) { str_append(nam, "l"); - ERR_I(retstat=instCurve(nam, channel[j+2])); - } - if (sampleStick) { - nP=n; - } else { - nX=n; + ERR_I(retstat=instCurve(nam, part->ch2)); } + part->nSens=n; return(0); OnError: return(retstat); } int loadCache() { - int i, j; - char *res, *p; + int i, j, k; + char *res; char buf[256], nbuf[256], lbuf[16]; + char *bufi[4]; FILE *fil; fil=NULL; @@ -320,26 +350,30 @@ int loadCache() { str_copy(nbuf, logDir); str_append(nbuf, lbuf); ERR_SP(fil=fopen(nbuf, "w")); - if (manualX) ERR_SI(fputs(deviceX, fil)); + if (cryo.manual) ERR_SI(fputs(cryo.device, fil)); ERR_SI(fputs("/", fil)); - if (manualP) ERR_SI(fputs(deviceP, fil)); + if (samp.manual) ERR_SI(fputs(samp.device, fil)); ERR_SI(fputs("\n", fil)); + bufi[0]=buf1; + bufi[1]=buf2; + bufi[2]=buf3; + bufi[3]=buf4; for (i=60; i>21; i-=4) { - sprintf(buf, "CRVHDR?%d;CRVHDR?%d;CRVHDR?%d;CRVHDR?%d", i, i-1, i-2, i-3); - ERR_P(res=SerCmd(ser, buf)); + sprintf(buf, "CRVHDR?%d>buf1;CRVHDR?%d>buf2;CRVHDR?%d>buf3;CRVHDR?%d>buf4", i, i-1, i-2, i-3); + ERR_P(LscCmd(ser, buf)); + k=0; for (j=i; j>i-4; j--) { - p=str_split1(res, ';'); + res=bufi[k]; k++; if (res[1]=='s') { i=0; break;} /* s of "User", must be empty slot, lowercase letters are not programmable */ - sprintf(buf, "%d:%s", j, res); + sprintf(buf, "%d:", j); ERR_SI(fputs(buf, fil)); + ERR_SI(fputs(res, fil)); ERR_SI(fputs("\n", fil)); - if (p==NULL) break; - res=p; } } ERR_SI(fclose(fil)); /* re-read cache */ - ERR_P(cache=str_read_arg(nbuf, NULL, 0)); + ERR_P(cache=str_read_file(nbuf)); return(0); OnError: if (fil!=NULL) fclose(fil); @@ -366,29 +400,32 @@ float WeightedAverage(int n, float t1, float t2) { } int SetTemp(int switchOn) { - char buf[32]; - char ch; + char *ch; - ch=channel[0]; - if (nX>1 && tempC<(tLow+tHigh)/2) ch=channel[2]; - if (nP>0) { + if (tempC==0) { + ERR_P(LscCmd(ser, "RANGE:0;SETP 1:0")); + return(0); + } + ch=cryo.ch1; + if (cryo.nSens>1 && tempC<(tLow+tHigh)/2) ch=cryo.ch2; + if (samp.nSens>0) { if (controlMode==1) { /* control directly on sample sensor */ tShift=0; - ch=channel[1]; - if (nX>1 && tempC<(tLow+tHigh)/2) ch=channel[3]; + ch=samp.ch1; + if (cryo.nSens>1 && tempC<(tLow+tHigh)/2) ch=samp.ch2; } else if (controlMode!=2) { tShift=0; } } else { tShift=0; } + str_copy(chan, ch); tempH=tempC+tShift; if (switchOn) { - sprintf(buf, "CSET 1:%c,1;RANGE:5;SETP 1:%f", ch, tempH); + ERR_P(LscCmd(ser, "CSET 1:[chan],1;RANGE:5;SETP 1:[tempH]")); } else { - sprintf(buf, "CSET 1:%c,1;SETP 1:%f", ch, tempH); + ERR_P(LscCmd(ser, "CSET 1:[chan],1;SETP 1:[tempH]")); } - ERR_I(LscCmdChk(ser, buf)); return(0); OnError: return(-1); } @@ -396,227 +433,210 @@ int SetTemp(int switchOn) { int ReadTemp() { char buf[256], lbuf[16]; char *res; - int i, key, k; - int cod1, cod2, out1, out2; /* codes read from digital input/output */ - int codX1, codP1; - float t2[2], t4[4], p, d; + int i, k; + float t2[2], p, d; - ERR_P(res=SerCmdC(ser, "DIOST?;HTR?;BUSY?;DOUT 3,29")); - if (0==strcmp(res, "?TMO")) { - if (0==noResp) logfileOut(LOG_MAIN ,"no response\n"); - noResp=1; - return(0); + ERR_P(LscCmd(ser, "DIOST?>cod1,out1;DOUT 3,29;HTR?>htr;BUSY?>busy")); + if (cryo.codDefined) { + per=period; + } else { + per=1; /* advance fast when initializing */ } - i=sscanf(res, "%d%*c%d%*c%f%*c%d", &cod1, &out1, &htr, &busy); - if (i!=4) ERR_MSG("bad answer 0"); if (noResp) { /* check serial number */ - ERR_P(res=SerCmdC(ser, "*IDN?")); - if (0!=strncmp(res, "LSCI,MODEL340,", 14)) return(0); - res+=14; - k=0; - sscanf(res, "%d", &k); - if (k!=0 && k!=serialNo) { - serialNo=k; - dirtyX=1; dirtyP=1; - ERR_I(LscCmdChkC(ser, "RANGE:0")); /* switch off heater */ + k=serialNo; + ERR_P(LscCmd(ser, "*IDN?>buf1,buf2,serialNo")); + if (0!=strcmp(buf1, "LSCI") || 0!=strcmp(buf2, "MODEL340") || serialNo==0) return(0); + if (k!=serialNo) { + if (cryo.manual || cryo.code!=0) cryo.dirty=1; + if (samp.manual || samp.code!=0) samp.dirty=1; + ERR_P(LscCmd(ser, "RANGE:0")); /* switch off heater */ /* reload curve cache: */ if (cache!=NULL) free(cache); sprintf(lbuf, "lsc.%d", serialNo); str_copy(buf, logDir); str_append(buf, lbuf); - cache=str_read_arg(buf, NULL, 0); + cache=str_read_file(buf); if (cache==NULL && 0==strcmp(ErrMessage, "file not found")) ERR_I(loadCache()); - deviceX[0]='\0'; - deviceP[0]='\0'; - sscanf(cache, "%15[^/!]%*c%15[^\n!]", deviceX, deviceP); /* read device names separated by '/' */ - if (deviceX[0]!='\0') manualX=1; - if (deviceP[0]!='\0') manualP=1; + cryo.device[0]='\0'; + samp.device[0]='\0'; + sscanf(cache, "%15[^/!]%*c%15[^\n!]", cryo.device, samp.device); /* read device names separated by '/' */ + if (cryo.device[0]!='\0') cryo.manual=1; + if (samp.device[0]!='\0') samp.manual=1; concatDevice(); } noResp=0; } - sprintf(buf, "KRDG?%c;KRDG?%c;KRDG?%c;KRDG?%c", channel[0], channel[1], channel[2], channel[3]); - ERR_P(res=SerCmd(ser, buf)); - i=sscanf(res, "%f%*c%f%*c%f%*c%f", &t4[0], &t4[1], &t4[2], &t4[3]); - if (i!=4) ERR_MSG("bad answer 1"); - tempX=WeightedAverage(nX, t4[0], t4[2]); - tempP=WeightedAverage(nP, t4[1], t4[3]); - if (tempP==0.0) tempP=tempX; - if (dirtyX==0 && dirtyP==0 && noResp==0 && tim>logTime) { - t2[0]=tempX; - t2[1]=tempP; + ERR_P(LscCmd(ser, + "KRDG?[cryo.ch1]>cryo.t1;KRDG?[cryo.ch2]>cryo.t2;KRDG?[samp.ch1]>samp.t1;KRDG?[samp.ch2]>samp.t2")); + + cryo.temp=WeightedAverage(cryo.nSens, cryo.t1, cryo.t2); + samp.temp=WeightedAverage(samp.nSens, samp.t1, samp.t2); + if (samp.temp==0.0) samp.temp=cryo.temp; + if (cryo.dirty==0 && samp.dirty==0 && noResp==0 && tim>logTime) { + t2[0]=cryo.temp; + t2[1]=samp.temp; DlogPut(&dset, tim, 2, t2); DlogUpd(&dset); logTime=(tim/logPeriod+1)*logPeriod; } - if (nP>0 && nX>0 && controlMode==2 && tempC!=0) { - d=tempH-tempX; d=exp(-d*d); /* if d is small, we are far from setpoint */ + if (samp.nSens>0 && cryo.nSens>0 && controlMode==2 && tempC!=0) { + d=tempH-cryo.temp; d=exp(-d*d); /* if d is small, we are far from setpoint */ if (tInt<60000/period) tInt+=d; /* increase integral time until 60 sec. */ if (tInt>d) { p=d/tInt; } else { p=1.0; } - tShift=tShift*(1.0-p)+p*(tempX-tempP); + tShift=tShift*(1.0-p)+p*(cryo.temp-samp.temp); ERR_I(SetTemp(0)); } - ERR_P(res=SerCmdC(ser, "KEYST?;DIOST?;DOUT 3,30")); - i=sscanf(res, "%d%*c%d%*c%d", &key, &cod2, &out2); - if (i!=3) ERR_MSG("bad answer 2"); + ERR_P(LscCmd(ser, "KEYST?>key;DIOST?>cod2,out2;DOUT 3,30")); if (busy==0) { - - while (out1!=30) { - ERR_I(LscCmdChkC(ser, "DOUT:3,30")); - ERR_P(res=SerCmdC(ser, "DIOST?")); - i=sscanf(res, "%d%*c%d", &cod1, &out1); + if (out1!=30) { + ERR_P(LscCmd(ser, "DOUT:3,30")); + ERR_P(LscCmd(ser, "DIOST?>cod1,out1")); } - while (out2!=29) { - ERR_I(LscCmdChkC(ser, "DOUT:3,29")); - ERR_P(res=SerCmdC(ser, "DIOST?;DOUT 3,30")); - i=sscanf(res, "%d%*c%d", &cod2, &out2); + if (out2!=29) { + ERR_P(LscCmd(ser, "DOUT:3,29")); + ERR_P(LscCmd(ser, "DIOST?>cod2,out2;DOUT 3,30")); } - /* code conversion */ - codX1=3*decod[cod2 % 8] ^ 2*decod[cod1 % 8]; /* ^ is exclusive OR */ - codP1=-(3*decod[cod2 / 8] ^ 2*decod[cod1 / 8]); - if (codX<0) { codX=codX1; codP=codP1; } /* first time after restart */ - if (codP1!=codP) { - dirtyP=1; - codP=codP1; manualP=0; - } - if (codX1!=codX) { - dirtyX=1; - codX=codX1; manualX=0; + if (out1==30 && out2==29) { + /* code conversion */ + cryo.code1=3*decod[cod2 % 8] ^ 2*decod[cod1 % 8]; /* ^ is exclusive OR */ + samp.code1=-(3*decod[cod2 / 8] ^ 2*decod[cod1 / 8]); + for (i=0; i<2; i++) { + part=parts[i]; + if (part->code1!=part->code) { + part->code=part->code1; + part->codChanged=1; + } else { + if (part->codChanged) { + part->codChanged=0; + if (part->code1==0) { + logfileOut(LOG_MAIN, "unplugged X\n"); + } else { + logfileOut(LOG_MAIN, "plugged (%d)\n", part->code1); + } + if (part->codDefined) { + part->manual=0; + } + part->dirty=1; + } + part->codDefined=1; + } + } } } if (key!=0) { auto_remote_time=tim+600; - if (!(dirtyX || dirtyP)) { + if (!(cryo.dirty || samp.dirty)) { logfileOut(LOG_MAIN ,"user touched keys\n"); } - dirtyX=1; dirtyP=1; - ERR_P(res=SerCmdC(ser, "MODE?")); + if (cryo.manual || cryo.code!=0) cryo.dirty=1; + if (samp.manual || samp.code!=0) samp.dirty=1; mode=0; - sscanf(res, "%d", &mode); + ERR_P(LscCmd(ser, "MODE?>mode")); if (mode==2) auto_remote_time=tim; /* user switched to remote mode */ } return(0); OnError: return(-1); } +int inputSettings(Part *this) { + + part=this; + if (part->dirty && samp.codDefined) { + if (busy==0 || cryo.dirty>=0 && part->dirty>=0) { /* do not enter when busy and cryo.dirty/P indicates error on last time */ + logfileOut(LOG_MAIN ,"configure inputs for "); + if (part->manual) { + logfileOut(LOG_MAIN ,"%s\n", part->device); + } else { + logfileOut(LOG_MAIN ,"%+d\n", part->code); + } + if (part->dirty>0) part->try=0; + part->nSens=0; + if (!part->manual) { part->device[0]='\0'; concatDevice(); } + part->dirty=configInput(); + if (part->dirty<0) { + part->try++; + if (part->dirty!=-1 || part->try>3) { + logfileShowErr("fatal error P"); + part->dirty=0; part->device[0]='\0'; concatDevice(); + } else { + logfileShowErr("try again P"); + } + } else { + ERR_P(LscCmd(ser, "ALARM [part.ch1]:[part.nSens],1,[tLimit],0,0,1;ALARM [part.ch2]:0;RELAY 1:1;BEEP:0")); + } + } + } + return(0); + OnError: return(-1); +} + int Settings() { - char buf[256]; - char *res; - int i, j, k, ia, ir; + int i, j, k; float pa, pr, pw, dif; - if (dirtyX || dirtyP) { - if (busy==0 || dirtyX>=0 && dirtyP>=0) { /* do not enter when busy and dirtyX/P indicates error on last time */ - logfileOut(LOG_MAIN ,"configure inputs for "); - if (manualX) { - logfileOut(LOG_MAIN ,"%s ", deviceX); - } else { - logfileOut(LOG_MAIN ,"%+d ", codX); + if (cryo.dirty && cryo.codDefined || samp.dirty && samp.codDefined) { + + for (i=0; i<2; i++) { + part=parts[i]; + if (part->dirty) { + ERR_P(LscCmd(ser, "DISPFLD 2,[part.ch1],1;DISPFLD 4,[part.ch2],1")); } - if (manualP) { - logfileOut(LOG_MAIN ,"%s\n", deviceP); - } else { - logfileOut(LOG_MAIN ,"%+d\n", codP); - } - if (dirtyP) { - sprintf(buf, "DISPFLD 2:%c,1;DISPFLD 4:%c,1", channel[1], channel[3]); - ERR_I(LscCmdChk(ser, buf)); - } - if (dirtyX) { - if (dirtyX>0) tryX=0; - sprintf(buf, "DISPFLD 1:%c,1;DISPFLD 3:%c,1", channel[0], channel[2]); - ERR_I(LscCmdChk(ser, buf)); - nX=0; - if (!manualX) { deviceX[0]='\0'; concatDevice(); } - dirtyX=configInput(0); - if (dirtyX<0) { - tryX++; - if (dirtyX!=-1 || tryX>3) { - logfileShowErr("fatal error X"); - dirtyX=0; deviceX[0]='\0'; concatDevice(); - } else { - logfileShowErr("try again X"); - } - } else { - /* control settings */ - sprintf(buf, "CDISP 1:1,%d,1;MOUT 1:0;CMODE 1:1", (int)(resist+0.5)); - ERR_I(LscCmdChk(ser, buf)); - ia=1; ir=0; - if (power>0) { - pa=resist*4; /* max. power */ - pw=0; dif=1.0e6; - for (i=4; i>0; i--) { - pr=pa; - for (j=5; j>0; j--) { - if (pr>power) { - if (pr/power0), tLimit, channel[2]); - ERR_I(LscCmdChk(ser, buf)); - } - } - if (dirtyP) { - if (dirtyP>0) tryP=0; - nP=0; - if (!manualP) { deviceP[0]='\0'; concatDevice(); } - dirtyP=configInput(1); - if (dirtyP<0) { - tryP++; - if (dirtyP!=-1 || tryP>3) { - logfileShowErr("fatal error P"); - dirtyP=0; deviceP[0]='\0'; concatDevice(); - } else { - logfileShowErr("try again P"); - } - } else { - sprintf(buf, "ALARM %c:%d,1,%f,0,0,1;ALARM %c:0;RELAY 1:1;BEEP:0" - , channel[1], (nP>0), tLimit, channel[3]); - ERR_I(LscCmdChk(ser, buf)); - } - } - if (nP>=nX) { - maxfld=2*nP; - } else { - maxfld=2*nX-1; - } - if (maxfld>0) { - sprintf(buf, "MODE:2;DISPLAY:%d", maxfld); - } else { - maxfld=1; - sprintf(buf, "MODE:2;DISPLAY:1;DISPFLD 1:A,3", maxfld); - } - ERR_I(LscCmdChkC(ser, buf)); - mode=2; + } + inputSettings(&cryo); + inputSettings(&samp); - if (saveIt) { - ERR_P(res=SerCmdC(ser, "CRVSAV;BUSY?")); - do { - idleHdl(200, 0); /* wait 200 ms */ - ERR_P(res=SerCmdC(ser, "BUSY?")); - sscanf(res, "%d", &busy); - } while (!busy); - saveIt=0; + if (cryo.nSens>0) { + /* control settings */ + ERR_P(LscCmd(ser, "CDISP 1:1,[resist],1;MOUT 1:0;CMODE 1:1")); + iAmp=1; iRange=0; + if (power>0) { + pa=resist*4; /* max. power */ + pw=0; dif=1.0e6; + for (i=4; i>0; i--) { + pr=pa; + for (j=5; j>0; j--) { + if (pr>power) { + if (pr/power=cryo.nSens) { + maxfld=2*samp.nSens; + } else { + maxfld=2*cryo.nSens-1; + } + if (maxfld>0) { + ERR_P(LscCmd(ser, "MODE:2;DISPLAY:[maxfld]")); + } else { + maxfld=1; + ERR_P(LscCmd(ser, "MODE:2;DISPLAY:1;DISPFLD 1,A,3")); + } + mode=2; + + if (saveTime!=0 && tim>saveTime) { + ERR_P(LscCmd(ser, "CRVSAV;BUSY?>busy")); + while (!busy) { + idleHdl(200, 0); /* wait 200 ms */ + ERR_P(LscCmd(ser, "BUSY?>busy")); + } + saveTime=0; } } return(0); @@ -624,58 +644,51 @@ int Settings() { } int ExecuteRequest() { - char *res, *t; - int iRet; + char *t, *res; struct CocClient *client; if (tim>auto_remote_time || setFlag) ERR_I(Settings()); if (setFlag) { - if (nX>0 && tempC!=0) { + if (cryo.nSens>0) { tInt=0; /* reset integral time */ ERR_I(SetTemp(1)); - logfileOut(LOG_MAIN ,"set point\n"); - } else { - logfileOut(LOG_MAIN ,"flag reset\n"); } setFlag=0; } client=CocGetNextCmd(); if (client!=NULL) { - if (NULL==strchr(client->cmd, ':')) { - res=SerCmdC(ser, client->cmd); - if (res==NULL) { - res=ErrMessage; - if (res==NULL) res="empty error message"; - } - str_copy(client->res, res); + if (NULL!=strchr(client->cmd, '>') || NULL!=strchr(client->cmd, '[')) ERR_MSG("no variables allowed"); + res=LscCmd(ser, client->cmd); + if (res==NULL && ErrMessage!=NULL) { + str_copy(client->res, ErrMessage); } else { - iRet=LscCmdChkC(ser, client->cmd); - if (iRet<0 && ErrMessage!=NULL) { - str_copy(client->res, ErrMessage); - } else { - str_copy(client->res, "o.k."); - } + str_copy(client->res, res); } client->cmd[0]='\0'; } if (deviceFlag) { t=strchr(device, '/'); if (t==NULL) { - str_copy(deviceX, device); - str_copy(deviceP, device); - manualX=1; dirtyX=1; - manualP=1; dirtyP=1; + if (0==strcmp(device, "0")) { + cryo.manual=0; cryo.dirty=1; + samp.manual=0; samp.dirty=1; + } else { + str_copy(cryo.device, device); + str_copy(samp.device, device); + cryo.manual=1; cryo.dirty=1; + samp.manual=1; samp.dirty=1; + } } else { if (t!=device) { *t='\0'; - str_copy(deviceX, device); + str_copy(cryo.device, device); *t='/'; - manualX=1; dirtyX=1; + cryo.manual=1; cryo.dirty=1; } t++; if (*t!='\0') { - str_copy(deviceP, t); - manualP=1; dirtyP=1; + str_copy(samp.device, t); + samp.manual=1; samp.dirty=1; } } concatDevice(); @@ -685,16 +698,60 @@ int ExecuteRequest() { OnError: return(-1); } +int mainBody(void) +{ + int i, iret, tdif; + struct timeb tim1; + + /* read & control temp */ + ERR_I(ReadTemp()); + if (tim>=auto_remote_time) ERR_I(Settings()); + logfileWrite(logMask); + + while (!quit) { + ftime(&tim1); + tdif=per-((tim1.time-tim0.time)*1000+tim1.millitm-tim0.millitm); + if (tdif<0) { tim=tim1.time; break; } /* timeout */ + ERR_I(iret=CocHandleRequests(tdif, 0)); + if (iret==0) { time(&tim); break; } /* timeout */ + tim=tim1.time; + ERR_I(ExecuteRequest()); + logfileWrite(logMask); + } + ftime(&tim1); + tdif=((tim1.time-tim0.time)*1000+tim1.millitm-tim0.millitm)/period; + i=period*tdif+tim0.millitm; + tim0.time+=i / 1000; + tim0.millitm=i % 1000; + if (tdif>1) { + logfileOut(LOG_MAIN ,"%d cycles lost\n", tdif-1); + } + return(0); + OnError: + if (0==strcmp(ErrMessage, "timeout")) { + if (!noResp) logfileOut(LOG_MAIN ,"no response\n"); + per=period+10000; /* long period if no response */ + noResp=1; + return(0); + } + return(-1); +} + int main(int argc, char *argv[]) { int logIt=0; - struct timeb tim1, tim0; - int i, tdif, iret; + int i, iret, use_stdout=0; char *host; char buf[256], opt; int port, msecTmo; - int logMask; - logMask=LOG_MAIN; + str_copy(cryo.ch1,"A"); + str_copy(cryo.ch2,"B"); + str_copy(samp.ch1,"C"); + str_copy(samp.ch2,"D"); + cryo.codChanged=1; + samp.codChanged=1; + + logMask=LOG_MAIN+LOG_WARN; binDir=""; logDir=""; serverId="tecs"; @@ -712,10 +769,9 @@ int main(int argc, char *argv[]) if ('l'==opt) { logIt=1; logMask=LOG_ALL; - period=5000; opt=' '; } else if ('s'==opt) { - logfileStd=1; + use_stdout=1; opt=' '; } else if ('n'==opt) { i++; @@ -743,71 +799,87 @@ int main(int argc, char *argv[]) } } if (port==0) port=9753; - if (msecTmo==0) msecTmo=4000; + if (msecTmo==0) msecTmo=500; str_copy(buf, logDir); str_append(buf, serverId); - logfileInit(buf, logIt); + logfileInit(buf, logIt, use_stdout, logIt); logfileOut(LOG_MAIN ,"\n"); logfileWrite(logMask); ERR_I(CocInitServer(1024, port)); - CocDefFlt(tempX, CocRD); - CocDefFlt(tempP, CocRD); + CocDefStruct(cryo, Part); + CocDefStruct(samp, Part); + CocDefPtr(part, Part); + + CocFltFld(Part, temp, CocRD); + CocFltFld(Part, t1, CocRD); + CocFltFld(Part, t2, CocRD); + + CocStrFld(Part, ch1, CocRD); + CocStrFld(Part, ch2, CocRD); + CocDefFlt(htr, CocRD); CocDefFlt(tempC, setFlag); + CocDefFlt(tempH, CocRD); + CocDefFlt(tLimit, CocRD); + + CocAlias(tempX,cryo.temp); + CocAlias(tempP,samp.temp); + CocDefStr(device, deviceFlag); + + CocDefStr(buf1, CocRD); + CocDefStr(buf2, CocRD); + CocDefStr(head, CocRD); + CocDefStr(chan, CocRD); + CocDefStr(intype, CocRD); + + CocDefInt(cod1, CocRD); + CocDefInt(cod2, CocRD); + CocDefInt(out1, CocRD); + CocDefInt(out2, CocRD); + CocDefInt(num, CocRD); + CocDefInt(fld, CocRD); + CocDefInt(key, CocRD); + CocDefInt(maxfld, CocRD); + CocDefInt(resist, CocRD); + CocDefInt(iAmp, CocRD); + CocDefInt(iRange, CocRD); + CocDefInt(mode, CocRD); + CocDefInt(controlMode, CocWR); + CocDefInt(busy, CocRD); + CocDefInt(serialNo, CocRD); CocDefInt(quit, CocWR); ERR_P(ser=SerOpen(host, msecTmo, idleHdl)); - ERR_I(CocHandleRequests(100, 0)); + ERR_I(iret=CocHandleRequests(100, 0)); ftime(&tim0); + tim=tim0.time; str_copy(buf, logDir); str_append(buf, serverId); str_append(buf, ".dlog"); iret=DlogOpen(&dset, buf, 1); if (iret<0) { - ERR_I(DlogCreate(&dset, buf, tim0.time, 2, 24*60*60/logPeriod, logPeriod, 0.0)); + logfileOut(LOG_MAIN, "create data log file: %s\n", buf); + ERR_I(DlogCreate(&dset, buf, tim0.time, 2, 7*24*60*60/logPeriod, logPeriod, 0.0)); + } else { + logfileOut(LOG_MAIN, "opened data log file: %s\n", buf); } + logfileWrite(logMask); + per=period; while (!quit) { - /* read & control temp */ - iret=ReadTemp(); - if (iret<0) logfileShowErr("ReadTemp"); - if (tim>=auto_remote_time) { - iret=Settings(); - if (iret<0) logfileShowErr("Settings"); - } - logfileWrite(logMask); - - while (!quit) { - ftime(&tim1); - tdif=period-((tim1.time-tim0.time)*1000+tim1.millitm-tim0.millitm); - if (tdif<0) { tim=tim1.time; break; } /* timeout */ - iret=CocHandleRequests(tdif, 0); - if (iret!=2) { time(&tim); break; } /* timeout */ - if (iret<0) logfileShowErr("CocHandleRequests"); - tim=tim1.time; - iret=ExecuteRequest(); - if (iret<0) logfileShowErr("ExecuteRequest"); - logfileWrite(logMask); - } - ftime(&tim1); - tdif=((tim1.time-tim0.time)*1000+tim1.millitm-tim0.millitm)/period; - i=period*tdif+tim0.millitm; - tim0.time+=i / 1000; - tim0.millitm=i % 1000; - if (tdif>1) { - logfileOut(LOG_MAIN ,"%d cycles lost\n", tdif-1); - } + iret=mainBody(); + if (iret<0) logfileShowErr("error in TecsServer"); } - logfileOut(LOG_MAIN ,"%s got quit command\n", serverId); - DlogClose(&dset); - return(1); + ERR_MSG("got quit command"); OnError: + logfileShowErr("exit TecsServer"); + DlogClose(&dset); SerClose(ser); CocCloseServer(); - ERR_EXIT("TECS"); + return(0); }