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
#--------------------------------------------------------------------------
LIBR_OBJ= coc_util.o err_handling.o str_util.o str_buf.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 $(LIBR_OBJ) $(DLOG_OBJ)
LIBR_OBJ= coc_util.o myc_err.o myc_str.o myc_buf.o myc_time.o
SERV_OBJ= tecs.o coc_server.o tecs_lsc.o tecs_serial.o coc_logfile.o tecs_data.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)
CC=cc
#CFLAGS= -std1 -g -warnprotos -I../ -I. -I../hardsup -DFORTIFY
CFLAGS= -std1 -g -warnprotos -I../ -I. -I../hardsup
#------------ for Linux
##CC=gcc
##CFLAGS = -fwritable-strings -DCYGNUS -DNONINTF -g -I../ -I. -I../hardsup
#------------
.f.o:
f77 -c -g $*.f
f77 -c -u -g $*.f
.c.o:
$(CC) $(CFLAGS) -c $*.c
libtecsl.a: $(CLI_OBJ)
- rm -f libtecsl.a
- rm libtecsl.a
ar cr libtecsl.a $(CLI_OBJ)
ranlib libtecsl.a
all: libtecsl.a bin/TecsServer tecs
all: libtecsl.a bin/TecsServer bin/TecsClient
tecs_plot.o: tecs_plot.f90
f90 -c -g tecs_plot.f90
f90 -c -u -g tecs_plot.f90
bin/TecsServer: $(SERV_OBJ)
- rm -f bin/TecsServer
- rm bin/TecsServer
$(CC) $(CFLAGS) -o bin/TecsServer -g $(SERV_OBJ) fortify1.c \
-lm -L../hardsup -lhlib -lfor
tecs: $(TCLI_OBJ)
f77 -o tecs -g $(TCLI_OBJ) \
bin/TecsClient: $(TECLI_OBJ)
f77 -o bin/TecsClient -g $(TECLI_OBJ) \
-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:
- rm -f *.o
- rm -f *.a
- rm -f bin/TecsServer
- rm -f tecs
- rm *.o
- rm *.a
- rm bin/TecsServer
- rm bin/TecsClient

View File

@ -1,19 +1,24 @@
#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include "err_handling.h"
#include <signal.h>
#include "myc_err.h"
#include "coc_util.h"
#include "coc_client.h"
#include "str_util.h"
#include "sys_util.h"
#include "myc_str.h"
/* --- non ANSI signal --- */
#ifndef SIGPIPE
#define SIGPIPE 13
#endif
#define COC_NETTMO 5
#define COC_RESTMO 60
/*-------------------------------------------------------------------------*/
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) {
assert(conn!=NULL);
if (bufsize==0) bufsize=1024;
ERR_P(conn->cmdbuf=str_create_buf(bufsize, '\0'));
ERR_P(conn->resbuf=str_create_buf(bufsize, '\0'));
StrLink(&conn->cmdbuf, conn->cmdbuf_);
StrLink(&conn->resbuf, conn->resbuf_);
conn->port=port;
ERR_I(str_copy(conn->host, host));
ERR_I(str_copy(conn->magic, magic));
ERR_I(str_copy(conn->startcmd, startcmd));
conn->fd=-1;
conn->varList=NULL;
CocVarList(&conn->varList);
ERR_I(CocOpen(conn));
ERR_I(CocSendMagic(conn, conn->magic));
return(0);
@ -86,15 +89,17 @@ int CocInitClient(CocConn *conn, char *host, int port, char *magic, int bufsize,
int CocSendMagic(CocConn *conn, char *magic) {
char *err;
int siz, n;
if (magic[0]!='#') ERR_MSG("magic must start with '#'");
str_put_start(conn->resbuf); /* use return buffer for command in order to preserve command buffer */
ERR_I(str_put_str(conn->resbuf, magic));
ERR_SI(send(conn->fd, conn->resbuf->buf, conn->resbuf->wrpos, 0));
ERR_I(CocRecv(conn->fd, conn->resbuf));
ERR_P(err=str_get_str(conn->resbuf, NULL));
if (*err!='\0') { ErrMsg(err); ErrTxt(": (response from server)",0); goto OnError; }
ERR_I(str_get_end(conn->resbuf));
StrClear(&conn->resbuf); /* use return buffer for command in order to preserve command buffer */
ERR_I(StrPut(&conn->resbuf, "", COC_MAGIC));
ERR_I(StrPut(&conn->resbuf, magic, COC_SEP));
ERR_I(CocSend(conn->fd, conn->resbuf.buf, conn->resbuf.wrpos));
ERR_I(CocRecv(conn->fd, &conn->resbuf, COC_NETTMO, NULL));
ERR_P(err=StrGet(&conn->resbuf, NULL, COC_SEP));
if (err[0]!=COC_MAGIC) ERR_MSG("magic synch error");
if (err[1]!='\0') { ErrMsg(err+1); ErrTxt(": (response from server)",0); goto OnError; }
ERR_I(StrGetEnd(&conn->resbuf));
return(0);
OnError: return(-1);
}
@ -102,9 +107,10 @@ int CocSendMagic(CocConn *conn, char *magic) {
/*-------------------------------------------------------------------------*/
int CocCheck(CocConn *conn) {
if (conn->fd<0) return(1);
ERR_SI(send(conn->fd, "quit", 5, 0));
ERR_I(CocRecv(conn->fd, conn->resbuf));
ERR_I(CocSend(conn->fd, "_quit", 6));
ERR_I(CocRecv(conn->fd, &conn->resbuf, COC_NETTMO, NULL));
return(0);
OnError:
if (ErrCode==ECONNRESET || ErrCode==EPIPE) return(1);
@ -114,16 +120,24 @@ int CocCheck(CocConn *conn) {
/*-------------------------------------------------------------------------*/
int CocTryCmd(CocConn *conn) {
int iret=-1;
int iret=-1, siz;
signal(SIGPIPE, SIG_IGN);
if (conn->fd<0) {
/*
ERR_I(iret=CocOpen(conn));
*/
ERR_I(iret=CocConnect(conn));
if (iret == 1) {
CocDelay(500);
ErrTxt("connect",1); return (-1);
}
iret=-1;
ERR_I(CocSendMagic(conn, conn->magic));
}
ERR_SI(send(conn->fd, conn->cmdbuf->buf, conn->cmdbuf->wrpos, 0));
ERR_I(CocRecv(conn->fd, conn->resbuf));
ERR_I(CocSend(conn->fd, conn->cmdbuf.buf, conn->cmdbuf.wrpos));
ERR_I(CocRecv(conn->fd, &conn->resbuf, COC_NETTMO, NULL));
return(0);
OnError:
if (ErrCode==ECONNRESET || ErrCode==EPIPE) return(-2);
@ -134,7 +148,6 @@ int CocTryCmd(CocConn *conn) {
int CocCmdWithRetry(CocConn *conn) {
int cnt, iret;
char *err;
if (conn==NULL) ERR_MSG("not connected");
cnt=3;
@ -152,118 +165,321 @@ int CocCmdWithRetry(CocConn *conn) {
ErrShort(ErrMessage);
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);
OnError: return(-1);
}
/*-------------------------------------------------------------------------*/
int CocSet(CocConn *conn, const char *name, const char *value) {
int iret=-1;
void CocReset(CocConn *conn) {
assert(conn!=NULL);
str_put_start(conn->cmdbuf);
ERR_I(str_put_str(conn->cmdbuf, "["));
ERR_I(str_put_str(conn->cmdbuf, name));
ERR_I(str_put_str(conn->cmdbuf, value));
ERR_I(str_put_str(conn->cmdbuf, "]"));
ERR_I(iret=CocCmdWithRetry(conn));
ERR_I(str_get_end(conn->resbuf));
return(0);
OnError: return(iret);
StrClear(&conn->cmdbuf);
if (conn->synch!=COC_SYN0) {
conn->synch=COC_SYN0;
} else {
conn->synch=COC_SYN1;
}
StrPut(&conn->cmdbuf, "", conn->synch);
conn->nargs=0;
}
/*-------------------------------------------------------------------------*/
int CocGetN(CocConn *conn, const char *name, char *value, int reslen) {
int iret=-1;
int CocPushArg(CocConn *conn, const char *name, void *value, int type) {
StrBuf *buf;
int n;
assert(conn!=NULL);
str_put_start(conn->cmdbuf);
ERR_I(str_put_str(conn->cmdbuf, name));
ERR_I(iret=CocCmdWithRetry(conn));
ERR_P(str_nget_str(conn->resbuf, value, reslen));
ERR_I(str_get_end(conn->resbuf));
assert(NULL==strchr(name, ' '));
buf=&conn->cmdbuf;
n=conn->nargs;
if (n>=sizeof(conn->args)) ERR_MSG("too many return arguments");
conn->args[n].adr=value;
conn->args[n].type=type;
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);
OnError: return(iret);
OnError: return(-1);
}
/*-------------------------------------------------------------------------*/
int CocCmd(CocConn *conn, const char *rwList)
{ int setmode, i, iret=-1;
const char *t, *s;
char nam[32];
CocVar *var;
void *adr;
int CocPutStr(CocConn *conn, const char *name, const char *value) {
StrBuf *buf;
ERR_I(CocPushArg(conn, name, NULL, 4));
ERR_I(StrPut(&conn->cmdbuf, value, COC_SEP));
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);
str_put_start(conn->cmdbuf);
s=rwList;
setmode=0;
do {
t=strchr(s, ',');
if (t==NULL) t=s+strlen(s);
if (*s=='[') {
if (!setmode) ERR_I(str_put_str(conn->cmdbuf, "["));
s++;
setmode=1;
ERR_I(CocCmdWithRetry(conn));
buf=&conn->resbuf;
while (buf->buf[0] != conn->synch) { /* throw away unsynchronized answers */
ERR_I(CocRecv(conn->fd, buf, COC_NETTMO, NULL));
}
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));
/* read values */
s=rwList;
setmode=0;
do {
t=strchr(s, ',');
if (t==NULL) t=s+strlen(s);
if (*s=='[') {
s++;
setmode=1;
}
i=t-s;
if (setmode) {
if (*(t-1)==']') setmode=0;
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 {
str_ncpy(nam, s, i+1);
ERR_I(CocGetVar(conn->varList, conn->resbuf, nam, 0));
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 */
ERR_I(CocRecv(conn->fd, buf, COC_RESTMO, NULL));
}
return(iret);
OnError: return(-1);
}
static int interrupt, logFd=0;
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);
}
}
}
}
signal(SIGINT, SIG_DFL);
logFd=0;
if (interrupt==1) { /* send "clear log" message */
cbuf[0]=COC_CLRLOG;
cbuf[1]=COC_SEP; /* send "clear log" message */
printf("\nclrlog\n");
CocSend(fd, cbuf, 2);
do {
ERR_I(CocRecv(fd, buf, 10, NULL));
} while (buf->buf[0]!=COC_CLRLOG);
}
s=t+1;
} while (*t!='\0');
ERR_I(str_get_end(conn->resbuf));
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) {
assert(conn!=NULL);
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_
#define _COC_CLIENT_H_
#include "myc_buf.h"
#include "coc_util.h"
typedef struct {
void *adr;
int type;
char *cmd;
} CocArg;
typedef struct {
/* private */
int fd, port;
CocVar *varList;
Str_Buf *cmdbuf; /* for sending command */
Str_Buf *resbuf; /* for response */
StrBuf cmdbuf; /* for sending command */
StrBuf resbuf; /* for response */
char cmdbuf_[COC_CMD_LEN];
char resbuf_[COC_RES_LEN];
CocArg args[16];
int nargs;
char host[64];
char magic[32];
char startcmd[512];
char synch;
} CocConn;
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
*/
int CocCmd(CocConn *conn, const char *rwList);
/* rwList consists of a list of variables to be read or written.
Variables must be separated with commas, variables to be written
must be enclosed in square brackets.
void CocReset(CocConn *conn);
int CocPutStr(CocConn *conn, const char *name, const char *value);
int CocPutFloat(CocConn *conn, const char *name, float value);
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);
/*
returns 1, if not yet open
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);
/*
set one variable
*/
int CocGetN(CocConn *conn, const char *name, char *value, int reslen);
#define CocGet(C,N,V) CocGetN(C,N,V,sizeof(V))
/*
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);
/*
close the connection to the server
*/
#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>
#define __HIDE_FORBIDDEN_NAMES
#else
#include <stdio.h>
#endif
#else
#include <stdio.h>
#endif
#include <stdlib.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <string.h>
#include <stdarg.h>
#include <assert.h>
#include "coc_logfile.h"
#include "err_handling.h"
#include "str_util.h"
#include "myc_time.h"
#include "myc_err.h"
#include "myc_str.h"
static FILE *fil=NULL;
static char lnam[256]="", filnam[256]="";
static char lnam[224]="", filnam[256]="";
static char ebuf[20000]="";
static char *statusBuf=NULL;
static int statusSize;
static char *eptr=&ebuf[0];
static int lastStamp=0;
static int notDated=0;
static int dated=0;
static int logMask=0;
static int wrtMask=0;
static int newLine=1;
static int logfileStd;
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) {
struct tm *tim;
struct timeb btim;
void logfileOpen(int append) {
int year;
if (logfileStd) {
fil=stdout;
@ -47,35 +37,35 @@ void logfileOpen(int first) {
return;
}
assert(fil==NULL);
if (first) {
ftime(&btim);
tim=localtime(&btim.time);
if (notDated) {
openTime = mycNow();
openDate = mycDate(openTime); /* date in yyyymmdd decimal encoding */
openTime = openTime % (24*3600); /* seconds since midnight */
if (dated) {
sprintf(filnam, "%s%02d-%02d.log", lnam, openDate % 10000 / 100, openDate % 100);
} else {
if (lnam[0]=='\0') {
str_copy(filnam, "test.log");
} else {
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 {
sprintf(filnam, "%s%04d-%02d-%02d.log", lnam, tim->tm_year+1900, tim->tm_mon+1, tim->tm_mday);
fseek(fil, 0, SEEK_END); /* set position to end */
}
}
} 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) {
printf("Can not open %s\n", filnam);
fil=stdout;
@ -83,10 +73,10 @@ void logfileOpen(int first) {
return;
}
ErrSetOutFile(fil);
if (first) {
fprintf(fil, "%04d-%02d-%02d opened logfile\n"
, tim->tm_year+1900, tim->tm_mon+1, tim->tm_mday);
}
fprintf(fil, "%04d-%02d-%02d %02d:%02d:%02d opened logfile\n"
, openDate / 10000, openDate % 10000 / 100, openDate % 100
, openTime / 3600, openTime / 60 % 60, openTime % 60);
lastStamp = openTime / 60;
}
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) {
str_copy(lnam, path);
lastStamp=-2;
logfileStd=use_stdout;
writeAll=write_all;
notDated=nodate;
dated=!nodate;
logfileOpen(1);
return(filnam);
}
void logfileOut(int mask, const char *fmt, ...)
{ va_list ap;
char buf[256], *p;
char buf[8192], *p;
assert(mask>0 && mask<32);
va_start(ap, fmt);
if (mask & LOG_MAIN && statusBuf!=NULL) {
if (mask & LOG_STAT && statusBuf!=NULL) {
if (newLine) {
statusBuf[0]='\0';
newLine=0;
@ -119,17 +107,22 @@ void logfileOut(int mask, const char *fmt, ...)
buf[statusSize]='\0';
vsprintf(buf, fmt, ap);
assert(buf[statusSize]=='\0'); /* check for overflow */
if (buf[0]=='@') {
str_ncat(statusBuf, buf+1, statusSize);
} else {
str_ncat(statusBuf, buf, statusSize);
}
p=strchr(statusBuf, '\n');
if (p!=NULL) {
newLine=1;
*p='\0';
}
}
if (logfileOutRtn!=NULL) {
vsprintf(buf, fmt, ap); /* does not check for overflow! */
logfileOutRtn(mask, buf);
}
if (writeAll) {
#ifdef __VMS
if (fil==NULL) logfileOpen(0);
#endif
vfprintf(fil, fmt, ap);
wrtMask=LOG_ALL;
} else {
@ -139,10 +132,14 @@ void logfileOut(int mask, const char *fmt, ...)
eptr=NULL;
} else {
vsprintf(eptr, fmt, ap);
assert(NULL==strchr(eptr, '\1'));
p=strchr(eptr, '\1');
if (p==NULL) {
eptr+=strlen(eptr);
} else {
eptr=p; /* is in fact an error */
}
eptr[0]='\1'; /* put \1 as separator between blocks */
eptr[1]=mask;
eptr[1]=mask & 31;
eptr[2]='\0';
eptr+=2;
}
@ -157,33 +154,35 @@ void logfileMask(int mask) {
}
void logfileStamp(char *text) {
struct tm *tim;
struct timeb btim;
int stamp;
int time, date, stamp;
ftime(&btim);
tim=localtime(&btim.time);
stamp=tim->tm_hour*60+tim->tm_min;
if (stamp<lastStamp) { /* time smaller than last time -> new day -> new logfile */
time = mycNow();
date = mycDate(time); /* date in yyyymmdd decimal encoding */
time = time % (24*3600); /* seconds since midnight */
stamp=time / 60;
if (date != openDate ) { /* day has changed -> new logfile */
if (fil!=NULL) { fclose(fil); fil=NULL; }
lastpos=0;
lastline=1;
logfileOpen(1);
lastStamp=-2;
}
if (text==NULL) {
if (stamp>lastStamp+1) {
#ifdef __VMS
if (fil==NULL) logfileOpen(0);
#endif
lastStamp=stamp;
fprintf(fil, "%02d:%02d:%02d --- %s", tim->tm_hour, tim->tm_min, tim->tm_sec, text);
dirty=0;
fprintf(fil, "---\t%02d:%02d:%02d\n", stamp / 60, stamp % 60, time % 60, text);
}
} else {
fprintf(fil, "\t%02d:%02d:%02d %s", stamp / 60, stamp % 60, time % 60, text);
}
dirty=0;
lastStamp=stamp;
}
void logfileWrite0(int mask) {
char *s, *next;
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;
if (writeAll || *s!='\0' && wrtMask & logMask) {
@ -193,10 +192,9 @@ void logfileWrite0(int mask) {
next++;
if (*next & logMask) {
if (*s=='@') { /* write out time */
lastStamp-=2; /* force output */
logfileStamp(s+1);
} else {
logfileStamp("\n"); /* write stamp before write something */
logfileStamp(NULL); /* write stamp before write something */
fprintf(fil, "%s", s);
dirty=1;
}
@ -211,71 +209,131 @@ void logfileWrite0(int mask) {
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) {
#ifdef __VMS
if (fil==NULL) logfileOpen(0);
#endif
logfileWrite0(mask);
#ifdef __VMS
if (!logfileStd) { fclose(fil); fil=NULL; }
#else
fflush(fil);
#endif
}
void logfileShowErr(char *text)
{
#ifdef __VMS
if (fil==NULL) logfileOpen(0);
#endif
logfileWrite0(LOG_ALL); /* write all */
ErrShow(text);
#ifdef __VMS
if (!logfileStd) { fclose(fil); fil=NULL; }
#else
fflush(fil);
#endif
}
void logfileClose()
{
#ifdef __VMS
if (fil==NULL) logfileOpen(0);
#endif
logfileWrite0(LOG_MAIN+LOG_INFO);
lastStamp=-2;
logfileStamp("\n");
logfileOut(LOG_MAIN, "closed\n");
logfileStamp(NULL);
if (fil!=NULL) { fclose(fil); fil=NULL; }
filnam[0]='\0';
}
void logfileOutBuf(int mask, Str_Buf *buf)
void logfileOutBuf(int mask, StrBuf *buf)
{ char str[256];
int rd0, sep;
int rd0;
char *ret;
rd0=buf->rdpos;
if (buf->rdpos < 0 || buf->rdpos >= buf->dsize
|| buf->wrpos < 0 || buf->wrpos >= buf->dsize) {
logfileOut(mask, "<buffer corrupt>"); return;
}
sep=0;
while (buf->rdpos < buf->wrpos) {
str_get_str(buf, str);
if (buf->sep=='\0') {
if (sep) logfileOut(mask, " ");
if (*str=='\0') {
logfileOut(mask, ".");
} else {
logfileOut(mask, "%s", str);
while (!StrEnd(buf)) {
ret=StrGet(buf, str, '\0');
if (ret==NULL) {
ret="...";
buf->rdpos=buf->wrpos;
}
sep=1;
if (ret[0]<32 && ret[0]>0) {
logfileOut(mask, "[%d]%s;", ret[0], ret+1);
} else {
if (sep) logfileOut(mask, "%c", buf->sep);
logfileOut(mask, "%s", str);
sep=1;
logfileOut(mask, "%s;", ret);
}
}
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_
#define _COC_LOGFILE_H_
#include "str_buf.h"
#include "myc_buf.h"
#define LOG_ALL 31
#define LOG_STAT 32
#define LOG_SER 8
#define LOG_NET 4
#define LOG_INFO 2
@ -13,10 +14,15 @@
void logfileStatusBuffer(char *buffer, int bufsize);
char *logfileInit(char *path, int nodate, int use_stdout, int write_all);
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 logfileMask(int mask);
void logfileScan(int date, void (*scanLine)(void*, char*), void *arg);
void logfileWrite(int mask);
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_ */

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 <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <strings.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include "myc_mem.h"
#include "sys_util.h"
#include "err_handling.h"
#include "myc_err.h"
#include "coc_logfile.h"
#include "coc_util.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 int maxfd;
struct CocClient *cList, *cLastCmd=NULL;
CocClient *cList;
static int mainFd;
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;
struct sockaddr_in sadr;
char *err;
if (bufsize==0) bufsize=1024;
ERR_P(buf=str_create_buf(bufsize, '\0'));
ERR_P(bufo=str_create_buf(bufsize,'\0'));
NEW(cList); /* empty header */
/* first try to connect to an existing server */
setData=setDataRtn;
/*
clDataSize=clientDataSize;
clData=clientData;
*/
NEW(cList,CocClient); /* empty header */
ERR_SI(mainFd=socket(AF_INET, SOCK_STREAM, 0));
i = 1;
ERR_SI(setsockopt(mainFd,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(int))); /* allow quick port reuse */
ERR_I(CocCreateSockAdr(&sadr, NULL, port));
ERR_SI(bind(mainFd, (struct sockaddr *)&sadr, sizeof(sadr)));
logfileOutRtn=CocToClients;
logfileOut(LOG_INFO, "created server on port %d\n", port);
ERR_SI(listen(mainFd, 8));
FD_ZERO(&mask);
FD_SET(mainFd, &mask);
maxfd=mainFd+1;
CocDefStr(loglist, COC_RDWR);
return(0);
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) {
struct sockaddr_in cadr;
struct hostent *h;
struct timeval tmo={0,1};
struct CocClient *cl, *cl0;
int i, newfd, setmode;
size_t cadrlen;
char *err, *varname;
CocClient *cl, *cl0;
CocVar *var;
int i, lmask, newfd, n, iret;
sys_adr_len cadrlen; /* see sys_util.h */
char *err, *cmd, *arg, *varname;
void *base;
rmask=mask;
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));
FD_SET(newfd, &mask);
if (newfd>=maxfd) maxfd=newfd+1;
cl=cList;
NEW(cl, CocClient);
cl->fd=newfd;
cl->mode=0;
cl->cmd[0]='\0';
cl->res[0]='\0';
NEW(cList);
if (setData!=NULL) {
ERR_P(cl->data = setData(NULL)); /* create new client data object */
}
/*
ERR_SP(cList=calloc(1,sizeof(CocClient)+clDataSize));
*/
cl->next=cList->next;
cList->next=cl;
h=gethostbyaddr(&cadr.sin_addr, 4, AF_INET);
h=gethostbyaddr((void *)&cadr.sin_addr, 4, AF_INET);
if (h==NULL) {
logfileOut(LOG_INFO, "(%d) open from %s\n", newfd, "local");
} else {
@ -93,8 +479,8 @@ int CocHandle1Request(int tmo_msec, int fd) {
cl0=cList; cl=cl0->next;
while (cl!=NULL) {
if (FD_ISSET(cl->fd, &rmask)) {
buf->wrpos=recv(cl->fd, buf->buf, buf->dsize, 0);
if (buf->wrpos<=0) {
iret=CocRecv(cl->fd, &buf, -1, NULL);
if (iret<=0) {
logfileOut(LOG_INFO, "(%d) disconnected\n",cl->fd);
close(cl->fd);
FD_CLR(cl->fd, &mask);
@ -102,76 +488,81 @@ int CocHandle1Request(int tmo_msec, int fd) {
FREE(cl);
cl=cl0;
} else {
str_put_start(bufo);
str_get_start(buf);
ERR_I(str_put_str(bufo, "")); /* empty error message */
setmode=0;
cl->logmask=0; /* stop output to log client */
lmask=0;
StrReset(&buf);
StrClear(&bufo);
err=NULL;
ERR_P(varname=str_get_str(buf, NULL));
logfileOut(LOG_NET, "(%d) ", cl->fd);
if (varname[0]=='#') { /* access code */
if (0==strcmp(varname,"#rdacc")) {
logfileOutBuf(LOG_NET, &buf);
/* cl->npend=0; why that ? */
logfileOut(LOG_NET, "\n");
cl->synch=buf.buf[0];
ERR_P(StrGet(&buf, NULL, cl->synch));
ERR_I(StrPut(&bufo, "", cl->synch));
while (!StrEnd(&buf)) {
ERR_P(varname=StrGet(&buf, NULL, ' '));
if (cl->synch==COC_MAGIC) { /* access code */
if (0==strcmp(varname,"rdacs")) {
logfileOut(LOG_INFO, "set read mode\n");
cl->mode=1;
} else if (0==strcmp(varname,"#rwacs")) {
ERR_I(StrPut(&bufo, "", COC_SEP)); /* empty message */
} else if (0==strcmp(varname,"rwacs")) {
logfileOut(LOG_INFO, "set write mode\n");
cl->mode=2;
ERR_I(StrPut(&bufo, "", COC_SEP)); /* empty message */
} else {
err="bad access code";
ERR_I(StrPut(&bufo, "", COC_ERR)); /* signal error message */
ERR_I(StrPut(&bufo, "bad access code", COC_SEP));
}
ERR_P(StrGet(&buf, NULL, COC_NUL)); /* skip separator */
} else if (cl->mode==0) {
err="no access";
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 {
while (1) {
if (varname[0]=='[') {
if (cl->mode<2) { err="no write access"; break; }
setmode=1; /* switch to set mode */
} 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;
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 {
ERR_I(CocGetThisVar(var, base, &buf, COC_SEP));
if (0==strcmp(var->name,"loglist")) {
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 {
if (0==strcmp("$", varname)) { /* special case: response */
ERR_I(str_put_str(bufo, cl->res));
cl->res[0]='\0';
} else {
i=CocPutVar(serverVarList, bufo, varname, 0);
if (i<0) {
err=ErrMessage; break;
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, " ");
logfileOutBuf(LOG_NET, &bufo);
logfileOut(LOG_NET, "\n");
} else {
str_put_start(bufo); /* reset output */
str_put_str(bufo, err); /* put error message */
logfileOut(LOG_NET, " (%s)\n", err);
/* logfileMask(LOG_NET); */
}
ERR_SI(send(cl->fd, bufo->buf, bufo->wrpos, 0));
ERR_I(CocSend(cl->fd, bufo.buf, bufo.wrpos));
cl->logmask=lmask;
}
}
cl0=cl; cl=cl->next;
@ -183,54 +574,30 @@ int CocHandle1Request(int tmo_msec, int fd) {
}
int CocHandleRequests(int tmo_msec, int fd) {
struct timeb tim1, tim0;
int tdif, iret;
int tdif, iret, tim0;
if (modified && fd==0) { /* earlier modification */
modified=0;
return(2);
}
ftime(&tim0);
tim0=mycMsecSince(0);
tdif=tmo_msec;
while (tdif>=0) {
ERR_I(iret=CocHandle1Request(tdif, fd));
if (fd==0) {
if (iret==2) return(2); /* modification of a varaible */
if (iret==2) return(2); /* modification of a variable */
} else {
if (iret==1) return(1); /* event on fd */
}
if (iret==0) return(0); /* timeout */
ftime(&tim1);
tdif=tmo_msec-((tim1.time-tim0.time)*1000+tim1.millitm-tim0.millitm);
tdif = tmo_msec - mycMsecSince(tim0);
}
return(0); /* timeout */
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() {
struct CocClient *cl, *cl0;
CocClient *cl, *cl0;
cl=cList->next;
while (cl!=NULL) {
@ -241,6 +608,4 @@ void CocCloseServer() {
}
FREE(cList);
close(mainFd);
str_free_buf(buf); str_free_buf(bufo);
logfileClose();
}

View File

@ -1,11 +1,78 @@
#ifndef _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 CocHandle1Request(int tmo_msec, int fd);
@ -30,11 +97,13 @@ int CocHandle1Request(int tmo_msec, int fd);
*/
struct CocClient *CocGetNextCmd(void);
/*
get next client with a pending command
/* server handlers removed
int CocPushHandler(const char *name);
*/
int CocCallHandlers(void);
void CocShowHandlers(char *buf, int buf_len);
void CocCloseServer(void);
#endif /* _SERVER_H_ */

View File

@ -1,24 +1,15 @@
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <strings.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <assert.h>
#include "sys_util.h"
#include "err_handling.h"
#include "str_util.h"
#include "myc_err.h"
#include "myc_str.h"
#include "coc_util.h"
/*-------------------------------------------------------------------------*/
/* CreateSocketAddress stolen from Tcl. Thanks to John Ousterhout */
CocVar *serverVarList=NULL;
static CocVar **varListHdl=&serverVarList;
int CocRD=0;
int CocWR=0;
int CocCreateSockAdr(
struct sockaddr_in *sockaddrPtr, /* Socket address */
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) {
struct timeval tmo;
@ -258,3 +53,59 @@ void CocDelay(int msec) {
tmo.tv_usec=(msec % 1000)*1000+1;
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_
#include <netinet/in.h>
#include "str_buf.h"
#include "myc_buf.h"
#define COC_CMD_LEN 256
#define COC_RES_LEN 8192
int CocCreateSockAdr(
struct sockaddr_in *sockaddrPtr, /* Socket address */
@ -12,76 +15,34 @@ int CocCreateSockAdr(
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);
/*
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_FLT -2
#define COC_PTR -3
#define COC_STRUCT -4
#define COC_TYPE -5
#define COC_ALIAS -6
/* macros to define variables */
#define CocDefInt(V,F) CocDefVar(#V,&V,COC_INT,&F)
#define CocDefFlt(V,F) CocDefVar(#V,&V,COC_FLT,&F)
#define CocDefStr(V,F) CocDefVar(#V,V,sizeof(V),&F)
#define CocDefPtr(V,S) CocDefVarS(#V,#S,&V,COC_PTR*(V!=(S *)NULL));
#define CocDefStruct(V,S) CocDefVarS(#V,#S,&V,COC_STRUCT*(&V!=(S *)NULL));
#define CocIntFld(S,V,F) CocDefVar(#S":"#V,&((S *)NULL)->V,COC_INT,&F);
#define CocFltFld(S,V,F) CocDefVar(#S":"#V,&((S *)NULL)->V,COC_FLT,&F);
#define CocStrFld(S,V,F) CocDefVar(#S":"#V,((S *)NULL)->V,sizeof(((S *)NULL)->V),&F);
#define CocDefCmd(V) CocDefVar("$",V,sizeof(V),&CocWR)
#define CocDefStrPtr(V,S,F) CocDefVar(#V,V,S,&F)
#define CocAlias(A,V) CocDefVar(#A, #V, COC_ALIAS, &CocRD);
#define COC_SEP '\0'
#define COC_DELAYED '\1'
#define COC_ERR '\2'
#define COC_TRM '\3'
#define COC_SYN0 '\4'
#define COC_SYN1 '\5'
#define COC_MAGIC '\6'
#define COC_CLRLOG '\7'
#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 i
integer lnblnk
integer lnblnk, iargc
l=0
str=' '

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -1,98 +1,65 @@
#include <stdio.h>
#include <stdlib.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 "err_handling.h"
#include "str_util.h"
#include "coc_util.h"
#include "tecs_cli.h"
#include "tecs_data.h"
static char device[80], command[80];
static int readTemp, configuring;
static float tempX, tempP, tempC;
static char response[COC_RES_LEN];
pTecsClient TeccInit(char *startcmd, int port) {
CocConn *conn;
static char *rwCode="rwacs";
static char *rdCode="rdacs";
NEW(conn);
NEW(conn, CocConn);
if (startcmd[0]=='#') {
ERR_I(CocInitClient(conn, startcmd+1, port, "#rwacs", 0, ""));
ERR_I(CocInitClient(conn, startcmd+1, port, rdCode, 0, ""));
} 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);
OnError: return(NULL);
}
int TeccGet3(pTecsClient conn, float *tC, float *tX, float *tP) {
readTemp=1;
ERR_I(CocCmd(conn, "tempC,tempX,tempP,[readTemp],configuring"));
*tC=tempC;
*tX=tempX;
*tP=tempP;
return(configuring);
int iret;
CocReset(conn);
ERR_I(CocGetFloat(conn, "set", tC));
ERR_I(CocGetFloat(conn, "tempX", tX));
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);
}
int TeccGet(pTecsClient conn, float *temp) {
readTemp=1;
ERR_I(CocCmd(conn, "tempP,[readTemp],configuring"));
*temp=tempP;
return(configuring);
OnError: return(-1);
}
int iret;
int TeccWait(pTecsClient conn) {
int last, cnt;
last=0;
cnt=0;
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);
CocReset(conn);
ERR_I(CocGetFloat(conn, "tempP", temp));
ERR_I(CocPutInt(conn, "readTemp", 1));
ERR_I(iret=CocDoIt(conn, response, sizeof(response)));
if (iret) ERR_MSG(response);
return(0);
OnError: return(-1);
}
int TeccSet(pTecsClient conn, float temp) {
tempC=temp;
ERR_I(CocCmd(conn, "[tempC]"));
return(0);
OnError: return(-1);
}
int iret;
int TeccSend(pTecsClient conn, char *cmd, char *reply, int replyLen) {
char *res;
int cnt;
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);
CocReset(conn);
ERR_I(CocPutFloat(conn, "set", temp));
ERR_I(iret=CocDoIt(conn, response, sizeof(response)));
if (iret) ERR_MSG(response);
return(0);
OnError: return(-1);
}
@ -102,7 +69,9 @@ int TeccQuitServer(pTecsClient conn) {
ERR_I(iret=CocCheck(conn));
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;
while (iret==0 && cnt>0) {
CocDelay(100);
@ -110,12 +79,15 @@ int TeccQuitServer(pTecsClient conn) {
cnt--;
}
}
if (iret==1) return(0);
ERR_MSG("Does not quit within 5 seconds");
OnError:
return(-1);
}
int TeccSend(pTecsClient conn, char *cmd, char *reply, int replyLen) {
return(CocSetGetN(conn, "send", cmd, reply, replyLen));
}
void TeccClose(pTecsClient conn) {
if (conn!=NULL) {
CocCloseClient(conn);
@ -136,48 +108,86 @@ void TeccClose(pTecsClient conn) {
#ifdef __VMS
#define tecs_get_par_ tecs_get_par
#define tecs_get_mult_ tecs_get_mult
#define tecs_set_par_ tecs_set_par
#define tecs_send_ tecs_send
#define tecs_init_ tecs_init
#define tecs_get3_ tecs_get3
#define tecs_get_ tecs_get
#define tecs_set_ tecs_set
#define tecs_wait_ tecs_wait
#define tecs_is_open_ tecs_is_open
#define tecs_close_ tecs_close
#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
static pTecsClient conn=NULL;
int tecs_set_par_(F_CHAR(name), F_CHAR(par), int name_len, int par_len) {
char nbuf[64], pbuf[256];
int tecs_set_par_(F_CHAR(name), F_CHAR(par), int *show, int name_len, int par_len) {
char nbuf[64], pbuf[COC_CMD_LEN];
int iret=-1;
STR_TO_C(nbuf, name);
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);
OnError: return(iret);
OnError: return(-1);
}
int tecs_get_par_(F_CHAR(name), F_CHAR(par), int name_len, int par_len) {
char nbuf[64], pbuf[256];
int tecs_get_par_(F_CHAR(name), F_CHAR(par), int *show, int name_len, int par_len) {
char *b, nbuf[64], pbuf[COC_RES_LEN];
int iret=-1;
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));
OnError: return(iret);
OnError: return(-1);
}
int tecs_send_(F_CHAR(cmd), F_CHAR(reply), int cmd_len, int reply_len) {
char cbuf[80], rbuf[80];
int tecs_get_mult_(F_CHAR(names), int *time, int *nvalues, float values[], int names_len) {
char *b, nbuf[64], pbuf[COC_RES_LEN];
char *nams, nam[32];
int i;
STR_TO_C(cbuf, cmd);
ERR_I(TeccSend(conn, cbuf, rbuf, sizeof(rbuf)));
return(STR_TO_F(reply, rbuf));
STR_TO_C(nbuf, names);
CocReset(conn);
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);
}
@ -191,19 +201,21 @@ int tecs_init_(F_CHAR(startcmd), int *port, int startcmd_len) {
}
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) {
return(TeccGet3(conn, t1, t2, t3));
ERR_I(TeccGet3(conn, t1, t2, t3));
return(0);
OnError: return(-1);
}
int tecs_set_(float *temp) {
return(TeccSet(conn, *temp));
}
int tecs_wait_(void) {
return(TeccWait(conn));
ERR_I(TeccSet(conn, *temp));
return(0);
OnError: return(-1);
}
int tecs_is_open_() {
@ -216,7 +228,141 @@ void tecs_close_(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

View File

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

View File

@ -1,26 +1,33 @@
program tecs_client
real*4 temp(4)
character device*32, init*80, line*80, cmd*16, par*80, response*80
real temp
character device*32, init*80, line*80, cmd*16, par*80, response*1024
integer i,j,k,iret,l
character file*128, cmdpar*128
character cmdpar*128
character prompt*32/'tecs>'/
integer promptlen/6/
logical oneCommand
character logarg*4/'25'/
character defcmd*8/'status'/
! 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_get_cmdpar(line, l)
if (l .ne. 0) then
if (line .eq. 'off' .or. line .eq. 'OFF') init=' '
oneCommand=.true.
else
oneCommand=.false.
endif
if (init .eq. ' ') then
call tecs_open(0, ' ', iret)
if (oneCommand .and. line(1:1) .eq. '#') then
call tecs_open(0, line, iret)
oneCommand=.false.
else if (init .eq. ' ') then
call tecs_open(0, line, iret)
else
call tecs_open(1, init, iret)
endif
@ -38,7 +45,8 @@
print *,'device <device> set cryo device'
print *,'<parameter> show 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 *,'kill close TecsServer and exit'
print *,'exit,quit exit, but do not close TecsServer'
@ -47,7 +55,7 @@
l=0
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
11 l=l+1
line(l:l)=' '
@ -61,44 +69,54 @@
cmd(k:k)=char(ichar(cmd(k:k))+32)
endif
elseif (k .gt. 0) then ! end of command
goto 2
endif
enddo
if (k .eq. 0) then ! empty line
call tecs_get_t(6, temp, iret)
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
endif
print *,'command too long'
goto 1
2 par=' '
par=' '
do i=j,l
if (line(i:i) .gt. ' ') then
par=line(i:l)
goto 3
goto 3 ! command with parameter
endif
enddo
goto 2 ! parameterless command
endif
enddo
! simple query
if (k .ne. 0) then
print *,'command too long'
goto 1
endif
if (cmd .eq. 'kill' .or. cmd .eq. 'off') then
! empty command
12 cmd=defcmd
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()
elseif (cmd .eq. 'exit' .or. cmd .eq. 'quit') then
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
goto 11
elseif (cmd .eq. 'plot') then
iret=tecs_get_par('dlogfile', file)
if (iret .lt. 0) goto 19
call tecs_plot(file)
call tecs_plot('Tm Ts Tr P', 1)
elseif (cmd .eq. 'help') then
print *
print *,'Writeable parameters:'
@ -116,9 +134,9 @@
print *
print *,'Read only parameters:'
print *
print *,'tX heat exchanger temperature'
print *,'tS sample temperature'
print *,'tempH set-point on regulation'
print *,'Tm main temperature'
print *,'Ts sample temperature'
print *,'setH set-point on regulation'
print *,'tLimit temperature limit'
print *,'htr heater current percentage'
print *,'resist heater resistance'
@ -126,10 +144,7 @@
print *,'remoteMode 1: local, 2: remote '
1 ,'(switch on with device command)'
print *
print *,'t1 regulation temperature (hi-T sensor)'
print *,'t2 regulation temperature (low-T sensor)'
print *,'t3 sample temperature (hi-T sensor)'
print *,'t4 sample temperature (low-T sensor)'
print *,'Ta,Tb,Tc,Td values of channels A,B,C,D'
print *
print *,'Temperature devices:'
print *
@ -139,33 +154,43 @@
print *,'ccr4k (4K closed cycle), hef4c (TriCS 4circle cryo)'
print *,'sup4t (supra.magnet 4T)'
print *,'rdr11, rdr12 (LTF dilution 1 & 2, 20kOhm)'
1 ,', rdrn11_2, rdr12_2 (2kOhm)'
print *
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
call show_log(50, file)
else
iret=tecs_get_par(cmd, response)
iret=tecs_get_par(cmd, response, 2)
if (iret .lt. 0) goto 19
print '(7x,3a)',cmd(1:k),'=',response
endif
goto 1
3 if (cmd .eq. 'send') then
iret=tecs_send(par, response)
3 continue ! command with parameter
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
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
iret=tecs_set_par(cmd, par)
iret=tecs_set_par(cmd, par, 2)
if (iret .lt. 0) goto 19
print '(7x,3a)',cmd(1:k),':=',par
endif
goto 1
@ -182,27 +207,21 @@
99 end
subroutine show_log(lines, file)
integer function show_log(lines)
integer lines
character*(*) lines
integer i,l
character str*132, file*(*)
character str*8192
! functions
integer tecs_get_par, tecs_set_par
if (lines .ne. ' ') then
l=tecs_set_par('logstart', lines, 0)
print *,'line: ',lines
print *
print *
open(1, name=file, status='old', readonly, shared, err=39)
i=0
31 read(1,'(a)',end=32)
i=i+1
goto 31
32 rewind(1)
do i=1,i-lines
read(1,*,end=39)
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)
endif
show_log=tecs_get_par('logline', str, 1)
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 V01A 21-Mar-2000 DM. Integrate into TASMAD
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 V01D 12-May-2000 M.Z. Changed error handling, no longer automatic call to TECS_OPEN
c------------------------------------------------------------------------------
@ -102,11 +102,18 @@ c extract the port number from the start command
i=index(init, '-p ')
if (i .eq. 0) i=index(init, '-P ')
if (i .ne. 0) then
read(init,*,iostat=ios) port
read(init(min(len(init),i+3):),*,iostat=ios) port
endif
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
@ -131,7 +138,7 @@ c if INIT exists, read it to get the port number and the start command
end
SUBROUTINE TECS_GET_T (IOLUN, TEMP, IRET) !!
!! ============================================
!! =========================================
!!
!! Get temperatures and wait if TECS is configuring
!!
@ -152,18 +159,18 @@ c------------------------------------------------------------------------------
return
endif
if (iret .gt. 0) then
write(iolun, *) 'configuring temperature controller ...'
iret=tecs_wait()
if (iret .lt. 0) then
call err_txt('tecs_wait'//char(10)//'tecs_get_t')
return
endif
write(iolun, *) '... done'
iret=tecs_get3(temp(1), temp(3), temp(2)) ! temp(2) and temp(3) are exchanged in MSHOWT
if (iret .lt. 0) then
call err_txt('tecs_get3(2)'//char(10)//'tecs_get_t')
return
endif
! write(iolun, *) 'configuring temperature controller ...'
! iret=tecs_wait()
! if (iret .lt. 0) then
! call err_txt('tecs_wait'//char(10)//'tecs_get_t')
! return
! endif
! write(iolun, *) '... done'
! iret=tecs_get3(temp(1), temp(3), temp(2)) ! temp(2) and temp(3) are exchanged in MSHOWT
! if (iret .lt. 0) then
! call err_txt('tecs_get3(2)'//char(10)//'tecs_get_t')
! return
! endif
endif
temp(4)=0.0 ! no auxilliary sensor
end

View File

@ -3,11 +3,11 @@
#include <stdarg.h>
#include <string.h>
#include <assert.h>
#include "err_handling.h"
#include "myc_err.h"
#include "coc_logfile.h"
#include "coc_util.h"
#include "coc_server.h"
#include "tecs_lsc.h"
#include "str_util.h"
#include "myc_str.h"
#define MAX_PAR 16
#define MAX_ARG 9
@ -46,15 +46,14 @@ char *LscCmd(SerChannel *ser, const char *cmds) {
char *blank, *colon, *qu, *res;
const char *p, *this, *next, *cmd_ptr, *retreq;
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 varname[32];
Str_Buf sbuf;
DeclStrBuf(sbuf, SER_BUF_LEN);
int nres, i, j, response;
nres=0;
response=0;
str_link_buf(&sbuf, buf, sizeof(buf), STR_NOSEPARATOR);
this=cmds;
while (this!=NULL) {
next=str_split(cmd, this, ';');
@ -67,13 +66,13 @@ char *LscCmd(SerChannel *ser, const char *cmds) {
}
cmd_ptr=sbuf.buf+sbuf.wrpos; /* pointer to command in buffer */
p=str_split(seg, cmd, '[');
ERR_I(str_put_str(&sbuf, seg));
ERR_I(StrPut(&sbuf, seg, StrNONE));
while (p!=NULL) { /* substitute variables */
p=str_split(varname, p, ']');
if (p==NULL) ERR_MSG("missing ']'");
ERR_I(CocPutVar(serverVarList, &sbuf, varname, 0));
ERR_I(CocPutVar(varname, &sbuf, StrNONE));
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));
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]=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 */
if (colon==blank) colon++;
cmd[colon-cmd_ptr]='\0';
ERR_I(str_put_str(&sbuf, cmd)); /* put query */
ERR_I(str_put_str(&sbuf, ";"));
ERR_I(StrPut(&sbuf, cmd, ';')); /* put query */
response=1;
} else {
qu=strchr(cmd, '?');
ERR_I(str_put_str(&sbuf, ";"));
ERR_I(StrPut(&sbuf, ";", StrNONE));
if (qu!=NULL) { /* command is a query */
response=1;
if (retreq==NULL) {
@ -110,11 +108,11 @@ char *LscCmd(SerChannel *ser, const char *cmds) {
}
if (!response) {
ERR_I(str_put_str(&sbuf, "busy?"));
ERR_I(StrPut(&sbuf, "busy?",'\0'));
} 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");
/*
list[0..nres-1] contains a now:
@ -158,18 +156,19 @@ char *LscCmd(SerChannel *ser, const char *cmds) {
}
}
if (retreq!=NULL) { /* query */
str_link_buf(&sbuf, result, 0, ',');
StrLink(&sbuf, result);
str_split(par, retreq+1, ';');
p=par;
while (p!=NULL) {
p=str_split(varname, p, ',');
if (varname[0]!='\0') {
if (p==NULL) { /* last element: get rest of line */
sbuf.sep='\0';
}
ERR_I(CocGetVar(serverVarList, &sbuf, varname, 0));
ERR_I(CocGetVar(varname, &sbuf, '\0'));
} else {
ERR_P(str_get_str(&sbuf, NULL));
ERR_I(CocGetVar(varname, &sbuf, ','));
}
} else {
ERR_P(StrGet(&sbuf, varname, ','));
}
}
}
@ -177,3 +176,33 @@ char *LscCmd(SerChannel *ser, const char *cmds) {
return(res);
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"
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);
@ -49,4 +49,8 @@ int LscEqPar(char *par, char *res);
if any parameter in par is omitted, it is not compared
*/
char *LscReadStat(int stat);
char *LscHtrStat(int stat);
#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
real, parameter :: winmin=60., undef=-65535.0
integer, parameter :: dmax=1000, nmax=5, nmenu=11, chartfreq=1
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 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 ex,ey,fx,fy,hmenu,wmenu,ymenu,ticks
real*4 xbox(8), ybox(8)
integer l,j,i,t0,t1,ntot,i1,i2,rl,n,startday,thisday
integer first,last,tbase,lastj
integer color(3)/2,4,3/
real*4 ex,ey,fx,fy,row,ticks,tim0,tim1
integer l,j,i,n,t,leng,i1,i2,rl,startday,thisday
integer nset
integer first,last,step,tbase,lastj
integer color(nmax)
integer retLen(nmax)
character key*1
character text(nmenu)*12/ &
'live off','sel. zoom','zoom in','zoom out','show all','n days','n hours','n min','file','quit'/
character keys*(nmenu)/'LZ+-XDHMFQ'/
character weekdays(7)*3/'Mon','Tue','Wed','Thu','Fri','Sat','Sun'/
character buf*8, device*8, line*40, filnam*128
'live off','sel. zoom','zoom in','zoom out','show all','n days','n hours','n min','date','file','quit'/
character keys*(nmenu)/'LZ+-XDHMTFQ'/
character weekdays(7)*4/'Mon','Tue','Wed','Thu','Fri','Sat','Sun'/
character buf*8, device*8, name*40, filnam*128, numb*16
character(len=16) parnam(nmax)
external tplot_close
logical gap, done
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.
zoom=.false.
right=.true.
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)
if (device=='NULL') then
print *,'No PGPLOT-Device defined'
@ -38,72 +57,104 @@ subroutine tecs_plot(file)
endif
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.)
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
step=0
1 if (right .or. window==0 .or. live) then
ntot=dlog_get(dmax, nset, tbase, -window*1.1, 0.0, undef, xd, yd)
if (ntot<=0) then
if (ntot<0) then
call err_txt('dlog_get')
goto 99
endif
x2=last-tbase
else
x2=maxval(xd(1:ntot))
endif
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
1 iret=tecs_get_mult(pars, t, nset, yy0)
if (iret < 0) goto 99
if (window == 0) then
last=t
step=maxRange/dmax
window=maxRange
first=t-min(dmax*step-1,maxRange-step)
else if (right .or. live) then
step=window/(dmax-1)+0.99
last=t
first=t-min(dmax*step-1,nint(window)-step)
else
if (.not. zoom) then
x2=(x1+x2+window)/2
x1=x2-window
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
step=(x2-x1)/(dmax-1)+0.99
last=nint(x2)+tbase
first=nint(x1)+tbase
endif
if (ntot<0) then
call err_txt('dlog_get')
goto 99
endif
if (saveit) goto 9
if (ntot>0) then
xmin=minval(xd(1:ntot))
xmax=maxval(xd(1:ntot))
if (step == 0) step=1
iret=tecs_get_data(pars, first, last, step, yd, dmax, nmax, retLen)
if (iret < 0) goto 99
! 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
xmin=x1
xmax=x2
x1 = first - tbase;
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
call pgsvp(0.07,0.93,0.1,0.9) ! define window size
if (xmax<=xmin) then
xmax=xmin+1
! l=0
! print *,'no points found'
! print *
! goto 9
if (window>50*3600) then
ticks=8*3600
elseif (window>25*3600) then
ticks=4*3600
else
ticks=0.0 ! automatic
endif
call pgsch(1.0)
i1=1
i2=2
i2=nset-naux
do rl=1,2
if (zoom) then
ymin(1)=y1
@ -114,13 +165,13 @@ subroutine tecs_plot(file)
ylast1=ymin(rl)
ylast2=ymax(rl)
do i=i1,i2
do j=1,ntot
if (xd(j) >= x1 .and. xd(j) <= x2 .and. yd(j,i)/=undef) then
do j=1,retLen(i)
if (yd(j,i)/=undef) then
ymin(rl)=min(ymin(rl),yd(j,i))
ymax(rl)=max(ymax(rl),yd(j,i))
endif
enddo
do j=max(1,ntot-4),ntot
do j=max(1,retLen(i)-4),retLen(i)
if (yd(j, i)/=undef) then
ylast1=min(ylast1,yd(j, i))
ylast2=max(ylast2,yd(j, i))
@ -130,169 +181,190 @@ subroutine tecs_plot(file)
ey=(ymax(rl)-ymin(rl))
fy=abs(ymax(rl))
if (rl==1) then
ymax(rl)=ymax(rl)+max(fy*0.0075,ey*0.25)
ymax(rl)=ymax(rl)+max(fy*0.0075,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
ymin(rl)=min(ymin(rl),max(0.0,ylast1-ey*0.4))
ymax(rl)=max(ymax(rl),ylast2+ey*0.4)
endif
endif
if (ymax(rl) .lt. ymin(rl)) then
ymax(rl)=1
ymin(rl)=0
elseif (ymax(rl) .eq. ymin(rl)) then
ymax(rl)=ymin(rl)+1.0
if (ymax(rl) < ymin(rl)) then
ymax(rl)=1.0
ymin(rl)=0
elseif (ymax(rl) == ymin(rl)) then
ymax(rl)=ymin(rl)*1.00001+1.0
ymin(rl)=-1.0e-3
endif
zoom=.false.
call pgswin(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)
call set_win(rl,x1,x2,ymin(rl),ymax(rl))
do i=i1,i2
do i=i2,i1,-1
call pgsci(color(i))
n=0
lastj=1
do j=1,ntot
do j=1,retLen(i)
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
endif
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
i1=3
i2=3
enddo
rl=2
call pgsci(1)
! 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
call pgswin(x1,x2,ymin(rl),ymax(rl))
ey=ymax(rl)-(ymax(rl)-ymin(rl))*0.21
if (rl == 1) then
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
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 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 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
call pgsch(0.8)
rl=1
call set_win(rl,x1,x2,ymin(rl),ymax(rl))
call pgsci(1)
call pgsclp(0)
hmenu=(ymax(rl)-ymin(rl))/15.
ymenu=ymax(rl)+hmenu*0.5
wmenu=(x2-x1)/(nmenu+2)
if (live) then
text(1)='live off'
else
text(1)='live on'
endif
call pgsch(0.7)
ex=0.0
do i=1,nmenu
xbox(1)=x1+(i-0.7)*wmenu
ybox(1)=ymenu+hmenu
xbox(2)=xbox(1)
ybox(2)=ymenu+hmenu*0.5
xbox(3)=x1+(i-0.95)*wmenu
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))
call pglen(5, trim(text(i)), fx, fy)
call pgmtxt('T', 3.0, ex, 0.0, '|'//keys(i:i))
call pgmtxt('T', 2.5, ex, 0.0, '|')
call pgmtxt('T', 2.0, ex, 0.0, '|'//text(i))
ex=ex+fx+0.01
enddo
call pgmtxt('T', 3.5, 1.0, 1.0, 'any digit to enter n')
call pgmtxt('T', 2.0, 0.9, 1.0, 'n=')
thisday=(x1+x2)/2/(24*3600)
ey=ymin(rl)-hmenu*1.5
i=max(0,int((x1+12*3600)/(24*3600)))
call pgmtxt('T', 3.0, ex, 0.0, '|')
call pgmtxt('T', 2.5, ex, 0.0, '|')
call pgmtxt('T', 2.0, ex, 0.0, '|')
call pgmtxt('T', 3.0, 0.8, 0.0, 'any digit to enter n')
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
ex=(i+0.5)*24*3600
ex=(i+0.5)*oneDay
if (ex > x2) EXIT
thisday=0
call pgptxt(ex, ey, 0.0, 0.5, weekdays(mod(i,7)+1))
done=.true.
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
if (ex .gt. x1) then
if (ex > x1) then
call pgmove(ex, ey)
call pgdraw(ex, ey+hmenu/2)
call pgdraw(ex, ey+row)
endif
ex=ex+24*3600
if (ex .lt. x2) then
ex=ex+oneDay
if (ex < x2) then
call pgmove(ex, ey)
call pgdraw(ex, ey+hmenu/2)
call pgdraw(ex, ey+row)
endif
i=i+1
enddo
if (thisday>0) then
call pgptxt((x1+x2)/2, ey, 0.0, 0.5, weekdays(mod(thisday,7)+1))
if (.not. done) then
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
call pgsclp(1)
call get_key(key, 0, 0) ! purge buffer
numb=0
numl=0
numb=' '
7 if (live) 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
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)
if (ntot<0) then
call err_txt('dlog_open_r 2')
goto 99
endif
if (ntot .gt. 1) then
i1=1
i2=2
do rl=1,2
call pgswin(x1,x2,ymin(rl),ymax(rl))
do i=i1,i2
call pgsci(color(i))
n=0
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
do while (key == char(0)) ! no key pressed
iret=tecs_get_mult(pars, t, nset, yy1)
if (iret<0) goto 99
tim1=t-tbase
if (tim1 > x2) then
call pgpage
window=x2-x1
goto 1
endif
if (tim1 > tim0) then
i1=1
i2=nset-naux
do rl=1,2
call set_win(rl,x1,x2,ymin(rl),ymax(rl))
do i=i2,i1,-1
if (yy0(i) .ne. undef .and. yy1(i) .ne. undef) then
if (yy1(i) < ymin(rl) .or. yy1(i) > ymax(rl)) then
call pgpage
window=x2-x1
goto 1
endif
call pgsci(color(i))
call pgmove(tim0, yy0(i))
call pgdraw(tim1, yy1(i))
endif
yy0(i)=yy1(i)
enddo
if (ntot .gt. lastj) call pgline(ntot+1-lastj, xd(lastj), yd(lastj,i))
i1=nset-naux+1
i2=nset
enddo
i1=3
i2=3
enddo
xmax=max(xmax,xd(ntot))
tim0=tim1
endif
call get_key(key, 0, chartfreq)
enddo
@ -301,16 +373,11 @@ subroutine tecs_plot(file)
call must_purge
endif
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)
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
window=min(window*2, 8*24*3600.)
window=min(window*2, 8.0*oneDay)
elseif (key=='X') then
window=0
live=.false.
@ -319,10 +386,10 @@ subroutine tecs_plot(file)
elseif (key=='Z') then
call pgsci(1)
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)
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
call pgsci(5)
xmin=x1
@ -349,16 +416,13 @@ subroutine tecs_plot(file)
zoom=.true.
live=.false.
right=.false.
elseif (key .ge. '0' .and. key .le. '9') then
numb=numb*10+(ichar(key)-ichar('0'))
if (numb>0) then
write(buf, '(i8)') numb
l=1
do while (buf(l:l)==' ')
l=l+1
enddo
elseif (key >= '0' .and. key <= '9' .or. key == '.') then ! number
if (numl .lt. len(numb)) then
numl=numl+1
numb(numl:numl)=key
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
if (device(1:1)=='X' .and. .not. live) then
call pgcurs(ex, ey, key)
@ -368,35 +432,59 @@ subroutine tecs_plot(file)
endif
if (key/=char(0)) goto 8
goto 7
elseif (key .eq. 'D') then
window=min(7*24*3600,24*3600*max(1,numb))
elseif (key == 'D') then
ex=1
read(numb, *, iostat=i) ex
window=min(maxRange,max(minRange, nint(oneDay*ex)))
right=.true.
x1=0
elseif (key .eq. 'H') then
window=min(7*24*3600,3600*max(1,numb))
elseif (key == 'H') then
ex=1
read(numb, *, iostat=i) ex
window=min(maxRange,max(minRange, nint(3600*ex)))
right=.true.
x1=0
elseif (key .eq. 'M') then
window=min(7*24*3600,60*max(1,numb))
elseif (key == 'M') then
ex=1
read(numb, *, iostat=i) ex
window=min(maxRange,max(minRange, nint(60*ex)))
right=.true.
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
if (live) then
right=.true.
x2=xmax
endif
elseif (key .eq. 'F') then
elseif (key == 'F') then
saveit=.true.
elseif (key=='Q' .or. key==char(13)) then
elseif (key=='Q' .or. key==char(13) .or. key==char(10)) then
goto 9
elseif (key == 'R') then
elseif (live) then
goto 7
endif
numb=0
numl=0
numb=' '
call pgpage
goto 1
99 call tecs_write_error(6)
99 call tecs_write_msg(6)
9 continue
call tplot_close
call get_key(key, 0, 0) ! purge type-ahead-buffer
@ -406,19 +494,35 @@ subroutine tecs_plot(file)
print '(x,a,$)', 'Filename: '
read(*,'(a)') filnam
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
write(line, '(4(f9.4,a))') xd(i)/3600., (char(9), max(-999.,min(9999.,yd(i,j))), j=1,3)
do j=1,3
gap=.false.
do j=1,nset
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
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
enddo
write(lund, *) line(1:39)
enddo
close(lund)
print *, ntot+1, ' lines written to ',filnam(1:48)
print *, retLen(1)+1, ' lines written to ',filnam(1:48)
endif
end subroutine
subroutine get_key(key, tmo1, tmo2)
@ -439,7 +543,20 @@ entry must_purge
purge=.true.
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
call pgclos
call dlog_close_r
! call dlog_close_r
end subroutine

View File

@ -1,27 +1,37 @@
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/timeb.h>
#include <assert.h>
#include <sys/socket.h>
#include <sys/time.h>
#include "rs232c_def.h"
#include "asynsrv_def.h"
#include "sinq_prototypes.h"
#include "sys_util.h"
#include "err_handling.h"
#include "myc_err.h"
#include "tecs_serial.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 */
void (*idleHandler)(int,int);
struct SerChan {
typedef struct {
int type; /* = ASYNSRV_TYPE */
struct AsynSrv__info asyn_info; /* Contains skt, host, port & chan */
struct RS__MsgStruct to_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) {
char *a_txt;
@ -31,43 +41,182 @@ void SerA_error(void) {
ErrMsg("asynsrv error"); ErrTxt(a_txt,0);
}
SerChannel *SerOpen(const char *host, int msecTmo, void (*idleHdl)(int,int)) {
struct SerChan *ser;
char hbuf[64], cport[16];
char *p, *c;
int port, chan, iRet;
int SerWait(int tmo_msec, int fd) {
struct timeval tmo;
fd_set mask;
int i;
idleHandler=idleHdl;
NEW(ser);
str_copy(hbuf, host);
p=str_split(ser->asyn_info.host, hbuf, ':');
port=4000;
chan=0;
if (p!=NULL) {
c=str_split(cport, p, '/');
if (c!=NULL) chan=atoi(c);
port=atoi(cport);
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);
}
ser->asyn_info.port=port;
ser->asyn_info.chan=chan;
A_CHK(AsynSrv_Open(&ser->asyn_info));
SerChannel *SerOpen(const char *hostPort, int msecTmo, int (*idleHdl)(int,int)) {
AsynSrvChan *aser;
TermSrvChan *tser;
char hbuf[64], cport[16], host[32];
char *p, *c;
struct sockaddr_in sadr;
int iret;
time_t t1, t2;
static int ecnt;
time(&t1);
str_copy(hbuf, hostPort);
p=str_split(host, hbuf, ':');
assert(p!=NULL);
c=str_split(cport, p, '/');
if (msecTmo==0) msecTmo=5000;
A_CHK(AsynSrv_Config(&ser->asyn_info, "msecTmo", msecTmo, "idleHdl", idleHdl, NULL));
logfileOut(LOG_MAIN, "connection to %s:%d/%d opened\n", ser->asyn_info.host, ser->asyn_info.port, ser->asyn_info.chan);
return((SerChannel *)ser);
if (c!=NULL) {
NEW(aser, AsynSrvChan); aser->type=ASYNSRV_TYPE;
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:
return(NULL);
}
int SerClose(SerChannel *serch) {
struct SerChan *ser;
ser=(struct SerChan *)serch;
A_CHK(AsynSrv_Close(&ser->asyn_info, 0));
return(0);
OnError: return(-1);
}
/* obsolete ?
char *SerCmdC(SerChannel *serch, const char *cmnd) {
char cmd[SER_BUF_LEN];
int l;
@ -78,33 +227,5 @@ char *SerCmdC(SerChannel *serch, const char *cmnd) {
return(SerCmd(serch, cmd));
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
typedef struct { int private; } SerChannel;
typedef struct {
/* private */
int type;
} SerChannel;
SerChannel *SerOpen(const char *host, int msecTmo, void (*idleHdl)(int,int));
char *SerCmdC(SerChannel *ser, const char *cmnd);
SerChannel *SerOpen(const char *host, int msecTmo, int (*idleHdl)(int,int));
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_ */