new tecs version M.Z.08.2001

This commit is contained in:
cvs
2001-08-16 10:17:09 +00:00
parent b56745eb46
commit 0cda158849
35 changed files with 5289 additions and 2065 deletions

View File

@ -3,47 +3,55 @@
# #
# Markus Zolliker, March 2000 # Markus Zolliker, March 2000
#-------------------------------------------------------------------------- #--------------------------------------------------------------------------
LIBR_OBJ= coc_util.o err_handling.o str_util.o str_buf.o LIBR_OBJ= coc_util.o myc_err.o myc_str.o myc_buf.o myc_time.o
DLOG_OBJ= sys_util.o tecs_dlog.o SERV_OBJ= tecs.o coc_server.o tecs_lsc.o tecs_serial.o coc_logfile.o tecs_data.o $(LIBR_OBJ)
SERV_OBJ= tecs.o coc_server.o tecs_lsc.o tecs_serial.o coc_logfile.o $(LIBR_OBJ) $(DLOG_OBJ)
CLI_OBJ= tecs_cli.o coc_client.o $(LIBR_OBJ) CLI_OBJ= tecs_cli.o coc_client.o $(LIBR_OBJ)
TCLI_OBJ= tecs_client.o tecs_plot.o tecs_for.o sys_aunix.o sys_aunix_c.o str.o cho.o $(CLI_OBJ) $(DLOG_OBJ) TCLI_OBJ= sys_aunix.o sys_aunix_c.o $(CLI_OBJ)
TECLI_OBJ= tecs_client.o tecs_plot.o tecs_for.o sys_util.o str.o $(TCLI_OBJ)
#------------ for DigitalUnix (add -DFORTIFY to CFLAGS for fortified version) #------------ for DigitalUnix (add -DFORTIFY to CFLAGS for fortified version)
CC=cc CC=cc
#CFLAGS= -std1 -g -warnprotos -I../ -I. -I../hardsup -DFORTIFY
CFLAGS= -std1 -g -warnprotos -I../ -I. -I../hardsup CFLAGS= -std1 -g -warnprotos -I../ -I. -I../hardsup
#------------ for Linux
##CC=gcc
##CFLAGS = -fwritable-strings -DCYGNUS -DNONINTF -g -I../ -I. -I../hardsup
#------------
.f.o: .f.o:
f77 -c -g $*.f f77 -c -u -g $*.f
.c.o: .c.o:
$(CC) $(CFLAGS) -c $*.c $(CC) $(CFLAGS) -c $*.c
libtecsl.a: $(CLI_OBJ) libtecsl.a: $(CLI_OBJ)
- rm -f libtecsl.a - rm libtecsl.a
ar cr libtecsl.a $(CLI_OBJ) ar cr libtecsl.a $(CLI_OBJ)
ranlib libtecsl.a ranlib libtecsl.a
all: libtecsl.a bin/TecsServer tecs all: libtecsl.a bin/TecsServer bin/TecsClient
tecs_plot.o: tecs_plot.f90 tecs_plot.o: tecs_plot.f90
f90 -c -g tecs_plot.f90 f90 -c -u -g tecs_plot.f90
bin/TecsServer: $(SERV_OBJ) bin/TecsServer: $(SERV_OBJ)
- rm -f bin/TecsServer - rm bin/TecsServer
$(CC) $(CFLAGS) -o bin/TecsServer -g $(SERV_OBJ) fortify1.c \ $(CC) $(CFLAGS) -o bin/TecsServer -g $(SERV_OBJ) fortify1.c \
-lm -L../hardsup -lhlib -lfor -lm -L../hardsup -lhlib -lfor
tecs: $(TCLI_OBJ) bin/TecsClient: $(TECLI_OBJ)
f77 -o tecs -g $(TCLI_OBJ) \ f77 -o bin/TecsClient -g $(TECLI_OBJ) \
-L/data/lnslib/lib -lpgplot -so_archive -lreadline -ltermcap -lX11 -lXm -L/data/lnslib/lib -lpgplot -so_archive -lreadline -ltermcap -lX11 -lXm
six: six.c term.c sys_select.c $(LIBR_OBJ)
$(CC) $(CFLAGS) -o six six.c term.c sys_select.c $(LIBR_OBJ) \
-L/data/lnslib/lib -so_archive -lreadline -ltermcap -lX11 -lXm
rstart: $(LIBR_OBJ) rstart.c myc_str.o myc_err.o
$(CC) $(CFLAGS) -o rstart rstart.c myc_str.o myc_err.o
keep_running: keep_running.c
$(CC) $(CFLAGS) -o keep_running keep_running.c
clean: clean:
- rm -f *.o - rm *.o
- rm -f *.a - rm *.a
- rm -f bin/TecsServer - rm bin/TecsServer
- rm -f tecs - rm bin/TecsClient

View File

@ -1,19 +1,24 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <signal.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <assert.h> #include <assert.h>
#include "err_handling.h" #include <signal.h>
#include "myc_err.h"
#include "coc_util.h"
#include "coc_client.h" #include "coc_client.h"
#include "str_util.h" #include "sys_util.h"
#include "myc_str.h"
/* --- non ANSI signal --- */ /* --- non ANSI signal --- */
#ifndef SIGPIPE #ifndef SIGPIPE
#define SIGPIPE 13 #define SIGPIPE 13
#endif #endif
#define COC_NETTMO 5
#define COC_RESTMO 60
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
int CocConnect(CocConn *conn) { int CocConnect(CocConn *conn) {
@ -67,15 +72,13 @@ int CocOpen(CocConn *conn)
int CocInitClient(CocConn *conn, char *host, int port, char *magic, int bufsize, char *startcmd) { int CocInitClient(CocConn *conn, char *host, int port, char *magic, int bufsize, char *startcmd) {
assert(conn!=NULL); assert(conn!=NULL);
if (bufsize==0) bufsize=1024; if (bufsize==0) bufsize=1024;
ERR_P(conn->cmdbuf=str_create_buf(bufsize, '\0')); StrLink(&conn->cmdbuf, conn->cmdbuf_);
ERR_P(conn->resbuf=str_create_buf(bufsize, '\0')); StrLink(&conn->resbuf, conn->resbuf_);
conn->port=port; conn->port=port;
ERR_I(str_copy(conn->host, host)); ERR_I(str_copy(conn->host, host));
ERR_I(str_copy(conn->magic, magic)); ERR_I(str_copy(conn->magic, magic));
ERR_I(str_copy(conn->startcmd, startcmd)); ERR_I(str_copy(conn->startcmd, startcmd));
conn->fd=-1; conn->fd=-1;
conn->varList=NULL;
CocVarList(&conn->varList);
ERR_I(CocOpen(conn)); ERR_I(CocOpen(conn));
ERR_I(CocSendMagic(conn, conn->magic)); ERR_I(CocSendMagic(conn, conn->magic));
return(0); return(0);
@ -86,15 +89,17 @@ int CocInitClient(CocConn *conn, char *host, int port, char *magic, int bufsize,
int CocSendMagic(CocConn *conn, char *magic) { int CocSendMagic(CocConn *conn, char *magic) {
char *err; char *err;
int siz, n;
if (magic[0]!='#') ERR_MSG("magic must start with '#'"); StrClear(&conn->resbuf); /* use return buffer for command in order to preserve command buffer */
str_put_start(conn->resbuf); /* use return buffer for command in order to preserve command buffer */ ERR_I(StrPut(&conn->resbuf, "", COC_MAGIC));
ERR_I(str_put_str(conn->resbuf, magic)); ERR_I(StrPut(&conn->resbuf, magic, COC_SEP));
ERR_SI(send(conn->fd, conn->resbuf->buf, conn->resbuf->wrpos, 0)); ERR_I(CocSend(conn->fd, conn->resbuf.buf, conn->resbuf.wrpos));
ERR_I(CocRecv(conn->fd, conn->resbuf)); ERR_I(CocRecv(conn->fd, &conn->resbuf, COC_NETTMO, NULL));
ERR_P(err=str_get_str(conn->resbuf, NULL)); ERR_P(err=StrGet(&conn->resbuf, NULL, COC_SEP));
if (*err!='\0') { ErrMsg(err); ErrTxt(": (response from server)",0); goto OnError; } if (err[0]!=COC_MAGIC) ERR_MSG("magic synch error");
ERR_I(str_get_end(conn->resbuf)); if (err[1]!='\0') { ErrMsg(err+1); ErrTxt(": (response from server)",0); goto OnError; }
ERR_I(StrGetEnd(&conn->resbuf));
return(0); return(0);
OnError: return(-1); OnError: return(-1);
} }
@ -102,9 +107,10 @@ int CocSendMagic(CocConn *conn, char *magic) {
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
int CocCheck(CocConn *conn) { int CocCheck(CocConn *conn) {
if (conn->fd<0) return(1); if (conn->fd<0) return(1);
ERR_SI(send(conn->fd, "quit", 5, 0)); ERR_I(CocSend(conn->fd, "_quit", 6));
ERR_I(CocRecv(conn->fd, conn->resbuf)); ERR_I(CocRecv(conn->fd, &conn->resbuf, COC_NETTMO, NULL));
return(0); return(0);
OnError: OnError:
if (ErrCode==ECONNRESET || ErrCode==EPIPE) return(1); if (ErrCode==ECONNRESET || ErrCode==EPIPE) return(1);
@ -114,16 +120,24 @@ int CocCheck(CocConn *conn) {
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
int CocTryCmd(CocConn *conn) { int CocTryCmd(CocConn *conn) {
int iret=-1; int iret=-1, siz;
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
if (conn->fd<0) { if (conn->fd<0) {
/*
ERR_I(iret=CocOpen(conn)); ERR_I(iret=CocOpen(conn));
*/
ERR_I(iret=CocConnect(conn));
if (iret == 1) {
CocDelay(500);
ErrTxt("connect",1); return (-1);
}
iret=-1; iret=-1;
ERR_I(CocSendMagic(conn, conn->magic)); ERR_I(CocSendMagic(conn, conn->magic));
} }
ERR_SI(send(conn->fd, conn->cmdbuf->buf, conn->cmdbuf->wrpos, 0)); ERR_I(CocSend(conn->fd, conn->cmdbuf.buf, conn->cmdbuf.wrpos));
ERR_I(CocRecv(conn->fd, conn->resbuf)); ERR_I(CocRecv(conn->fd, &conn->resbuf, COC_NETTMO, NULL));
return(0); return(0);
OnError: OnError:
if (ErrCode==ECONNRESET || ErrCode==EPIPE) return(-2); if (ErrCode==ECONNRESET || ErrCode==EPIPE) return(-2);
@ -134,7 +148,6 @@ int CocTryCmd(CocConn *conn) {
int CocCmdWithRetry(CocConn *conn) { int CocCmdWithRetry(CocConn *conn) {
int cnt, iret; int cnt, iret;
char *err;
if (conn==NULL) ERR_MSG("not connected"); if (conn==NULL) ERR_MSG("not connected");
cnt=3; cnt=3;
@ -152,118 +165,321 @@ int CocCmdWithRetry(CocConn *conn) {
ErrShort(ErrMessage); ErrShort(ErrMessage);
ErrShort("try to reconnect"); ErrShort("try to reconnect");
} }
ERR_P(err=str_get_str(conn->resbuf, NULL));
if (*err!='\0') { ErrMsg(err); ErrTxt(": (response from server)",0 ); return(-2); }
return(0); return(0);
OnError: return(-1); OnError: return(-1);
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
int CocSet(CocConn *conn, const char *name, const char *value) { void CocReset(CocConn *conn) {
int iret=-1;
assert(conn!=NULL); assert(conn!=NULL);
str_put_start(conn->cmdbuf); StrClear(&conn->cmdbuf);
ERR_I(str_put_str(conn->cmdbuf, "[")); if (conn->synch!=COC_SYN0) {
ERR_I(str_put_str(conn->cmdbuf, name)); conn->synch=COC_SYN0;
ERR_I(str_put_str(conn->cmdbuf, value)); } else {
ERR_I(str_put_str(conn->cmdbuf, "]")); conn->synch=COC_SYN1;
}
ERR_I(iret=CocCmdWithRetry(conn)); StrPut(&conn->cmdbuf, "", conn->synch);
conn->nargs=0;
ERR_I(str_get_end(conn->resbuf));
return(0);
OnError: return(iret);
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
int CocGetN(CocConn *conn, const char *name, char *value, int reslen) { int CocPushArg(CocConn *conn, const char *name, void *value, int type) {
int iret=-1; StrBuf *buf;
int n;
assert(conn!=NULL); assert(conn!=NULL);
str_put_start(conn->cmdbuf); assert(NULL==strchr(name, ' '));
ERR_I(str_put_str(conn->cmdbuf, name)); buf=&conn->cmdbuf;
n=conn->nargs;
ERR_I(iret=CocCmdWithRetry(conn)); if (n>=sizeof(conn->args)) ERR_MSG("too many return arguments");
conn->args[n].adr=value;
ERR_P(str_nget_str(conn->resbuf, value, reslen)); conn->args[n].type=type;
ERR_I(str_get_end(conn->resbuf)); conn->args[n].cmd=buf->buf + buf->wrpos;
conn->nargs=n+1;
if (value==NULL) {
ERR_I(StrPut(buf, name, ' '));
} else {
ERR_I(StrPut(buf, name, COC_SEP));
}
return(0); return(0);
OnError: return(-1);
OnError: return(iret);
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
int CocCmd(CocConn *conn, const char *rwList) int CocPutStr(CocConn *conn, const char *name, const char *value) {
{ int setmode, i, iret=-1; StrBuf *buf;
const char *t, *s;
char nam[32]; ERR_I(CocPushArg(conn, name, NULL, 4));
CocVar *var; ERR_I(StrPut(&conn->cmdbuf, value, COC_SEP));
void *adr; return(0);
OnError: return(-1);
}
/*-------------------------------------------------------------------------*/
int CocPutFloat(CocConn *conn, const char *name, float value) {
ERR_I(CocPushArg(conn, name, NULL, COC_FLT));
ERR_I(StrPutFloat(&conn->cmdbuf, value, COC_SEP));
return(0);
OnError: return(-1);
}
/*-------------------------------------------------------------------------*/
int CocPutInt(CocConn *conn, const char *name, int value) {
ERR_I(CocPushArg(conn, name, NULL, COC_INT));
ERR_I(StrPutInt(&conn->cmdbuf, value, COC_SEP));
return(0);
OnError: return(-1);
}
/*-------------------------------------------------------------------------*/
int CocGetStr(CocConn *conn, const char *name, char *value, int value_len) {
return(CocPushArg(conn, name, value, value_len));
}
/*-------------------------------------------------------------------------*/
int CocGetFloat(CocConn *conn, const char *name, float *value) {
return(CocPushArg(conn, name, value, COC_FLT));
}
/*-------------------------------------------------------------------------*/
int CocGetInt(CocConn *conn, const char *name, int *value) {
return(CocPushArg(conn, name, value, COC_INT));
}
/*-------------------------------------------------------------------------*/
int CocDoIt(CocConn *conn, char *res, int res_len) {
StrBuf *buf;
int i, pending;
CocArg *a;
char *resp, *t, tag;
int iret=0;
assert(conn!=NULL); assert(conn!=NULL);
str_put_start(conn->cmdbuf); ERR_I(CocCmdWithRetry(conn));
s=rwList; buf=&conn->resbuf;
setmode=0; while (buf->buf[0] != conn->synch) { /* throw away unsynchronized answers */
do { ERR_I(CocRecv(conn->fd, buf, COC_NETTMO, NULL));
t=strchr(s, ','); }
if (t==NULL) t=s+strlen(s);
if (*s=='[') {
if (!setmode) ERR_I(str_put_str(conn->cmdbuf, "["));
s++;
setmode=1;
}
i=t-s;
assert(i<32);
str_ncpy(nam, s, i+1);
if (setmode) {
if (nam[i-1]==']') { i--; nam[i]='\0'; setmode=0; }
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, NULL);
if (var==NULL) ERR_MSG("variable not found");
ERR_I(str_put_str(conn->cmdbuf, nam));
}
s=t+1;
} while (*t!='\0');
ERR_I(iret=CocCmdWithRetry(conn)); pending=conn->nargs;
*res='\0';
while (1) {
if (buf->buf[0] != conn->synch) ERR_MSG("synch error");
ERR_P(StrGet(buf, NULL, conn->synch));
i=0;
a=conn->args;
while (pending>0 && i<conn->nargs) {
if (a->type!=0) {
resp=buf->buf + buf->rdpos;
tag=*resp;
if (tag==COC_DELAYED) { /* delayed response */
resp++;
ERR_P(StrGet(buf, NULL, COC_SEP));
} else {
pending--;
if (tag==COC_ERR || tag==COC_TRM) { /* error response */
str_ncat(res, a->cmd, res_len);
resp++;
ERR_P(StrGet(buf, NULL, COC_SEP));
str_ncat(res, ": ", res_len);
iret=1;
if (tag==COC_TRM) return(1);
} else {
if (a->adr==NULL) {
t=strchr(res, COC_SEP);
str_ncat(res, a->cmd, res_len);
t=strchr(t, ' ');
assert(t!=NULL); /* truncate argument */
*t=COC_SEP;
str_ncat(res, "=", res_len);
ERR_P(StrGet(buf, NULL, COC_SEP));
} else {
str_ncat(res, a->cmd, res_len);
str_ncat(res, "=", res_len);
if (a->type==COC_INT) {
ERR_I(StrGetInt(buf, (int *)a->adr, COC_SEP));
} else if (a->type==COC_FLT) {
ERR_I(StrGetFloat(buf, (float *)a->adr, COC_SEP));
} else if (a->type>1) {
ERR_P(StrNGet(buf, (char *)a->adr, a->type, COC_SEP));
} else {
ERR_MSG("unknown type");
}
a->type=0;
}
}
str_ncat(res, resp, res_len);
str_ncat(res, "\n", res_len);
}
}
i++; a++;
}
ERR_I(StrGetEnd(buf));
if (pending==0) return(iret); /* no more delayed response awaiting */
/* read values */ ERR_I(CocRecv(conn->fd, buf, COC_RESTMO, NULL));
s=rwList; }
setmode=0; return(iret);
do { OnError: return(-1);
t=strchr(s, ','); }
if (t==NULL) t=s+strlen(s);
if (*s=='[') { static int interrupt, logFd=0;
s++;
setmode=1; void CocIntSignal(int sig) {
char buf[4];
int siz;
if (logFd) {
interrupt=2;
buf[0]=COC_CLRLOG;
buf[1]=COC_SEP; /* send "clear log" message */
printf("\nCLRLOG\n");
CocSend(logFd, buf, 2);
} else {
printf("\ninterrupt\n");
interrupt=1;
}
}
int CocWatchLog(CocConn *conn, char *loglist) {
char cbuf[1024];
StrBuf *buf;
int fd, iret;
int i, siz, n;
sys_ctrl_init();
fd=conn->fd;
CocReset(conn);
ERR_I(CocPutStr(conn, "loglist", loglist));
ERR_I(CocDoIt(conn, cbuf, sizeof(cbuf)));
buf=&conn->resbuf;
interrupt=0;
logFd=fd;
signal(SIGINT, CocIntSignal);
while (!interrupt) {
logFd=fd;
ERR_I(iret=CocRecv(fd, buf, 60, &logFd));
if (iret>0) {
if (buf->buf[0]==COC_CLRLOG) { /* confirmed "clear log" message */
interrupt=3;
} else { /* it's a log message */
StrReset(buf);
while (!StrEnd(buf)) {
ERR_P(StrGet(buf, cbuf, COC_SEP));
printf("%s", cbuf);
}
}
} }
i=t-s; }
if (setmode) { signal(SIGINT, SIG_DFL);
if (*(t-1)==']') setmode=0; logFd=0;
} else { if (interrupt==1) { /* send "clear log" message */
str_ncpy(nam, s, i+1); cbuf[0]=COC_CLRLOG;
ERR_I(CocGetVar(conn->varList, conn->resbuf, nam, 0)); cbuf[1]=COC_SEP; /* send "clear log" message */
} printf("\nclrlog\n");
s=t+1; CocSend(fd, cbuf, 2);
} while (*t!='\0'); do {
ERR_I(str_get_end(conn->resbuf)); ERR_I(CocRecv(fd, buf, 10, NULL));
} while (buf->buf[0]!=COC_CLRLOG);
}
return(0); return(0);
OnError:
signal(SIGINT, SIG_DFL);
return(-1);
}
OnError: return(iret); int CocShowLog(CocConn *conn, char *loglist, int start, int lines) {
char cbuf[1024];
StrBuf *buf;
int fd, iret;
int i, siz, n;
fd=conn->fd;
CocReset(conn);
if (start>0) {
ERR_I(CocPutInt(conn, "logstart", start));
}
ERR_I(CocPutInt(conn, "loglines", lines));
ERR_I(CocPutStr(conn, "logshow", loglist));
ERR_I(CocDoIt(conn, cbuf, sizeof(cbuf)));
buf=&conn->resbuf;
while (1) {
ERR_I(iret=CocRecv(fd, buf, 10, NULL));
if (iret<=0) break;
if (buf->buf[0]==COC_CLRLOG) { /* end of log message */
break;
} else { /* it's a log message */
StrReset(buf);
while (!StrEnd(buf)) {
ERR_P(StrGet(buf, cbuf, COC_SEP));
printf("%s", cbuf);
}
}
}
return(0);
OnError:
signal(SIGINT, SIG_DFL);
return(-1);
} }
void CocCloseClient(CocConn *conn) { void CocCloseClient(CocConn *conn) {
assert(conn!=NULL); assert(conn!=NULL);
close(conn->fd); close(conn->fd);
str_free_buf(conn->cmdbuf);
str_free_buf(conn->resbuf);
CocFreeVarList(&conn->varList);
} }
/*-------------------------------------------------------------------------*/
static char rbuf[256];
int CocSet(CocConn *conn, const char *name, const char *value) {
int iret;
assert(conn!=NULL);
CocReset(conn);
ERR_I(CocPutStr(conn, name, value));
ERR_I(iret=CocDoIt(conn, rbuf, sizeof(rbuf)));
if (iret) ERR_MSG(rbuf);
return(0);
OnError: return(-1);
}
int CocGetN(CocConn *conn, const char *name, char *value, int reslen) {
int iret;
assert(conn!=NULL);
CocReset(conn);
ERR_I(CocGetStr(conn, name, value, reslen));
ERR_I(iret=CocDoIt(conn, rbuf, sizeof(rbuf)));
if (iret) ERR_MSG(rbuf);
return(0);
OnError: return(-1);
}
int CocSetGetN(CocConn *conn, const char *name, const char *cmd, char *value, int reslen) {
int iret;
assert(conn!=NULL);
CocReset(conn);
ERR_I(CocPutStr(conn, name, cmd));
ERR_I(CocDoIt(conn, value, reslen));
return(0);
OnError: return(-1);
}

View File

@ -1,17 +1,28 @@
#ifndef _COC_CLIENT_H_ #ifndef _COC_CLIENT_H_
#define _COC_CLIENT_H_ #define _COC_CLIENT_H_
#include "myc_buf.h"
#include "coc_util.h" #include "coc_util.h"
typedef struct {
void *adr;
int type;
char *cmd;
} CocArg;
typedef struct { typedef struct {
/* private */ /* private */
int fd, port; int fd, port;
CocVar *varList; StrBuf cmdbuf; /* for sending command */
Str_Buf *cmdbuf; /* for sending command */ StrBuf resbuf; /* for response */
Str_Buf *resbuf; /* for response */ char cmdbuf_[COC_CMD_LEN];
char resbuf_[COC_RES_LEN];
CocArg args[16];
int nargs;
char host[64]; char host[64];
char magic[32]; char magic[32];
char startcmd[512]; char startcmd[512];
char synch;
} CocConn; } CocConn;
int CocInitClient(CocConn *conn, char *host, int port, char *magic, int bufsize, char *startcmd); int CocInitClient(CocConn *conn, char *host, int port, char *magic, int bufsize, char *startcmd);
@ -22,33 +33,47 @@ int CocSendMagic(CocConn *conn, char *magic);
/* send magic word to the server for changing access rights /* send magic word to the server for changing access rights
*/ */
int CocCmd(CocConn *conn, const char *rwList); void CocReset(CocConn *conn);
/* rwList consists of a list of variables to be read or written. int CocPutStr(CocConn *conn, const char *name, const char *value);
Variables must be separated with commas, variables to be written int CocPutFloat(CocConn *conn, const char *name, float value);
must be enclosed in square brackets. int CocPutInt(CocConn *conn, const char *name, int value);
int CocGetStr(CocConn *conn, const char *name, char *value, int value_len);
int CocGetFloat(CocConn *conn, const char *name, float *value);
int CocGetInt(CocConn *conn, const char *name, int *value);
int CocDoIt(CocConn *conn, char *error, int error_len);
Example (read p1 and p4, write p2 and p3):
CocCmd(&conn, "p1,[p2,p3],p4")
see COC_UTIL.H for the definiton of variables
*/
int CocCheck(CocConn *conn); int CocCheck(CocConn *conn);
/* /*
returns 1, if not yet open returns 1, if not yet open
returns 0, if connection o.k. returns 0, if connection o.k.
retruns -1 (error message), if connection died returns -1 (error message), if connection died
*/ */
int CocWatchLog(CocConn *conn, char *list);
/*
Watch indefinitely for log messages
*/
int CocSet(CocConn *conn, const char *name, const char *value); int CocSet(CocConn *conn, const char *name, const char *value);
/* /*
set one variable set one variable
*/ */
int CocGetN(CocConn *conn, const char *name, char *value, int reslen); int CocGetN(CocConn *conn, const char *name, char *value, int reslen);
#define CocGet(C,N,V) CocGetN(C,N,V,sizeof(V)) #define CocGet(C,N,V) CocGetN(C,N,V,sizeof(V))
/* /*
read one variable. Use the macro if value is a fixed length array read one variable. Use the macro if value is a fixed length array
*/ */
int CocSetGetN(CocConn *conn, const char *name, const char *cmd, char *value, int reslen);
#define CocSetGet(C,N,S,V) CocSetGetN(C,N,S,V,sizeof(V))
/*
set and get a variable. Use the macro if value is a fixed length array
*/
void CocCloseClient(CocConn *conn); void CocCloseClient(CocConn *conn);
/* /*
close the connection to the server close the connection to the server
*/ */
#endif /* _COC_CLIENT_H_ */ #endif /* _COC_CLIENT_H_ */

View File

@ -1,45 +1,35 @@
/* switch off ANSI_C_SOURCE for VMS-extended fopen, even when compiling with /ANSI */
#ifdef __VMS
#ifdef __HIDE_FORBIDDEN_NAMES
#undef __HIDE_FORBIDDEN_NAMES
#include <stdio.h> #include <stdio.h>
#define __HIDE_FORBIDDEN_NAMES
#else
#include <stdio.h>
#endif
#else
#include <stdio.h>
#endif
#include <stdlib.h> #include <stdlib.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <string.h> #include <string.h>
#include <stdarg.h> #include <stdarg.h>
#include <assert.h> #include <assert.h>
#include "coc_logfile.h" #include "coc_logfile.h"
#include "err_handling.h" #include "myc_time.h"
#include "str_util.h" #include "myc_err.h"
#include "myc_str.h"
static FILE *fil=NULL; static FILE *fil=NULL;
static char lnam[256]="", filnam[256]=""; static char lnam[224]="", filnam[256]="";
static char ebuf[20000]=""; static char ebuf[20000]="";
static char *statusBuf=NULL; static char *statusBuf=NULL;
static int statusSize; static int statusSize;
static char *eptr=&ebuf[0]; static char *eptr=&ebuf[0];
static int lastStamp=0; static int dated=0;
static int notDated=0;
static int logMask=0; static int logMask=0;
static int wrtMask=0; static int wrtMask=0;
static int newLine=1; static int newLine=1;
static int logfileStd; static int logfileStd;
static int dirty, writeAll; static int dirty, writeAll;
static int lastline=1;
static long int lastpos=0;
static int lastStamp=0;
static int openTime;
static int openDate;
int ftime (struct timeb *__timeptr); /* for some reason not defined in timeb.h with flag -std1 */ void (*logfileOutRtn)(int, char *)=NULL;
void logfileOpen(int first) { void logfileOpen(int append) {
struct tm *tim; int year;
struct timeb btim;
if (logfileStd) { if (logfileStd) {
fil=stdout; fil=stdout;
@ -47,35 +37,35 @@ void logfileOpen(int first) {
return; return;
} }
assert(fil==NULL); assert(fil==NULL);
if (first) { openTime = mycNow();
ftime(&btim); openDate = mycDate(openTime); /* date in yyyymmdd decimal encoding */
tim=localtime(&btim.time); openTime = openTime % (24*3600); /* seconds since midnight */
if (notDated) { if (dated) {
if (lnam[0]=='\0') { sprintf(filnam, "%s%02d-%02d.log", lnam, openDate % 10000 / 100, openDate % 100);
str_copy(filnam, "test.log"); } else {
} else { if (lnam[0]=='\0') {
str_copy(filnam, lnam); str_copy(filnam, "test.log");
str_append(filnam, ".log");
}
} else { } else {
sprintf(filnam, "%s%04d-%02d-%02d.log", lnam, tim->tm_year+1900, tim->tm_mon+1, tim->tm_mday); str_copy(filnam, lnam);
str_append(filnam, ".log");
}
}
if (dated) {
fil=fopen(filnam, "a+");
if (fil != NULL) {
fseek(fil, 0, SEEK_SET); /* set position to start */
year=0;
fscanf(fil, "%4d", &year);
if (year != openDate / 10000) {
fclose(fil);
fil=fopen(filnam, "w+"); /* overwrite old logfile */
} else {
fseek(fil, 0, SEEK_END); /* set position to end */
}
} }
} else { } else {
assert(filnam[0]!='\0'); fil=fopen(filnam, "w+"); /* overwrite last logfile */
} }
#ifdef __VMS
if (first && notDated) {
fil=fopen(filnam, "w", "SHR=UPD"); /* new version at restart */
} else {
fil=fopen(filnam, "a", "SHR=UPD");
}
#else
if (first && notDated) {
fil=fopen(filnam, "w"); /* overwrite at restart */
} else {
fil=fopen(filnam, "a");
}
#endif
if (fil==NULL) { if (fil==NULL) {
printf("Can not open %s\n", filnam); printf("Can not open %s\n", filnam);
fil=stdout; fil=stdout;
@ -83,10 +73,10 @@ void logfileOpen(int first) {
return; return;
} }
ErrSetOutFile(fil); ErrSetOutFile(fil);
if (first) { fprintf(fil, "%04d-%02d-%02d %02d:%02d:%02d opened logfile\n"
fprintf(fil, "%04d-%02d-%02d opened logfile\n" , openDate / 10000, openDate % 10000 / 100, openDate % 100
, tim->tm_year+1900, tim->tm_mon+1, tim->tm_mday); , openTime / 3600, openTime / 60 % 60, openTime % 60);
} lastStamp = openTime / 60;
} }
void logfileStatusBuffer(char *buffer, int bufsize) { void logfileStatusBuffer(char *buffer, int bufsize) {
@ -96,22 +86,20 @@ void logfileStatusBuffer(char *buffer, int bufsize) {
char *logfileInit(char *path, int nodate, int use_stdout, int write_all) { char *logfileInit(char *path, int nodate, int use_stdout, int write_all) {
str_copy(lnam, path); str_copy(lnam, path);
lastStamp=-2;
logfileStd=use_stdout; logfileStd=use_stdout;
writeAll=write_all; writeAll=write_all;
notDated=nodate; dated=!nodate;
logfileOpen(1); logfileOpen(1);
return(filnam); return(filnam);
} }
void logfileOut(int mask, const char *fmt, ...) void logfileOut(int mask, const char *fmt, ...)
{ va_list ap; { va_list ap;
char buf[256], *p; char buf[8192], *p;
assert(mask>0 && mask<32);
va_start(ap, fmt); va_start(ap, fmt);
if (mask & LOG_MAIN && statusBuf!=NULL) { if (mask & LOG_STAT && statusBuf!=NULL) {
if (newLine) { if (newLine) {
statusBuf[0]='\0'; statusBuf[0]='\0';
newLine=0; newLine=0;
@ -119,17 +107,22 @@ void logfileOut(int mask, const char *fmt, ...)
buf[statusSize]='\0'; buf[statusSize]='\0';
vsprintf(buf, fmt, ap); vsprintf(buf, fmt, ap);
assert(buf[statusSize]=='\0'); /* check for overflow */ assert(buf[statusSize]=='\0'); /* check for overflow */
str_ncat(statusBuf, buf, statusSize); if (buf[0]=='@') {
str_ncat(statusBuf, buf+1, statusSize);
} else {
str_ncat(statusBuf, buf, statusSize);
}
p=strchr(statusBuf, '\n'); p=strchr(statusBuf, '\n');
if (p!=NULL) { if (p!=NULL) {
newLine=1; newLine=1;
*p='\0'; *p='\0';
} }
} }
if (logfileOutRtn!=NULL) {
vsprintf(buf, fmt, ap); /* does not check for overflow! */
logfileOutRtn(mask, buf);
}
if (writeAll) { if (writeAll) {
#ifdef __VMS
if (fil==NULL) logfileOpen(0);
#endif
vfprintf(fil, fmt, ap); vfprintf(fil, fmt, ap);
wrtMask=LOG_ALL; wrtMask=LOG_ALL;
} else { } else {
@ -139,10 +132,14 @@ void logfileOut(int mask, const char *fmt, ...)
eptr=NULL; eptr=NULL;
} else { } else {
vsprintf(eptr, fmt, ap); vsprintf(eptr, fmt, ap);
assert(NULL==strchr(eptr, '\1')); p=strchr(eptr, '\1');
eptr+=strlen(eptr); if (p==NULL) {
eptr+=strlen(eptr);
} else {
eptr=p; /* is in fact an error */
}
eptr[0]='\1'; /* put \1 as separator between blocks */ eptr[0]='\1'; /* put \1 as separator between blocks */
eptr[1]=mask; eptr[1]=mask & 31;
eptr[2]='\0'; eptr[2]='\0';
eptr+=2; eptr+=2;
} }
@ -157,33 +154,35 @@ void logfileMask(int mask) {
} }
void logfileStamp(char *text) { void logfileStamp(char *text) {
struct tm *tim; int time, date, stamp;
struct timeb btim;
int stamp;
ftime(&btim); time = mycNow();
tim=localtime(&btim.time); date = mycDate(time); /* date in yyyymmdd decimal encoding */
stamp=tim->tm_hour*60+tim->tm_min; time = time % (24*3600); /* seconds since midnight */
if (stamp<lastStamp) { /* time smaller than last time -> new day -> new logfile */
stamp=time / 60;
if (date != openDate ) { /* day has changed -> new logfile */
if (fil!=NULL) { fclose(fil); fil=NULL; } if (fil!=NULL) { fclose(fil); fil=NULL; }
lastpos=0;
lastline=1;
logfileOpen(1); logfileOpen(1);
lastStamp=-2;
} }
if (stamp>lastStamp+1) { if (text==NULL) {
#ifdef __VMS if (stamp>lastStamp+1) {
if (fil==NULL) logfileOpen(0); fprintf(fil, "---\t%02d:%02d:%02d\n", stamp / 60, stamp % 60, time % 60, text);
#endif }
lastStamp=stamp; } else {
fprintf(fil, "%02d:%02d:%02d --- %s", tim->tm_hour, tim->tm_min, tim->tm_sec, text); fprintf(fil, "\t%02d:%02d:%02d %s", stamp / 60, stamp % 60, time % 60, text);
dirty=0;
} }
dirty=0;
lastStamp=stamp;
} }
void logfileWrite0(int mask) { void logfileWrite0(int mask) {
char *s, *next; char *s, *next;
logMask=logMask | mask; logMask=logMask | mask;
if (dirty) logfileStamp("\n"); /* there was something written since last time */ if (dirty) logfileStamp(NULL); /* there was something written since last time */
s=ebuf; s=ebuf;
if (writeAll || *s!='\0' && wrtMask & logMask) { if (writeAll || *s!='\0' && wrtMask & logMask) {
@ -193,10 +192,9 @@ void logfileWrite0(int mask) {
next++; next++;
if (*next & logMask) { if (*next & logMask) {
if (*s=='@') { /* write out time */ if (*s=='@') { /* write out time */
lastStamp-=2; /* force output */
logfileStamp(s+1); logfileStamp(s+1);
} else { } else {
logfileStamp("\n"); /* write stamp before write something */ logfileStamp(NULL); /* write stamp before write something */
fprintf(fil, "%s", s); fprintf(fil, "%s", s);
dirty=1; dirty=1;
} }
@ -211,71 +209,131 @@ void logfileWrite0(int mask) {
wrtMask=0; wrtMask=0;
} }
void logfileScan(int date, void (*scanLine)(void*, char*), void *arg) {
FILE *sFile;
char buf[256], *res;
if (date == openDate) {
sFile=fil;
rewind(sFile);
} else {
sprintf(filnam, "%s%02d-%02d.log", lnam, date % 10000 / 100, date % 100);
sFile=fopen(filnam, "r+");
if (sFile==NULL) return;
}
res=fgets(buf, sizeof(buf), sFile);
while (res!=NULL) {
if (res[0]=='\t') {
scanLine(arg, res+1);
}
res=fgets(buf, sizeof(buf), sFile);
}
if (sFile==fil) {
fseek(fil, 0, SEEK_END);
} else {
fclose(sFile);
}
}
void logfileWrite(int mask) { void logfileWrite(int mask) {
#ifdef __VMS
if (fil==NULL) logfileOpen(0);
#endif
logfileWrite0(mask); logfileWrite0(mask);
#ifdef __VMS
if (!logfileStd) { fclose(fil); fil=NULL; }
#else
fflush(fil); fflush(fil);
#endif
} }
void logfileShowErr(char *text) void logfileShowErr(char *text)
{ {
#ifdef __VMS
if (fil==NULL) logfileOpen(0);
#endif
logfileWrite0(LOG_ALL); /* write all */ logfileWrite0(LOG_ALL); /* write all */
ErrShow(text); ErrShow(text);
#ifdef __VMS
if (!logfileStd) { fclose(fil); fil=NULL; }
#else
fflush(fil); fflush(fil);
#endif
} }
void logfileClose() void logfileClose()
{ {
#ifdef __VMS
if (fil==NULL) logfileOpen(0);
#endif
logfileWrite0(LOG_MAIN+LOG_INFO); logfileWrite0(LOG_MAIN+LOG_INFO);
lastStamp=-2; lastStamp=-2;
logfileStamp("\n"); logfileOut(LOG_MAIN, "closed\n");
logfileStamp(NULL);
if (fil!=NULL) { fclose(fil); fil=NULL; } if (fil!=NULL) { fclose(fil); fil=NULL; }
filnam[0]='\0'; filnam[0]='\0';
} }
void logfileOutBuf(int mask, Str_Buf *buf) void logfileOutBuf(int mask, StrBuf *buf)
{ char str[256]; { char str[256];
int rd0, sep; int rd0;
char *ret;
rd0=buf->rdpos; rd0=buf->rdpos;
if (buf->rdpos < 0 || buf->rdpos >= buf->dsize if (buf->rdpos < 0 || buf->rdpos >= buf->dsize
|| buf->wrpos < 0 || buf->wrpos >= buf->dsize) { || buf->wrpos < 0 || buf->wrpos >= buf->dsize) {
logfileOut(mask, "<buffer corrupt>"); return; logfileOut(mask, "<buffer corrupt>"); return;
} }
sep=0; while (!StrEnd(buf)) {
while (buf->rdpos < buf->wrpos) { ret=StrGet(buf, str, '\0');
str_get_str(buf, str); if (ret==NULL) {
if (buf->sep=='\0') { ret="...";
if (sep) logfileOut(mask, " "); buf->rdpos=buf->wrpos;
if (*str=='\0') { }
logfileOut(mask, "."); if (ret[0]<32 && ret[0]>0) {
} else { logfileOut(mask, "[%d]%s;", ret[0], ret+1);
logfileOut(mask, "%s", str);
}
sep=1;
} else { } else {
if (sep) logfileOut(mask, "%c", buf->sep); logfileOut(mask, "%s;", ret);
logfileOut(mask, "%s", str);
sep=1;
} }
} }
buf->rdpos=rd0; buf->rdpos=rd0;
} }
int logfileLength(void) {
char lin[256];
int l, ll;
if (logfileStd || fil==NULL) return 0;
fseek(fil, lastpos, SEEK_SET);
ll=lastpos;
l=lastline;
while (NULL!=fgets(lin, sizeof(lin), fil)) {
lastpos=ll;
ll=ftell(fil);
lastline=l;
l++;
}
return(lastline);
}
long int logfilePos(int n) {
/* set file to the start of n-th last line n, if n<0 then position to the -n-th line */
int i;
char lin[256];
if (logfileStd || fil==NULL) return 0;
if (n>0) {
n=logfileLength()-n+1;
} else {
n=-n;
}
fseek(fil, 0, SEEK_SET);
for (i=1; i<n; i++) {
if (NULL==fgets(lin, sizeof(lin), fil)) return ftell(fil);
}
return ftell(fil);
}
long int logfileGetLines(long int pos, int linmax, char *line, int len_line) {
int l,i;
if (logfileStd || fil==NULL) {
line[0]='\0';
return 0;
}
l=0;
fseek(fil, pos, SEEK_SET);
for (i=0; i<linmax; i++) {
if (NULL==fgets(line+l, len_line-l, fil)) {
line[l]='\0';
return ftell(fil);
}
l=strlen(line);
}
pos=ftell(fil);
fseek(fil, 0, SEEK_END);
return pos;
}

View File

@ -1,9 +1,10 @@
#ifndef _COC_LOGFILE_H_ #ifndef _COC_LOGFILE_H_
#define _COC_LOGFILE_H_ #define _COC_LOGFILE_H_
#include "str_buf.h" #include "myc_buf.h"
#define LOG_ALL 31 #define LOG_ALL 31
#define LOG_STAT 32
#define LOG_SER 8 #define LOG_SER 8
#define LOG_NET 4 #define LOG_NET 4
#define LOG_INFO 2 #define LOG_INFO 2
@ -13,10 +14,15 @@
void logfileStatusBuffer(char *buffer, int bufsize); void logfileStatusBuffer(char *buffer, int bufsize);
char *logfileInit(char *path, int nodate, int use_stdout, int write_all); char *logfileInit(char *path, int nodate, int use_stdout, int write_all);
void logfileOut(int mask, const char *fmt, ...); void logfileOut(int mask, const char *fmt, ...);
void logfileOutBuf(int mask, Str_Buf *buf); void logfileOutBuf(int mask, StrBuf *buf);
void logfileShowErr(char *text); void logfileShowErr(char *text);
void logfileMask(int mask); void logfileMask(int mask);
void logfileScan(int date, void (*scanLine)(void*, char*), void *arg);
void logfileWrite(int mask); void logfileWrite(int mask);
void logfileClose(void); void logfileClose(void);
long int logfilePos(int n);
long int logfileGetLines(long int pos, int linmax, char *line, int len_line);
extern void (*logfileOutRtn)(int, char *); /* custom output routine */
#endif /* _COC_LOGFILE_H_ */ #endif /* _COC_LOGFILE_H_ */

View File

@ -1,67 +1,449 @@
/* needed to define accept() and gethostbyaddr() correctly when using flag -std1
*/
#ifdef __unix__
#ifndef _XOPEN_SOURCE_EXTENDED
#define _XOPEN_SOURCE_EXTENDED
#endif
#endif
#include <sys/socket.h> #include <sys/socket.h>
#include <netdb.h> #include <netdb.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/timeb.h> #include <sys/timeb.h>
#include <strings.h> #include <strings.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <assert.h>
#include "myc_mem.h"
#include "sys_util.h" #include "sys_util.h"
#include "err_handling.h" #include "myc_err.h"
#include "coc_logfile.h" #include "coc_logfile.h"
#include "coc_util.h"
#include "coc_server.h" #include "coc_server.h"
#include "str_util.h" #include "myc_str.h"
#include "myc_time.h"
static Str_Buf *buf, *bufo; #define COC_NUL COC_SEP
typedef struct _CocVar {
struct _CocVar *next;
char name[32];
void *var;
int access;
int type;
void *strucType;
int (*hdl)(int, void *);
int pending;
} CocVar;
CocVar *serverVarList=NULL;
static CocVar **varListHandle=&serverVarList;
static CocVar *lastDef=NULL;
typedef struct {
CocVar *var;
void *base;
int mode;
} Pend;
typedef struct _CocClient {
struct _CocClient *next;
int fd;
int mode;
Pend pend[16];
int npend;
int logmask;
char synch;
void *data;
} CocClient;
void *(*setData)(void *);
/*
static CocClientData **clData;
static int clDataSize;
*/
DeclStrBuf(buf, COC_CMD_LEN);
DeclStrBuf(bufo, COC_RES_LEN);
static fd_set mask, rmask; static fd_set mask, rmask;
static int maxfd; static int maxfd;
struct CocClient *cList, *cLastCmd=NULL; CocClient *cList;
static int mainFd; static int mainFd;
static int modified; static int modified;
static char loglist[16];
int CocInitServer(int bufsize, int port) { void CocVarList(void **varList) {
if (varList==NULL) {
varListHandle=(CocVar **)varList;
} else {
varListHandle=&serverVarList;
}
}
void CocList() {
CocVar *p;
p=*varListHandle;
while (p!=NULL) {
printf("%s %d ", p->name, p->type);
p=p->next;
}
printf("\n");
}
CocVar *CocFindVar1(const char *name) {
CocVar *p;
p=*varListHandle;
while (p!=NULL && 0!=strcasecmp(p->name,name)) p=p->next;
return(p);
}
void *CocFindVar(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(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(nam);
if (p!=NULL && p->type==COC_ALIAS) { /* recursive call for alias */
p=CocFindVar(p->var, adr);
}
return(p);
}
void *CocIntPtr(int *ptr) { return(ptr); }
void *CocFltPtr(float *ptr) { return(ptr); }
void *CocChrPtr(char *ptr) { return(ptr); }
void *CocDefVar(const char *name, void *var, int type, int access) {
CocVar *p;
const char *f;
void *adr;
assert(varListHandle!=NULL);
p=CocFindVar1(name);
if (p==NULL) {
NEW(p,CocVar);
p->next=*varListHandle;
*varListHandle=p;
str_copy(p->name, name);
p->type=type;
} else {
assert(p->type==type);
}
p->var=var;
p->access=access;
/* printf("define %s %d\n", name, (int)var); */
lastDef=p;
return(p);
OnError:
assert(0);
}
void CocHdl(int (*handler)(int, void *)) {
assert(lastDef!=NULL);
lastDef->hdl=handler;
}
void CocDefVarS(const char *name, const char *tname, void *var, int type) {
CocVar *p, *t;
assert(type==COC_PTR || type==COC_STRUCT);
p=CocDefVar(name, var, type, COC_RDONLY);
p->strucType=CocDefVar(tname, NULL, COC_TYPE, COC_RDONLY);
}
char err_name[64];
int CocGetThisVar(CocVar *var, void *base, StrBuf *buf, int separator) {
void *adr;
int iret;
if (base==NULL) {
adr=var->var;
if (adr==NULL)
ERR_MSG("NULL pointer accessed");
} else { /* dereference */
adr=(char *)base + (int)var->var;
}
/* printf("get %s %d\n", name, (int)adr); */
if (var->type==-1) {
ERR_I(StrGetInt(buf, (int *)adr, separator));
} else if (var->type==-2) {
ERR_I(StrGetFloat(buf, (float *)adr, separator));
} else if (var->type>1) {
ERR_P(StrNGet(buf, (char *)adr, var->type, separator));
} else {
ERR_MSG("unknown type");
}
return(0);
OnError: return(-1);
}
int CocPutThisVar(CocVar *var, void *base, StrBuf *buf, int separator) {
void *adr;
int iret;
if (base==NULL) {
adr=var->var;
if (adr==NULL)
ERR_MSG("NULL pointer accessed");
} else { /* dereference */
adr=(char *)base + (int)var->var;
}
/* printf("put %s %d\n", name, (int)adr); */
if (var->type==-1) {
ERR_I(StrPutInt(buf, *(int *)adr, separator));
} else if (var->type==-2) {
ERR_I(StrPutFloat(buf, *(float *)adr, separator));
} else if (var->type>1) {
ERR_I(StrPut(buf, adr, separator));
} else {
ERR_MSG("unknown type");
}
return(0);
OnError: return(-1);
}
int CocGetVar(const char *name, StrBuf *buf, int separator) {
CocVar *var;
void *base;
var=CocFindVar(name, &base);
if (var==NULL) ERR_MSG("undefined variable");
ERR_I(CocGetThisVar(var, base, buf, separator));
return(0);
OnError: str_copy(err_name, name); ErrTxt(err_name,0); return(-1);
}
int CocPutVar(const char *name, StrBuf *buf, int separator) {
CocVar *var;
void *base;
var=CocFindVar(name, &base);
if (var==NULL) ERR_MSG("undefined variable");
ERR_I(CocPutThisVar(var, base, buf, separator));
return(0);
OnError: str_copy(err_name, name); ErrTxt(err_name,0); return(-1);
}
void CocFreeVarList(void) {
CocVar *p, *v;
v=*varListHandle;
while (v!=NULL) {
p=v;
v=p->next;
p->next=NULL;
FREE(p);
}
*varListHandle=NULL;
}
void CocToClients(int mask, char *str) {
int iret;
CocClient *cl;
cl=cList->next;
while (cl!=NULL) {
if (cl->logmask & mask) {
iret=CocSend(cl->fd, str, strlen(str)+1);
if (iret<0) {
cl->logmask=0; /* disable logging for dead clients */
logfileOut(LOG_MAIN, "(%d) disconnected while logging\n", cl->fd);
}
}
cl=cl->next;
}
}
int CocInitServer(void *(*setDataRtn)(void *), int port) {
int i; int i;
struct sockaddr_in sadr; struct sockaddr_in sadr;
char *err; char *err;
if (bufsize==0) bufsize=1024; setData=setDataRtn;
ERR_P(buf=str_create_buf(bufsize, '\0')); /*
ERR_P(bufo=str_create_buf(bufsize,'\0')); clDataSize=clientDataSize;
NEW(cList); /* empty header */ clData=clientData;
*/
/* first try to connect to an existing server */ NEW(cList,CocClient); /* empty header */
ERR_SI(mainFd=socket(AF_INET, SOCK_STREAM, 0)); ERR_SI(mainFd=socket(AF_INET, SOCK_STREAM, 0));
i = 1; i = 1;
ERR_SI(setsockopt(mainFd,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(int))); /* allow quick port reuse */ ERR_SI(setsockopt(mainFd,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(int))); /* allow quick port reuse */
ERR_I(CocCreateSockAdr(&sadr, NULL, port)); ERR_I(CocCreateSockAdr(&sadr, NULL, port));
ERR_SI(bind(mainFd, (struct sockaddr *)&sadr, sizeof(sadr))); ERR_SI(bind(mainFd, (struct sockaddr *)&sadr, sizeof(sadr)));
logfileOutRtn=CocToClients;
logfileOut(LOG_INFO, "created server on port %d\n", port); logfileOut(LOG_INFO, "created server on port %d\n", port);
ERR_SI(listen(mainFd, 8)); ERR_SI(listen(mainFd, 8));
FD_ZERO(&mask); FD_ZERO(&mask);
FD_SET(mainFd, &mask); FD_SET(mainFd, &mask);
maxfd=mainFd+1; maxfd=mainFd+1;
CocDefStr(loglist, COC_RDWR);
return(0); return(0);
OnError: return(-1); OnError: return(-1);
} }
int CocHandleThis(CocVar *var, void *base, StrBuf *outBuf, int mode) {
int iret;
if (var->hdl!=NULL) {
iret=var->hdl(mode, base);
if (iret<0) { /* error */
ErrShow(var->name);
ERR_I(StrPut(outBuf, "", COC_ERR)); /* signal error message */
ERR_I(StrPut(outBuf, ErrMessage, COC_SEP));
return(0);
}
if (iret==COC_DRD) {
ERR_I(StrPut(outBuf, "", COC_DELAYED)); /* delayed response message */
ERR_I(StrPut(outBuf, "", COC_SEP)); /* empty message */
return(COC_DRD);
}
if (iret!=0 && iret!=COC_DWR)
ERR_MSG("illegal return value from handler");
} else {
iret=0;
}
ERR_I(CocPutThisVar(var, base, outBuf, COC_NUL));
return(iret);
OnError: return(-1);
}
int CocPushThisHandler(CocVar *var, CocClient *cl, void *base, int mode) {
int n;
if (mode==COC_DWR) {
if (var->pending) return(0);
var->pending=1;
}
n=cl->npend;
if (n>=sizeof(cl->pend)) {
ERR_MSG("too many commands")
}
cl->pend[n].var=var;
cl->pend[n].base=base;
cl->pend[n].mode=mode;
cl->npend=n+1;
return(0);
OnError: return(-1);
}
int CocCallHandlers(void) {
CocClient *cl;
CocVar *var;
Pend *p;
int i, iret, mode, delayedRead;
char synch;
DeclStrBuf(bufr, COC_RES_LEN);
cl=cList->next;
while (cl!=NULL) {
delayedRead=0;
/* treat delayed write handlers first */
for (i=0; i<cl->npend; i++) {
p=&cl->pend[i];
mode=p->mode;
var=p->var;
assert(var!=NULL && var->hdl!=NULL);
if (mode==COC_DWR) {
var->pending=0;
ERR_I(var->hdl(mode, p->base));
p->mode=0;
} else {
delayedRead=1;
}
}
if (delayedRead) {
StrClear(&bufr);
synch=cl->synch;
ERR_I(StrPut(&bufr, "", cl->synch));
for (i=0; i<cl->npend; i++) {
p=&cl->pend[i];
mode=p->mode;
var=p->var;
assert(var!=NULL && var->hdl!=NULL);
if (mode==COC_DRD) {
iret=var->hdl(mode, p->base);
if (iret<0) { /* error */
ERR_I(StrPut(&bufr, "", COC_ERR)); /* signal error message */
ERR_I(StrPut(&bufr, ErrMessage, COC_SEP));
}
ERR_I(CocPutThisVar(var, p->base, &bufr, COC_NUL));
}
}
if (cl->synch==synch) { /* send only if no new request from client received */
assert(cl->fd!=0);
ERR_I(CocSend(cl->fd, bufr.buf, bufr.wrpos));
}
}
cl->npend=0;
cl=cl->next;
}
return(0);
OnError:
cl->npend=0;
return(-1);
}
void CocShowHandlers(char *buf, int buf_len) {
CocClient *cl;
Pend *p;
int i;
buf[0]='\0';
cl=cList->next;
while (cl!=NULL) {
for (i=0; i<cl->npend; i++) {
p=&cl->pend[i];
if (p->mode==COC_DWR) {
assert(p->var!=NULL);
if (buf[0]!='\0') str_ncat(buf, ", ", buf_len);
str_ncat(buf, p->var->name, buf_len);
}
}
cl=cl->next;
}
return;
}
int CocHandle1Request(int tmo_msec, int fd) { int CocHandle1Request(int tmo_msec, int fd) {
struct sockaddr_in cadr; struct sockaddr_in cadr;
struct hostent *h; struct hostent *h;
struct timeval tmo={0,1}; struct timeval tmo={0,1};
struct CocClient *cl, *cl0; CocClient *cl, *cl0;
int i, newfd, setmode; CocVar *var;
size_t cadrlen; int i, lmask, newfd, n, iret;
char *err, *varname; sys_adr_len cadrlen; /* see sys_util.h */
char *err, *cmd, *arg, *varname;
void *base;
rmask=mask; rmask=mask;
if (fd>0) FD_SET(fd, &rmask); if (fd>0) FD_SET(fd, &rmask);
@ -76,14 +458,18 @@ int CocHandle1Request(int tmo_msec, int fd) {
ERR_SI(newfd=accept(mainFd, (struct sockaddr *)&cadr, &cadrlen)); ERR_SI(newfd=accept(mainFd, (struct sockaddr *)&cadr, &cadrlen));
FD_SET(newfd, &mask); FD_SET(newfd, &mask);
if (newfd>=maxfd) maxfd=newfd+1; if (newfd>=maxfd) maxfd=newfd+1;
cl=cList; NEW(cl, CocClient);
cl->fd=newfd; cl->fd=newfd;
cl->mode=0; cl->mode=0;
cl->cmd[0]='\0'; if (setData!=NULL) {
cl->res[0]='\0'; ERR_P(cl->data = setData(NULL)); /* create new client data object */
NEW(cList); }
/*
ERR_SP(cList=calloc(1,sizeof(CocClient)+clDataSize));
*/
cl->next=cList->next;
cList->next=cl; cList->next=cl;
h=gethostbyaddr(&cadr.sin_addr, 4, AF_INET); h=gethostbyaddr((void *)&cadr.sin_addr, 4, AF_INET);
if (h==NULL) { if (h==NULL) {
logfileOut(LOG_INFO, "(%d) open from %s\n", newfd, "local"); logfileOut(LOG_INFO, "(%d) open from %s\n", newfd, "local");
} else { } else {
@ -93,8 +479,8 @@ int CocHandle1Request(int tmo_msec, int fd) {
cl0=cList; cl=cl0->next; cl0=cList; cl=cl0->next;
while (cl!=NULL) { while (cl!=NULL) {
if (FD_ISSET(cl->fd, &rmask)) { if (FD_ISSET(cl->fd, &rmask)) {
buf->wrpos=recv(cl->fd, buf->buf, buf->dsize, 0); iret=CocRecv(cl->fd, &buf, -1, NULL);
if (buf->wrpos<=0) { if (iret<=0) {
logfileOut(LOG_INFO, "(%d) disconnected\n",cl->fd); logfileOut(LOG_INFO, "(%d) disconnected\n",cl->fd);
close(cl->fd); close(cl->fd);
FD_CLR(cl->fd, &mask); FD_CLR(cl->fd, &mask);
@ -102,76 +488,81 @@ int CocHandle1Request(int tmo_msec, int fd) {
FREE(cl); FREE(cl);
cl=cl0; cl=cl0;
} else { } else {
cl->logmask=0; /* stop output to log client */
str_put_start(bufo); lmask=0;
str_get_start(buf); StrReset(&buf);
ERR_I(str_put_str(bufo, "")); /* empty error message */ StrClear(&bufo);
setmode=0;
err=NULL; err=NULL;
ERR_P(varname=str_get_str(buf, NULL));
logfileOut(LOG_NET, "(%d) ", cl->fd); logfileOut(LOG_NET, "(%d) ", cl->fd);
if (varname[0]=='#') { /* access code */ logfileOutBuf(LOG_NET, &buf);
if (0==strcmp(varname,"#rdacc")) { /* cl->npend=0; why that ? */
logfileOut(LOG_INFO, "set read mode\n"); logfileOut(LOG_NET, "\n");
cl->mode=1; cl->synch=buf.buf[0];
} else if (0==strcmp(varname,"#rwacs")) { ERR_P(StrGet(&buf, NULL, cl->synch));
logfileOut(LOG_INFO, "set write mode\n"); ERR_I(StrPut(&bufo, "", cl->synch));
cl->mode=2; while (!StrEnd(&buf)) {
} else { ERR_P(varname=StrGet(&buf, NULL, ' '));
err="bad access code"; if (cl->synch==COC_MAGIC) { /* access code */
} if (0==strcmp(varname,"rdacs")) {
} else if (cl->mode==0) { logfileOut(LOG_INFO, "set read mode\n");
err="no access"; cl->mode=1;
} else { ERR_I(StrPut(&bufo, "", COC_SEP)); /* empty message */
while (1) { } else if (0==strcmp(varname,"rwacs")) {
if (varname[0]=='[') { logfileOut(LOG_INFO, "set write mode\n");
if (cl->mode<2) { err="no write access"; break; } cl->mode=2;
setmode=1; /* switch to set mode */ ERR_I(StrPut(&bufo, "", COC_SEP)); /* empty message */
} else if (varname[0]==']') { /* switch to read mode */
setmode=0;
} else if (setmode) {
if (0==strcmp("$", varname)) { /* special case: command */
ERR_P(str_get_str(buf, cl->cmd));
cl->res[0]='\0';
} else {
i=CocGetVar(serverVarList, buf, varname, 1);
if (i<0) {
err=ErrMessage; break;
}
}
modified=1;
} else { } else {
if (0==strcmp("$", varname)) { /* special case: response */ ERR_I(StrPut(&bufo, "", COC_ERR)); /* signal error message */
ERR_I(str_put_str(bufo, cl->res)); ERR_I(StrPut(&bufo, "bad access code", COC_SEP));
cl->res[0]='\0'; }
ERR_P(StrGet(&buf, NULL, COC_NUL)); /* skip separator */
} else if (cl->mode==0) {
ERR_I(StrPut(&bufo, "", COC_ERR)); /* signal terminal error message */
ERR_I(StrPut(&bufo, "no access", COC_SEP));
ERR_P(StrGet(&buf, NULL, COC_NUL)); /* skip separator */
} else {
if (cl->data!=NULL) {
setData(cl->data);
}
var=CocFindVar(varname, &base);
if (var==NULL) {
ERR_I(StrPut(&bufo, "", COC_ERR)); /* signal error message */
ERR_I(StrPut(&bufo, "undefined variable", COC_SEP));
ERR_P(StrGet(&buf, NULL, COC_NUL)); /* skip separator */
} else if (buf.seen) { /* separator was there: set mode */
if (var->access > cl->mode) {
ERR_I(StrPut(&bufo, "", COC_ERR)); /* signal error message */
ERR_I(StrPut(&bufo, "no access", COC_SEP));
ERR_P(StrGet(&buf, NULL, COC_NUL)); /* skip separator */
} else { } else {
i=CocPutVar(serverVarList, bufo, varname, 0); ERR_I(CocGetThisVar(var, base, &buf, COC_SEP));
if (i<0) { if (0==strcmp(var->name,"loglist")) {
err=ErrMessage; break; str_upcase(loglist, loglist);
if (NULL!=strchr(loglist,'A')) lmask = lmask | LOG_ALL;
if (NULL!=strchr(loglist,'S')) lmask = lmask | LOG_SER;
if (NULL!=strchr(loglist,'N')) lmask = lmask | LOG_NET;
if (NULL!=strchr(loglist,'I')) lmask = lmask | LOG_INFO;
if (NULL!=strchr(loglist,'M')) lmask = lmask | LOG_MAIN;
ERR_I(StrPut(&bufo, "", COC_NUL)); /* o.k. */
} else {
ERR_I(iret=CocHandleThis(var, base, &bufo, COC_WR));
if (iret) ERR_I(CocPushThisHandler(var, cl, base, iret));
} }
modified=1;
} }
} else {
ERR_P(StrGet(&buf, NULL, COC_NUL)); /* skip separator */
ERR_I(iret=CocHandleThis(var, base, &bufo, COC_RD));
if (iret) ERR_I(CocPushThisHandler(var, cl, base, iret));
} }
if (buf->rdpos>=buf->wrpos) {
ERR_I(str_get_end(buf));
break;
}
ERR_P(varname=str_get_str(buf, NULL));
} }
str_get_start(buf);
logfileOutBuf(LOG_NET, buf);
str_get_start(bufo);
logfileOut(LOG_NET, " |");
logfileOutBuf(LOG_NET, bufo);
} }
if (err==NULL) { ERR_I(StrGetEnd(&buf));
logfileOut(LOG_NET, "\n"); logfileOut(LOG_NET, " ");
} else { logfileOutBuf(LOG_NET, &bufo);
str_put_start(bufo); /* reset output */ logfileOut(LOG_NET, "\n");
str_put_str(bufo, err); /* put error message */ ERR_I(CocSend(cl->fd, bufo.buf, bufo.wrpos));
logfileOut(LOG_NET, " (%s)\n", err); cl->logmask=lmask;
/* logfileMask(LOG_NET); */
}
ERR_SI(send(cl->fd, bufo->buf, bufo->wrpos, 0));
} }
} }
cl0=cl; cl=cl->next; cl0=cl; cl=cl->next;
@ -183,54 +574,30 @@ int CocHandle1Request(int tmo_msec, int fd) {
} }
int CocHandleRequests(int tmo_msec, int fd) { int CocHandleRequests(int tmo_msec, int fd) {
struct timeb tim1, tim0; int tdif, iret, tim0;
int tdif, iret;
if (modified && fd==0) { /* earlier modification */ if (modified && fd==0) { /* earlier modification */
modified=0; modified=0;
return(2); return(2);
} }
ftime(&tim0); tim0=mycMsecSince(0);
tdif=tmo_msec; tdif=tmo_msec;
while (tdif>=0) { while (tdif>=0) {
ERR_I(iret=CocHandle1Request(tdif, fd)); ERR_I(iret=CocHandle1Request(tdif, fd));
if (fd==0) { if (fd==0) {
if (iret==2) return(2); /* modification of a varaible */ if (iret==2) return(2); /* modification of a variable */
} else { } else {
if (iret==1) return(1); /* event on fd */ if (iret==1) return(1); /* event on fd */
} }
if (iret==0) return(0); /* timeout */ if (iret==0) return(0); /* timeout */
ftime(&tim1); tdif = tmo_msec - mycMsecSince(tim0);
tdif=tmo_msec-((tim1.time-tim0.time)*1000+tim1.millitm-tim0.millitm);
} }
return(0); /* timeout */ return(0); /* timeout */
OnError: return(-1); OnError: return(-1);
} }
struct CocClient *CocGetNextCmd() {
struct CocClient *cl;
cl=cLastCmd;
while (cl!=NULL) {
if (cl->cmd[0]!='\0') {
cLastCmd=cl->next;
return(cl);
}
cl=cl->next;
}
cl=cList->next;
while (cl!=NULL && cl!=cLastCmd) {
if (cl->cmd[0]!='\0') {
cLastCmd=cl->next;
return(cl);
}
cl=cl->next;
}
return(NULL);
}
void CocCloseServer() { void CocCloseServer() {
struct CocClient *cl, *cl0; CocClient *cl, *cl0;
cl=cList->next; cl=cList->next;
while (cl!=NULL) { while (cl!=NULL) {
@ -241,6 +608,4 @@ void CocCloseServer() {
} }
FREE(cList); FREE(cList);
close(mainFd); close(mainFd);
str_free_buf(buf); str_free_buf(bufo);
logfileClose();
} }

View File

@ -1,11 +1,78 @@
#ifndef _SERVER_H_ #ifndef _SERVER_H_
#define _SERVER_H_ #define _SERVER_H_
#include "coc_util.h" #include "myc_buf.h"
struct CocClient { struct CocClient *next; int fd; int mode; char cmd[80]; char res[80]; }; void CocVarList(void **varlist);
/*
instal a variable list
*/
int CocInitServer(int bufsize, int port); void CocFreeVarList(void);
/*
free variable list
*/
void *CocFindVar(const char *name, void **adr);
/*
find a variable. returns NULL if not found.
*/
int CocPutVar(const char *name, StrBuf *buf, int separator);
/*
put a variable named <name> of variable list <varList> to the buffer <buf>
*/
int CocGetVar(const char *name, StrBuf *buf, int separator);
/*
get a variable named <name> of variable list <varList> from the buffer <buf>
*/
void CocHdl(int (*handler)(int, void *));
/*
define handler for last defined item
*/
void *CocIntPtr(int *ptr);
void *CocFltPtr(float *ptr);
void *CocChrPtr(char *ptr);
void *CocDefVar(const char *name, void *var, int type, int access);
void CocDefVarS(const char *name, const char *tname, void *var, int type);
/*
Define variables. Call this routines not directly, but through
one of the macros below.
*/
#define CocDefInt(V,A) CocDefVar(#V,CocIntPtr(&V),COC_INT,A)
#define CocDefFlt(V,A) CocDefVar(#V,CocFltPtr(&V),COC_FLT,A)
#define CocDefStr(V,A) CocDefVar(#V,CocChrPtr(V),sizeof(V),A)
#define CocDefPtr(V,S) CocDefVarS(#V,#S,&V,(V!=(S *)NULL,COC_PTR));
#define CocDefStruct(V,S) CocDefVarS(#V,#S,&V,(&V!=(S *)NULL,COC_STRUCT));
#define CocIntFld(S,V,A) CocDefVar(#S":"#V,CocIntPtr(&((S *)NULL)->V),COC_INT,A);
#define CocFltFld(S,V,A) CocDefVar(#S":"#V,CocFltPtr(&((S *)NULL)->V),COC_FLT,A);
#define CocStrFld(S,V,A) CocDefVar(#S":"#V,CocChrPtr(((S *)NULL)->V),sizeof(((S *)NULL)->V),A);
#define CocDefCmd(V) CocDefVar("$",V,sizeof(V),0)
#define CocDefStrPtr(V,S,A) CocDefVar(#V,V,S,A)
#define CocAlias(A,V) CocDefVar(#A, #V, COC_ALIAS,0);
#define COC_RDONLY 3
#define COC_RDWR 2
#define COC_RDWRALL 1
#define COC_WR 1
#define COC_RD 2
#define COC_DWR 3
#define COC_DRD 4
#define COC_SHOW 5
#define COC_INT -1
#define COC_FLT -2
#define COC_PTR -3
#define COC_STRUCT -4
#define COC_TYPE -5
#define COC_ALIAS -6
int CocInitServer(void *(*setDataRtn)(void *), int port);
int CocHandleRequests(int tmo_msec, int fd); int CocHandleRequests(int tmo_msec, int fd);
int CocHandle1Request(int tmo_msec, int fd); int CocHandle1Request(int tmo_msec, int fd);
@ -30,11 +97,13 @@ int CocHandle1Request(int tmo_msec, int fd);
*/ */
struct CocClient *CocGetNextCmd(void); /* server handlers removed
/* int CocPushHandler(const char *name);
get next client with a pending command
*/ */
int CocCallHandlers(void);
void CocShowHandlers(char *buf, int buf_len);
void CocCloseServer(void); void CocCloseServer(void);
#endif /* _SERVER_H_ */ #endif /* _SERVER_H_ */

View File

@ -1,24 +1,15 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <strings.h> #include <sys/time.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netdb.h> #include <netdb.h>
#include <string.h> #include <string.h>
#include <assert.h> #include "myc_err.h"
#include "sys_util.h" #include "myc_str.h"
#include "err_handling.h"
#include "str_util.h"
#include "coc_util.h" #include "coc_util.h"
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/* CreateSocketAddress stolen from Tcl. Thanks to John Ousterhout */ /* CreateSocketAddress stolen from Tcl. Thanks to John Ousterhout */
CocVar *serverVarList=NULL;
static CocVar **varListHdl=&serverVarList;
int CocRD=0;
int CocWR=0;
int CocCreateSockAdr( int CocCreateSockAdr(
struct sockaddr_in *sockaddrPtr, /* Socket address */ struct sockaddr_in *sockaddrPtr, /* Socket address */
const char *host, /* Host. NULL implies INADDR_ANY */ const char *host, /* Host. NULL implies INADDR_ANY */
@ -55,202 +46,6 @@ int CocCreateSockAdr(
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
int CocRecv(int fd, Str_Buf *buf)
{
struct timeval tmo={0,1};
fd_set mask;
int i;
tmo.tv_sec=5; /* timeout 5 sec. */
FD_ZERO(&mask);
FD_SET(fd, &mask);
ERR_SI(i=select(fd+1,&mask,NULL,NULL,&tmo));
if (i==0) ERR_MSG("time out");
ERR_SI(buf->wrpos=recv(fd, buf->buf, buf->dsize, 0));
if (buf->wrpos==0) { ERR_COD(ECONNRESET); }
str_get_start(buf);
return(buf->wrpos);
OnError: return(-1);
}
void CocVarList(CocVar **varList) {
assert(varList!=NULL);
varListHdl=varList;
}
void CocList() {
CocVar *p;
p=*varListHdl;
while (p!=NULL) {
printf("%s %d ", p->name, p->type);
p=p->next;
}
printf("\n");
}
CocVar *CocFindVar1(CocVar *varList, const char *name) {
CocVar *p;
p=varList;
while (p!=NULL && 0!=strcasecmp(p->name,name)) p=p->next;
return(p);
}
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=CocFindVar1(*varListHdl, name);
if (p==NULL) {
NEW(p);
p->next=*varListHdl;
*varListHdl=p;
str_copy(p->name, name);
p->type=type;
} else {
assert(p->type==type);
}
p->var=var;
p->flag=flag;
/* printf("define %s %d\n", name, (int)var); */
return(p);
OnError:
assert(0);
}
void CocDefVarS(const char *name, const char *tname, void *var, int type) {
CocVar *p, *t;
assert(type==COC_PTR || type==COC_STRUCT);
p=CocDefVar(name, var, type, &CocRD);
p->strucType=CocDefVar(tname, NULL, COC_TYPE, &CocRD);
}
char err_name[64];
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 (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");
}
/* printf("get %s %d\n", name, (int)adr); */
if (var->type==-1) {
ERR_I(str_get_int(buf, (int *)adr));
} else if (var->type==-2) {
ERR_I(str_get_float(buf, (float *)adr));
} else if (var->type>1) {
ERR_P(str_nget_str(buf, (char *)adr, var->type));
} else {
ERR_MSG("unknown type");
}
if (secure) { /* we are the server */
(*var->flag)++;
}
return(0);
OnError: str_copy(err_name, name); ErrTxt(err_name,0); return(-1);
}
int CocPutVar(CocVar *varList, Str_Buf *buf, const char *name, int secure) {
CocVar *var;
void *adr;
char *c;
var=CocFindVar(varList, name, &adr);
if (var==NULL) ERR_MSG("undefined variable");
if (adr==NULL) {
adr=var->var;
} else {
adr=(char *)adr + (int)var->var;
}
if (secure) { /* check access */
if (var->flag==&CocRD) ERR_MSG("variable is read only");
}
/* printf("put %s %d\n", name, (int)adr); */
if (var->type==-1) {
ERR_I(str_put_int(buf, *(int *)adr));
} else if (var->type==-2) {
ERR_I(str_put_float(buf, *(float *)adr));
} else if (var->type>1) {
ERR_I(str_put_str(buf, adr));
} else {
ERR_MSG("unknown type");
}
if (secure) { /* we are a client */
if (var->flag!=NULL) (*var->flag)++;
}
return(0);
OnError: str_copy(err_name, name); ErrTxt(err_name,0); return(-1);
}
void CocFreeVarList(CocVar **varList) {
CocVar *p, *v;
if (varList==NULL) varList=&serverVarList;
v=*varList;
while (v!=NULL) {
p=v;
v=p->next;
p->next=NULL;
FREE(p);
}
*varList=NULL;
}
void CocDelay(int msec) { void CocDelay(int msec) {
struct timeval tmo; struct timeval tmo;
@ -258,3 +53,59 @@ void CocDelay(int msec) {
tmo.tv_usec=(msec % 1000)*1000+1; tmo.tv_usec=(msec % 1000)*1000+1;
select(1,NULL,NULL,NULL,&tmo); select(1,NULL,NULL,NULL,&tmo);
} }
/*-------------------------------------------------------------------------*/
int CocSend(int fd, char *str, int size) {
int siz;
siz=htonl(size);
ERR_SI(send(fd, &siz, 4, 0));
ERR_SI(send(fd, str, size, 0));
return(0);
OnError: return(-1);
}
/*-------------------------------------------------------------------------*/
int CocRecv(int fd, StrBuf *buf, int timeout, int *flag) {
struct timeval tmo={0,1};
fd_set mask;
int i, l;
int siz, n;
if (timeout>=0) {
tmo.tv_sec=timeout;
FD_ZERO(&mask);
FD_SET(fd, &mask);
ERR_SI(i=select(fd+1,&mask,NULL,NULL,&tmo));
if (flag!=NULL) {
*flag=0;
if (i==0) return(0);
} else {
if (i==0) { ERR_MSG("time out"); }
}
}
n=0;
ERR_SI(i=recv(fd, &n, 4, 0));
if (i!=4) {
ERR_COD(ECONNRESET);
}
siz=ntohl(n);
if (siz > buf->dsize)
ERR_MSG("buffer too small");
ERR_SI(l=recv(fd, buf->buf, siz, 0));
buf->wrpos=l;
while (buf->wrpos<siz) {
if (l==0) {
ERR_COD(ECONNRESET);
}
ERR_SI(l=recv(fd, buf->buf+buf->wrpos, siz, 0));
buf->wrpos+=l;
}
StrReset(buf);
return(buf->wrpos);
OnError: return(-1);
}

View File

@ -2,7 +2,10 @@
#define _COC_UTIL_H_ #define _COC_UTIL_H_
#include <netinet/in.h> #include <netinet/in.h>
#include "str_buf.h" #include "myc_buf.h"
#define COC_CMD_LEN 256
#define COC_RES_LEN 8192
int CocCreateSockAdr( int CocCreateSockAdr(
struct sockaddr_in *sockaddrPtr, /* Socket address */ struct sockaddr_in *sockaddrPtr, /* Socket address */
@ -12,76 +15,34 @@ int CocCreateSockAdr(
compose internet address compose internet address
*/ */
int CocRecv(int fd, Str_Buf *buf);
/*
receive data
*/
typedef struct {
/* private */
void *next;
char name[32];
void *var;
int *flag;
int type;
void *strucType;
} CocVar;
extern int CocRD; /* readonly variable (used as argument for CocDefXXX) */
extern int CocWR; /* read/write variable (used as argument for CocDefXXX) */
CocVar *serverVarList; /* variable list for the server process */
CocVar *CocDefVar(const char *name, void *var, int type, int *flag);
void CocDefVarS(const char *name, const char *tname, void *var, int type);
/*
Define variables. Call this routines not directly, but through
one of the macros below.
*/
void CocVarList(CocVar **varlist);
/*
print a variable list (for debugging purposes)
*/
void CocFreeVarList(CocVar **varList);
/*
free a variable list
*/
CocVar *CocFindVar(CocVar *varList, const char *name, void **adr);
/*
find a variable. returns NULL if not found.
*/
int CocPutVar(CocVar *varList, Str_Buf *buf, const char *name, int secure);
/*
put a variable named <name> of variable list <varList> to the buffer <buf>
if <secure>, access rights are checked
*/
int CocGetVar(CocVar *varList, Str_Buf *buf, const char *name, int secure);
/*
get a variable named <name> of variable list <varList> from the buffer <buf>
if <secure>, access rights are checked
*/
void CocDelay(int msec); void CocDelay(int msec);
/* /*
system independent delay function with msec resolution system independent delay function with msec resolution
*/ */
int CocSend(int fd, char *buf, int size);
/*
send a message
*/
int CocRecv(int fd, StrBuf *buf, int timeout, int *flag);
/*
receive message
if flag is NULL, a timeout generates an error
else *flag is set to zero between the select and the recv command
*/
#define COC_INT -1 #define COC_INT -1
#define COC_FLT -2 #define COC_FLT -2
#define COC_PTR -3 #define COC_PTR -3
#define COC_STRUCT -4
#define COC_TYPE -5
#define COC_ALIAS -6
/* macros to define variables */ #define COC_SEP '\0'
#define CocDefInt(V,F) CocDefVar(#V,&V,COC_INT,&F) #define COC_DELAYED '\1'
#define CocDefFlt(V,F) CocDefVar(#V,&V,COC_FLT,&F) #define COC_ERR '\2'
#define CocDefStr(V,F) CocDefVar(#V,V,sizeof(V),&F) #define COC_TRM '\3'
#define CocDefPtr(V,S) CocDefVarS(#V,#S,&V,COC_PTR*(V!=(S *)NULL)); #define COC_SYN0 '\4'
#define CocDefStruct(V,S) CocDefVarS(#V,#S,&V,COC_STRUCT*(&V!=(S *)NULL)); #define COC_SYN1 '\5'
#define CocIntFld(S,V,F) CocDefVar(#S":"#V,&((S *)NULL)->V,COC_INT,&F); #define COC_MAGIC '\6'
#define CocFltFld(S,V,F) CocDefVar(#S":"#V,&((S *)NULL)->V,COC_FLT,&F); #define COC_CLRLOG '\7'
#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);
#endif /* _COC_UTIL_H_ */ #endif /* _COC_UTIL_H_ */

218
tecs/myc_buf.c Normal file
View File

@ -0,0 +1,218 @@
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include "sys_util.h"
#include "myc_err.h"
#include "myc_str.h"
#include "myc_buf.h"
char *StrNGet(StrBuf *buf, char *result, int reslen, int sep) {
char *b, *f, *e, quote;
int res, l, ll;
if (buf->rdpos < 0 || buf->rdpos >= buf->dsize || buf->buf==NULL)
ERR_MSG("buffer corrupt");
b=buf->buf + buf->rdpos;
if (*b=='"' || *b=='\'') { /* take string within quotes (single or double) */
quote=*b; b++;
f=strchr(b, quote);
if (f==NULL)
ERR_MSG("missing '""'");
l=f-b;
e=strchr(f+1, sep);
if (e==NULL) {
buf->rdpos = f - buf->buf + 1 + strlen(f+1);
buf->seen=0;
} else {
buf->rdpos = e - buf->buf + 1;
buf->seen=1;
}
} else {
f=strchr(b, sep);
if (f==NULL) {
l=strlen(b);
f=b+l;
buf->rdpos+=l;
buf->seen=0;
} else {
l=f-b;
buf->rdpos+=l+1;
buf->seen=1;
}
}
if (result==NULL) {
if (reslen==-1) { /* special case for StrGetBuf */
return(f);
}
*f='\0';
return(b);
} else {
if (l>=reslen) l=reslen-1; /* ERR_MSG("result too short"); */
strncpy(result, b, l);
result[l]='\0';
return(result);
}
OnError:
buf->rdpos=buf->dsize; /* illegal value */
return(NULL);
}
int StrGetBuf(StrBuf *buf, StrBuf *res, int sep) {
char *b, *f;
b = buf->buf + buf->rdpos;
ERR_P(f=StrNGet(buf, NULL, -1, sep));
res->buf = b;
res->wrpos = f-b;
res->rdpos = 0;
res->dsize = f-b;
return(0);
OnError:
buf->rdpos=buf->dsize; /* illegal value */
return(-1);
}
int StrGetInt(StrBuf *buf, int *res, int sep) {
char num[32];
int i, l, p;
p=buf->rdpos;
ERR_P(StrGet(buf, num, sep));
i=sscanf(num, "%d%n", res, &l);
if (i==0)
ERR_MSG("illegal number");
if (sep==StrNONE) {
buf->rdpos=p+l;
}
return(0);
OnError:
buf->rdpos=buf->dsize; /* illegal value */
return(0);
}
int StrGetFloat(StrBuf *buf, float *res, int sep) {
char num[32];
int i, l, p;
p=buf->rdpos;
ERR_P(StrGet(buf, num, sep));
if (num[0]=='N' && num[1]=='a' && num[2]=='N') {
l=3;
*res = MYC_NAN;
} else {
i=sscanf(num, "%f%n", res, &l);
if (i==0) {
ERR_MSG("illegal number");
}
}
if (sep==StrNONE) {
buf->rdpos=p+l;
}
return(0);
OnError:
buf->rdpos=buf->dsize; /* illegal value */
return(-1);
}
int StrGetEnd(StrBuf *buf) {
if (buf->buf!=NULL) {
if (buf->rdpos < 0 || buf->rdpos >= buf->dsize)
ERR_MSG("buffer corrupt");
if (buf->rdpos != buf->wrpos)
ERR_MSG("superflous content in buffer");
}
return(0);
OnError:
return(-1);
}
int StrPut(StrBuf *buf, const char *str, int sep) {
int l, pos;
char quote;
pos=buf->wrpos;
if (pos < 0 || pos >= buf->dsize || buf->buf==NULL)
ERR_MSG("buffer corrupt");
l=strlen(str);
quote='\0';
if (sep>0) {
if (strchr(str, sep)!=NULL) {
if (strchr(str, '"')!=NULL) {
quote='"'; l+=2;
}
if (strchr(str, '\'')!=NULL) {
if (quote!='\0')
ERR_MSG("str must not contain separator and both kind of quotes");
quote='\''; l+=2;
}
}
}
if (pos+l >= buf->dsize)
ERR_MSG("buffer too short");
if (quote!='\0') {
buf->buf[pos]=quote; pos++;
strcpy(buf->buf + pos, str);
buf->buf[pos]=quote; pos++;
} else {
strcpy(buf->buf + pos, str);
}
pos+=l;
if (sep!=StrNONE) {
buf->buf[pos]=sep;
pos++;
} else {
buf->buf[pos]='\0';
}
buf->wrpos=pos;
return(0);
OnError:
buf->wrpos=-1;
return(-1);
}
int StrPutInt(StrBuf *buf, int val, int sep) {
char num[32];
sprintf(num, "%d", val);
ERR_I(StrPut(buf, num, sep));
return(0);
OnError:
return(-1);
}
int StrPutFloat(StrBuf *buf, float val, int sep) {
char num[32];
int l;
if (val == MYC_NAN) {
ERR_I(StrPut(buf, "NaN", sep));
} else {
sprintf(num, "%g", val);
ERR_I(StrPut(buf, num, sep));
}
return(0);
OnError:
return(-1);
}
void StrReset(StrBuf *buf) {
buf->rdpos=0;
}
void StrClear(StrBuf *buf) {
buf->rdpos=0;
buf->wrpos=0;
}
void StrNLink(StrBuf *buf, char *str, int length) {
int l;
buf->buf=str;
buf->rdpos=0;
l=strlen(str);
if (l<length) l=length;
buf->wrpos=l;
buf->dsize=buf->wrpos;
}

58
tecs/myc_buf.h Normal file
View File

@ -0,0 +1,58 @@
#ifndef _STR_BUF_H_
#define _STR_BUF_H_
/*
This module is used to write and read from character strings
It is a simplified, safe replacement for sprintf/sscanf.
DeclStrBuf(buf, size) declares and initializes a buffer of a given size.
Use this macro in the declaration part of a function.
*/
typedef struct { char *buf; int dsize, rdpos, wrpos, seen; } StrBuf;
#define DeclStrBuf(BUF,SIZ) static char STR__##BUF[SIZ]; StrBuf BUF={STR__##BUF,SIZ}
/*------------------------------------------------------------------------
Write content to the buffer, and add separator sep, if sep!=StrNONE
*/
#define StrNONE -1
int StrPut(StrBuf *buf, const char *str, int sep);
int StrPutInt(StrBuf *buf, int val, int sep);
int StrPutFloat(StrBuf *buf, float val, int sep);
/*------------------------------------------------------------------------
Read from the buffer until separator sep.
Use the StrGet macro if the result is a fixed size.
Special case sep=StrNONE:
- StrGet reads until the end of the buffer
- StrGetInt and StrGetFloat read until the end of a legal number
*/
char *StrNGet(StrBuf *buf, char *result, int reslen, int sep);
#define StrGet(BUF,RES,SEP) StrNGet(BUF,RES,sizeof(RES),SEP)
int StrGetInt(StrBuf *buf, int *res, int sep);
int StrGetFloat(StrBuf *buf, float *res, int sep);
#define StrEnd(BUF) ((BUF)->rdpos>=(BUF)->wrpos)
/*------------------------------------------------------------------------
reset the buffer to read from the beginning
*/
void StrReset(StrBuf *buf);
/*------------------------------------------------------------------------
Clear the buffer
*/
void StrClear(StrBuf *buf);
/*------------------------------------------------------------------------
Verify that the end is reached
*/
int StrGetEnd(StrBuf *buf);
/*------------------------------------------------------------------------
Link the buffer to a string. The buffer length is set to
sizeof(STR) or strlen(STR), whichever is greater
*/
#define StrLink(BUF, STR) StrNLink(BUF, STR, sizeof(STR))
void StrNLink(StrBuf *buf, char *str, int size);
#endif /* _STR_BUF_H_ */

144
tecs/myc_err.c Normal file
View File

@ -0,0 +1,144 @@
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include "sys_util.h"
#include "myc_str.h"
#include "myc_err.h"
#define SLEN 64
#define MLEN 64
static char *txt[SLEN];
static int sp=0;
static int stack_empty=1;
int ErrCode;
char *ErrMessage=NULL;
void (*outrtn)()=NULL;
void *outarg;
void ErrTxt(char *text, int systemError)
{
if (systemError) {
sp=0; ErrCode=errno; ErrMessage=strerror(errno);
}
if (stack_empty && sp>0) {
sp=0;
stack_empty=0;
}
if (sp<SLEN) {
txt[sp++]=text;
}
}
void ErrMsg(char *msg)
{
ErrCode=-1;
ErrMessage=msg; sp=0;
}
void ErrCod(int code)
{
ErrCode=code;
ErrMessage=strerror(code); sp=0;
}
void ErrOutFil(void *arg, char *text) {
fprintf((FILE *)arg, "%s\n", text);
}
void ErrShow(char *text)
{
int i, l;
char buf[256];
if (outrtn==NULL) {
outrtn=ErrOutFil;
outarg=stdout;
}
l=strlen(text)+strlen(ErrMessage)+6;
assert(l<256);
sprintf(buf, "--- %s: %s", text, ErrMessage);
for (i=0;i<sp;i++) {
if (txt[i][0]==':') {
l+=strlen(txt[i]);
assert(l<256);
strcat(buf, &(txt[i][1]));
} else {
outrtn(outarg, buf);
l=strlen(txt[i]);
assert(l<256);
strcpy(buf, txt[i]);
}
}
outrtn(outarg, buf);
outrtn(outarg, "");
stack_empty=1;
}
void ErrShort(char *msg) {
if (outrtn==NULL) {
outrtn=ErrOutFil;
outarg=stdout;
}
outrtn(outarg, msg);
}
void ErrSetOutRtn(void (*rtn)(), void *arg) {
outrtn=rtn;
outarg=arg;
}
void ErrSetOutFile(FILE *arg) {
outrtn=ErrOutFil;
outarg=arg;
}
void ERR_EXIT(char *text) {
ErrShow(text); exit(1);
}
/* FORTRAN wrappers */
#ifdef F_CHAR
/* compile only when fortran c interface stuff is defined */
#ifdef __VMS
#define err_show_ err_show
#define err_txt_ err_txt
#define err_msg_ err_msg
#define err_set_outrtn_ err_set_outrtn
#define err_short_ err_short
#endif
void err_show_(F_CHAR(text), int text_len) {
char buf[256];
STR_TO_C(buf, text);
ErrShow(buf);
}
void err_txt_(F_CHAR(text), int text_len) {
char buf[256];
STR_TO_C(buf, text);
ErrTxt(buf,0);
}
void err_msg_(F_CHAR(text), int text_len) {
char buf[256];
STR_TO_C(buf, text);
ErrMsg(buf);
}
void err_set_outrtn_(void (*rtn)(), void *arg) {
ErrSetOutRtn(rtn, arg);
}
void err_short_(void) {
ErrShort(ErrMessage);
}
#endif

85
tecs/myc_err.h Normal file
View File

@ -0,0 +1,85 @@
#ifndef _ERR_HANDLING_H_
#define _ERR_HANDLING_H_
#include <stdio.h>
#include <sys/errno.h>
/* ErrHDL Error handling utilities
-------------------------------
Makes code more readable by hiding annoying error condition checks.
Macros and routines:
Spelling in uppercase indicates, that it the program flow
may be modified (jump to OnError label or program exit).
ERR_x
Usage Error condition Error message taken from
-----------------------------------------------------------------------------------------
ERR_SI(res=routine1(...)) res<0 errno
ERR_SP(ptr=routine2(...)) ptr==NULL errno
ERR_I(res=routine3(...)) res<0 stored by routine3 using errhdl mechanism
ERR_P(ptr=routine4(...)) ptr==NULL stored by routine4 using errhdl mechanism
The result assignment "res=" or "ptr=" is optional.
Description:
The routine routineX is called.
If the result indicates an error, the source text is saved and the
program continues at the OnError label.
The error message and the source code of the calling instructions is
saved for a later call to ErrShow or ErrExit.
ERR_EXIT("program_name")
Show error and exit program.
ERR_MSG("message")
Signals an error condition. If "message" is replaced by a variable,
take care that it is not modified until ErrShow is called.
ERR_COD(cod)
Signals an error condition as code from errno.h
ErrShow("program_name")
Show actual error message with traceback information to stdout
or a file fil
Global Variables (read only)
int ErrCode
actual error message code
= errno for system errors or
= -1 for custom errors signaled by ERRMSG
char *ErrMessage
actual error message
*/
#define ERR_SI(R) { if(0>(R)) { ErrTxt(#R,1); goto OnError; }; }
#define ERR_SP(R) { if(NULL==(R)) { ErrTxt(#R,1); goto OnError; }; }
#define ERR_I(R) { if(0>(R)) { ErrTxt(#R,0); goto OnError; }; }
#define ERR_P(R) { if(NULL==(R)) { ErrTxt(#R,0); goto OnError; }; }
#define ERR_MSG(R) { ErrMsg(R); goto OnError; }
#define ERR_COD(R) { ErrCod(R); goto OnError; }
void ErrTxt(char *text, int systemError);
void ErrMsg(char *msg);
void ErrCod(int code);
void ErrShow(char *text); /* write out error message with stack info */
void ErrShort(char *msg); /* write out short error message */
void ERR_EXIT(char *text);
void ErrSetOutRtn(void (*rtn)(), void *arg);
void ErrSetOutFile(FILE *file);
extern int ErrCode;
extern char *ErrMessage;
#endif /* _ERR_HANDLING_H_ */

30
tecs/myc_mem.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef _MEM_UTIL_H_
#define _MEM_UTIL_H_
#include <stdlib.h>
#include <string.h>
#ifdef FORTIFY
#include "fortify.h"
#endif
/* ------------------------------------------------------------
these macros help for safer dynamic memory
you may change these macros if you want to log dynamic memory access
*/
#define NEW(PTR,TYP) {TYP _0_={0}; ERR_SP(PTR=malloc(sizeof(*PTR))); *PTR=_0_; }
/*
allocates and initializes an object of type TYP and make PTR point to it
TYP must be defined with an appropriate typedef declaration, and
INIT(TYP) must follow the declaration to initialize a dummy initializer
object.
*/
#define NEW_STR(TO,FROM) {ERR_SP(TO=malloc(strlen(FROM)+1)); strcpy(TO,FROM); }
#define MALLOC(SIZE) malloc(SIZE)
#define FREE(PTR) free(PTR)
#endif /* _MEM_UTIL_H_ */

252
tecs/myc_str.c Normal file
View File

@ -0,0 +1,252 @@
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <assert.h>
#include <string.h>
#include <ctype.h>
#include "sys_util.h"
#include "myc_err.h"
#include "myc_str.h"
#include "myc_mem.h"
char *str_splitx(char *str, char sep, char *list[], int *n) {
int i;
char *s, *e;
s=str;
for (i=0; i<*n; i++) {
list[i]=s;
e=strchr(s, sep);
if (e==NULL) { *n=i+1; return(NULL); }
s=e+1;
e--;
while (e>str && *e==' ') e--; /* trim sequence */
e[1]='\0';
}
return(s);
}
char *str_split1(char *str, char sep) {
char *s, *e;
e=strchr(str, sep);
if (e==NULL) {
s=NULL;
e=str+strlen(str);
} else {
s=e+1;
}
e--;
while (e>str && *e==' ') e--; /* trim sequence */
e[1]='\0';
return(s);
}
int str_ntrim(char *dest, const char *src, int ldest, int lsrc) {
int i;
if (lsrc>=ldest) lsrc=ldest-1;
if (dest!=src) strncpy(dest, src, lsrc);
dest[lsrc]='\0';
i=strlen(dest)-1;
while (i>=0 && dest[i]==' ') i--; /* trim sequence */
i++;
dest[i]='\0';
return(i);
}
int str_npad(char *dest, const char *src, int ldest) {
int i, lsrc;
lsrc=strlen(src);
if (lsrc>=ldest) {
if (dest!=src) strncpy(dest, src, ldest);
lsrc=ldest;
} else {
if (dest!=src) strcpy(dest, src);
for (i=lsrc; i<ldest; i++) {
dest[i]=' ';
}
}
return(lsrc);
}
char *str_nsplit(char *dst, const char *src, char sep, int dstlen) {
char *s;
int i;
s=strchr(src, sep);
if (s==NULL) {
s=NULL;
i=strlen(src);
} else {
i=s-src;
s++; /* skip separator */
}
if (i>=dstlen) {
str_copy(dst, src);
} else {
strncpy(dst, src, i);
dst[i]='\0';
}
return(s);
}
char *str_read_until(FILE *fil, char *term, char *buf, char *end) {
char *s;
char fmt[24];
int i, l, siz;
char ch;
siz=end-buf-1;
if (siz<1) return(NULL);
sprintf(fmt, "%s%d[^%s%s", "%", siz, term, "]%n%c");
i=fscanf(fil, fmt, buf, &l, &ch);
if (i<0) { /* eof */
buf[0]='\0';
return(&buf[0]);
} else if (i==0) { /* fscanf returns 0 if first char is terminator */
buf[0]=fgetc(fil);
return(&buf[0]);
} else if (i==1) { /* terminator not found -> read until eof */
buf[l]='\0';
return(&buf[l]);
} else {
buf[l]=ch;
if (l==siz && NULL==strchr(term, ch)) return(NULL);
return(&buf[l]);
}
}
char *str_read_file(char *file) {
FILE *fil;
char *str, *s, *e, *p, *q;
char ch;
int i, l, size;
struct stat statbuf;
i=stat(file, &statbuf);
if (i<0) ERR_MSG("file not found");
size=statbuf.st_size+4;
ERR_SP(str=MALLOC(size));
e=&str[size-1];
ERR_SP(fil=fopen(file, "r"));
s=str;
while (1) {
p=str_read_until(fil, "!", s, e);
if (p==NULL) break;
if (*p=='!') {
q=str_read_until(fil, "\n", p, e);
if (q==NULL) { p=NULL; break; }
s=p; *s='\n'; s++;
} else {
assert(*p=='\0');
break;
}
}
ERR_SI(fclose(fil));
assert(strlen(str)<size);
return(str);
OnError: return(NULL);
}
void str_replace_char(char *str, char ch, char rep) {
char *s;
assert(ch!='\0' && ch!=rep);
s=strchr(str, ch);
while (s!=NULL) {
*s=rep;
s=strchr(s, ch);
}
}
int str_nsubstitute(char *result, char *str, char *old, char *new, int reslen) {
char *s, *p, *r;
int l, ln, lo;
p=str;
r=result;
ln=strlen(new);
lo=strlen(old);
s=strstr(p, old);
reslen--;
if (reslen<0) ERR_MSG("result buffer too short");
while (s!=NULL) {
l=s-p;
if (l>reslen) ERR_MSG("result buffer too short");
strncpy(r, p, l);
r+=l; reslen-=l;
if (ln>reslen) ERR_MSG("result buffer too short");
strncpy(r, new, reslen);
r+=ln; reslen-=ln;
p=s+lo;
s=strstr(p, old);
}
l=strlen(p);
if (l>reslen) ERR_MSG("result buffer too short");
strncpy(r, p, l);
r+=l;
*r='\0';
return(r-result);
OnError:
result[0]='\0';
return(-1);
}
void str_nupcase(char *dst, const char *src, int dstlen) {
dstlen--; /* space for trailing nul */
while (*src!='\0' && dstlen>0) {
*dst=toupper(*src);
dst++; src++;
dstlen--;
}
*dst='\0';
}
void str_nlowcase(char *dst, const char *src, int dstlen) {
dstlen--; /* space for trailing nul */
while (*src!='\0' && dstlen>0) {
*dst=tolower(*src);
dst++; src++;
dstlen--;
}
*dst='\0';
}
int strcasecmp(const char *str1, const char *str2) {
int i;
char ch1, ch2;
ch1=tolower(*(str1++)); ch2=tolower(*(str2++));
i=1;
while (ch1!='\0' && ch2!='\0' && ch1==ch2) {
ch1=tolower(*(str1++)); ch2=tolower(*(str2++)); i++;
}
if (ch1<ch2) {
return(-i);
} else if (ch1>ch2) {
return(i);
}
return(0);
}
int str_ncpy(char *dst, const char *src, int maxdest) {
strncpy(dst, src, maxdest);
if (dst[maxdest-1]!='\0') {
dst[maxdest-1]='\0';
ERR_MSG("destination string too short");
}
return(0);
OnError: return(-1);
}
int str_ncat(char *dst, const char *src, int maxdest) {
strncat(dst, src, maxdest-strlen(dst)-1);
if (dst[maxdest-1]!='\0') {
dst[maxdest-1]='\0';
ERR_MSG("destination string too short");
}
return(0);
OnError: return(-1);
}

122
tecs/myc_str.h Normal file
View File

@ -0,0 +1,122 @@
#ifndef _MYC_STR_H_
#define _MYC_STR_H_
#define MYC_NAN (-1.125/1024./1024./1024.)
/*
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_pad(DST,SRC) str_npad(DST,SRC,sizeof(DST))
#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_lowcase(DST,SRC) str_nlowcase(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).
*/
int str_npad(char *dest, const char *src, int ldest);
/*
copy src to dest and fill with spaces (fortran string format)
*/
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
*/
void str_nlowcase(char *dst, const char *src, int dstlen);
/*
convert *str to lowercase
*/
#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 <strings.h>
#endif /* __VMS_VER<70000000 */
#else
#include <strings.h>
#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 /* _MYC_STR_H_ */

120
tecs/myc_time.c Normal file
View File

@ -0,0 +1,120 @@
#include <assert.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include "sys_util.h"
#include "myc_time.h"
int ftime (struct timeb *__timeptr); /* for some reason not defined in timeb.h with flag -std1 */
static time_t my_base=0;
void initBase(void) {
struct tm tim;
time_t now;
time(&now);
tim = *localtime(&now);
tim.tm_year = MYC_TIME_BASE / 10000 - 1900;
tim.tm_mon = (MYC_TIME_BASE % 10000) / 100 - 1;
tim.tm_mday = MYC_TIME_BASE % 100;
tim.tm_hour = 12;
tim.tm_min = 0;
tim.tm_sec = 0;
/* take daylight saving time flag and gmt offset from today */
my_base=mktime(&tim) - 12*3600;
assert(tim.tm_wday == 1); /* time base must be a monday */
}
int mycNow(void) {
time_t now;
if (my_base == 0) initBase();
time(&now);
return (int)(now-my_base);
}
int mycMsecSince(int since) {
struct timeb now;
int msec;
if (my_base == 0) initBase();
ftime(&now);
msec = (now.time - my_base) % (24*3600) * 1000 + now.millitm - since;
if (msec < 0) msec+=24*3600000;
return msec;
}
int mycDate(int time) {
struct tm tim;
time_t t;
if (my_base == 0) initBase();
t = time + my_base;
tim=*localtime(&t);
return (tim.tm_year + 1900) * 10000 + (tim.tm_mon + 1) * 100 + tim.tm_mday;
}
int mycTime(int date) {
struct tm tim;
time_t t, now;
int y, m, d;
if (my_base == 0) initBase();
time(&now);
tim=*localtime(&now);
tim.tm_hour=0;
tim.tm_min=0;
tim.tm_sec=0;
if (date != 0) {
d = date % 100;
date = date / 100;
m = date % 100;
y = date / 100;
if (y == 0) {
if (m == 0) {
if (d > tim.tm_mday) {
if (tim.tm_mon == 0) { /* jan */
tim.tm_mon=11; /* dec */
tim.tm_year--;
} else {
tim.tm_mon--; /* last month */
}
}
} else {
tim.tm_mon = m - 1;
}
} else {
tim.tm_year = y - 1900;
if (m == 0) {
if (d == 0) {
tim.tm_mon = 0;
}
} else {
tim.tm_mon = m - 1;
}
}
if (d == 0) d = 1;
tim.tm_mday = d;
}
return (int)(mktime(&tim)-my_base);
}
/* fortran routines --------------------------------------------------
*/
#ifdef F_CHAR
/* compile only when fortran c interface stuff is defined */
#ifdef __VMS
#define myc_date_ myc_date
#define myc_time_ myc_time
#define myc_now_ myc_now
#endif
int myc_now_(void) { return mycNow(); }
int myc_date_(int *time) { return mycDate(*time); }
int myc_time_(int *date) { return mycTime(*date); }
#endif

42
tecs/myc_time.h Normal file
View File

@ -0,0 +1,42 @@
#ifndef _MYC_TIME_H_
#define _MYC_TIME_H_
#define MYC_TIME_BASE 20010101
int mycNow(void);
/*
return seconds since a Monday specified by MYC_TIME_BASE
mycNow() % (24*3600) is always 0 at 00:00 even in daylight saving time
*/
int mycMsecSince(int since);
/*
mycMsecSince(0) return milliseconds since midnight
mycMsecSince(x) return milliseconds since x (x is time since midnight)
*/
int mycDate(int time);
/*
return year * 10000 + month * 100 + day_of_month of a time obtained by mycNow
year > 1900
1 <= month <= 12
1 <= day_of_month <= 31
*/
int mycTime(int date);
/*
does the inverse of MycDate. Chooses the last possible date not later than today
*/
/* the following subroutines are to be called from FORTRAN
integer function myc_now()
real function myc_date(time)
integer function myc_time(date)
integer time
real date
*/
#endif /* _MYC_TIME_H_ */

131
tecs/str.f Normal file
View File

@ -0,0 +1,131 @@
!! string handling
!!
subroutine STR_TRIM(RETSTR, STR, RETLEN) !!
!!
!! if RETSTR=STR then RETSTR is not touched
!!
!! Arguments:
character*(*) STR, RETSTR !! in,out
integer RETLEN !! out
integer i
i=len(str)
if (str(1:1) .gt. ' ') then
10 if (str(i:i) .le. ' ') then
i=i-1
goto 10
endif
else
20 if (str(i:i) .le. ' ') then
if (i .gt. 1) then
i=i-1
goto 20
endif
endif
endif
retlen=min(len(retstr),i)
if (retstr .ne. str) then ! avoid copy to retstr if equal
retstr=str(1:i)
endif
end
!!
subroutine STR_UPCASE(RETSTR, STR) !!
!!
!! Arguments:
character STR*(*), RETSTR*(*) !! in,out
integer i, ch
retstr=str
do i=1,len(retstr)
ch=ichar(retstr(i:i))
if (ch .ge. ichar('a') .and. ch .le. ichar('z')) then
retstr(i:i)=char(ch-(ichar('a')-ichar('A')))
endif
enddo
end
!!
subroutine STR_LOWCASE(RETSTR, STR) !!
!!
!! Arguments:
character STR*(*), RETSTR*(*) !! in,out
integer i, ch
retstr=str
do i=1,len(retstr)
ch=ichar(retstr(i:i))
if (ch .ge. ichar('A') .and. ch .le. ichar('Z')) then
retstr(i:i)=char(ch+(ichar('a')-ichar('A')))
endif
enddo
end
!!
subroutine STR_APPEND(str, length, add) !!
!!
implicit none
character*(*) str, add !!
integer length !!
if (len(add)+length .gt. len(str)) then
if (length .lt. len(str)) then
str(length+1:)=add
length=len(str)
endif
else
str(length+1:length+len(add))=add
length=length+len(add)
endif
end
!!
integer function STR_CMP(str1, str2) !!
!!
!! if strings are equal: return 0
!! else return position of first different character
character str1*(*), str2*(*) !!
integer i
do i=0,min(len(str1),len(str2))-1
if (str1(i+1:i+1) .ne. str2(i+1:i+1)) then
str_cmp=i+1
return
endif
enddo
do i=len(str1),len(str2)-1
if (str2(i+1:i+1) .ne. ' ') then
str_cmp=i+1
return
endif
enddo
do i=len(str2),len(str1)-1
if (str1(i+1:i+1) .ne. ' ') then
str_cmp=i+1
return
endif
enddo
str_cmp=0
return
end
!!
subroutine STR_FIRST_NONBLANK(STR, POS) !!
!!
!! Arguments:
character*(*) STR !! in
integer POS !! out
integer i
do i=1,len(str)
if (str(i:i) .gt. ' ') then
pos=i
return
endif
enddo
pos=0
end

View File

@ -292,7 +292,7 @@
integer L !! integer L !!
integer i integer i
integer lnblnk integer lnblnk, iargc
l=0 l=0
str=' ' str=' '

View File

@ -1,5 +1,5 @@
#include <termios.h> #include <termios.h>
#include <time.h> #include <sys/time.h>
#include <assert.h> #include <assert.h>
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
@ -18,16 +18,13 @@ int usleep(time_t delay);
void sys_rd_line_(char *cmd, int *retlen, char *prompt, int clen, int plen) void sys_rd_line_(char *cmd, int *retlen, char *prompt, int clen, int plen)
{ {
char *line_read, *p; char *line_read, p[64];
int l;
assert(plen < sizeof(p));
l = lnblnk_(prompt, clen); strncpy(p,prompt,plen); p[plen] = '\0';
p = malloc((unsigned) l+2); if( p == NULL ) return;
strncpy(p+1,prompt,l); p[0]='\n'; p[l] = '\0';
if (last_line == NULL) { last_line =malloc(1); last_line[0] = '\0';}; if (last_line == NULL) { last_line =malloc(1); last_line[0] = '\0';};
line_read = readline(p); line_read = readline(p);
free(p);
if (line_read) if (line_read)
{ {
@ -156,10 +153,10 @@ int ilen1, ilen2;
return(rc); return(rc);
} }
struct termios atts;
void sys_rd_tmo_(char *prompt, char *result, int *reslen, int p_len, int r_len) void sys_rd_tmo_(char *prompt, char *result, int *reslen, int p_len, int r_len)
{ {
struct termios atts;
struct termios attr; struct termios attr;
int ires, i, ntmo, chr; int ires, i, ntmo, chr;

View File

@ -1,5 +1,6 @@
#include <signal.h>
#include <stdlib.h> #include <stdlib.h>
#include "str_util.h" #include "myc_str.h"
#include "sys_util.h" #include "sys_util.h"
#if __VMS #if __VMS
@ -16,10 +17,17 @@ int sys_gmt_off() {
return(0); return(0);
} }
void sys_ctrl_init(void) {
static int init=1;
if (init) {
init=0;
DECC$CRTL_INIT();
}
}
#else #else
#include <unistd.h> #include <unistd.h>
#include <sys/time.h>
int sys_remove_file_(F_CHAR(file), int file_len) { int sys_remove_file_(F_CHAR(file), int file_len) {
char buf[128]; char buf[128];
@ -27,12 +35,4 @@ int sys_remove_file_(F_CHAR(file), int file_len) {
return(unlink(buf)); return(unlink(buf));
} }
int sys_gmt_off_() {
struct tm *timp;
time_t tim;
time(&tim);
timp=localtime(&tim);
return(timp->tm_gmtoff);
}
#endif #endif

View File

@ -1,33 +1,35 @@
#ifndef _SYS_UTIL_H_ #ifndef _SYS_UTIL_H_
#define _SYS_UTIL_H_ #define _SYS_UTIL_H_
#ifdef FORTIFY /*
#include "fortify.h"
#endif
/* secure allocation stuff ---------------------------------- fortran interface stuff
change these macros if you want to log dynamic memory access
*/
#define NEW(PTR) ERR_SP(PTR=calloc(1,sizeof(*PTR))) declare fortran character arguments as F_CHAR(arg)
#define MALLOC(SIZ) calloc(1,SIZ) and at at the end for each character argument <arg> add
#define FREE(PTR) free(PTR) int <arg>_len to the argument list
/* fortran interface stuff ---------------------------------- Use macros STR_TO_C and STR_TO_F to convert from Fortran character strings
to C character arrays and vice versa.
declare fortran character arguments as CHAR(arg) sys_adr_len (argument of accept and gethostbyadr, system dependent)
and at at the end for each character argument <arg> add
int <arg>_len to the argument list sys_ctrl_init() (needed in VMS only)
*/ */
#if defined __VMS #if defined __VMS
typedef struct { short size, dummy; char *text; } SysVmsChar;
#define F_CHAR(VAR) SysVmsChar *VAR##_desc #define F_CHAR(VAR) SysVmsChar *VAR##_desc
#define STR_TO_C(DST,SRC) str_ntrim(DST, SRC##_desc->text, sizeof(DST), SRC##_len=SRC##_desc->size) #define STR_TO_C(DST,SRC) str_ntrim(DST, SRC##_desc->text, sizeof(DST), SRC##_len=SRC##_desc->size)
#define STR_TO_F(DST,SRC) str_npad(DST##_desc->text, SRC, DST##_len=DST##_desc->size) #define STR_TO_F(DST,SRC) str_npad(DST##_desc->text, SRC, DST##_len=DST##_desc->size)
typedef struct { short size, dummy; char *text; } SysVmsChar; typedef size_t sys_adr_len; /* argument of accept and gethostbyadr */
void sys_ctrl_init(void);
#elif defined __alpha #elif defined __alpha
@ -35,9 +37,13 @@ typedef struct { short size, dummy; char *text; } SysVmsChar;
#define STR_TO_C(DST,SRC) str_ntrim(DST, SRC, sizeof(DST), SRC##_len) #define STR_TO_C(DST,SRC) str_ntrim(DST, SRC, sizeof(DST), SRC##_len)
#define STR_TO_F(DST,SRC) str_npad(DST, SRC, DST##_len) #define STR_TO_F(DST,SRC) str_npad(DST, SRC, DST##_len)
typedef int sys_adr_len; /* argument of accept and gethostbyadr */
#define sys_ctrl_init(DUMMY)
#else #else
/* other machines are not yet supported */ /* other machines are not supported */
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -1,98 +1,65 @@
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "myc_mem.h"
#include "myc_err.h"
#include "myc_str.h"
#include "myc_time.h"
#include "sys_util.h" #include "sys_util.h"
#include "err_handling.h" #include "coc_util.h"
#include "str_util.h"
#include "tecs_cli.h" #include "tecs_cli.h"
#include "tecs_data.h"
static char device[80], command[80]; static char response[COC_RES_LEN];
static int readTemp, configuring;
static float tempX, tempP, tempC;
pTecsClient TeccInit(char *startcmd, int port) { pTecsClient TeccInit(char *startcmd, int port) {
CocConn *conn; CocConn *conn;
static char *rwCode="rwacs";
static char *rdCode="rdacs";
NEW(conn); NEW(conn, CocConn);
if (startcmd[0]=='#') { if (startcmd[0]=='#') {
ERR_I(CocInitClient(conn, startcmd+1, port, "#rwacs", 0, "")); ERR_I(CocInitClient(conn, startcmd+1, port, rdCode, 0, ""));
} else { } else {
ERR_I(CocInitClient(conn, "", port, "#rwacs", 0, startcmd)); ERR_I(CocInitClient(conn, "", port, rwCode, 0, startcmd));
} }
CocDefFlt(tempC, CocRD);
CocDefFlt(tempP, CocRD);
CocDefFlt(tempX, CocRD);
CocDefStr(device, CocWR);
CocDefInt(configuring, CocRD);
CocDefInt(readTemp, CocWR);
CocDefCmd(command);
return((pTecsClient)conn); return((pTecsClient)conn);
OnError: return(NULL); OnError: return(NULL);
} }
int TeccGet3(pTecsClient conn, float *tC, float *tX, float *tP) { int TeccGet3(pTecsClient conn, float *tC, float *tX, float *tP) {
readTemp=1; int iret;
ERR_I(CocCmd(conn, "tempC,tempX,tempP,[readTemp],configuring"));
*tC=tempC; CocReset(conn);
*tX=tempX; ERR_I(CocGetFloat(conn, "set", tC));
*tP=tempP; ERR_I(CocGetFloat(conn, "tempX", tX));
return(configuring); ERR_I(CocGetFloat(conn, "tempP", tP));
ERR_I(CocPutInt(conn, "readTemp", 1));
ERR_I(iret=CocDoIt(conn, response, sizeof(response)));
if (iret) ERR_MSG(response);
return(0);
OnError: return(-1); OnError: return(-1);
} }
int TeccGet(pTecsClient conn, float *temp) { int TeccGet(pTecsClient conn, float *temp) {
readTemp=1; int iret;
ERR_I(CocCmd(conn, "tempP,[readTemp],configuring"));
*temp=tempP;
return(configuring);
OnError: return(-1);
}
int TeccWait(pTecsClient conn) { CocReset(conn);
int last, cnt; ERR_I(CocGetFloat(conn, "tempP", temp));
ERR_I(CocPutInt(conn, "readTemp", 1));
last=0; ERR_I(iret=CocDoIt(conn, response, sizeof(response)));
cnt=0; if (iret) ERR_MSG(response);
do {
CocDelay(250);
ERR_I(CocCmd(conn, "configuring"));
if (configuring==last || configuring>1000) {
cnt++;
if (cnt>20) ERR_MSG("configuring timeout");
} else {
cnt=0;
last=configuring;
}
} while (configuring>0);
return(0); return(0);
OnError: return(-1); OnError: return(-1);
} }
int TeccSet(pTecsClient conn, float temp) { int TeccSet(pTecsClient conn, float temp) {
tempC=temp; int iret;
ERR_I(CocCmd(conn, "[tempC]"));
return(0);
OnError: return(-1);
}
int TeccSend(pTecsClient conn, char *cmd, char *reply, int replyLen) { CocReset(conn);
char *res; ERR_I(CocPutFloat(conn, "set", temp));
int cnt; ERR_I(iret=CocDoIt(conn, response, sizeof(response)));
if (iret) ERR_MSG(response);
str_copy(command, cmd);
ERR_I(CocCmd(conn, "[$]"));
cnt=40;
CocDelay(100);
while (cnt>0) {
ERR_I(CocCmd(conn, "$"));
if (command[0]!='\0') {
str_ncpy(reply, command, replyLen);
return(0);
}
CocDelay(250);
cnt--;
}
str_ncpy(reply, "<no response>", replyLen);
return(0); return(0);
OnError: return(-1); OnError: return(-1);
} }
@ -102,7 +69,9 @@ int TeccQuitServer(pTecsClient conn) {
ERR_I(iret=CocCheck(conn)); ERR_I(iret=CocCheck(conn));
if (iret==0) { if (iret==0) {
ERR_I(CocSet(conn, "quit", "1")); CocReset(conn);
ERR_I(CocPutInt(conn, "quit", 1));
ERR_I(CocDoIt(conn, response, sizeof(response)));
cnt=50; cnt=50;
while (iret==0 && cnt>0) { while (iret==0 && cnt>0) {
CocDelay(100); CocDelay(100);
@ -110,12 +79,15 @@ int TeccQuitServer(pTecsClient conn) {
cnt--; cnt--;
} }
} }
if (iret==1) return(0);
ERR_MSG("Does not quit within 5 seconds"); ERR_MSG("Does not quit within 5 seconds");
OnError: OnError:
return(-1); return(-1);
} }
int TeccSend(pTecsClient conn, char *cmd, char *reply, int replyLen) {
return(CocSetGetN(conn, "send", cmd, reply, replyLen));
}
void TeccClose(pTecsClient conn) { void TeccClose(pTecsClient conn) {
if (conn!=NULL) { if (conn!=NULL) {
CocCloseClient(conn); CocCloseClient(conn);
@ -136,48 +108,86 @@ void TeccClose(pTecsClient conn) {
#ifdef __VMS #ifdef __VMS
#define tecs_get_par_ tecs_get_par #define tecs_get_par_ tecs_get_par
#define tecs_get_mult_ tecs_get_mult
#define tecs_set_par_ tecs_set_par #define tecs_set_par_ tecs_set_par
#define tecs_send_ tecs_send
#define tecs_init_ tecs_init #define tecs_init_ tecs_init
#define tecs_get3_ tecs_get3 #define tecs_get3_ tecs_get3
#define tecs_get_ tecs_get
#define tecs_set_ tecs_set #define tecs_set_ tecs_set
#define tecs_wait_ tecs_wait
#define tecs_is_open_ tecs_is_open #define tecs_is_open_ tecs_is_open
#define tecs_close_ tecs_close #define tecs_close_ tecs_close
#define tecs_quit_server_ tecs_quit_server #define tecs_quit_server_ tecs_quit_server
#define tecs_watch_log_ tecs_watch_log
#define tecs_get_data_ tecs_get_data
#define tecs_date_ tecs_date
#define tecs_time_ tecs_time
#endif #endif
static pTecsClient conn=NULL; static pTecsClient conn=NULL;
int tecs_set_par_(F_CHAR(name), F_CHAR(par), int name_len, int par_len) { int tecs_set_par_(F_CHAR(name), F_CHAR(par), int *show, int name_len, int par_len) {
char nbuf[64], pbuf[256]; char nbuf[64], pbuf[COC_CMD_LEN];
int iret=-1; int iret=-1;
STR_TO_C(nbuf, name); STR_TO_C(nbuf, name);
STR_TO_C(pbuf, par); STR_TO_C(pbuf, par);
ERR_I(iret=CocSet(conn, nbuf, pbuf)); CocReset(conn);
ERR_I(CocPutStr(conn, nbuf, pbuf));
ERR_I(CocDoIt(conn, response, sizeof(response)));
if (*show) {
printf("%s", response);
}
return(0); return(0);
OnError: return(iret); OnError: return(-1);
} }
int tecs_get_par_(F_CHAR(name), F_CHAR(par), int name_len, int par_len) { int tecs_get_par_(F_CHAR(name), F_CHAR(par), int *show, int name_len, int par_len) {
char nbuf[64], pbuf[256]; char *b, nbuf[64], pbuf[COC_RES_LEN];
int iret=-1; int iret=-1;
STR_TO_C(nbuf, name); STR_TO_C(nbuf, name);
ERR_I(iret=CocGet(conn, nbuf, pbuf)); CocReset(conn);
ERR_I(CocGetStr(conn, nbuf, pbuf, sizeof(pbuf)));
ERR_I(CocDoIt(conn, response, sizeof(response)));
if (*show==2) {
b=response;
} else {
b=strchr(response,'=');
if (b==NULL) {
b=response;
} else {
b++;
}
}
if (*show) {
printf("%s", b);
}
return(STR_TO_F(par, pbuf)); return(STR_TO_F(par, pbuf));
OnError: return(iret); OnError: return(-1);
} }
int tecs_send_(F_CHAR(cmd), F_CHAR(reply), int cmd_len, int reply_len) { int tecs_get_mult_(F_CHAR(names), int *time, int *nvalues, float values[], int names_len) {
char cbuf[80], rbuf[80]; char *b, nbuf[64], pbuf[COC_RES_LEN];
char *nams, nam[32];
int i;
STR_TO_C(cbuf, cmd); STR_TO_C(nbuf, names);
ERR_I(TeccSend(conn, cbuf, rbuf, sizeof(rbuf))); CocReset(conn);
return(STR_TO_F(reply, rbuf));
ERR_I(CocGetInt(conn, "rdTim", time));
i=0;
nams=nbuf;
while (nams!=NULL && i < *nvalues) {
nams=str_split(nam, nams, ' ');
if (nam[0]!='\0') {
ERR_I(CocGetFloat(conn, nam, values+i));
i++;
}
}
ERR_I(CocDoIt(conn, response, sizeof(response)));
return(0);
OnError: return(-1); OnError: return(-1);
} }
@ -191,19 +201,21 @@ int tecs_init_(F_CHAR(startcmd), int *port, int startcmd_len) {
} }
int tecs_get_(float *temp) { int tecs_get_(float *temp) {
return(TeccGet(conn, temp)); ERR_I(TeccGet(conn, temp));
return(0);
OnError: return(-1);
} }
int tecs_get3_(float *t1, float *t2, float *t3) { int tecs_get3_(float *t1, float *t2, float *t3) {
return(TeccGet3(conn, t1, t2, t3)); ERR_I(TeccGet3(conn, t1, t2, t3));
return(0);
OnError: return(-1);
} }
int tecs_set_(float *temp) { int tecs_set_(float *temp) {
return(TeccSet(conn, *temp)); ERR_I(TeccSet(conn, *temp));
} return(0);
OnError: return(-1);
int tecs_wait_(void) {
return(TeccWait(conn));
} }
int tecs_is_open_() { int tecs_is_open_() {
@ -216,7 +228,141 @@ void tecs_close_(void) {
} }
int tecs_quit_server_(void) { int tecs_quit_server_(void) {
return(TeccQuitServer(conn)); ERR_I(TeccQuitServer(conn));
return(0);
OnError: return(-1);
} }
int tecs_watch_log_(F_CHAR(list), int list_len) {
char buf[16];
STR_TO_C(buf, list);
ERR_I(CocWatchLog(conn, buf));
return(0);
OnError: return(-1);
}
static char *encode=DATA_CODE;
int DataDecode(float *data, int dataSize, char *coded, int *retSize) {
int i, p, gap, dig1, dig2;
float minD, range;
char ch, *q;
static int decode[256];
static int init=1;
if (coded[0] == '\0') {
*retSize=0;
return 0;
}
if (init) {
init=0;
for (i=0; i<256; i++) {
decode[i]=-1;
}
i=0;
while (encode[i]!=0) {
decode[encode[i]]=i;
i++;
}
}
p=0;
ERR_SI(sscanf(coded, "%d %e %e %n", retSize, &minD, &range, &p)-3);
if (*retSize < dataSize) dataSize = *retSize;
i=0;
while (i < dataSize) {
ch=coded[p++];
dig1=decode[ch];
if (dig1 < 0) { /* code is no 64-digit */
if (ch=='\0' || ch==',') break;
if (ch=='/') { data[i++] = DATA_UNDEF; }
} else {
ch=coded[p++];
dig2=decode[ch];
while (dig2<0) {
if (ch=='\0' || ch==',') break;
ch=coded[p++];
dig2=decode[ch];
}
if (ch=='\0' || ch==',') break;
data[i++] = (dig1 + dig2 * 64) / 4095.0 * range + minD;
}
}
while (i < dataSize) {
data[i++] = DATA_UNDEF;
}
if (ch=='\0') {
return p-1;
} else if (ch!=',') {
q=strchr(coded+p, ',');
if (q==NULL) return strlen(coded);
return q-coded+1;
}
return p;
OnError:
*retSize=0;
return -1;
}
int tecs_get_data_(F_CHAR(names), int *startTime, int *endTime, int *step, float data[], int *maxLen, int *width
, int retLen[], int names_len) {
char nam[64];
char str[128];
char res[COC_RES_LEN];
char *cod;
int i, l, iret, retSize;
if (*endTime - *startTime > *step * (*maxLen-1)) {
printf("maxLen too small\n");
}
STR_TO_C(nam, names);
if (*step <= 0) {
*step = 60;
}
sprintf(str, "%d %d %d %s", *startTime, *endTime, *step, nam);
CocReset(conn);
ERR_I(CocPutStr(conn, "pltdata", str));
ERR_I(CocGetStr(conn, "pltdata", res, sizeof(res)));
ERR_I(iret=CocDoIt(conn, response, sizeof(response)));
if (iret) ERR_MSG(response);
cod=res;
for (i=0; i < *width; i++) {
ERR_I(l=DataDecode(data + i * *maxLen, *maxLen, cod, retLen+i));
cod+=l;
}
return 0;
OnError:
return -1;
}
/*
float tecs_date_(time_t *time) {
struct tm tim;
tim=*localtime(time);
return(tim.tm_mday+(tim.tm_mon+1)*0.01);
}
time_t tecs_time_(float *date) {
struct tm tim;
time_t t, now;
int m;
time(&now);
tim=*localtime(&now);
tim.tm_hour=0;
tim.tm_min=0;
tim.tm_sec=0;
tim.tm_mday=(int)*date;
m=(int)(*date*100+0.1) % 100;
if (m > 0) tim.tm_mon=m-1;
t=mktime(&tim);
if (t > now) {
tim.tm_year--;
t=mktime(&tim);
}
return t;
}
*/
#endif #endif

View File

@ -20,9 +20,6 @@ int TeccGet(pTecsClient conn, float *temp);
int TeccSet(pTecsClient conn, float temp); int TeccSet(pTecsClient conn, float temp);
/* set temperature */ /* set temperature */
int TeccWait(pTecsClient conn);
/* wait until the controller is configured */
int TeccSend(pTecsClient conn, char *cmd, char *reply, int replyLen); int TeccSend(pTecsClient conn, char *cmd, char *reply, int replyLen);
/* send a command transparently to the controller /* send a command transparently to the controller
replyLen is the maximal length of reply */ replyLen is the maximal length of reply */

View File

@ -1,26 +1,33 @@
program tecs_client program tecs_client
real*4 temp(4) real temp
character device*32, init*80, line*80, cmd*16, par*80, response*80 character device*32, init*80, line*80, cmd*16, par*80, response*1024
integer i,j,k,iret,l integer i,j,k,iret,l
character file*128, cmdpar*128 character cmdpar*128
character prompt*32/'tecs>'/
integer promptlen/6/
logical oneCommand logical oneCommand
character logarg*4/'25'/
character defcmd*8/'status'/
! functions ! functions
integer tecs_get_par, tecs_quit_server, tecs_send, tecs_set_par integer tecs_get_par, tecs_quit_server, tecs_set_par, tecs_watch_log
integer tecs_get, show_log
call sys_getenv('TECS_INIT', init) call sys_getenv('TECS_INIT', init)
call sys_get_cmdpar(line, l) call sys_get_cmdpar(line, l)
if (l .ne. 0) then if (l .ne. 0) then
if (line .eq. 'off' .or. line .eq. 'OFF') init=' '
oneCommand=.true. oneCommand=.true.
else else
oneCommand=.false. oneCommand=.false.
endif endif
if (init .eq. ' ') then if (oneCommand .and. line(1:1) .eq. '#') then
call tecs_open(0, ' ', iret) call tecs_open(0, line, iret)
oneCommand=.false.
else if (init .eq. ' ') then
call tecs_open(0, line, iret)
else else
call tecs_open(1, init, iret) call tecs_open(1, init, iret)
endif endif
@ -38,7 +45,8 @@
print *,'device <device> set cryo device' print *,'device <device> set cryo device'
print *,'<parameter> show parameter' print *,'<parameter> show parameter'
print *,'<parameter> <value> set parameter' print *,'<parameter> <value> set parameter'
print *,'plot temperature and power chart' print *,'plot <var> chart for temperature and <var>'
1 ,' var = P (default), He, Aux'
print *,'log <n> show last n lines of logfile' print *,'log <n> show last n lines of logfile'
print *,'kill close TecsServer and exit' print *,'kill close TecsServer and exit'
print *,'exit,quit exit, but do not close TecsServer' print *,'exit,quit exit, but do not close TecsServer'
@ -47,7 +55,7 @@
l=0 l=0
1 if (oneCommand) goto 99 1 if (oneCommand) goto 99
call sys_rd_line(line, l, 'tecs> ') call sys_rd_line(line, l, prompt(1:promptlen))
if (l .lt. 0) goto 99 if (l .lt. 0) goto 99
11 l=l+1 11 l=l+1
line(l:l)=' ' line(l:l)=' '
@ -61,44 +69,54 @@
cmd(k:k)=char(ichar(cmd(k:k))+32) cmd(k:k)=char(ichar(cmd(k:k))+32)
endif endif
elseif (k .gt. 0) then ! end of command elseif (k .gt. 0) then ! end of command
goto 2 par=' '
do i=j,l
if (line(i:i) .gt. ' ') then
par=line(i:l)
goto 3 ! command with parameter
endif
enddo
goto 2 ! parameterless command
endif endif
enddo enddo
if (k .eq. 0) then ! empty line if (k .ne. 0) then
call tecs_get_t(6, temp, iret) print *,'command too long'
if (iret .ne. 0) goto 1
iret=tecs_get_par('device', device)
if (iret .lt. 0) goto 19
print '(x,3(a,f8.3),2a)','tempX=', temp(3),', tempP=',temp(2)
1 ,', set=',temp(1), ', device=',device
goto 1 goto 1
endif endif
print *,'command too long' ! empty command
goto 1
2 par=' '
do i=j,l
if (line(i:i) .gt. ' ') then
par=line(i:l)
goto 3
endif
enddo
! simple query 12 cmd=defcmd
if (cmd .eq. 'kill' .or. cmd .eq. 'off') then 2 continue ! parameterless command
defcmd='status'
if (cmd(1:1) .eq. '#') then
call tecs_close
call tecs_open(0, cmd, iret)
if (iret .lt. 0) goto 91
prompt='tecs/'//cmd(2:)
promptlen=1
do i=1,len(prompt)-2
if (prompt(i:i) .ne. ' ') promptlen=i
enddo
promptlen=promptlen+1
prompt(promptlen:promptlen)='>'
promptlen=promptlen+1
else if (cmd .eq. 'kill') then
iret=tecs_quit_server() iret=tecs_quit_server()
elseif (cmd .eq. 'exit' .or. cmd .eq. 'quit') then elseif (cmd .eq. 'exit' .or. cmd .eq. 'quit') then
goto 99 goto 99
elseif (cmd .eq. 'on') then elseif (cmd .eq. 'status') then
iret=tecs_get_par('status', response, 1)
if (iret .lt. 0) goto 19
elseif (cmd .eq. 'on' .or. cmd .eq. 'off') then
l=0 l=0
goto 11 goto 11
elseif (cmd .eq. 'plot') then elseif (cmd .eq. 'plot') then
iret=tecs_get_par('dlogfile', file) call tecs_plot('Tm Ts Tr P', 1)
if (iret .lt. 0) goto 19
call tecs_plot(file)
elseif (cmd .eq. 'help') then elseif (cmd .eq. 'help') then
print * print *
print *,'Writeable parameters:' print *,'Writeable parameters:'
@ -116,9 +134,9 @@
print * print *
print *,'Read only parameters:' print *,'Read only parameters:'
print * print *
print *,'tX heat exchanger temperature' print *,'Tm main temperature'
print *,'tS sample temperature' print *,'Ts sample temperature'
print *,'tempH set-point on regulation' print *,'setH set-point on regulation'
print *,'tLimit temperature limit' print *,'tLimit temperature limit'
print *,'htr heater current percentage' print *,'htr heater current percentage'
print *,'resist heater resistance' print *,'resist heater resistance'
@ -126,10 +144,7 @@
print *,'remoteMode 1: local, 2: remote ' print *,'remoteMode 1: local, 2: remote '
1 ,'(switch on with device command)' 1 ,'(switch on with device command)'
print * print *
print *,'t1 regulation temperature (hi-T sensor)' print *,'Ta,Tb,Tc,Td values of channels A,B,C,D'
print *,'t2 regulation temperature (low-T sensor)'
print *,'t3 sample temperature (hi-T sensor)'
print *,'t4 sample temperature (low-T sensor)'
print * print *
print *,'Temperature devices:' print *,'Temperature devices:'
print * print *
@ -139,33 +154,43 @@
print *,'ccr4k (4K closed cycle), hef4c (TriCS 4circle cryo)' print *,'ccr4k (4K closed cycle), hef4c (TriCS 4circle cryo)'
print *,'sup4t (supra.magnet 4T)' print *,'sup4t (supra.magnet 4T)'
print *,'rdr11, rdr12 (LTF dilution 1 & 2, 20kOhm)' print *,'rdr11, rdr12 (LTF dilution 1 & 2, 20kOhm)'
1 ,', rdrn11_2, rdr12_2 (2kOhm)'
print * print *
elseif (cmd .eq. 'log') then elseif (cmd .eq. 'log') then
iret=tecs_get_par('logfile', file) if (line(1:l) .eq. ' ') then
print '(x,a)'
1 ,char(27)//'[A'//char(13)//char(27)//'[K'//char(27)//'[2A'
endif
if (show_log(logarg) .le. 0) then
logarg='25'
print *,'-------- end of logfile --------'
goto 12
endif
defcmd='log'
logarg=' '
elseif (cmd .eq. 'watch') then
iret=tecs_watch_log('M')
if (iret .lt. 0) goto 19 if (iret .lt. 0) goto 19
call show_log(50, file)
else else
iret=tecs_get_par(cmd, response) iret=tecs_get_par(cmd, response, 2)
if (iret .lt. 0) goto 19 if (iret .lt. 0) goto 19
print '(7x,3a)',cmd(1:k),'=',response
endif endif
goto 1 goto 1
3 if (cmd .eq. 'send') then 3 continue ! command with parameter
iret=tecs_send(par, response)
if (cmd .eq. 'log') then
if (show_log(par) .gt. 0) then
defcmd='log'
endif
logarg=' '
elseif (cmd .eq. 'plot') then
call tecs_plot('Tm Ts Tr '//par, 1)
elseif (cmd .eq. 'watch') then
iret=tecs_watch_log(par)
if (iret .lt. 0) goto 19 if (iret .lt. 0) goto 19
print '(7x,2a)','response: ',response
elseif (cmd .eq. 'log') then
i=50
read(par, *, err=31) i
31 iret=tecs_get_par('logfile', file)
if (iret .lt. 0) goto 19
call show_log(i, file)
else else
iret=tecs_set_par(cmd, par) iret=tecs_set_par(cmd, par, 2)
if (iret .lt. 0) goto 19 if (iret .lt. 0) goto 19
print '(7x,3a)',cmd(1:k),':=',par
endif endif
goto 1 goto 1
@ -182,27 +207,21 @@
99 end 99 end
subroutine show_log(lines, file) integer function show_log(lines)
integer lines character*(*) lines
integer i,l integer i,l
character str*132, file*(*) character str*8192
print * ! functions
print * integer tecs_get_par, tecs_set_par
open(1, name=file, status='old', readonly, shared, err=39)
i=0 if (lines .ne. ' ') then
31 read(1,'(a)',end=32) l=tecs_set_par('logstart', lines, 0)
i=i+1 print *,'line: ',lines
goto 31 print *
32 rewind(1) endif
do i=1,i-lines
read(1,*,end=39) show_log=tecs_get_par('logline', str, 1)
enddo
33 read(1,'(q,a)',end=39) l,str
print *,str(1:min(len(str),max(1,l)))
goto 33
39 continue
close(1)
end end

585
tecs/tecs_data.c Normal file
View File

@ -0,0 +1,585 @@
#include <stdlib.h>
#include <float.h>
#include <string.h>
#include <assert.h>
#include "myc_mem.h"
#include "myc_str.h"
#include "myc_err.h"
#include "myc_time.h"
#include "coc_logfile.h"
#include "tecs_data.h"
#define RUN_SIZE 1024
#define SET_LEN 1024
typedef struct {
int tmin, tmax, tlim;
float dmin, dmax;
int reset;
} Summary;
typedef struct _Run {
struct _Run *next;
int size, step;
int startTime, endTime;
float data[RUN_SIZE];
} Run;
typedef struct _Set {
DataSet set;
struct _Set *next;
int nRuns;
int step, lifetime;
int start, end;
float *var;
Run *runs;
Summary sum;
} Set;
typedef struct {
Set *head;
} Base;
typedef struct {
Base *base;
int tim, from, to;
int stdStep;
} ScanData;
static Base database;
void InsSum(Summary *sum, int t, float d) {
if (sum->tmin == 0) {
sum->tmin = t;
sum->tmax = t;
sum->dmin = d;
sum->dmax = d;
} else {
if (d <= sum->dmin) {
sum->dmin = d;
sum->tmin = t;
} else if (d >= sum->dmax) {
sum->dmax = d;
sum->tmax = t;
}
}
}
void ResetSum(Summary *sum) {
sum->reset = 1;
sum->tmin = 0;
sum->dmin = DATA_UNDEF;
sum->dmax = DATA_UNDEF;
}
void PutSum(Summary *sum, float *data) {
if (sum->tmin == 0) {
data[1] = sum->dmin;
data[0] = sum->dmax;
} else if (sum->tmin > sum->tmax) {
data[1] = sum->dmin;
data[0] = sum->dmax;
sum->dmin = sum->dmax;
} else if (sum->tmin < sum->tmax) {
data[1] = sum->dmax;
data[0] = sum->dmin;
sum->dmax = sum->dmin;
} else {
data[1] = sum->dmin;
data[0] = sum->dmax;
}
sum->tmin = 0;
if (sum->reset) {
sum->dmin = DATA_UNDEF;
sum->dmax = DATA_UNDEF;
sum->reset = 0;
}
}
Set *FindSet(Base *base, char *name) {
Set *s;
int total;
total=0;
s = base->head;
while (s!=NULL && 0!=strcmp(name, s->set.name)) {
s = s->next;
}
return s;
}
Set *CreateSet(Base *base, char *name, float *var, int step, int lifetime, int start) {
Set *s;
char *nam;
s = FindSet(base, name);
if (s != NULL) ERR_MSG("dataset exists");
NEW(s, Set);
s->next = base->head;
base->head = s;
NEW_STR(nam, name);
s->set.name = nam;
s->runs = NULL;
s->nRuns = 0;
s->lifetime = lifetime;
s->start = start;
s->step = step;
s->var = var;
ResetSum(&s->sum);
return s;
OnError:
return NULL;
}
DataSet *DataFindSet(DataBase *dBase, char *name) {
Base *base;
if (dBase==NULL) {
base=&database;
} else {
base=(Base *)dBase;
}
return (DataSet *) FindSet(base, name);
}
DataSet *DataCreateSet(DataBase *dBase, char *name, float *var, int step, int lifetime, int start) {
Base *base;
if (dBase==NULL) {
base=&database;
} else {
base=(Base *)dBase;
}
return (DataSet *) CreateSet(base, name, var, step, lifetime, start);
}
int DataSetStep(DataSet *set, int step) {
Set *s;
ERR_P(set);
ERR_I(step-1); /* step > 0 */
s = (Set *)set;
s->step = step;
return 0;
OnError: return -1;
}
int DataSetLifetime(DataSet *set, int lifetime) {
Set *s;
ERR_P(set);
s = (Set *)set;
s->lifetime = lifetime;
return 0;
OnError: return -1;
}
Run *InsertRun(Set *s, int time) {
Run *r, *next, *last;
NEW(r, Run);
r->next = s->runs;
s->runs = r;
r->step = s->step;
s->nRuns++;
if (s->nRuns * s->step > s->lifetime) {
next=r->next;
last=r;
while (next!=NULL && next->endTime > time - s->lifetime) {
last = next;
next = last->next;
}
while (next!=NULL) {
last->next = next->next;
FREE(next);
s->nRuns--;
next = last->next;
}
}
return r;
OnError:
return NULL;
}
int Put(Set *set, int time, float value) {
Run *r;
int t, try = 1;
int size;
float last;
ERR_P(set);
if (value == DATA_UNDEF) return 0;
r = set->runs;
if (r == NULL || r->step != set->step || r->size+3 > RUN_SIZE) {
ERR_P(r = InsertRun(set, time));
r->startTime = time;
r->endTime = time - r->step;
size = 0;
t = 1;
} else {
size = r->size;
t = (time - r->endTime) / r->step;
last = r->data[size-1];
}
if (t<0) {
if (t<-1) {
logfileOut(LOG_MAIN, "%s %d <? %d\n", set->set.name, time, r->endTime);
ERR_MSG("back in time not possible");
}
t=0;
}
if (t == 0) {
InsSum(&set->sum, time, value);
} else {
if (size % 2) {
PutSum(&set->sum, r->data+size-1); size++;
r->endTime += r->step;
t--;
}
if (t > 2) {
r->data[size]=t-1; size++;
r->data[size]=DATA_UNDEF; size++;
set->sum.reset = 1;
r->endTime += r->step * (t-1);
t=1;
}
InsSum(&set->sum, time, value);
if (t % 2) {
r->data[size]=value; size++; /* put a provisory value */
r->endTime += r->step;
} else {
PutSum(&set->sum, r->data+size); size+=2;
r->endTime += r->step * 2;
}
}
r->size = size;
return 0;
OnError:
return -1;
}
int DataPut(DataSet *set, int time, float value) {
return Put((Set *)set, time, value);
}
int DataPutAll(DataBase *base, int time) {
Set *s;
if (base == NULL) {
s=database.head;
} else {
s=((Base *)base)->head;
}
while (s!=NULL) {
if (s->var!=NULL) {
ERR_I(Put(s, time, *s->var));
}
s=s->next;
}
return 0;
OnError:
return -1;
}
int Start(Set *s) {
Run *r;
int t1, t2;
r = s->runs;
t1 = s->start;
if (r != NULL) {
t2 = r->endTime - s->lifetime;
if (t1 < t2) {
while (r != NULL) {
t1 = r->startTime;
r = r->next;
}
if (t1 > t2) {
t1 = t2;
}
}
}
return t1;
}
void FreeBase(Base *base) {
Set *s, *sFree;
Run *r, *rFree;
s = base->head;
while (s != NULL) {
r = s->runs;
while (r != NULL) {
rFree = r;
r = r->next;
FREE(rFree);
}
sFree=s;
s = s->next;
FREE(sFree);
}
}
int GetSet(Set *s, int startTime, int endTime, int size, float *data) {
Run *r;
int t, tlim, tmin;
float d;
int i, idx;
Summary sum;
if (size<=0 || size%2 != 0) ERR_MSG("size must be even and positive");
ERR_P(s);
ERR_P(data);
r = s->runs;
ResetSum(&sum);
idx = size - 2;
tlim = (endTime - startTime) * idx / size + startTime;
while (r != NULL) {
if (startTime > r->endTime) break;
if (endTime >= r->startTime) {
t = r->endTime;
d = 0;
for (i = r->size - 1; i>=0; i--, t-=r->step) {
d = r->data[i];
if (d == DATA_UNDEF) {
i--;
t -= (int)(r->data[i] + 0.5) * r->step;
sum.reset = 1;
} else {
if (t < startTime) break;
if (t < endTime) {
while (t < tlim) {
PutSum(&sum, data+idx); idx-=2;
tlim = (endTime - startTime) * idx / size + startTime;
}
InsSum(&sum, t, d);
}
}
}
}
r = r->next;
}
sum.reset = 1;
while (idx >= 0) {
PutSum(&sum, data+idx); idx-=2;
}
return 0;
OnError:
return -1;
}
void Scan(void *sData, char *line) {
Set *set;
Run *run;
Base *base;
char str[64], nam[64];
int l, iret, hh, mm, ss;
float num;
int tim, tshift, t0;
base=((ScanData *)sData)->base;
tim=((ScanData *)sData)->tim;
/* read time */
l=0; iret=sscanf(line, "%d:%d:%d%n", &hh, &mm, &ss, &l); line+=l;
if (iret!=3) return;
tim+=hh*3600+mm*60+ss;
if (tim < ((ScanData *)sData)->from || tim > ((ScanData *)sData)->to) return;
set=NULL;
l=0; iret=sscanf(line, "%64s%n", str, &l); line+=l;
while (iret==1) {
if (str[0] >= 'A') {
str_copy(nam, str);
l=0; iret=sscanf(line, "%64s%n", str, &l); line+=l;
if (iret==1) {
iret=sscanf(str, "%f", &num);
if (iret==1) {
tshift = 0;
if (0 != strcmp(nam, "_")) {
set=FindSet(base, nam);
if (set!=NULL) tshift = 1;
}
if (set!=NULL && tim < set->end) {
if (tshift) {
t0 = tim - ((ScanData *)sData)->stdStep*2;
run = set->runs;
if (run != NULL && run->endTime >= t0) {
t0 = run->endTime;
}
t0 += set->step;
if (t0 > tim) t0 = tim;
Put(set, t0, num);
} else {
Put(set, tim, num);
}
}
}
}
} else {
l=0; iret=sscanf(line, "%64s%n", str, &l); line+=l;
}
}
}
void Load(Base *base, int from, int to, int stdStep) {
Set *set;
ScanData scanData;
int t, date;
scanData.base = base;
scanData.stdStep = stdStep;
scanData.from = from;
scanData.to = to;
/* round down "from" and "to" to 00:00 local time */
from = from - (from % (24*3600));
to = to - (to % (24*3600));
for (t=from; t<=to; t+=24*3600) {
scanData.tim=t;
logfileScan(mycDate(t), Scan, &scanData);
}
}
static char *encode=DATA_CODE;
int DataEncode(float *data, int dataSize, char *coded, int codedLen) {
int i, n, p, gap;
float minD, maxD, range;
if (dataSize >= (codedLen-26)/2) ERR_MSG("codedLen too small");
minD=DATA_UNDEF;
maxD=DATA_UNDEF;
for (i=0; i<dataSize; i++) {
if (data[i]!=DATA_UNDEF) {
if (maxD==DATA_UNDEF) {
maxD=data[i]; minD=data[i];
} else {
if (data[i] > maxD) maxD=data[i];
if (data[i] < minD) minD=data[i];
}
}
}
range = maxD - minD;
if (range == 0) range=1;
ERR_SI(p=sprintf(coded, "%d %5g %5g ", dataSize, minD, range));
gap=0;
for (i=0; i<dataSize; i++) {
if ( data[i] == DATA_UNDEF ) {
coded[p++]='/';
} else {
n=( (data[i] - minD) * 4095 ) / range + 0.5;
assert(n>=0 && n <4096);
coded[p++]=encode[n % 64];
coded[p++]=encode[n / 64];
}
}
coded[p++]=',';
coded[p]='\0';
assert(p < codedLen);
return p;
OnError:
return -1;
}
int DataGetCoded(char *names, int startTime, int endTime, int step, int stdStep, char *coded, int codedLen) {
Base base;
Set *set, *s;
int stp, minStep, period, s1;
char *nams, nam[32];
int p, l, n, i, j, siz1, siz2, halfsiz, start;
float data[SET_LEN];
base.head = NULL;
period = endTime - startTime;
n=0; nams = names;
while (nams != NULL) {
nams = str_split(nam, nams, ' ');
if (nam[0] != '\0') n++;
}
stp=step;
if (stp<stdStep) stp=stdStep;
nams=names;
while (nams!=NULL) {
nams=str_split(nam, nams, ' ');
if (nam[0]!='\0') {
set=FindSet(&database, nam);
if (set != NULL) {
start = Start(set);
} else {
start = endTime;
}
if (set == NULL || start > startTime) {
set=CreateSet(&base, nam, NULL, stp, period, startTime);
set->end = start;
}
}
}
if (base.head != NULL) {
Load(&base, startTime, endTime, stdStep);
}
p=0;
nams=names;
coded[0]='\0';
while (nams!=NULL) {
nams=str_split(nam, nams, ' ');
if (nam[0]!='\0') {
s = FindSet(&database, nam);
set = FindSet(&base, nam);
s1 = startTime;
if (s == NULL) {
if (set == NULL) {
s1 = 0;
} else {
s = set;
}
} else {
minStep = s->step;
if (set != NULL) {
s1 = Start(s);
if (s1 >= endTime) {
s = set;
s1 = startTime;
} else if (s1 < startTime || s1 <= Start(set)) {
s1 = startTime;
}
}
}
if (s1 == 0) {
data[0]=DATA_UNDEF;
ERR_I(l=DataEncode(data, 1, coded+p, codedLen-p));
} else {
minStep = s->step;
stp = step;
halfsiz = period / (2 * stp) + 1;
if (startTime + minStep * halfsiz * 2 > endTime) {
if (stp < minStep) stp = minStep;
halfsiz = period / (2 * stp) + 1;
if (halfsiz * 2 > SET_LEN) halfsiz = SET_LEN / 2;
if (halfsiz * 4 + 32 * n > codedLen) {
halfsiz = ((codedLen - p) / n - 32) / 4;
}
}
siz1 = (s1 - startTime) * halfsiz / period * 2;
siz2 = halfsiz * 2 - siz1;
s1 = startTime + (siz1 * period + halfsiz) / halfsiz / 2;
if (siz1 > 0) {
ERR_I(GetSet(set, startTime, s1, siz1, data));
}
if (siz2 > 0) {
ERR_I(GetSet(s, s1, endTime, siz2, data+siz1));
}
ERR_I(l=DataEncode(data, siz1+siz2, coded+p, codedLen-p));
}
p+=l;
n--;
}
}
FreeBase(&base);
return (0);
OnError:
return(-1);
}

47
tecs/tecs_data.h Normal file
View File

@ -0,0 +1,47 @@
#ifndef TECS_DATA_H_
#define TECS_DATA_H_
typedef struct {
char *name;
} DataSet;
typedef struct {
void *private;
} DataBase;
DataSet *DataCreateSet(DataBase *dBase, char *name, float *var, int step, int lifetime, int start);
/*
create a new dataset
if the dataset already exists, or memory allocation failed, NULL is returned
set <dBase> to NULL to use the common database
*/
DataSet *DataFindSet(DataBase *dBase, char *name);
/*
find a previously created dataset.
returns NULL if dataset not found
set <dBase> to NULL to use the common database
*/
int DataSetStep(DataSet *set, int step);
int DataSetLifetime(DataSet *set, int lifetime);
int DataPut(DataSet *set, int time, float value);
/*
put one value to dataset
*/
int DataPutAll(DataBase *dBase, int time);
/*
put all variables in a set to their dataset
*/
int DataDecode(float *data, int dataSize, char *coded, int *retLen);
int DataGetCoded(char *names, int startTime, int endTime, int step, int stdStep, char *coded, int codedLen);
/*
define DATA_UNDEF as a binary and decimal well defined, hopefully rarely used number
*/
#define DATA_UNDEF MYC_NAN
#define DATA_CODE "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ[]abcdefghijklmnopqrstuvwxyz"
#endif /* TECS_DATA_H_ */

View File

@ -9,7 +9,7 @@ c M. Zolliker, March 2000
c Updates: c Updates:
c V01A 21-Mar-2000 DM. Integrate into TASMAD c V01A 21-Mar-2000 DM. Integrate into TASMAD
c 05-Apr-2000 M.Z. modifed error handling/changed arguments in TeccGet3 c 05-Apr-2000 M.Z. modifed error handling/changed arguments in TeccGet3
c 01-May-2000 M.Z. renamed source, TECS_OPEN is now in a separate, system dependend file c 01-May-2000 M.Z. renamed source, TECS_OPEN is now in a separate, system dependent file
c V01C 11-May-2000 DM. Split into modules. c V01C 11-May-2000 DM. Split into modules.
c V01D 12-May-2000 M.Z. Changed error handling, no longer automatic call to TECS_OPEN c V01D 12-May-2000 M.Z. Changed error handling, no longer automatic call to TECS_OPEN
c------------------------------------------------------------------------------ c------------------------------------------------------------------------------
@ -102,11 +102,18 @@ c extract the port number from the start command
i=index(init, '-p ') i=index(init, '-p ')
if (i .eq. 0) i=index(init, '-P ') if (i .eq. 0) i=index(init, '-P ')
if (i .ne. 0) then if (i .ne. 0) then
read(init,*,iostat=ios) port read(init(min(len(init),i+3):),*,iostat=ios) port
endif endif
if (port .eq. 0) port=9753 if (port .eq. 0) port=9753
iret=tecs_init(init, port)
if (init(1:1) .eq. '#') then
i=index(init, '-')-1
if (i .le. 0) i=len(init)
else
i=len(init)
endif
iret=tecs_init(init(1:i), port)
else else
@ -131,7 +138,7 @@ c if INIT exists, read it to get the port number and the start command
end end
SUBROUTINE TECS_GET_T (IOLUN, TEMP, IRET) !! SUBROUTINE TECS_GET_T (IOLUN, TEMP, IRET) !!
!! ============================================ !! =========================================
!! !!
!! Get temperatures and wait if TECS is configuring !! Get temperatures and wait if TECS is configuring
!! !!
@ -152,18 +159,18 @@ c------------------------------------------------------------------------------
return return
endif endif
if (iret .gt. 0) then if (iret .gt. 0) then
write(iolun, *) 'configuring temperature controller ...' ! write(iolun, *) 'configuring temperature controller ...'
iret=tecs_wait() ! iret=tecs_wait()
if (iret .lt. 0) then ! if (iret .lt. 0) then
call err_txt('tecs_wait'//char(10)//'tecs_get_t') ! call err_txt('tecs_wait'//char(10)//'tecs_get_t')
return ! return
endif ! endif
write(iolun, *) '... done' ! write(iolun, *) '... done'
iret=tecs_get3(temp(1), temp(3), temp(2)) ! temp(2) and temp(3) are exchanged in MSHOWT ! iret=tecs_get3(temp(1), temp(3), temp(2)) ! temp(2) and temp(3) are exchanged in MSHOWT
if (iret .lt. 0) then ! if (iret .lt. 0) then
call err_txt('tecs_get3(2)'//char(10)//'tecs_get_t') ! call err_txt('tecs_get3(2)'//char(10)//'tecs_get_t')
return ! return
endif ! endif
endif endif
temp(4)=0.0 ! no auxilliary sensor temp(4)=0.0 ! no auxilliary sensor
end end

View File

@ -3,11 +3,11 @@
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include "err_handling.h" #include "myc_err.h"
#include "coc_logfile.h" #include "coc_logfile.h"
#include "coc_util.h" #include "coc_server.h"
#include "tecs_lsc.h" #include "tecs_lsc.h"
#include "str_util.h" #include "myc_str.h"
#define MAX_PAR 16 #define MAX_PAR 16
#define MAX_ARG 9 #define MAX_ARG 9
@ -46,15 +46,14 @@ char *LscCmd(SerChannel *ser, const char *cmds) {
char *blank, *colon, *qu, *res; char *blank, *colon, *qu, *res;
const char *p, *this, *next, *cmd_ptr, *retreq; const char *p, *this, *next, *cmd_ptr, *retreq;
const char *list[nLIST]; const char *list[nLIST];
char seg[SER_BUF_LEN], buf[SER_BUF_LEN], result[SER_BUF_LEN], par[SER_BUF_LEN]; char seg[SER_BUF_LEN], result[SER_BUF_LEN], par[SER_BUF_LEN];
char cmd[SER_BUF_LEN]; char cmd[SER_BUF_LEN];
char varname[32]; char varname[32];
Str_Buf sbuf; DeclStrBuf(sbuf, SER_BUF_LEN);
int nres, i, j, response; int nres, i, j, response;
nres=0; nres=0;
response=0; response=0;
str_link_buf(&sbuf, buf, sizeof(buf), STR_NOSEPARATOR);
this=cmds; this=cmds;
while (this!=NULL) { while (this!=NULL) {
next=str_split(cmd, this, ';'); next=str_split(cmd, this, ';');
@ -67,13 +66,13 @@ char *LscCmd(SerChannel *ser, const char *cmds) {
} }
cmd_ptr=sbuf.buf+sbuf.wrpos; /* pointer to command in buffer */ cmd_ptr=sbuf.buf+sbuf.wrpos; /* pointer to command in buffer */
p=str_split(seg, cmd, '['); p=str_split(seg, cmd, '[');
ERR_I(str_put_str(&sbuf, seg)); ERR_I(StrPut(&sbuf, seg, StrNONE));
while (p!=NULL) { /* substitute variables */ while (p!=NULL) { /* substitute variables */
p=str_split(varname, p, ']'); p=str_split(varname, p, ']');
if (p==NULL) ERR_MSG("missing ']'"); if (p==NULL) ERR_MSG("missing ']'");
ERR_I(CocPutVar(serverVarList, &sbuf, varname, 0)); ERR_I(CocPutVar(varname, &sbuf, StrNONE));
p=str_split(seg, p, '['); p=str_split(seg, p, '[');
ERR_I(str_put_str(&sbuf, seg)); ERR_I(StrPut(&sbuf, seg, StrNONE));
} }
ERR_I(str_copy(cmd, cmd_ptr)); ERR_I(str_copy(cmd, cmd_ptr));
colon=strchr(cmd_ptr, ':'); colon=strchr(cmd_ptr, ':');
@ -86,16 +85,15 @@ char *LscCmd(SerChannel *ser, const char *cmds) {
} }
list[nres]=colon+1; nres++; assert(nres<=nLIST); /* pointer to parameters */ list[nres]=colon+1; nres++; assert(nres<=nLIST); /* pointer to parameters */
list[nres]=cmd_ptr; nres++; assert(nres<=nLIST); /* pointer to command */ list[nres]=cmd_ptr; nres++; assert(nres<=nLIST); /* pointer to command */
ERR_I(str_put_str(&sbuf, ";")); ERR_I(StrPut(&sbuf, ";", StrNONE));
cmd[blank-cmd_ptr]='?'; /* build query */ cmd[blank-cmd_ptr]='?'; /* build query */
if (colon==blank) colon++; if (colon==blank) colon++;
cmd[colon-cmd_ptr]='\0'; cmd[colon-cmd_ptr]='\0';
ERR_I(str_put_str(&sbuf, cmd)); /* put query */ ERR_I(StrPut(&sbuf, cmd, ';')); /* put query */
ERR_I(str_put_str(&sbuf, ";"));
response=1; response=1;
} else { } else {
qu=strchr(cmd, '?'); qu=strchr(cmd, '?');
ERR_I(str_put_str(&sbuf, ";")); ERR_I(StrPut(&sbuf, ";", StrNONE));
if (qu!=NULL) { /* command is a query */ if (qu!=NULL) { /* command is a query */
response=1; response=1;
if (retreq==NULL) { if (retreq==NULL) {
@ -110,11 +108,11 @@ char *LscCmd(SerChannel *ser, const char *cmds) {
} }
if (!response) { if (!response) {
ERR_I(str_put_str(&sbuf, "busy?")); ERR_I(StrPut(&sbuf, "busy?",'\0'));
} else { } else {
buf[sbuf.wrpos-1]='\0'; /* strip off trailing ";" */ sbuf.buf[sbuf.wrpos-1]='\0'; /* strip off trailing ";" */
} }
ERR_P(res=SerCmd(ser, buf)); ERR_P(res=SerCmd(ser, sbuf.buf));
if (0==strncmp("?TMO", res, 4)) ERR_MSG("timeout"); if (0==strncmp("?TMO", res, 4)) ERR_MSG("timeout");
/* /*
list[0..nres-1] contains a now: list[0..nres-1] contains a now:
@ -158,18 +156,19 @@ char *LscCmd(SerChannel *ser, const char *cmds) {
} }
} }
if (retreq!=NULL) { /* query */ if (retreq!=NULL) { /* query */
str_link_buf(&sbuf, result, 0, ','); StrLink(&sbuf, result);
str_split(par, retreq+1, ';'); str_split(par, retreq+1, ';');
p=par; p=par;
while (p!=NULL) { while (p!=NULL) {
p=str_split(varname, p, ','); p=str_split(varname, p, ',');
if (varname[0]!='\0') { if (varname[0]!='\0') {
if (p==NULL) { /* last element: get rest of line */ if (p==NULL) { /* last element: get rest of line */
sbuf.sep='\0'; ERR_I(CocGetVar(varname, &sbuf, '\0'));
} else {
ERR_I(CocGetVar(varname, &sbuf, ','));
} }
ERR_I(CocGetVar(serverVarList, &sbuf, varname, 0));
} else { } else {
ERR_P(str_get_str(&sbuf, NULL)); ERR_P(StrGet(&sbuf, varname, ','));
} }
} }
} }
@ -177,3 +176,33 @@ char *LscCmd(SerChannel *ser, const char *cmds) {
return(res); return(res);
OnError: return(NULL); OnError: return(NULL);
} }
char *LscReadStat(int stat) {
if (stat &128) return("units overrange");
if (stat & 64) return("units zero");
if (stat & 32) return("temp overrange");
if (stat & 16) return("temp underrange");
if (stat & 2) return("old reading");
if (stat & 1) return("invalid reading");
return ("");
}
static char
*heaterStatus[7]={
"",
"heater supply over V",
"heater supply under V",
"heater output DAC error",
"heater Ilimit DAC error",
"open heater load",
"heater load < 10 Ohm",
};
char *LscHtrStat(int stat) {
if (stat<0 || stat>sizeof(heaterStatus)) {
return("unknown heater status");
} else {
return(heaterStatus[stat]);
}
}

View File

@ -40,7 +40,7 @@ char *LscCmd(SerChannel *ser, const char *cmds);
name="CTI5" name="CTI5"
head="R10410 ,3,+330.000E+0,2" head="R10410 ,3,+330.000E+0,2"
All used variables have to be declared with CocDef... (see coc_util.h) All used variables have to be declared with CocDef... (see coc_server.h)
*/ */
int LscEqPar(char *par, char *res); int LscEqPar(char *par, char *res);
@ -49,4 +49,8 @@ int LscEqPar(char *par, char *res);
if any parameter in par is omitted, it is not compared if any parameter in par is omitted, it is not compared
*/ */
char *LscReadStat(int stat);
char *LscHtrStat(int stat);
#endif /* _TECS_LSC_H_ */ #endif /* _TECS_LSC_H_ */

View File

@ -1,36 +1,55 @@
subroutine tecs_plot(file) subroutine tecs_plot(pars, naux)
character(len=*) file character(len=*) pars ! parameters to plot
integer naux ! number of auxiliary, non-T parameters
integer, parameter :: dmax=500, nset=3, nmenu=10, chartfreq=2 integer, parameter :: dmax=1000, nmax=5, nmenu=11, chartfreq=1
real, parameter :: winmin=60., undef=-65535.0 integer, parameter :: minRange=60, maxRange=7*24*3600
integer, parameter :: oneDay = 24*3600
real, parameter :: winmin=60., undef=-1.125/1024./1024./1024.
real*4 x1,x2,xmin,xmax,ymin(2),ymax(2),window real*4 x1,x2,xmin,xmax,ymin(2),ymax(2),window
real*4 xd(dmax),yd(dmax,nset) real*4 xd(dmax, nmax),yd(dmax,nmax), yy0(nmax), yy1(nmax)
real*4 ylast1,ylast2,y1,y2 real*4 ylast1,ylast2,y1,y2
real*4 ex,ey,fx,fy,hmenu,wmenu,ymenu,ticks real*4 ex,ey,fx,fy,row,ticks,tim0,tim1
real*4 xbox(8), ybox(8) integer l,j,i,n,t,leng,i1,i2,rl,startday,thisday
integer l,j,i,t0,t1,ntot,i1,i2,rl,n,startday,thisday integer nset
integer first,last,tbase,lastj integer first,last,step,tbase,lastj
integer color(3)/2,4,3/ integer color(nmax)
integer retLen(nmax)
character key*1 character key*1
character text(nmenu)*12/ & character text(nmenu)*12/ &
'live off','sel. zoom','zoom in','zoom out','show all','n days','n hours','n min','file','quit'/ 'live off','sel. zoom','zoom in','zoom out','show all','n days','n hours','n min','date','file','quit'/
character keys*(nmenu)/'LZ+-XDHMFQ'/ character keys*(nmenu)/'LZ+-XDHMTFQ'/
character weekdays(7)*3/'Mon','Tue','Wed','Thu','Fri','Sat','Sun'/ character weekdays(7)*4/'Mon','Tue','Wed','Thu','Fri','Sat','Sun'/
character buf*8, device*8, line*40, filnam*128 character buf*8, device*8, name*40, filnam*128, numb*16
character(len=16) parnam(nmax)
external tplot_close external tplot_close
logical gap, done
logical live, xwin, zoom, right, saveit logical live, xwin, zoom, right, saveit
integer iret, numb, lund integer iret, lund, numl, mon, day
integer dlog_open_r, dlog_get, dlog_close_r ! functions
integer sys_gmt_off, myc_now, myc_time, myc_date, tecs_get_data, tecs_get_mult
data window/1800./ data window/0./
if (window==0) window=1800.
saveit=.false. saveit=.false.
zoom=.false. zoom=.false.
right=.true. right=.true.
call pgopen(" ") call pgopen(" ")
call pgscr(0, 1.0, 1.0, 1.0)
call pgscr(1, 0.0, 0.0, 0.0)
call pgscr(2, 1.0, 0.0, 0.0)
call pgscr(3, 0.0, 1.0, 0.0)
call pgscr(4, 0.0, 0.0, 1.0)
call pgscr(5, 0.0, 1.0, 1.0)
call pgscr(6, 1.0, 0.0, 1.0)
call pgscr(7, 1.0, 1.0, 0.0)
call pgscr(8, 1.0, 0.5, 0.0)
call pgqinf('TYPE', device, l) call pgqinf('TYPE', device, l)
if (device=='NULL') then if (device=='NULL') then
print *,'No PGPLOT-Device defined' print *,'No PGPLOT-Device defined'
@ -38,72 +57,104 @@ subroutine tecs_plot(file)
endif endif
live=device(1:1)/='X' ! live switched off by default on X-Windows live=device(1:1)/='X' ! live switched off by default on X-Windows
nset=1
l=1
i=1
do while (i <= nmax)
do while (l < len(pars) .and. pars(l:l) <= ' ')
l=l+1
enddo
if (pars(l:l) > ' ') then
j=l
do while (l < len(pars) .and. pars(l:l) > ' ')
l=l+1
enddo
parnam(i)=pars(j:l)
nset=i
if (l == len(pars)) i=nmax
else
i=nmax
endif
i=i+1
enddo
call pgask(.false.) call pgask(.false.)
l=0 l=0
iret=dlog_open_r(file, first, last, tbase)
if (iret<0) then
call err_txt('dlog_open_r')
goto 99
endif
xmax=0
x1=0 x1=0
step=0
1 if (right .or. window==0 .or. live) then 1 iret=tecs_get_mult(pars, t, nset, yy0)
ntot=dlog_get(dmax, nset, tbase, -window*1.1, 0.0, undef, xd, yd) if (iret < 0) goto 99
if (ntot<=0) then if (window == 0) then
if (ntot<0) then last=t
call err_txt('dlog_get') step=maxRange/dmax
goto 99 window=maxRange
endif first=t-min(dmax*step-1,maxRange-step)
x2=last-tbase else if (right .or. live) then
else step=window/(dmax-1)+0.99
x2=maxval(xd(1:ntot)) last=t
endif first=t-min(dmax*step-1,nint(window)-step)
if (live) then
if (x1 .eq. 0) then
x1=max(x2-window,xd(1))
else
window=x2-x1
endif
x2=max(x1+window,x2+min(window*0.2,max(window*0.01,300.)))
elseif (window==0) then
x1=minval(xd(1:ntot))
window=x2-x1
else
x1=x2-window
endif
else else
if (.not. zoom) then if (.not. zoom) then
x2=(x1+x2+window)/2 x2=(x1+x2+window)/2
x1=x2-window x1=x2-window
endif endif
ntot=dlog_get(dmax, nset, tbase, x1-window*0.1, x2+window*0.1, undef, xd, yd) if (x1 .gt. x2-minRange) x1=x2-minRange
endif step=(x2-x1)/(dmax-1)+0.99
if (ntot<0) then last=nint(x2)+tbase
call err_txt('dlog_get') first=nint(x1)+tbase
goto 99 endif
endif if (step == 0) step=1
if (saveit) goto 9
if (ntot>0) then iret=tecs_get_data(pars, first, last, step, yd, dmax, nmax, retLen)
xmin=minval(xd(1:ntot)) if (iret < 0) goto 99
xmax=maxval(xd(1:ntot)) ! do i=1,nmax
! if (retLen(i) > 0) nset=i
! enddo
! if (nset == 0) then
! retLen(1)=0
! nset=1
! endif
color(1)=2
color(2)=4
color(3)=3
color(4)=5
color(5)=8
if (naux > 0) color(nset)=8
tbase=first-mod(first,7*oneDay);
x2 = last - tbase;
if (right .or. live) then
x1=x2-window
else else
xmin=x1 x1 = first - tbase;
xmax=x2 endif
tim0=t-tbase
do j=1,nset
leng=retLen(j)
do i=1,leng
xd(i,j)=(float(i-1)*(last-tbase)+float(leng-i)*(first-tbase))/(leng-1)
enddo
if (live .and. leng>0) then
xd(leng,j)=tim0
yd(leng,j)=yy0(j)
endif
enddo
if (saveit) goto 9
if (live) then
x2=max(tim0,x2)+min(1800., window*0.5)
endif endif
call pgsvp(0.07,0.93,0.1,0.9) ! define window size if (window>50*3600) then
ticks=8*3600
if (xmax<=xmin) then elseif (window>25*3600) then
xmax=xmin+1 ticks=4*3600
! l=0 else
! print *,'no points found' ticks=0.0 ! automatic
! print *
! goto 9
endif endif
call pgsch(1.0)
i1=1 i1=1
i2=2 i2=nset-naux
do rl=1,2 do rl=1,2
if (zoom) then if (zoom) then
ymin(1)=y1 ymin(1)=y1
@ -114,13 +165,13 @@ subroutine tecs_plot(file)
ylast1=ymin(rl) ylast1=ymin(rl)
ylast2=ymax(rl) ylast2=ymax(rl)
do i=i1,i2 do i=i1,i2
do j=1,ntot do j=1,retLen(i)
if (xd(j) >= x1 .and. xd(j) <= x2 .and. yd(j,i)/=undef) then if (yd(j,i)/=undef) then
ymin(rl)=min(ymin(rl),yd(j,i)) ymin(rl)=min(ymin(rl),yd(j,i))
ymax(rl)=max(ymax(rl),yd(j,i)) ymax(rl)=max(ymax(rl),yd(j,i))
endif endif
enddo enddo
do j=max(1,ntot-4),ntot do j=max(1,retLen(i)-4),retLen(i)
if (yd(j, i)/=undef) then if (yd(j, i)/=undef) then
ylast1=min(ylast1,yd(j, i)) ylast1=min(ylast1,yd(j, i))
ylast2=max(ylast2,yd(j, i)) ylast2=max(ylast2,yd(j, i))
@ -130,169 +181,190 @@ subroutine tecs_plot(file)
ey=(ymax(rl)-ymin(rl)) ey=(ymax(rl)-ymin(rl))
fy=abs(ymax(rl)) fy=abs(ymax(rl))
if (rl==1) then ymax(rl)=ymax(rl)+max(fy*0.0075,ey*0.01)
ymax(rl)=ymax(rl)+max(fy*0.0075,ey*0.25) ymin(rl)=ymin(rl)-max(fy*0.005,ey*0.01)
ymin(rl)=ymin(rl)-max(fy*0.005,ey*0.01)
else
ymax(rl)=ymax(rl)+max(fy*0.1,ey*0.01)
ymin(rl)=ymin(rl)-max(fy,ey*4)
endif
if (live) then if (live) then
ymin(rl)=min(ymin(rl),max(0.0,ylast1-ey*0.4)) ymin(rl)=min(ymin(rl),max(0.0,ylast1-ey*0.4))
ymax(rl)=max(ymax(rl),ylast2+ey*0.4) ymax(rl)=max(ymax(rl),ylast2+ey*0.4)
endif endif
endif endif
if (ymax(rl) .lt. ymin(rl)) then if (ymax(rl) < ymin(rl)) then
ymax(rl)=1 ymax(rl)=1.0
ymin(rl)=0
elseif (ymax(rl) .eq. ymin(rl)) then
ymax(rl)=ymin(rl)+1.0
ymin(rl)=0 ymin(rl)=0
elseif (ymax(rl) == ymin(rl)) then
ymax(rl)=ymin(rl)*1.00001+1.0
ymin(rl)=-1.0e-3
endif endif
zoom=.false. zoom=.false.
call pgswin(x1,x2,ymin(rl),ymax(rl)) call set_win(rl,x1,x2,ymin(rl),ymax(rl))
call pgscr(0, 1.0, 1.0, 1.0)
call pgscr(1, 0.0, 0.0, 0.0)
call pgscr(2, 1.0, 0.0, 0.0)
call pgscr(3, 0.0, 0.7, 0.0)
call pgscr(4, 0.0, 0.0, 1.0)
do i=i1,i2 do i=i2,i1,-1
call pgsci(color(i)) call pgsci(color(i))
n=0
lastj=1 lastj=1
do j=1,ntot do j=1,retLen(i)
if (yd(j,i)==undef) then if (yd(j,i)==undef) then
if (j>lastj) call pgline(j-lastj, xd(lastj), yd(lastj,i)) if (j>lastj) then
call pgline(j-lastj, xd(lastj,i), yd(lastj,i))
endif
lastj=j+1 lastj=j+1
endif endif
enddo enddo
if (ntot .gt. lastj) call pgline(ntot+1-lastj, xd(lastj), yd(lastj,i)) if (retLen(i) > lastj) call pgline(retLen(i)+1-lastj, xd(lastj,i), yd(lastj,i))
enddo enddo
i1=3 call pgsci(1)
i2=3 if (rl == 1) then
call pgsch(1.0)
call pgtbox('ZHXYBINST', ticks, 0, 'BCINMST', 0.0, 0)
call pgtbox('C', 0.0, 0, ' ', 0.0, 0)
ey=0.0
do i=i1,i2
name=parnam(i)
if (name=="Tm") then
name="Main Sensor"
elseif (name=="Ts") then
name="Sample Sensor"
elseif (name=="Tr") then
name="SetPoint"
endif
call pglen(5, trim(name), fx, fy)
call pgsci(color(i))
call pgmtxt ('L', 2.5, ey, 0.0, trim(name))
ey=ey+fy+0.04
enddo
call pgsci(1)
call pgmtxt ('L', 2.5, ey, 0.0, 'T [K]')
else if (naux > 0) then
call pgsch(0.7)
call pgtbox('ZCIST', ticks, 0, 'BCVINMST', 0.0, 0)
call pgtbox('B', 0.0, 0, ' ', 0.0, 0)
call pgsci(color(nset))
call pgsch(1.0)
if (parnam(nset) == 'P' .or. parnam(nset) == 'p') then
call pgmtxt ('L', 2.5, 0.5, 0.5, 'Power [W]')
else
call pgmtxt ('L', 2.5, 0.5, 0.5, parnam(nset))
endif
endif
i1=nset-naux+1
i2=nset
enddo enddo
rl=2
call pgsci(1) call pgsch(0.8)
! call pgtbox(' ', 0.0, 0, 'CIMST', 0.0, 0)
ey=ymax(rl)-(ymax(rl)-ymin(rl))*0.20
call pgsch(0.7)
call pgaxis('N', x1, ey, x1, ymax(rl), ey, ymax(rl), 0, 0, 0.5, 0.0, 0.0, -1.0, 0.0)
rl=1 rl=1
call pgswin(x1,x2,ymin(rl),ymax(rl)) call set_win(rl,x1,x2,ymin(rl),ymax(rl))
ey=ymax(rl)-(ymax(rl)-ymin(rl))*0.21
call pgsch(1.0)
call pgaxis('N', x1, ymin(rl), x1, ey, ymin(rl), ey, 0, 0, 0.5, 0.0, 0.5, -1.0, 0.0)
if (window>50*3600) then
ticks=8*3600
elseif (window>25*3600) then
ticks=4*3600
else
ticks=0.0 ! automatic
endif
call pgtbox('ZHXYBCINST', ticks, 0, 'CIMST', 0.0, 0)
call pgmtxt ('L', 2.5, 0.4, 0.5, 'T [K]')
call pgsci(color(1))
call pgmtxt ('L', 2.5, 0.2, 0.5, 'Main Sensor')
call pgsci(color(2))
call pgmtxt ('L', 2.5, 0.6, 0.5, 'Sample Sensor')
call pgsci(color(3))
call pgmtxt ('L', 2.5, 0.9, 0.5, 'Power [W]')
call pgsci(1) call pgsci(1)
call pgsclp(0) call pgsclp(0)
hmenu=(ymax(rl)-ymin(rl))/15.
ymenu=ymax(rl)+hmenu*0.5
wmenu=(x2-x1)/(nmenu+2)
if (live) then if (live) then
text(1)='live off' text(1)='live off'
else else
text(1)='live on' text(1)='live on'
endif endif
call pgsch(0.7) ex=0.0
do i=1,nmenu do i=1,nmenu
xbox(1)=x1+(i-0.7)*wmenu call pglen(5, trim(text(i)), fx, fy)
ybox(1)=ymenu+hmenu call pgmtxt('T', 3.0, ex, 0.0, '|'//keys(i:i))
xbox(2)=xbox(1) call pgmtxt('T', 2.5, ex, 0.0, '|')
ybox(2)=ymenu+hmenu*0.5 call pgmtxt('T', 2.0, ex, 0.0, '|'//text(i))
xbox(3)=x1+(i-0.95)*wmenu ex=ex+fx+0.01
ybox(3)=ybox(2)
xbox(4)=xbox(3)
ybox(4)=ybox(1)
xbox(5)=xbox(1)
ybox(5)=ybox(1)
call pgline(5, xbox, ybox)
call pgptxt(x1+(i-0.9)*wmenu, ymenu+0.65*hmenu, 0.0, 0.0, keys(i:i))
call pgptxt(x1+(i-0.9)*wmenu, ymenu+0.15*hmenu, 0.0, 0.0, text(i))
enddo enddo
call pgmtxt('T', 3.5, 1.0, 1.0, 'any digit to enter n') call pgmtxt('T', 3.0, ex, 0.0, '|')
call pgmtxt('T', 2.0, 0.9, 1.0, 'n=') call pgmtxt('T', 2.5, ex, 0.0, '|')
thisday=(x1+x2)/2/(24*3600) call pgmtxt('T', 2.0, ex, 0.0, '|')
ey=ymin(rl)-hmenu*1.5 call pgmtxt('T', 3.0, 0.8, 0.0, 'any digit to enter n')
i=max(0,int((x1+12*3600)/(24*3600))) call pgmtxt('T', 2.0, 0.8, 0.0, 'n=')
done=.false.
row=(ymax(rl)-ymin(rl))/30.
ey=ymin(rl)-row*3.5
i=max(0,int((x1+oneDay/2)/oneDay))
do do
ex=(i+0.5)*24*3600 ex=(i+0.5)*oneDay
if (ex>x2) EXIT if (ex > x2) EXIT
thisday=0 done=.true.
call pgptxt(ex, ey, 0.0, 0.5, weekdays(mod(i,7)+1)) write(buf,'(i8.8)') myc_date(nint(ex)+tbase)
call pgptxt(ex, ey, 0.0, 0.5, weekdays(mod(i,7)+1)//buf(7:8)//'.'//buf(5:6))
ex=ex-12*3600 ex=ex-12*3600
if (ex .gt. x1) then if (ex > x1) then
call pgmove(ex, ey) call pgmove(ex, ey)
call pgdraw(ex, ey+hmenu/2) call pgdraw(ex, ey+row)
endif endif
ex=ex+24*3600 ex=ex+oneDay
if (ex .lt. x2) then if (ex < x2) then
call pgmove(ex, ey) call pgmove(ex, ey)
call pgdraw(ex, ey+hmenu/2) call pgdraw(ex, ey+row)
endif endif
i=i+1 i=i+1
enddo enddo
if (thisday>0) then if (.not. done) then
call pgptxt((x1+x2)/2, ey, 0.0, 0.5, weekdays(mod(thisday,7)+1)) n=nint(x2)/oneDay*oneDay;
i=nint(x1)-n
j=nint(x2)-n
if (i < 0) then
if (-i > j) then
ex=0.0
i=nint(x1)+tbase
else
ex=1.0
i=nint(x2)+tbase
endif
else
ex=0.5
i=nint(x2)+tbase
endif
thisday=mod(i/oneDay,7)+1
write(buf,'(i8.8)') myc_date(i)
! call pgptxt((x1+x2)/2, ey, 0.0, ex, weekdays(mod(thisday,7)+1)//buf(7:8)//'.'//buf(5:6))
call pgmtxt('B', 3.5, ex, ex, weekdays(thisday)//buf(7:8)//'.'//buf(5:6))
endif endif
call pgsclp(1) call pgsclp(1)
call get_key(key, 0, 0) ! purge buffer call get_key(key, 0, 0) ! purge buffer
numb=0 numl=0
numb=' '
7 if (live) then 7 if (live) then
if (device(1:1)=='X') then if (device(1:1)=='X') then
call pgmtxt('T', 1.0, 1.0, 1.0, 'LIVE MODE (click on text window before pressing any further key)') call pgmtxt('T', 0.5, 0.0, 0.0, 'LIVE MODE (click on text window before pressing any further key)')
endif endif
call get_key(key, 0, chartfreq) call get_key(key, 0, chartfreq)
do while (key .eq. char(0)) ! no key pressed
ntot=dlog_get(dmax, nset, tbase, xmax-0.5, 1e10, undef, xd, yd) do while (key == char(0)) ! no key pressed
if (ntot<0) then iret=tecs_get_mult(pars, t, nset, yy1)
call err_txt('dlog_open_r 2') if (iret<0) goto 99
goto 99 tim1=t-tbase
if (tim1 > x2) then
call pgpage
window=x2-x1
goto 1
endif endif
if (ntot .gt. 1) then if (tim1 > tim0) then
i1=1 i1=1
i2=2 i2=nset-naux
do rl=1,2 do rl=1,2
call pgswin(x1,x2,ymin(rl),ymax(rl)) call set_win(rl,x1,x2,ymin(rl),ymax(rl))
do i=i1,i2 do i=i2,i1,-1
call pgsci(color(i)) if (yy0(i) .ne. undef .and. yy1(i) .ne. undef) then
n=0 if (yy1(i) < ymin(rl) .or. yy1(i) > ymax(rl)) then
lastj=1
do j=1,ntot
if (yd(j,i)==undef) then
if (j>lastj) call pgline(j-lastj, xd(lastj), yd(lastj,i))
lastj=j+1
elseif (xd(j)>x2 .or. yd(j,i)<ymin(rl) .or. yd(j,i)>ymax(rl)) then
call pgpage call pgpage
window=x2-x1 window=x2-x1
goto 1 goto 1
endif endif
enddo call pgsci(color(i))
if (ntot .gt. lastj) call pgline(ntot+1-lastj, xd(lastj), yd(lastj,i)) call pgmove(tim0, yy0(i))
call pgdraw(tim1, yy1(i))
endif
yy0(i)=yy1(i)
enddo enddo
i1=3 i1=nset-naux+1
i2=3 i2=nset
enddo enddo
xmax=max(xmax,xd(ntot)) tim0=tim1
endif endif
call get_key(key, 0, chartfreq) call get_key(key, 0, chartfreq)
enddo enddo
@ -301,16 +373,11 @@ subroutine tecs_plot(file)
call must_purge call must_purge
endif endif
rl=1 rl=1
call pgswin(x1,x2,ymin(rl),ymax(rl)) call set_win(rl,x1,x2,ymin(rl),ymax(rl))
8 if (key>='a') key=char(ichar(key)-32) 8 if (key>='a') key=char(ichar(key)-32)
if (ey>ymenu) then
i=max(0,min(nmenu,int((ex-x1)/wmenu+1)))
key=keys(i:i)
ex=(x1+x2)/2
endif
if (key=='-') then if (key=='-') then
window=min(window*2, 8*24*3600.) window=min(window*2, 8.0*oneDay)
elseif (key=='X') then elseif (key=='X') then
window=0 window=0
live=.false. live=.false.
@ -319,10 +386,10 @@ subroutine tecs_plot(file)
elseif (key=='Z') then elseif (key=='Z') then
call pgsci(1) call pgsci(1)
if (live) then if (live) then
call pgmtxt('T', 1.0, 0.0, 0.0, 'click on two opposite corners of a selection rectangle') call pgmtxt('T', 0.5, 0.0, 0.0, 'click on two opposite corners of a selection rectangle')
call pgcurs(ex, ey, key) call pgcurs(ex, ey, key)
else else
call pgmtxt('T', 1.0, 0.3, 0.0, 'click on second corner of selection rectangle') call pgmtxt('T', 0.5, 0.0, 0.0, 'click on second corner of selection rectangle')
endif endif
call pgsci(5) call pgsci(5)
xmin=x1 xmin=x1
@ -349,16 +416,13 @@ subroutine tecs_plot(file)
zoom=.true. zoom=.true.
live=.false. live=.false.
right=.false. right=.false.
elseif (key .ge. '0' .and. key .le. '9') then elseif (key >= '0' .and. key <= '9' .or. key == '.') then ! number
numb=numb*10+(ichar(key)-ichar('0')) if (numl .lt. len(numb)) then
if (numb>0) then numl=numl+1
write(buf, '(i8)') numb numb(numl:numl)=key
l=1
do while (buf(l:l)==' ')
l=l+1
enddo
call pgsci(1) call pgsci(1)
call pgmtxt('T', 2.0, 0.9, 0.0, buf(l:)) call pgsch(0.8)
call pgmtxt('T', 2.0, 0.825, 0.0, numb(1:numl))
endif endif
if (device(1:1)=='X' .and. .not. live) then if (device(1:1)=='X' .and. .not. live) then
call pgcurs(ex, ey, key) call pgcurs(ex, ey, key)
@ -368,35 +432,59 @@ subroutine tecs_plot(file)
endif endif
if (key/=char(0)) goto 8 if (key/=char(0)) goto 8
goto 7 goto 7
elseif (key .eq. 'D') then elseif (key == 'D') then
window=min(7*24*3600,24*3600*max(1,numb)) ex=1
read(numb, *, iostat=i) ex
window=min(maxRange,max(minRange, nint(oneDay*ex)))
right=.true. right=.true.
x1=0 x1=0
elseif (key .eq. 'H') then elseif (key == 'H') then
window=min(7*24*3600,3600*max(1,numb)) ex=1
read(numb, *, iostat=i) ex
window=min(maxRange,max(minRange, nint(3600*ex)))
right=.true. right=.true.
x1=0 x1=0
elseif (key .eq. 'M') then elseif (key == 'M') then
window=min(7*24*3600,60*max(1,numb)) ex=1
read(numb, *, iostat=i) ex
window=min(maxRange,max(minRange, nint(60*ex)))
right=.true. right=.true.
x1=0 x1=0
elseif (key .eq. 'L') then elseif (key == 'T' .or. numl>0 .and. (key==char(13) .or. key==char(10))) then
j=index(numb,'.')
day=0
if (j > 1 .and. j < numl) then
read(numb(1:j-1), *, iostat=i) day
mon=0
read(numb(j+1:numl), *, iostat=i) mon
tbase = myc_time(day+mon*100);
else
read(numb, *, iostat=i) day
tbase = myc_time(day);
endif
x1=0
x2=oneDay
window=x2
live=.false.
right=.false.
elseif (key == 'L') then
live=.not. live live=.not. live
if (live) then if (live) then
right=.true. right=.true.
x2=xmax
endif endif
elseif (key .eq. 'F') then elseif (key == 'F') then
saveit=.true. saveit=.true.
elseif (key=='Q' .or. key==char(13)) then elseif (key=='Q' .or. key==char(13) .or. key==char(10)) then
goto 9 goto 9
elseif (key == 'R') then
elseif (live) then elseif (live) then
goto 7 goto 7
endif endif
numb=0 numl=0
numb=' '
call pgpage call pgpage
goto 1 goto 1
99 call tecs_write_error(6) 99 call tecs_write_msg(6)
9 continue 9 continue
call tplot_close call tplot_close
call get_key(key, 0, 0) ! purge type-ahead-buffer call get_key(key, 0, 0) ! purge type-ahead-buffer
@ -406,19 +494,35 @@ subroutine tecs_plot(file)
print '(x,a,$)', 'Filename: ' print '(x,a,$)', 'Filename: '
read(*,'(a)') filnam read(*,'(a)') filnam
open(lund, file=filnam, status='unknown', carriagecontrol='list') open(lund, file=filnam, status='unknown', carriagecontrol='list')
write(lund, *) ' time [h]',char(9),' T1 [K]',char(9),' T2 [K]',char(9),'power [W]'
do i=1,ntot gap=.false.
write(line, '(4(f9.4,a))') xd(i)/3600., (char(9), max(-999.,min(9999.,yd(i,j))), j=1,3) do j=1,nset
do j=1,3 if (j == 1) then
write(lund, *) ' time [h]',char(9),' Tm [K]'
elseif (j == 2) then
write(lund,*)
write(lund, *) ' time [h]',char(9),' Ts [K]'
else
write(lund,*)
write(lund, *) ' time [h]',char(9), ' ',trim(parnam(j))
endif
do i=1,retLen(j)
if (yd(i,j)==undef) then if (yd(i,j)==undef) then
line(10*j+1:10*j+9)=' ' if (gap) then
write(lund, '(f9.4,2a)') xd(i,j)/3600., char(9), ' '
gap=.false.
endif
else
write(lund, '(f9.4,a,f9.4)') xd(i,j)/3600., char(9), max(-999.,min(9999.,yd(i,j)))
gap=.true.
endif endif
enddo enddo
write(lund, *) line(1:39)
enddo enddo
close(lund) close(lund)
print *, ntot+1, ' lines written to ',filnam(1:48) print *, retLen(1)+1, ' lines written to ',filnam(1:48)
endif endif
end subroutine end subroutine
subroutine get_key(key, tmo1, tmo2) subroutine get_key(key, tmo1, tmo2)
@ -439,7 +543,20 @@ entry must_purge
purge=.true. purge=.true.
end subroutine end subroutine
subroutine set_win(rl, x1, x2, y1, y2)
integer rl
real x1, x2, y1, y2
if (rl == 1) then
call pgsvp(0.07,0.93,0.3,0.9)
else
call pgsvp(0.07,0.93,0.01,0.20)
endif
call pgswin(x1,x2,y1,y2)
end subroutine
subroutine tplot_close subroutine tplot_close
call pgclos call pgclos
call dlog_close_r ! call dlog_close_r
end subroutine end subroutine

View File

@ -1,27 +1,37 @@
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h>
#include <string.h> #include <string.h>
#include <sys/timeb.h> #include <assert.h>
#include <sys/socket.h>
#include <sys/time.h>
#include "rs232c_def.h" #include "rs232c_def.h"
#include "asynsrv_def.h" #include "asynsrv_def.h"
#include "sinq_prototypes.h" #include "sinq_prototypes.h"
#include "sys_util.h" #include "sys_util.h"
#include "err_handling.h" #include "myc_err.h"
#include "tecs_serial.h" #include "tecs_serial.h"
#include "coc_logfile.h" #include "coc_logfile.h"
#include "str_util.h" #include "coc_util.h"
#include "myc_str.h"
#include "myc_mem.h"
#define A_CHK(R) if (1!=(R)) { SerA_error(); ErrTxt(#R,0); goto OnError; } #define ASYNSRV_TYPE 1
#define TERMSRV_TYPE 2
#define EOT '\r'
int ftime (struct timeb *__timeptr); /* for some reason not defined in timeb.h with flag -std1 */ typedef struct {
int type; /* = ASYNSRV_TYPE */
void (*idleHandler)(int,int);
struct SerChan {
struct AsynSrv__info asyn_info; /* Contains skt, host, port & chan */ struct AsynSrv__info asyn_info; /* Contains skt, host, port & chan */
struct RS__MsgStruct to_host; struct RS__MsgStruct to_host;
struct RS__RespStruct from_host; struct RS__RespStruct from_host;
char cmd[SER_BUF_LEN]; } AsynSrvChan;
};
typedef struct {
int type; /* = TERMSRV_TYPE */
char res[SER_BUF_LEN];
int fd, tmo;
int (*idleHdl)(int,int);
} TermSrvChan;
void SerA_error(void) { void SerA_error(void) {
char *a_txt; char *a_txt;
@ -31,43 +41,182 @@ void SerA_error(void) {
ErrMsg("asynsrv error"); ErrTxt(a_txt,0); ErrMsg("asynsrv error"); ErrTxt(a_txt,0);
} }
SerChannel *SerOpen(const char *host, int msecTmo, void (*idleHdl)(int,int)) { int SerWait(int tmo_msec, int fd) {
struct SerChan *ser; struct timeval tmo;
char hbuf[64], cport[16]; fd_set mask;
char *p, *c; int i;
int port, chan, iRet;
FD_ZERO(&mask);
FD_SET(fd, &mask);
tmo.tv_sec=tmo_msec / 1000;
tmo.tv_usec=(tmo_msec % 1000) % 1000 +1;
ERR_SI(i=select(fd+1,&mask,NULL,NULL,&tmo));
if (i==0) return(0); /* timeout */
return(1);
OnError: return(-1);
}
idleHandler=idleHdl; SerChannel *SerOpen(const char *hostPort, int msecTmo, int (*idleHdl)(int,int)) {
NEW(ser); AsynSrvChan *aser;
str_copy(hbuf, host); TermSrvChan *tser;
p=str_split(ser->asyn_info.host, hbuf, ':'); char hbuf[64], cport[16], host[32];
port=4000; char *p, *c;
chan=0; struct sockaddr_in sadr;
if (p!=NULL) { int iret;
c=str_split(cport, p, '/'); time_t t1, t2;
if (c!=NULL) chan=atoi(c); static int ecnt;
port=atoi(cport);
} time(&t1);
ser->asyn_info.port=port; str_copy(hbuf, hostPort);
ser->asyn_info.chan=chan; p=str_split(host, hbuf, ':');
A_CHK(AsynSrv_Open(&ser->asyn_info)); assert(p!=NULL);
c=str_split(cport, p, '/');
if (msecTmo==0) msecTmo=5000; if (msecTmo==0) msecTmo=5000;
A_CHK(AsynSrv_Config(&ser->asyn_info, "msecTmo", msecTmo, "idleHdl", idleHdl, NULL)); if (c!=NULL) {
logfileOut(LOG_MAIN, "connection to %s:%d/%d opened\n", ser->asyn_info.host, ser->asyn_info.port, ser->asyn_info.chan); NEW(aser, AsynSrvChan); aser->type=ASYNSRV_TYPE;
return((SerChannel *)ser); str_copy(aser->asyn_info.host, host);
aser->asyn_info.port=atoi(cport);
aser->asyn_info.chan=atoi(c);
iret=AsynSrv_Open(&aser->asyn_info);
if (iret==1) {
iret=AsynSrv_Config(&aser->asyn_info, "msecTmo", msecTmo, "idleHdl", idleHdl, NULL);
}
if (iret!=1) {
SerA_error();
goto OnError;
}
time(&t2);
ecnt=0;
logfileOut(LOG_MAIN, "connection to %s:%d/%d opened (%d sec)\n",
aser->asyn_info.host, aser->asyn_info.port, aser->asyn_info.chan,
t2-t1);
return((SerChannel *)aser);
} else {
NEW(tser, TermSrvChan); tser->type=TERMSRV_TYPE;
tser->tmo=msecTmo;
if (idleHdl==NULL) {
tser->idleHdl=SerWait;
} else {
tser->idleHdl=idleHdl;
}
ERR_I(CocCreateSockAdr(&sadr, host, atoi(p)));
ERR_SI(tser->fd=socket(AF_INET, SOCK_STREAM, 0));
/* do we need this really as a client ?
i = 1;
ERR_SI(setsockopt(conn->fd,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(int)));
*/ /* allow quick port reuse */
ERR_SI(connect(tser->fd, (struct sockaddr *)&sadr, sizeof(sadr)));
time(&t2);
ecnt=0;
logfileOut(LOG_MAIN, "connected to %s (%d sec)\n", hostPort, t2-t1);
return ((SerChannel *)tser);
}
OnError:
time(&t2);
if (ecnt<4) {
logfileOut(LOG_MAIN, "failed after %d sec\n", t2-t1);
ecnt++;
}
return(NULL);
}
void SerClose(SerChannel *serch) {
AsynSrvChan *aser;
TermSrvChan *tser;
if (serch->type==ASYNSRV_TYPE) {
aser=(AsynSrvChan *)serch;
AsynSrv_Close(&aser->asyn_info, 0);
} else if (serch->type==TERMSRV_TYPE) {
tser=(TermSrvChan *)serch;
close(tser->fd);
}
serch->type=0;
}
SerChannel *SerCheck(SerChannel *serch) {
if (serch==NULL || serch->type==0) {
return(NULL);
} else {
return(serch);
}
}
char *SerCmd(SerChannel *serch, char *cmnd) {
int l, n;
AsynSrvChan *aser;
TermSrvChan *tser;
char *result, *pos, *trm;
int iret, incomplete;
l=strlen(cmnd);
if (l>=SER_BUF_LEN-1) ERR_COD(ENOBUFS);
cmnd[l]=EOT; l++;
cmnd[l]='\0';
logfileOut(LOG_SER, ">%s\n", cmnd);
if (serch->type==ASYNSRV_TYPE) {
aser=(AsynSrvChan *)serch;
iret=AsynSrv_SendCmnds(&aser->asyn_info, &aser->to_host, &aser->from_host, cmnd, NULL);
if (iret!=1) {
SerA_error();
SerClose(serch);
return(NULL);
}
result=AsynSrv_GetReply(&aser->asyn_info, &aser->from_host, NULL);
if (result==NULL) ERR_MSG("empty result");
} else if (serch->type==TERMSRV_TYPE) {
tser=(TermSrvChan *)serch;
iret=send(tser->fd, cmnd, l, 0);
if (iret<0) {
ErrMsg("disconnected");
SerClose(serch);
goto OnError;
}
n=sizeof(tser->res);
pos=tser->res;
result=NULL;
incomplete=1;
while (incomplete) {
/* Wait for an event on tser->fd or a timeout tmo */
iret=tser->idleHdl(tser->tmo, tser->fd);
if (iret==0) {
if (result==NULL) ERR_MSG("time out");
ERR_MSG("missing terminator");
}
ERR_SI(l=recv(tser->fd, pos, n, 0));
if (l==0) {
ErrMsg("disconnected");
SerClose(serch);
goto OnError;
}
n -= l;
if (n==0) ERR_MSG("answer too long");
while (l>0) {
if (*pos>' ') {
if (result==NULL) result=pos; /* skip trailing white space */
} else if (*pos<' ') { /* all control characters are treated as terminators */
if (result!=NULL) {
*pos='\0';
incomplete=0;
}
}
pos++; l--;
}
}
} else {
serch->type=0;
ERR_MSG("invalid channel");
}
logfileOut(LOG_SER, "<%s\n", result);
return(result);
OnError: OnError:
return(NULL); return(NULL);
} }
int SerClose(SerChannel *serch) { /* obsolete ?
struct SerChan *ser;
ser=(struct SerChan *)serch;
A_CHK(AsynSrv_Close(&ser->asyn_info, 0));
return(0);
OnError: return(-1);
}
char *SerCmdC(SerChannel *serch, const char *cmnd) { char *SerCmdC(SerChannel *serch, const char *cmnd) {
char cmd[SER_BUF_LEN]; char cmd[SER_BUF_LEN];
int l; int l;
@ -78,33 +227,5 @@ char *SerCmdC(SerChannel *serch, const char *cmnd) {
return(SerCmd(serch, cmd)); return(SerCmd(serch, cmd));
OnError: return(NULL); OnError: return(NULL);
} }
*/
char *SerCmd(SerChannel *serch, char *cmnd) {
int l;
struct SerChan *ser;
char *result;
struct timeb tim0, tim1;
int tdif;
l=strlen(cmnd);
if (l>=SER_BUF_LEN-1) ERR_COD(ENOBUFS);
ser=(struct SerChan *)serch;
logfileOut(LOG_SER, ">%s\n", cmnd);
cmnd[l]=ser->asyn_info.eot[1];
cmnd[l+1]='\0';
ftime(&tim0);
A_CHK(AsynSrv_SendCmnds(&ser->asyn_info, &ser->to_host, &ser->from_host, cmnd, NULL));
result=AsynSrv_GetReply(&ser->asyn_info, &ser->from_host, NULL);
ftime(&tim1);
tdif=(tim1.time-tim0.time)*1000+tim1.millitm-tim0.millitm;
if (result==NULL) ERR_MSG("empty result");
/* if (idleHandler!=NULL) idleHandler(50,0); */
logfileOut(LOG_SER, "<%s\n", result);
if (tdif>1000) {
logfileOut(LOG_SER, "%d msec:\n >%s\n", tdif, cmnd);
logfileOut(LOG_SER, " <%s\n", result);
}
return(result);
OnError: return(NULL);
}

View File

@ -3,11 +3,16 @@
#define SER_BUF_LEN 320 #define SER_BUF_LEN 320
typedef struct { int private; } SerChannel; typedef struct {
/* private */
int type;
} SerChannel;
SerChannel *SerOpen(const char *host, int msecTmo, void (*idleHdl)(int,int)); SerChannel *SerOpen(const char *host, int msecTmo, int (*idleHdl)(int,int));
char *SerCmdC(SerChannel *ser, const char *cmnd);
char *SerCmd(SerChannel *ser, char *cmnd); char *SerCmd(SerChannel *ser, char *cmnd);
int SerClose(SerChannel *ser); SerChannel *SerCheck(SerChannel *ser);
void SerClose(SerChannel *ser);
/* char *SerCmdC(SerChannel *ser, const char *cmnd); */
#endif /* _SERUTIL_H_ */ #endif /* _SERUTIL_H_ */