new tecs version M.Z.08.2001
This commit is contained in:
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
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(CocCmdWithRetry(conn));
|
||||
buf=&conn->resbuf;
|
||||
while (buf->buf[0] != conn->synch) { /* throw away unsynchronized answers */
|
||||
ERR_I(CocRecv(conn->fd, buf, COC_NETTMO, NULL));
|
||||
}
|
||||
|
||||
ERR_I(iret=CocCmdWithRetry(conn));
|
||||
pending=conn->nargs;
|
||||
*res='\0';
|
||||
while (1) {
|
||||
if (buf->buf[0] != conn->synch) ERR_MSG("synch error");
|
||||
ERR_P(StrGet(buf, NULL, conn->synch));
|
||||
i=0;
|
||||
a=conn->args;
|
||||
while (pending>0 && i<conn->nargs) {
|
||||
if (a->type!=0) {
|
||||
resp=buf->buf + buf->rdpos;
|
||||
tag=*resp;
|
||||
if (tag==COC_DELAYED) { /* delayed response */
|
||||
resp++;
|
||||
ERR_P(StrGet(buf, NULL, COC_SEP));
|
||||
} else {
|
||||
pending--;
|
||||
if (tag==COC_ERR || tag==COC_TRM) { /* error response */
|
||||
str_ncat(res, a->cmd, res_len);
|
||||
resp++;
|
||||
ERR_P(StrGet(buf, NULL, COC_SEP));
|
||||
str_ncat(res, ": ", res_len);
|
||||
iret=1;
|
||||
if (tag==COC_TRM) return(1);
|
||||
} else {
|
||||
if (a->adr==NULL) {
|
||||
t=strchr(res, COC_SEP);
|
||||
str_ncat(res, a->cmd, res_len);
|
||||
t=strchr(t, ' ');
|
||||
assert(t!=NULL); /* truncate argument */
|
||||
*t=COC_SEP;
|
||||
str_ncat(res, "=", res_len);
|
||||
ERR_P(StrGet(buf, NULL, COC_SEP));
|
||||
} else {
|
||||
str_ncat(res, a->cmd, res_len);
|
||||
str_ncat(res, "=", res_len);
|
||||
if (a->type==COC_INT) {
|
||||
ERR_I(StrGetInt(buf, (int *)a->adr, COC_SEP));
|
||||
} else if (a->type==COC_FLT) {
|
||||
ERR_I(StrGetFloat(buf, (float *)a->adr, COC_SEP));
|
||||
} else if (a->type>1) {
|
||||
ERR_P(StrNGet(buf, (char *)a->adr, a->type, COC_SEP));
|
||||
} else {
|
||||
ERR_MSG("unknown type");
|
||||
}
|
||||
a->type=0;
|
||||
}
|
||||
}
|
||||
str_ncat(res, resp, res_len);
|
||||
str_ncat(res, "\n", res_len);
|
||||
}
|
||||
}
|
||||
i++; a++;
|
||||
}
|
||||
ERR_I(StrGetEnd(buf));
|
||||
if (pending==0) return(iret); /* no more delayed response awaiting */
|
||||
|
||||
/* read values */
|
||||
s=rwList;
|
||||
setmode=0;
|
||||
do {
|
||||
t=strchr(s, ',');
|
||||
if (t==NULL) t=s+strlen(s);
|
||||
if (*s=='[') {
|
||||
s++;
|
||||
setmode=1;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
i=t-s;
|
||||
if (setmode) {
|
||||
if (*(t-1)==']') setmode=0;
|
||||
} else {
|
||||
str_ncpy(nam, s, i+1);
|
||||
ERR_I(CocGetVar(conn->varList, conn->resbuf, nam, 0));
|
||||
}
|
||||
s=t+1;
|
||||
} while (*t!='\0');
|
||||
ERR_I(str_get_end(conn->resbuf));
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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_ */
|
||||
|
@ -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) {
|
||||
if (lnam[0]=='\0') {
|
||||
str_copy(filnam, "test.log");
|
||||
} else {
|
||||
str_copy(filnam, lnam);
|
||||
str_append(filnam, ".log");
|
||||
}
|
||||
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 {
|
||||
sprintf(filnam, "%s%04d-%02d-%02d.log", lnam, tim->tm_year+1900, tim->tm_mon+1, tim->tm_mday);
|
||||
str_copy(filnam, lnam);
|
||||
str_append(filnam, ".log");
|
||||
}
|
||||
}
|
||||
if (dated) {
|
||||
fil=fopen(filnam, "a+");
|
||||
if (fil != NULL) {
|
||||
fseek(fil, 0, SEEK_SET); /* set position to start */
|
||||
year=0;
|
||||
fscanf(fil, "%4d", &year);
|
||||
if (year != openDate / 10000) {
|
||||
fclose(fil);
|
||||
fil=fopen(filnam, "w+"); /* overwrite old logfile */
|
||||
} else {
|
||||
fseek(fil, 0, SEEK_END); /* set position to end */
|
||||
}
|
||||
}
|
||||
} else {
|
||||
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 */
|
||||
str_ncat(statusBuf, buf, statusSize);
|
||||
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'));
|
||||
eptr+=strlen(eptr);
|
||||
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 (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;
|
||||
if (text==NULL) {
|
||||
if (stamp>lastStamp+1) {
|
||||
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);
|
||||
}
|
||||
sep=1;
|
||||
while (!StrEnd(buf)) {
|
||||
ret=StrGet(buf, str, '\0');
|
||||
if (ret==NULL) {
|
||||
ret="...";
|
||||
buf->rdpos=buf->wrpos;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
@ -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_ */
|
||||
|
@ -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")) {
|
||||
logfileOut(LOG_INFO, "set read mode\n");
|
||||
cl->mode=1;
|
||||
} else if (0==strcmp(varname,"#rwacs")) {
|
||||
logfileOut(LOG_INFO, "set write mode\n");
|
||||
cl->mode=2;
|
||||
} else {
|
||||
err="bad access code";
|
||||
}
|
||||
} else if (cl->mode==0) {
|
||||
err="no access";
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
modified=1;
|
||||
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;
|
||||
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 {
|
||||
if (0==strcmp("$", varname)) { /* special case: response */
|
||||
ERR_I(str_put_str(bufo, cl->res));
|
||||
cl->res[0]='\0';
|
||||
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_I(StrPut(&bufo, "", COC_ERR)); /* signal terminal error message */
|
||||
ERR_I(StrPut(&bufo, "no access", COC_SEP));
|
||||
ERR_P(StrGet(&buf, NULL, COC_NUL)); /* skip separator */
|
||||
} else {
|
||||
if (cl->data!=NULL) {
|
||||
setData(cl->data);
|
||||
}
|
||||
var=CocFindVar(varname, &base);
|
||||
if (var==NULL) {
|
||||
ERR_I(StrPut(&bufo, "", COC_ERR)); /* signal error message */
|
||||
ERR_I(StrPut(&bufo, "undefined variable", COC_SEP));
|
||||
ERR_P(StrGet(&buf, NULL, COC_NUL)); /* skip separator */
|
||||
} else if (buf.seen) { /* separator was there: set mode */
|
||||
if (var->access > cl->mode) {
|
||||
ERR_I(StrPut(&bufo, "", COC_ERR)); /* signal error message */
|
||||
ERR_I(StrPut(&bufo, "no access", COC_SEP));
|
||||
ERR_P(StrGet(&buf, NULL, COC_NUL)); /* skip separator */
|
||||
} else {
|
||||
i=CocPutVar(serverVarList, bufo, varname, 0);
|
||||
if (i<0) {
|
||||
err=ErrMessage; break;
|
||||
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 {
|
||||
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) {
|
||||
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(StrGetEnd(&buf));
|
||||
logfileOut(LOG_NET, " ");
|
||||
logfileOutBuf(LOG_NET, &bufo);
|
||||
logfileOut(LOG_NET, "\n");
|
||||
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();
|
||||
}
|
||||
|
@ -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_ */
|
||||
|
267
tecs/coc_util.c
267
tecs/coc_util.c
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
218
tecs/myc_buf.c
Normal 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
58
tecs/myc_buf.h
Normal 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
144
tecs/myc_err.c
Normal 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
85
tecs/myc_err.h
Normal 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
30
tecs/myc_mem.h
Normal 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
252
tecs/myc_str.c
Normal 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
122
tecs/myc_str.h
Normal 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
120
tecs/myc_time.c
Normal 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
42
tecs/myc_time.h
Normal 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
131
tecs/str.f
Normal 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
|
||||
|
@ -292,7 +292,7 @@
|
||||
integer L !!
|
||||
|
||||
integer i
|
||||
integer lnblnk
|
||||
integer lnblnk, iargc
|
||||
|
||||
l=0
|
||||
str=' '
|
||||
|
@ -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;
|
||||
|
||||
l = lnblnk_(prompt, clen);
|
||||
p = malloc((unsigned) l+2); if( p == NULL ) return;
|
||||
strncpy(p+1,prompt,l); p[0]='\n'; p[l] = '\0';
|
||||
char *line_read, p[64];
|
||||
|
||||
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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
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
|
||||
|
||||
/* fortran interface stuff ----------------------------------
|
||||
Use macros STR_TO_C and STR_TO_F to convert from Fortran character strings
|
||||
to C character arrays and vice versa.
|
||||
|
||||
declare fortran character arguments as CHAR(arg)
|
||||
and at at the end for each character argument <arg> add
|
||||
int <arg>_len to the argument list
|
||||
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
|
||||
|
||||
|
2125
tecs/tecs.c
2125
tecs/tecs.c
File diff suppressed because it is too large
Load Diff
332
tecs/tecs_cli.c
332
tecs/tecs_cli.c
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
par=' '
|
||||
do i=j,l
|
||||
if (line(i:i) .gt. ' ') then
|
||||
par=line(i:l)
|
||||
goto 3 ! command with parameter
|
||||
endif
|
||||
enddo
|
||||
goto 2 ! parameterless command
|
||||
endif
|
||||
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
|
||||
if (k .ne. 0) then
|
||||
print *,'command too long'
|
||||
goto 1
|
||||
endif
|
||||
|
||||
print *,'command too long'
|
||||
goto 1
|
||||
|
||||
2 par=' '
|
||||
do i=j,l
|
||||
if (line(i:i) .gt. ' ') then
|
||||
par=line(i:l)
|
||||
goto 3
|
||||
endif
|
||||
enddo
|
||||
! empty command
|
||||
|
||||
! simple query
|
||||
12 cmd=defcmd
|
||||
|
||||
if (cmd .eq. 'kill' .or. cmd .eq. 'off') then
|
||||
2 continue ! parameterless command
|
||||
|
||||
defcmd='status'
|
||||
|
||||
if (cmd(1:1) .eq. '#') then
|
||||
call tecs_close
|
||||
call tecs_open(0, cmd, iret)
|
||||
if (iret .lt. 0) goto 91
|
||||
prompt='tecs/'//cmd(2:)
|
||||
promptlen=1
|
||||
do i=1,len(prompt)-2
|
||||
if (prompt(i:i) .ne. ' ') promptlen=i
|
||||
enddo
|
||||
promptlen=promptlen+1
|
||||
prompt(promptlen:promptlen)='>'
|
||||
promptlen=promptlen+1
|
||||
else if (cmd .eq. 'kill') then
|
||||
iret=tecs_quit_server()
|
||||
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
|
||||
|
||||
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)
|
||||
! functions
|
||||
integer tecs_get_par, tecs_set_par
|
||||
|
||||
if (lines .ne. ' ') then
|
||||
l=tecs_set_par('logstart', lines, 0)
|
||||
print *,'line: ',lines
|
||||
print *
|
||||
endif
|
||||
|
||||
show_log=tecs_get_par('logline', str, 1)
|
||||
end
|
||||
|
585
tecs/tecs_data.c
Normal file
585
tecs/tecs_data.c
Normal 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
47
tecs/tecs_data.h
Normal 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_ */
|
@ -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
|
||||
|
@ -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(varname, &sbuf, '\0'));
|
||||
} else {
|
||||
ERR_I(CocGetVar(varname, &sbuf, ','));
|
||||
}
|
||||
ERR_I(CocGetVar(serverVarList, &sbuf, varname, 0));
|
||||
} else {
|
||||
ERR_P(str_get_str(&sbuf, NULL));
|
||||
ERR_P(StrGet(&sbuf, varname, ','));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -177,3 +176,33 @@ char *LscCmd(SerChannel *ser, const char *cmds) {
|
||||
return(res);
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
@ -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_ */
|
||||
|
@ -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)
|
||||
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 (x1 .gt. x2-minRange) x1=x2-minRange
|
||||
step=(x2-x1)/(dmax-1)+0.99
|
||||
last=nint(x2)+tbase
|
||||
first=nint(x1)+tbase
|
||||
endif
|
||||
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)
|
||||
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
|
||||
ymax(rl)=ymax(rl)+max(fy*0.0075,ey*0.01)
|
||||
ymin(rl)=ymin(rl)-max(fy*0.005,ey*0.01)
|
||||
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
|
||||
call pgsci(1)
|
||||
if (rl == 1) then
|
||||
call pgsch(1.0)
|
||||
call pgtbox('ZHXYBINST', ticks, 0, 'BCINMST', 0.0, 0)
|
||||
call pgtbox('C', 0.0, 0, ' ', 0.0, 0)
|
||||
ey=0.0
|
||||
do i=i1,i2
|
||||
name=parnam(i)
|
||||
if (name=="Tm") then
|
||||
name="Main Sensor"
|
||||
elseif (name=="Ts") then
|
||||
name="Sample Sensor"
|
||||
elseif (name=="Tr") then
|
||||
name="SetPoint"
|
||||
endif
|
||||
call pglen(5, trim(name), fx, fy)
|
||||
call pgsci(color(i))
|
||||
call pgmtxt ('L', 2.5, ey, 0.0, trim(name))
|
||||
ey=ey+fy+0.04
|
||||
enddo
|
||||
call pgsci(1)
|
||||
call pgmtxt ('L', 2.5, ey, 0.0, 'T [K]')
|
||||
else if (naux > 0) then
|
||||
call pgsch(0.7)
|
||||
call pgtbox('ZCIST', ticks, 0, 'BCVINMST', 0.0, 0)
|
||||
call pgtbox('B', 0.0, 0, ' ', 0.0, 0)
|
||||
call pgsci(color(nset))
|
||||
call pgsch(1.0)
|
||||
if (parnam(nset) == 'P' .or. parnam(nset) == 'p') then
|
||||
call pgmtxt ('L', 2.5, 0.5, 0.5, 'Power [W]')
|
||||
else
|
||||
call pgmtxt ('L', 2.5, 0.5, 0.5, parnam(nset))
|
||||
endif
|
||||
endif
|
||||
i1=nset-naux+1
|
||||
i2=nset
|
||||
enddo
|
||||
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)
|
||||
|
||||
call pgsch(0.8)
|
||||
rl=1
|
||||
call pgswin(x1,x2,ymin(rl),ymax(rl))
|
||||
ey=ymax(rl)-(ymax(rl)-ymin(rl))*0.21
|
||||
call pgsch(1.0)
|
||||
call pgaxis('N', x1, ymin(rl), x1, ey, ymin(rl), ey, 0, 0, 0.5, 0.0, 0.5, -1.0, 0.0)
|
||||
if (window>50*3600) then
|
||||
ticks=8*3600
|
||||
elseif (window>25*3600) then
|
||||
ticks=4*3600
|
||||
else
|
||||
ticks=0.0 ! automatic
|
||||
endif
|
||||
call pgtbox('ZHXYBCINST', ticks, 0, 'CIMST', 0.0, 0)
|
||||
call pgmtxt ('L', 2.5, 0.4, 0.5, 'T [K]')
|
||||
call pgsci(color(1))
|
||||
call pgmtxt ('L', 2.5, 0.2, 0.5, 'Main Sensor')
|
||||
call pgsci(color(2))
|
||||
call pgmtxt ('L', 2.5, 0.6, 0.5, 'Sample Sensor')
|
||||
call pgsci(color(3))
|
||||
call pgmtxt ('L', 2.5, 0.9, 0.5, 'Power [W]')
|
||||
call 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
|
||||
if (ex>x2) EXIT
|
||||
thisday=0
|
||||
call pgptxt(ex, ey, 0.0, 0.5, weekdays(mod(i,7)+1))
|
||||
ex=(i+0.5)*oneDay
|
||||
if (ex > x2) EXIT
|
||||
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
|
||||
|
||||
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 (ntot .gt. 1) then
|
||||
if (tim1 > tim0) then
|
||||
i1=1
|
||||
i2=2
|
||||
i2=nset-naux
|
||||
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
|
||||
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
|
||||
enddo
|
||||
if (ntot .gt. lastj) call pgline(ntot+1-lastj, xd(lastj), yd(lastj,i))
|
||||
call pgsci(color(i))
|
||||
call pgmove(tim0, yy0(i))
|
||||
call pgdraw(tim1, yy1(i))
|
||||
endif
|
||||
yy0(i)=yy1(i)
|
||||
enddo
|
||||
i1=3
|
||||
i2=3
|
||||
i1=nset-naux+1
|
||||
i2=nset
|
||||
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
|
||||
goto 9
|
||||
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
|
||||
|
@ -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;
|
||||
|
||||
FD_ZERO(&mask);
|
||||
FD_SET(fd, &mask);
|
||||
tmo.tv_sec=tmo_msec / 1000;
|
||||
tmo.tv_usec=(tmo_msec % 1000) % 1000 +1;
|
||||
ERR_SI(i=select(fd+1,&mask,NULL,NULL,&tmo));
|
||||
if (i==0) return(0); /* timeout */
|
||||
return(1);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
idleHandler=idleHdl;
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
@ -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_ */
|
||||
|
Reference in New Issue
Block a user