summaryrefslogtreecommitdiffstats
path: root/usr.sbin/xntpd/parse/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/xntpd/parse/parse.c')
-rw-r--r--usr.sbin/xntpd/parse/parse.c1193
1 files changed, 1193 insertions, 0 deletions
diff --git a/usr.sbin/xntpd/parse/parse.c b/usr.sbin/xntpd/parse/parse.c
new file mode 100644
index 0000000..7a36002
--- /dev/null
+++ b/usr.sbin/xntpd/parse/parse.c
@@ -0,0 +1,1193 @@
+#if defined(REFCLOCK) && (defined(PARSE) || defined(PARSEPPS))
+/*
+ * /src/NTP/REPOSITORY/v3/parse/parse.c,v 3.17 1993/11/11 11:20:29 kardel Exp
+ *
+ * parse.c,v 3.17 1993/11/11 11:20:29 kardel Exp
+ *
+ * Parser module for reference clock
+ *
+ * PARSEKERNEL define switches between two personalities of the module
+ * if PARSEKERNEL is defined this module can be used with dcf77sync.c as
+ * a PARSEKERNEL kernel module. In this case the time stamps will be
+ * a struct timeval.
+ * when PARSEKERNEL is not defined NTP time stamps will be used.
+ *
+ * Copyright (c) 1992,1993
+ * Frank Kardel Friedrich-Alexander Universitaet Erlangen-Nuernberg
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+#if !(defined(lint) || defined(__GNUC__))
+static char rcsid[] = "parse.c,v 3.17 1993/11/11 11:20:29 kardel Exp";
+#endif
+
+#include "sys/types.h"
+#include "sys/time.h"
+#include "sys/errno.h"
+
+#include "ntp_fp.h"
+#include "ntp_unixtime.h"
+#include "ntp_calendar.h"
+
+#include "parse.h"
+
+#if defined(PARSESTREAM) && (defined(SYS_SUNOS4) || defined(SYS_SOLARIS)) && defined(STREAM)
+/*
+ * Sorry, but in SunOS 4.x kernels there are no
+ * mem* operations. I don't want them - bcopy, bzero
+ * are fine in the kernel
+ */
+#define _ntp_string_h
+extern void bcopy();
+extern void bzero();
+#endif
+
+#include "ntp_stdlib.h"
+
+#ifdef PARSESTREAM
+#include "sys/parsestreams.h"
+#endif
+
+extern clockformat_t *clockformats[];
+extern unsigned short nformats;
+
+static unsigned LONG timepacket();
+
+/*
+ * strings support usually not in kernel - duplicated, but what the heck
+ */
+static int
+Strlen(s)
+ register char *s;
+{
+ register int c;
+
+ c = 0;
+ if (s)
+ {
+ while (*s++)
+ {
+ c++;
+ }
+ }
+ return c;
+}
+
+static int
+Strcmp(s, t)
+ register char *s;
+ register char *t;
+{
+ register int c = 0;
+
+ if (!s || !t || (s == t))
+ {
+ return 0;
+ }
+
+ while (!(c = *s++ - *t++) && *s && *t)
+ /* empty loop */;
+
+ return c;
+}
+
+static int
+timedout(parseio, ctime)
+ register parse_t *parseio;
+ register timestamp_t *ctime;
+{
+ struct timeval delta;
+
+#ifdef PARSEKERNEL
+ delta.tv_sec = ctime->tv.tv_sec - parseio->parse_lastchar.tv.tv_sec;
+ delta.tv_usec = ctime->tv.tv_usec - parseio->parse_lastchar.tv.tv_usec;
+ if (delta.tv_usec < 0)
+ {
+ delta.tv_sec -= 1;
+ delta.tv_usec += 1000000;
+ }
+#else
+ extern LONG tstouslo[];
+ extern LONG tstousmid[];
+ extern LONG tstoushi[];
+
+ l_fp delt;
+
+ delt = ctime->fp;
+ L_SUB(&delt, &parseio->parse_lastchar.fp);
+ TSTOTV(&delt, &delta);
+#endif
+
+ if (timercmp(&delta, &parseio->parse_timeout, >))
+ {
+ parseprintf(DD_PARSE, ("parse: timedout: TRUE\n"));
+ return 1;
+ }
+ else
+ {
+ parseprintf(DD_PARSE, ("parse: timedout: FALSE\n"));
+ return 0;
+ }
+}
+
+/*
+ * setup_bitmaps
+ */
+static int
+setup_bitmaps(parseio, low, high)
+ register parse_t *parseio;
+ register unsigned short low;
+ register unsigned short high;
+{
+ register unsigned short i;
+ register int f = 0;
+ register clockformat_t *fmt;
+ register unsigned index, mask;
+
+ if ((low >= high) ||
+ (high > nformats))
+ {
+ parseprintf(DD_PARSE, ("setup_bitmaps: failed: bounds error (low=%d, high=%d, nformats=%d)\n", low, high, nformats));
+ return 0;
+ }
+
+ bzero(parseio->parse_startsym, sizeof (parseio->parse_startsym));
+ bzero(parseio->parse_endsym, sizeof (parseio->parse_endsym));
+ bzero(parseio->parse_syncsym, sizeof (parseio->parse_syncsym));
+ parseio->parse_syncflags = 0;
+ parseio->parse_timeout.tv_sec = 0;
+ parseio->parse_timeout.tv_usec = 0;
+
+ /*
+ * gather bitmaps of possible start and end values
+ */
+ for (i=low; i < high; i++)
+ {
+ fmt = clockformats[i];
+
+ if (fmt->flags & F_START)
+ {
+ index = fmt->startsym / 8;
+ mask = 1 << (fmt->startsym % 8);
+
+ if (parseio->parse_endsym[index] & mask)
+ {
+#ifdef PARSEKERNEL
+ printf("parse: setup_bitmaps: failed: START symbol collides with END symbol (format %d)\n", i);
+#else
+ syslog(LOG_ERR, "parse: setup_bitmaps: failed: START symbol collides with END symbol (format %d)\n", i);
+#endif
+ return 0;
+ }
+ else
+ {
+ parseio->parse_startsym[index] |= mask;
+ f = 1;
+ }
+ }
+
+ if (fmt->flags & F_END)
+ {
+ index = fmt->endsym / 8;
+ mask = 1 << (fmt->endsym % 8);
+
+ if (parseio->parse_startsym[index] & mask)
+ {
+#ifdef PARSEKERNEL
+ printf("parse: setup_bitmaps: failed: END symbol collides with START symbol (format %d)\n", i);
+#else
+ syslog(LOG_ERR, "parse: setup_bitmaps: failed: END symbol collides with START symbol (format %d)\n", i);
+#endif
+ return 0;
+ }
+ else
+ {
+ parseio->parse_endsym[index] |= mask;
+ f = 1;
+ }
+ }
+
+ if (fmt->flags & SYNC_CHAR)
+ {
+ parseio->parse_syncsym[fmt->syncsym / 8] |= (1 << (fmt->syncsym % 8));
+ }
+
+ parseio->parse_syncflags |= fmt->flags & (SYNC_START|SYNC_END|SYNC_CHAR|SYNC_ONE|SYNC_ZERO|SYNC_TIMEOUT|SYNC_SYNTHESIZE);
+
+ if ((fmt->flags & SYNC_TIMEOUT) &&
+ ((parseio->parse_timeout.tv_sec || parseio->parse_timeout.tv_usec) ? timercmp(&parseio->parse_timeout, &fmt->timeout, >) : 1))
+ {
+ parseio->parse_timeout = fmt->timeout;
+ }
+
+ if (parseio->parse_dsize < fmt->length)
+ parseio->parse_dsize = fmt->length;
+ }
+
+ if (!f && ((int)(high - low) > 1))
+ {
+ /*
+ * need at least one start or end symbol
+ */
+#ifdef PARSEKERNEL
+ printf("parse: setup_bitmaps: failed: neither START nor END symbol defined\n");
+#else
+ syslog(LOG_ERR, "parse: setup_bitmaps: failed: neither START nor END symbol defined\n");
+#endif
+ return 0;
+ }
+
+ return 1;
+}
+
+/*ARGSUSED*/
+int
+parse_ioinit(parseio)
+ register parse_t *parseio;
+{
+ parseprintf(DD_PARSE, ("parse_iostart\n"));
+
+ if (!setup_bitmaps(parseio, 0, nformats))
+ return 0;
+
+ parseio->parse_data = MALLOC(parseio->parse_dsize * 2 + 2);
+ if (!parseio->parse_data)
+ {
+ parseprintf(DD_PARSE, ("init failed: malloc for data area failed\n"));
+ return 0;
+ }
+
+ /*
+ * leave room for '\0'
+ */
+ parseio->parse_ldata = parseio->parse_data + parseio->parse_dsize + 1;
+ parseio->parse_lformat = 0;
+ parseio->parse_badformat = 0;
+ parseio->parse_ioflags = PARSE_IO_CS7; /* usual unix default */
+ parseio->parse_flags = 0; /* true samples */
+ parseio->parse_index = 0;
+ parseio->parse_ldsize = 0;
+
+ return 1;
+}
+
+/*ARGSUSED*/
+void
+parse_ioend(parseio)
+ register parse_t *parseio;
+{
+ parseprintf(DD_PARSE, ("parse_ioend\n"));
+ if (parseio->parse_data)
+ FREE(parseio->parse_data, parseio->parse_dsize * 2 + 2);
+}
+
+/*ARGSUSED*/
+int
+parse_ioread(parseio, ch, ctime)
+ register parse_t *parseio;
+ register unsigned char ch;
+ register timestamp_t *ctime;
+{
+ register unsigned updated = CVT_NONE;
+ register unsigned short low, high;
+ register unsigned index, mask;
+
+ parseprintf(DD_PARSE, ("parse_ioread(0x%x, char=0x%x, ..., ...)\n", (unsigned int)parseio, ch & 0xFF));
+
+ if (parseio->parse_flags & PARSE_FIXED_FMT)
+ {
+ if (!clockformats[parseio->parse_lformat]->convert)
+ {
+ parseprintf(DD_PARSE, ("parse_ioread: input dropped.\n"));
+ return CVT_NONE;
+ }
+ low = parseio->parse_lformat;
+ high = low + 1;
+ }
+ else
+ {
+ low = 0;
+ high = nformats;
+ }
+
+ /*
+ * within STREAMS CSx (x < 8) chars still have the upper bits set
+ * so we normalize the characters by masking unecessary bits off.
+ */
+ switch (parseio->parse_ioflags & PARSE_IO_CSIZE)
+ {
+ case PARSE_IO_CS5:
+ ch &= 0x1F;
+ break;
+
+ case PARSE_IO_CS6:
+ ch &= 0x3F;
+ break;
+
+ case PARSE_IO_CS7:
+ ch &= 0x7F;
+ break;
+
+ case PARSE_IO_CS8:
+ break;
+ }
+
+ index = ch / 8;
+ mask = 1 << (ch % 8);
+
+ if ((parseio->parse_syncflags & SYNC_CHAR) &&
+ (parseio->parse_syncsym[index] & mask))
+ {
+ register clockformat_t *fmt;
+ register unsigned short i;
+ /*
+ * got a sync event - call sync routine
+ */
+
+ for (i = low; i < high; i++)
+ {
+ fmt = clockformats[i];
+
+ if ((fmt->flags & SYNC_CHAR) &&
+ (fmt->syncsym == ch))
+ {
+ parseprintf(DD_PARSE, ("parse_ioread: SYNC_CHAR event\n"));
+ if (fmt->syncevt)
+ fmt->syncevt(parseio, ctime, fmt->data, SYNC_CHAR);
+ }
+ }
+ }
+
+ if ((((parseio->parse_syncflags & SYNC_START) &&
+ (parseio->parse_startsym[index] & mask)) ||
+ (parseio->parse_index == 0)) ||
+ ((parseio->parse_syncflags & SYNC_TIMEOUT) &&
+ timedout(parseio, ctime)))
+ {
+ register unsigned short i;
+ /*
+ * packet start - re-fill buffer
+ */
+ if (parseio->parse_index)
+ {
+ /*
+ * filled buffer - thus not end character found
+ * do processing now
+ */
+ parseio->parse_data[parseio->parse_index] = '\0';
+
+ updated = timepacket(parseio);
+ bcopy(parseio->parse_data, parseio->parse_ldata, parseio->parse_index+1);
+ parseio->parse_ldsize = parseio->parse_index+1;
+ if (parseio->parse_syncflags & SYNC_TIMEOUT)
+ parseio->parse_dtime.parse_stime = *ctime;
+ }
+
+ /*
+ * could be a sync event - call sync routine if needed
+ */
+ if (parseio->parse_syncflags & SYNC_START)
+ for (i = low; i < high; i++)
+ {
+ register clockformat_t *fmt = clockformats[i];
+
+ if ((parseio->parse_index == 0) ||
+ ((fmt->flags & SYNC_START) && (fmt->startsym == ch)))
+ {
+ parseprintf(DD_PARSE, ("parse_ioread: SYNC_START event\n"));
+ if (fmt->syncevt)
+ fmt->syncevt(parseio, ctime, fmt->data, SYNC_START);
+ }
+ }
+ parseio->parse_index = 1;
+ parseio->parse_data[0] = ch;
+ parseprintf(DD_PARSE, ("parse: parse_ioread: buffer start\n"));
+ }
+ else
+ {
+ register unsigned short i;
+
+ if (parseio->parse_index < parseio->parse_dsize)
+ {
+ /*
+ * collect into buffer
+ */
+ parseprintf(DD_PARSE, ("parse: parse_ioread: buffer[%d] = 0x%x\n", parseio->parse_index, ch));
+ parseio->parse_data[parseio->parse_index++] = ch;
+ }
+
+ if ((parseio->parse_endsym[index] & mask) ||
+ (parseio->parse_index >= parseio->parse_dsize))
+ {
+ /*
+ * packet end - process buffer
+ */
+ if (parseio->parse_syncflags & SYNC_END)
+ for (i = low; i < high; i++)
+ {
+ register clockformat_t *fmt = clockformats[i];
+
+ if ((fmt->flags & SYNC_END) && (fmt->endsym == ch))
+ {
+ parseprintf(DD_PARSE, ("parse_ioread: SYNC_END event\n"));
+ if (fmt->syncevt)
+ fmt->syncevt(parseio, ctime, fmt->data, SYNC_END);
+ }
+ }
+ parseio->parse_data[parseio->parse_index] = '\0';
+ updated = timepacket(parseio);
+ bcopy(parseio->parse_data, parseio->parse_ldata, parseio->parse_index+1);
+ parseio->parse_ldsize = parseio->parse_index+1;
+ parseio->parse_index = 0;
+ parseprintf(DD_PARSE, ("parse: parse_ioread: buffer end\n"));
+ }
+ }
+
+ if ((updated == CVT_NONE) &&
+ (parseio->parse_flags & PARSE_FIXED_FMT) &&
+ (parseio->parse_syncflags & SYNC_SYNTHESIZE) &&
+ ((parseio->parse_dtime.parse_status & CVT_MASK) == CVT_OK) &&
+ clockformats[parseio->parse_lformat]->synth)
+ {
+ updated = clockformats[parseio->parse_lformat]->synth(parseio, ctime);
+ }
+
+ /*
+ * remember last character time
+ */
+ parseio->parse_lastchar = *ctime;
+
+#ifdef DEBUG
+ if ((updated & CVT_MASK) != CVT_NONE)
+ parseprintf(DD_PARSE, ("parse_ioread: time sample accumulated (status=0x%x)\n", updated));
+#endif
+
+ parseio->parse_dtime.parse_status = updated;
+
+ return (updated & CVT_MASK) != CVT_NONE;
+}
+
+/*
+ * parse_iopps
+ *
+ * take status line indication and derive synchronisation information
+ * from it.
+ * It can also be used to decode a serial serial data format (such as the
+ * ONE, ZERO, MINUTE sync data stream from DCF77)
+ */
+/*ARGSUSED*/
+int
+parse_iopps(parseio, status, ptime)
+ register parse_t *parseio;
+ register int status;
+ register timestamp_t *ptime;
+{
+ register unsigned updated = CVT_NONE;
+
+ /*
+ * PPS pulse information will only be delivered to ONE clock format
+ * this is either the last successful conversion module with a ppssync
+ * routine, or a fixed format with a ppssync routine
+ */
+ parseprintf(DD_PARSE, ("parse_iopps: STATUS %s\n", (status == SYNC_ONE) ? "ONE" : "ZERO"));
+
+ if (((parseio->parse_flags & PARSE_FIXED_FMT) ||
+ ((parseio->parse_dtime.parse_status & CVT_MASK) == CVT_OK)) &&
+ clockformats[parseio->parse_lformat]->syncpps &&
+ (status & clockformats[parseio->parse_lformat]->flags))
+ {
+ updated = clockformats[parseio->parse_lformat]->syncpps(parseio, status == SYNC_ONE, ptime);
+ parseprintf(DD_PARSE, ("parse_iopps: updated = 0x%x\n", updated));
+ }
+ else
+ {
+ parseprintf(DD_PARSE, ("parse_iopps: STATUS dropped\n"));
+ }
+
+ return (updated & CVT_MASK) != CVT_NONE;
+}
+
+/*
+ * parse_iodone
+ *
+ * clean up internal status for new round
+ */
+/*ARGSUSED*/
+void
+parse_iodone(parseio)
+ register parse_t *parseio;
+{
+ /*
+ * we need to clean up certain flags for the next round
+ */
+ parseio->parse_dtime.parse_state = 0; /* no problems with ISRs */
+}
+
+/*---------- conversion implementation --------------------*/
+
+/*
+ * convert a struct clock to UTC since Jan, 1st 1970 0:00 (the UNIX EPOCH)
+ */
+#define dysize(x) ((x) % 4 ? 365 : ((x % 400) ? 365 :366))
+
+time_t
+parse_to_unixtime(clock, cvtrtc)
+ register clocktime_t *clock;
+ register unsigned LONG *cvtrtc;
+{
+#define SETRTC(_X_) { if (cvtrtc) *cvtrtc = (_X_); }
+ static int days_of_month[] =
+ {
+ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+ };
+ register int i;
+ time_t t;
+
+ if (clock->year < 100)
+ clock->year += 1900;
+
+ if (clock->year < 1970)
+ clock->year += 100; /* XXX this will do it till <2070 */
+
+ if (clock->year < 0)
+ {
+ SETRTC(CVT_FAIL|CVT_BADDATE);
+ return -1;
+ }
+
+ /*
+ * sorry, slow section here - but it's not time critical anyway
+ */
+ t = (clock->year - 1970) * 365;
+ t += (clock->year >> 2) - (1970 >> 2);
+ t -= clock->year / 400 - 1970 / 400;
+
+ /* month */
+ if (clock->month <= 0 || clock->month > 12)
+ {
+ SETRTC(CVT_FAIL|CVT_BADDATE);
+ return -1; /* bad month */
+ }
+ /* adjust leap year */
+ if (clock->month >= 3 && dysize(clock->year) == 366)
+ t++;
+
+ for (i = 1; i < clock->month; i++)
+ {
+ t += days_of_month[i];
+ }
+ /* day */
+ if (clock->day < 1 || ((clock->month == 2 && dysize(clock->year) == 366) ?
+ clock->day > 29 : clock->day > days_of_month[clock->month]))
+ {
+ SETRTC(CVT_FAIL|CVT_BADDATE);
+ return -1; /* bad day */
+ }
+
+ t += clock->day - 1;
+ /* hour */
+ if (clock->hour < 0 || clock->hour >= 24)
+ {
+ SETRTC(CVT_FAIL|CVT_BADTIME);
+ return -1; /* bad hour */
+ }
+
+ t = TIMES24(t) + clock->hour;
+
+ /* min */
+ if (clock->minute < 0 || clock->minute > 59)
+ {
+ SETRTC(CVT_FAIL|CVT_BADTIME);
+ return -1; /* bad min */
+ }
+
+ t = TIMES60(t) + clock->minute;
+ /* sec */
+
+ if (clock->second < 0 || clock->second > 60) /* allow for LEAPs */
+ {
+ SETRTC(CVT_FAIL|CVT_BADTIME);
+ return -1; /* bad sec */
+ }
+
+ t = TIMES60(t) + clock->second;
+
+ t += clock->utcoffset; /* warp to UTC */
+
+ /* done */
+ return t;
+}
+
+/*--------------- format conversion -----------------------------------*/
+
+int
+Stoi(s, zp, cnt)
+ char *s;
+ LONG *zp;
+ int cnt;
+{
+ char *b = s;
+ int f,z,v;
+ char c;
+
+ f=z=v=0;
+
+ while(*s == ' ')
+ s++;
+
+ if (*s == '-')
+ {
+ s++;
+ v = 1;
+ }
+ else
+ if (*s == '+')
+ s++;
+
+ for(;;)
+ {
+ c = *s++;
+ if (c == '\0' || c < '0' || c > '9' || (cnt && ((s-b) > cnt)))
+ {
+ if (f == 0)
+ {
+ return(-1);
+ }
+ if (v)
+ z = -z;
+ *zp = z;
+ return(0);
+ }
+ z = (z << 3) + (z << 1) + ( c - '0' );
+ f=1;
+ }
+}
+
+
+int
+Strok(s, m)
+ char *s;
+ char *m;
+{
+ if (!s || !m)
+ return 0;
+
+ while(*s && *m)
+ {
+ if ((*m == ' ') ? 1 : (*s == *m))
+ {
+ s++;
+ m++;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ return !*m;
+}
+
+unsigned LONG
+updatetimeinfo(parseio, t, usec, flags)
+ register parse_t *parseio;
+ register time_t t;
+ register unsigned LONG usec;
+ register unsigned LONG flags;
+{
+ register LONG usecoff;
+ register LONG mean;
+ LONG delta[PARSE_DELTA];
+
+#ifdef PARSEKERNEL
+ usecoff = (t - parseio->parse_dtime.parse_stime.tv.tv_sec) * 1000000
+ - parseio->parse_dtime.parse_stime.tv.tv_usec + usec;
+#else
+ extern LONG tstouslo[];
+ extern LONG tstousmid[];
+ extern LONG tstoushi[];
+
+ TSFTOTVU(parseio->parse_dtime.parse_stime.fp.l_uf, usecoff);
+ usecoff = -usecoff;
+ usecoff += (t - parseio->parse_dtime.parse_stime.fp.l_ui + JAN_1970) * 1000000
+ + usec;
+#endif
+
+ /*
+ * filtering (median) if requested
+ */
+ if (parseio->parse_flags & PARSE_STAT_FILTER)
+ {
+ register int n, i, s, k;
+
+ parseio->parse_delta[parseio->parse_dindex] = usecoff;
+
+ parseio->parse_dindex = (parseio->parse_dindex + 1) % PARSE_DELTA;
+
+ /*
+ * sort always - thus every sample gets its data
+ */
+ bcopy((caddr_t)parseio->parse_delta, (caddr_t)delta, sizeof(delta));
+
+ for (s = 0; s < PARSE_DELTA; s++)
+ for (k = s+1; k < PARSE_DELTA; k++)
+ { /* Yes - it's slow sort */
+ if (delta[s] > delta[k])
+ {
+ register LONG tmp;
+
+ tmp = delta[k];
+ delta[k] = delta[s];
+ delta[s] = tmp;
+ }
+ }
+
+ i = 0;
+ n = PARSE_DELTA;
+
+ /*
+ * you know this median loop if you have read the other code
+ */
+ while ((n - i) > 8)
+ {
+ register LONG top = delta[n-1];
+ register LONG mid = delta[(n+i)>>1];
+ register LONG low = delta[i];
+
+ if ((top - mid) > (mid - low))
+ {
+ /*
+ * cut off high end
+ */
+ n--;
+ }
+ else
+ {
+ /*
+ * cut off low end
+ */
+ i++;
+ }
+ }
+
+ parseio->parse_dtime.parse_usecdisp = delta[n-1] - delta[i];
+
+ if (parseio->parse_flags & PARSE_STAT_AVG)
+ {
+ /*
+ * take the average of the median samples as this clock
+ * is a little bumpy
+ */
+ mean = 0;
+
+ while (i < n)
+ {
+ mean += delta[i++];
+ }
+
+ mean >>= 3;
+ }
+ else
+ {
+ mean = delta[(n+i)>>1];
+ }
+
+ parseio->parse_dtime.parse_usecerror = mean;
+ }
+ else
+ {
+ parseio->parse_dtime.parse_usecerror = usecoff;
+ parseio->parse_dtime.parse_usecdisp = 0;
+ }
+
+ parseprintf(DD_PARSE,("parse: updatetimeinfo: T=%x+%d usec, useccoff=%d, usecerror=%d, usecdisp=%d\n",
+ t, usec, usecoff, parseio->parse_dtime.parse_usecerror, parseio->parse_dtime.parse_usecdisp));
+
+
+#ifdef PARSEKERNEL
+ {
+ int s = splhigh();
+#endif
+
+ parseio->parse_lstate = parseio->parse_dtime.parse_state | flags | PARSEB_TIMECODE;
+
+ parseio->parse_dtime.parse_state = parseio->parse_lstate;
+
+#ifdef PARSEKERNEL
+ (void)splx(s);
+ }
+#endif
+
+ return CVT_OK; /* everything fine and dandy... */
+}
+
+
+/*
+ * syn_simple
+ *
+ * handle a sync time stamp
+ */
+/*ARGSUSED*/
+void
+syn_simple(parseio, ts, format, why)
+ register parse_t *parseio;
+ register timestamp_t *ts;
+ register struct format *format;
+ register unsigned LONG why;
+{
+ parseio->parse_dtime.parse_stime = *ts;
+}
+
+/*
+ * pps_simple
+ *
+ * handle a pps time stamp
+ */
+/*ARGSUSED*/
+unsigned LONG
+pps_simple(parseio, status, ptime)
+ register parse_t *parseio;
+ register int status;
+ register timestamp_t *ptime;
+{
+ parseio->parse_dtime.parse_ptime = *ptime;
+ parseio->parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
+
+ return CVT_NONE;
+}
+
+/*
+ * timepacket
+ *
+ * process a data packet
+ */
+static unsigned LONG
+timepacket(parseio)
+ register parse_t *parseio;
+{
+ register int k;
+ register unsigned short format;
+ register time_t t;
+ register unsigned LONG cvtsum = 0;/* accumulated CVT_FAIL errors */
+ unsigned LONG cvtrtc; /* current conversion result */
+ clocktime_t clock;
+
+ format = parseio->parse_lformat;
+
+ k = 0;
+
+ if (parseio->parse_flags & PARSE_FIXED_FMT)
+ {
+ switch ((cvtrtc = clockformats[format]->convert ? clockformats[format]->convert(parseio->parse_data, parseio->parse_index, clockformats[format]->data, &clock) : CVT_NONE) & CVT_MASK)
+ {
+ case CVT_FAIL:
+ parseio->parse_badformat++;
+ cvtsum = cvtrtc & ~CVT_MASK;
+
+ /*
+ * may be too often ... but is nice to know when it happens
+ */
+#ifdef PARSEKERNEL
+ printf("parse: \"%s\" failed to convert\n", clockformats[format]->name);
+#else
+ syslog(LOG_WARNING, "parse: \"%s\" failed to convert\n", clockformats[format]->name);
+#endif
+ break;
+
+ case CVT_NONE:
+ /*
+ * too bad - pretend bad format
+ */
+ parseio->parse_badformat++;
+ cvtsum = CVT_BADFMT;
+
+ break;
+
+ case CVT_OK:
+ k = 1;
+ break;
+
+ default:
+ /* shouldn't happen */
+#ifdef PARSEKERNEL
+ printf("parse: INTERNAL error: bad return code of convert routine \"%s\"\n", clockformats[format]->name);
+#else
+ syslog(LOG_WARNING, "parse: INTERNAL error: bad return code of convert routine \"%s\"\n", clockformats[format]->name);
+#endif
+ return CVT_FAIL|cvtrtc;
+ }
+ }
+ else
+ {
+ /*
+ * find correct conversion routine
+ * and convert time packet
+ * RR search starting at last successful conversion routine
+ */
+
+ if (nformats) /* very careful ... */
+ {
+ do
+ {
+ switch ((cvtrtc = (clockformats[format]->convert && !(clockformats[format]->flags & CVT_FIXEDONLY)) ?
+ clockformats[format]->convert(parseio->parse_data, parseio->parse_index, clockformats[format]->data, &clock) :
+ CVT_NONE) & CVT_MASK)
+ {
+ case CVT_FAIL:
+ parseio->parse_badformat++;
+ cvtsum |= cvtrtc & ~CVT_MASK;
+
+ /*
+ * may be too often ... but is nice to know when it happens
+ */
+#ifdef PARSEKERNEL
+ printf("parse: \"%s\" failed to convert\n", clockformats[format]->name);
+#else
+ syslog(LOG_WARNING, "parse: \"%s\" failed to convert\n", clockformats[format]->name);
+#endif
+ /*FALLTHROUGH*/
+ case CVT_NONE:
+ format++;
+ break;
+
+ case CVT_OK:
+ k = 1;
+ break;
+
+ default:
+ /* shouldn't happen */
+#ifdef PARSEKERNEL
+ printf("parse: INTERNAL error: bad return code of convert routine \"%s\"\n", clockformats[format]->name);
+#else
+ syslog(LOG_WARNING, "parse: INTERNAL error: bad return code of convert routine \"%s\"\n", clockformats[format]->name);
+#endif
+ return CVT_BADFMT;
+ }
+ if (format >= nformats)
+ format = 0;
+ }
+ while (!k && (format != parseio->parse_lformat));
+ }
+ }
+
+ if (!k)
+ {
+#ifdef PARSEKERNEL
+ printf("parse: time format \"%s\" not convertable\n", parseio->parse_data);
+#else
+ syslog(LOG_WARNING, "parse: time format \"%s\" not convertable\n", parseio->parse_data);
+#endif
+ return CVT_FAIL|cvtsum;
+ }
+
+ if ((t = parse_to_unixtime(&clock, &cvtrtc)) == -1)
+ {
+#ifdef PARSEKERNEL
+ printf("parse: bad time format \"%s\"\n", parseio->parse_data);
+#else
+ syslog(LOG_WARNING,"parse: bad time format \"%s\"\n", parseio->parse_data);
+#endif
+ return CVT_FAIL|cvtrtc;
+ }
+
+ parseio->parse_lformat = format;
+
+ /*
+ * time stamp
+ */
+#ifdef PARSEKERNEL
+ parseio->parse_dtime.parse_time.tv.tv_sec = t;
+ parseio->parse_dtime.parse_time.tv.tv_usec = clock.usecond;
+#else
+ parseio->parse_dtime.parse_time.fp.l_ui = t + JAN_1970;
+ TVUTOTSF(clock.usecond, parseio->parse_dtime.parse_time.fp.l_uf);
+#endif
+
+ parseio->parse_dtime.parse_format = format;
+
+ return updatetimeinfo(parseio, t, clock.usecond, clock.flags);
+}
+
+
+/*
+ * control operations
+ */
+/*ARGSUSED*/
+int
+parse_getstat(dct, parse)
+ parsectl_t *dct;
+ parse_t *parse;
+{
+ dct->parsestatus.flags = parse->parse_flags & PARSE_STAT_FLAGS;
+ return 1;
+}
+
+
+/*ARGSUSED*/
+int
+parse_setstat(dct, parse)
+ parsectl_t *dct;
+ parse_t *parse;
+{
+ parse->parse_flags = (parse->parse_flags & ~PARSE_STAT_FLAGS) | dct->parsestatus.flags;
+ return 1;
+}
+
+
+/*ARGSUSED*/
+int
+parse_timecode(dct, parse)
+ parsectl_t *dct;
+ parse_t *parse;
+{
+ dct->parsegettc.parse_state = parse->parse_lstate;
+ dct->parsegettc.parse_format = parse->parse_lformat;
+ /*
+ * move out current bad packet count
+ * user program is expected to sum these up
+ * this is not a problem, as "parse" module are
+ * exclusive open only
+ */
+ dct->parsegettc.parse_badformat = parse->parse_badformat;
+ parse->parse_badformat = 0;
+
+ if (parse->parse_ldsize <= PARSE_TCMAX)
+ {
+ dct->parsegettc.parse_count = parse->parse_ldsize;
+ bcopy(parse->parse_ldata, dct->parsegettc.parse_buffer, dct->parsegettc.parse_count);
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+
+/*ARGSUSED*/
+int
+parse_setfmt(dct, parse)
+ parsectl_t *dct;
+ parse_t *parse;
+{
+ if (dct->parseformat.parse_count <= PARSE_TCMAX)
+ {
+ if (dct->parseformat.parse_count)
+ {
+ register unsigned short i;
+
+ for (i = 0; i < nformats; i++)
+ {
+ if (!Strcmp(dct->parseformat.parse_buffer, clockformats[i]->name))
+ {
+ parse->parse_lformat = i;
+ parse->parse_flags |= PARSE_FIXED_FMT; /* set fixed format indication */
+ return setup_bitmaps(parse, i, i+1);
+ }
+ }
+
+ return 0;
+ }
+ else
+ {
+ parse->parse_flags &= ~PARSE_FIXED_FMT; /* clear fixed format indication */
+ return setup_bitmaps(parse, 0, nformats);
+ }
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+/*ARGSUSED*/
+int
+parse_getfmt(dct, parse)
+ parsectl_t *dct;
+ parse_t *parse;
+{
+ if (dct->parseformat.parse_format < nformats &&
+ Strlen(clockformats[dct->parseformat.parse_format]->name) <= PARSE_TCMAX)
+ {
+ dct->parseformat.parse_count = Strlen(clockformats[dct->parseformat.parse_format]->name)+1;
+ bcopy(clockformats[dct->parseformat.parse_format]->name, dct->parseformat.parse_buffer, dct->parseformat.parse_count);
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+/*ARGSUSED*/
+int
+parse_setcs(dct, parse)
+ parsectl_t *dct;
+ parse_t *parse;
+{
+ parse->parse_ioflags &= ~PARSE_IO_CSIZE;
+ parse->parse_ioflags |= dct->parsesetcs.parse_cs & PARSE_IO_CSIZE;
+ return 1;
+}
+
+#endif /* defined(REFCLOCK) && defined(PARSE) */
+
+/*
+ * History:
+ *
+ * parse.c,v
+ * Revision 3.17 1993/11/11 11:20:29 kardel
+ * declaration fixes
+ *
+ * Revision 3.16 1993/11/06 22:26:07 duwe
+ * Linux cleanup after config change
+ *
+ * Revision 3.15 1993/11/04 11:14:18 kardel
+ * ansi/K&R traps
+ *
+ * Revision 3.14 1993/11/04 10:03:28 kardel
+ * disarmed ansiism
+ *
+ * Revision 3.13 1993/11/01 20:14:13 kardel
+ * useless comparision removed
+ *
+ * Revision 3.12 1993/11/01 20:00:22 kardel
+ * parse Solaris support (initial version)
+ *
+ * Revision 3.11 1993/10/30 09:41:25 kardel
+ * minor optimizations
+ *
+ * Revision 3.10 1993/10/22 14:27:51 kardel
+ * Oct. 22nd 1993 reconcilation
+ *
+ * Revision 3.9 1993/10/05 23:15:09 kardel
+ * more STREAM protection
+ *
+ * Revision 3.8 1993/09/27 21:08:00 kardel
+ * utcoffset now in seconds
+ *
+ * Revision 3.7 1993/09/26 23:40:16 kardel
+ * new parse driver logic
+ *
+ * Revision 3.6 1993/09/07 10:12:46 kardel
+ * September 7th reconcilation - 3.2 (alpha)
+ *
+ * Revision 3.5 1993/09/01 21:44:48 kardel
+ * conditional cleanup
+ *
+ * Revision 3.4 1993/08/27 00:29:39 kardel
+ * compilation cleanup
+ *
+ * Revision 3.3 1993/08/24 22:27:13 kardel
+ * cleaned up AUTOCONF DCF77 mess 8-) - wasn't too bad
+ *
+ * Revision 3.2 1993/07/09 11:37:11 kardel
+ * Initial restructured version + GPS support
+ *
+ * Revision 3.1 1993/07/06 10:00:08 kardel
+ * DCF77 driver goes generic...
+ *
+ */
OpenPOWER on IntegriCloud