1999-12-09 13:01:21 +00:00
|
|
|
|
/*
|
2000-01-28 14:55:50 +00:00
|
|
|
|
* /src/NTP/ntp-4/libparse/parse.c,v 4.14 1999/11/28 09:13:52 kardel RELEASE_19991128_A
|
1999-12-09 13:01:21 +00:00
|
|
|
|
*
|
2000-01-28 14:55:50 +00:00
|
|
|
|
* parse.c,v 4.14 1999/11/28 09:13:52 kardel RELEASE_19991128_A
|
1999-12-09 13:01:21 +00:00
|
|
|
|
*
|
|
|
|
|
* Parser module for reference clock
|
|
|
|
|
*
|
|
|
|
|
* PARSEKERNEL define switches between two personalities of the module
|
|
|
|
|
* if PARSEKERNEL is defined this module can be used
|
|
|
|
|
* as 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-1998 by Frank Kardel
|
|
|
|
|
* Friedrich-Alexander Universit<EFBFBD>t Erlangen-N<EFBFBD>rnberg, Germany
|
|
|
|
|
*
|
|
|
|
|
* 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.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
|
# include <config.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(REFCLOCK) && defined(CLOCK_PARSE)
|
|
|
|
|
|
|
|
|
|
#if !(defined(lint) || defined(__GNUC__))
|
2000-01-28 14:55:50 +00:00
|
|
|
|
static char rcsid[] = "parse.c,v 4.14 1999/11/28 09:13:52 kardel RELEASE_19991128_A";
|
1999-12-09 13:01:21 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <sys/time.h>
|
|
|
|
|
|
|
|
|
|
#include "ntp_fp.h"
|
|
|
|
|
#include "ntp_unixtime.h"
|
|
|
|
|
#include "ntp_calendar.h"
|
|
|
|
|
#include "ntp_stdlib.h"
|
|
|
|
|
#include "ntp_machine.h"
|
|
|
|
|
#include "ntp.h" /* (get Y2KFixes definitions) Y2KFixes */
|
|
|
|
|
|
|
|
|
|
#include "parse.h"
|
|
|
|
|
|
|
|
|
|
#ifndef PARSESTREAM
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#else
|
|
|
|
|
#include "sys/parsestreams.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
extern clockformat_t *clockformats[];
|
|
|
|
|
extern unsigned short nformats;
|
|
|
|
|
|
|
|
|
|
static u_long timepacket P((parse_t *));
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* strings support usually not in kernel - duplicated, but what the heck
|
|
|
|
|
*/
|
|
|
|
|
static int
|
|
|
|
|
Strlen(
|
|
|
|
|
register const char *s
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
register int c;
|
|
|
|
|
|
|
|
|
|
c = 0;
|
|
|
|
|
if (s)
|
|
|
|
|
{
|
|
|
|
|
while (*s++)
|
|
|
|
|
{
|
|
|
|
|
c++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
Strcmp(
|
|
|
|
|
register const char *s,
|
|
|
|
|
register const char *t
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
register int c = 0;
|
|
|
|
|
|
|
|
|
|
if (!s || !t || (s == t))
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (!(c = *s++ - *t++) && *s && *t)
|
|
|
|
|
/* empty loop */;
|
|
|
|
|
|
|
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
parse_timedout(
|
|
|
|
|
parse_t *parseio,
|
|
|
|
|
timestamp_t *tstamp,
|
|
|
|
|
struct timeval *del
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
struct timeval delta;
|
|
|
|
|
|
|
|
|
|
#ifdef PARSEKERNEL
|
|
|
|
|
delta.tv_sec = tstamp->tv.tv_sec - parseio->parse_lastchar.tv.tv_sec;
|
|
|
|
|
delta.tv_usec = tstamp->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 = tstamp->fp;
|
|
|
|
|
L_SUB(&delt, &parseio->parse_lastchar.fp);
|
|
|
|
|
TSTOTV(&delt, &delta);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (timercmp(&delta, del, >))
|
|
|
|
|
{
|
|
|
|
|
parseprintf(DD_PARSE, ("parse: timedout: TRUE\n"));
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
parseprintf(DD_PARSE, ("parse: timedout: FALSE\n"));
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*ARGSUSED*/
|
|
|
|
|
int
|
|
|
|
|
parse_ioinit(
|
|
|
|
|
register parse_t *parseio
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
parseprintf(DD_PARSE, ("parse_iostart\n"));
|
|
|
|
|
|
|
|
|
|
parseio->parse_plen = 0;
|
|
|
|
|
parseio->parse_pdata = (void *)0;
|
|
|
|
|
|
|
|
|
|
parseio->parse_data = 0;
|
|
|
|
|
parseio->parse_ldata = 0;
|
|
|
|
|
parseio->parse_dsize = 0;
|
|
|
|
|
|
|
|
|
|
parseio->parse_badformat = 0;
|
|
|
|
|
parseio->parse_ioflags = PARSE_IO_CS7; /* usual unix default */
|
|
|
|
|
parseio->parse_index = 0;
|
|
|
|
|
parseio->parse_ldsize = 0;
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*ARGSUSED*/
|
|
|
|
|
void
|
|
|
|
|
parse_ioend(
|
|
|
|
|
register parse_t *parseio
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
parseprintf(DD_PARSE, ("parse_ioend\n"));
|
|
|
|
|
|
|
|
|
|
if (parseio->parse_pdata)
|
|
|
|
|
FREE(parseio->parse_pdata, parseio->parse_plen);
|
|
|
|
|
|
|
|
|
|
if (parseio->parse_data)
|
|
|
|
|
FREE(parseio->parse_data, (unsigned)(parseio->parse_dsize * 2 + 2));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned int
|
|
|
|
|
parse_restart(
|
|
|
|
|
parse_t *parseio,
|
|
|
|
|
unsigned int ch
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
unsigned int updated = PARSE_INP_SKIP;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* re-start packet - timeout - overflow - start symbol
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (parseio->parse_index)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* filled buffer - thus not end character found
|
|
|
|
|
* do processing now
|
|
|
|
|
*/
|
|
|
|
|
parseio->parse_data[parseio->parse_index] = '\0';
|
|
|
|
|
memcpy(parseio->parse_ldata, parseio->parse_data, (unsigned)(parseio->parse_index+1));
|
|
|
|
|
parseio->parse_ldsize = parseio->parse_index+1;
|
|
|
|
|
updated = PARSE_INP_TIME;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parseio->parse_index = 1;
|
|
|
|
|
parseio->parse_data[0] = ch;
|
|
|
|
|
parseprintf(DD_PARSE, ("parse: parse_restart: buffer start (updated = %x)\n", updated));
|
|
|
|
|
return updated;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned int
|
|
|
|
|
parse_addchar(
|
|
|
|
|
parse_t *parseio,
|
|
|
|
|
unsigned int ch
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* add to buffer
|
|
|
|
|
*/
|
|
|
|
|
if (parseio->parse_index < parseio->parse_dsize)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* collect into buffer
|
|
|
|
|
*/
|
|
|
|
|
parseprintf(DD_PARSE, ("parse: parse_addchar: buffer[%d] = 0x%x\n", parseio->parse_index, ch));
|
|
|
|
|
parseio->parse_data[parseio->parse_index++] = ch;
|
|
|
|
|
return PARSE_INP_SKIP;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
/*
|
|
|
|
|
* buffer overflow - attempt to make the best of it
|
|
|
|
|
*/
|
|
|
|
|
return parse_restart(parseio, ch);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned int
|
|
|
|
|
parse_end(
|
|
|
|
|
parse_t *parseio
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* message complete processing
|
|
|
|
|
*/
|
|
|
|
|
parseio->parse_data[parseio->parse_index] = '\0';
|
|
|
|
|
memcpy(parseio->parse_ldata, parseio->parse_data, (unsigned)(parseio->parse_index+1));
|
|
|
|
|
parseio->parse_ldsize = parseio->parse_index+1;
|
|
|
|
|
parseio->parse_index = 0;
|
|
|
|
|
parseprintf(DD_PARSE, ("parse: parse_end: buffer end\n"));
|
|
|
|
|
return PARSE_INP_TIME;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*ARGSUSED*/
|
|
|
|
|
int
|
|
|
|
|
parse_ioread(
|
|
|
|
|
register parse_t *parseio,
|
|
|
|
|
register unsigned int ch,
|
|
|
|
|
register timestamp_t *tstamp
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
register unsigned updated = CVT_NONE;
|
|
|
|
|
/*
|
|
|
|
|
* 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:
|
|
|
|
|
ch &= 0xFF;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parseprintf(DD_PARSE, ("parse_ioread(0x%lx, char=0x%x, ..., ...)\n", (unsigned long)parseio, ch & 0xFF));
|
|
|
|
|
|
|
|
|
|
if (!clockformats[parseio->parse_lformat]->convert)
|
|
|
|
|
{
|
|
|
|
|
parseprintf(DD_PARSE, ("parse_ioread: input dropped.\n"));
|
|
|
|
|
return CVT_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (clockformats[parseio->parse_lformat]->input)
|
|
|
|
|
{
|
|
|
|
|
unsigned long input_status;
|
|
|
|
|
|
|
|
|
|
input_status = clockformats[parseio->parse_lformat]->input(parseio, ch, tstamp);
|
|
|
|
|
|
|
|
|
|
if (input_status & PARSE_INP_SYNTH)
|
|
|
|
|
{
|
|
|
|
|
updated = CVT_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (input_status & PARSE_INP_TIME) /* time sample is available */
|
|
|
|
|
{
|
|
|
|
|
updated = timepacket(parseio);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (input_status & PARSE_INP_DATA) /* got additional data */
|
|
|
|
|
{
|
|
|
|
|
updated |= CVT_ADDITIONAL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* remember last character time
|
|
|
|
|
*/
|
|
|
|
|
parseio->parse_lastchar = *tstamp;
|
|
|
|
|
|
|
|
|
|
#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) ||
|
|
|
|
|
((updated & CVT_ADDITIONAL) != 0));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 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(
|
|
|
|
|
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 (clockformats[parseio->parse_lformat]->syncpps)
|
|
|
|
|
{
|
|
|
|
|
updated = clockformats[parseio->parse_lformat]->syncpps(parseio, status == SYNC_ONE, ptime);
|
|
|
|
|
parseprintf(DD_PARSE, ("parse_iopps: updated = 0x%x\n", updated));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (updated & CVT_MASK) != CVT_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* parse_iodone
|
|
|
|
|
*
|
|
|
|
|
* clean up internal status for new round
|
|
|
|
|
*/
|
|
|
|
|
/*ARGSUSED*/
|
|
|
|
|
void
|
|
|
|
|
parse_iodone(
|
|
|
|
|
register parse_t *parseio
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* we need to clean up certain flags for the next round
|
|
|
|
|
*/
|
|
|
|
|
parseprintf(DD_PARSE, ("parse_iodone: DONE\n"));
|
|
|
|
|
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 days_per_year(x) ((x) % 4 ? 365 : ((x % 400) ? ((x % 100) ? 366 : 365) : 366))
|
|
|
|
|
|
|
|
|
|
time_t
|
|
|
|
|
parse_to_unixtime(
|
|
|
|
|
register clocktime_t *clock_time,
|
|
|
|
|
register u_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_time->utctime)
|
|
|
|
|
return clock_time->utctime; /* if the conversion routine gets it right away - why not */
|
|
|
|
|
|
|
|
|
|
if ( clock_time->year < YEAR_PIVOT ) /* Y2KFixes [ */
|
|
|
|
|
clock_time->year += 100; /* convert 20xx%100 to 20xx-1900 */
|
|
|
|
|
if ( clock_time->year < YEAR_BREAK ) /* expand to full four-digits */
|
|
|
|
|
clock_time->year += 1900;
|
|
|
|
|
|
|
|
|
|
if (clock_time->year < 1970 ) /* Y2KFixes ] */
|
|
|
|
|
{
|
|
|
|
|
SETRTC(CVT_FAIL|CVT_BADDATE);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* sorry, slow section here - but it's not time critical anyway
|
|
|
|
|
*/
|
|
|
|
|
t = julian0(clock_time->year) - julian0(1970); /* Y2kFixes */
|
|
|
|
|
/* month */
|
|
|
|
|
if (clock_time->month <= 0 || clock_time->month > 12)
|
|
|
|
|
{
|
|
|
|
|
SETRTC(CVT_FAIL|CVT_BADDATE);
|
|
|
|
|
return -1; /* bad month */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if 0 /* Y2KFixes */
|
|
|
|
|
/* adjust leap year */
|
|
|
|
|
if (clock_time->month < 3 && days_per_year(clock_time->year) == 366)
|
|
|
|
|
t--;
|
|
|
|
|
#else /* Y2KFixes [ */
|
|
|
|
|
if ( clock_time->month >= 3 && isleap_4(clock_time->year) )
|
|
|
|
|
t++; /* add one more if within leap year */
|
|
|
|
|
#endif /* Y2KFixes ] */
|
|
|
|
|
|
|
|
|
|
for (i = 1; i < clock_time->month; i++)
|
|
|
|
|
{
|
|
|
|
|
t += days_of_month[i];
|
|
|
|
|
}
|
|
|
|
|
/* day */
|
|
|
|
|
if (clock_time->day < 1 || ((clock_time->month == 2 && days_per_year(clock_time->year) == 366) ?
|
|
|
|
|
clock_time->day > 29 : clock_time->day > days_of_month[clock_time->month]))
|
|
|
|
|
{
|
|
|
|
|
SETRTC(CVT_FAIL|CVT_BADDATE);
|
|
|
|
|
return -1; /* bad day */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
t += clock_time->day - 1;
|
|
|
|
|
/* hour */
|
|
|
|
|
if (clock_time->hour < 0 || clock_time->hour >= 24)
|
|
|
|
|
{
|
|
|
|
|
SETRTC(CVT_FAIL|CVT_BADTIME);
|
|
|
|
|
return -1; /* bad hour */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
t = TIMES24(t) + clock_time->hour;
|
|
|
|
|
|
|
|
|
|
/* min */
|
|
|
|
|
if (clock_time->minute < 0 || clock_time->minute > 59)
|
|
|
|
|
{
|
|
|
|
|
SETRTC(CVT_FAIL|CVT_BADTIME);
|
|
|
|
|
return -1; /* bad min */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
t = TIMES60(t) + clock_time->minute;
|
|
|
|
|
/* sec */
|
|
|
|
|
|
|
|
|
|
if (clock_time->second < 0 || clock_time->second > 60) /* allow for LEAPs */
|
|
|
|
|
{
|
|
|
|
|
SETRTC(CVT_FAIL|CVT_BADTIME);
|
|
|
|
|
return -1; /* bad sec */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
t = TIMES60(t) + clock_time->second;
|
|
|
|
|
|
|
|
|
|
t += clock_time->utcoffset; /* warp to UTC */
|
|
|
|
|
|
|
|
|
|
/* done */
|
|
|
|
|
|
|
|
|
|
clock_time->utctime = t; /* documentray only */
|
|
|
|
|
|
|
|
|
|
return t;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*--------------- format conversion -----------------------------------*/
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
Stoi(
|
|
|
|
|
const unsigned char *s,
|
|
|
|
|
long *zp,
|
|
|
|
|
int cnt
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
char unsigned const *b = s;
|
|
|
|
|
int f,z,v;
|
|
|
|
|
char unsigned 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(
|
|
|
|
|
const unsigned char *s,
|
|
|
|
|
const unsigned char *m
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
if (!s || !m)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
while(*s && *m)
|
|
|
|
|
{
|
|
|
|
|
if ((*m == ' ') ? 1 : (*s == *m))
|
|
|
|
|
{
|
|
|
|
|
s++;
|
|
|
|
|
m++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return !*m;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u_long
|
|
|
|
|
updatetimeinfo(
|
|
|
|
|
register parse_t *parseio,
|
|
|
|
|
register u_long flags
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
#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((unsigned int)s);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef PARSEKERNEL
|
|
|
|
|
parseprintf(DD_PARSE, ("updatetimeinfo status=0x%x, time=%x\n", parseio->parse_dtime.parse_state,
|
|
|
|
|
parseio->parse_dtime.parse_time.tv.tv_sec));
|
|
|
|
|
#else
|
|
|
|
|
parseprintf(DD_PARSE, ("updatetimeinfo status=0x%lx, time=%x\n", (long)parseio->parse_dtime.parse_state,
|
|
|
|
|
parseio->parse_dtime.parse_time.fp.l_ui));
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return CVT_OK; /* everything fine and dandy... */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* syn_simple
|
|
|
|
|
*
|
|
|
|
|
* handle a sync time stamp
|
|
|
|
|
*/
|
|
|
|
|
/*ARGSUSED*/
|
|
|
|
|
void
|
|
|
|
|
syn_simple(
|
|
|
|
|
register parse_t *parseio,
|
|
|
|
|
register timestamp_t *ts,
|
|
|
|
|
register struct format *format,
|
|
|
|
|
register u_long why
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
parseio->parse_dtime.parse_stime = *ts;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* pps_simple
|
|
|
|
|
*
|
|
|
|
|
* handle a pps time stamp
|
|
|
|
|
*/
|
|
|
|
|
/*ARGSUSED*/
|
|
|
|
|
u_long
|
|
|
|
|
pps_simple(
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* pps_one
|
|
|
|
|
*
|
|
|
|
|
* handle a pps time stamp in ONE edge
|
|
|
|
|
*/
|
|
|
|
|
/*ARGSUSED*/
|
|
|
|
|
u_long
|
|
|
|
|
pps_one(
|
|
|
|
|
register parse_t *parseio,
|
|
|
|
|
register int status,
|
|
|
|
|
register timestamp_t *ptime
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
if (status)
|
|
|
|
|
return pps_simple(parseio, status, ptime);
|
|
|
|
|
|
|
|
|
|
return CVT_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* pps_zero
|
|
|
|
|
*
|
|
|
|
|
* handle a pps time stamp in ZERO edge
|
|
|
|
|
*/
|
|
|
|
|
/*ARGSUSED*/
|
|
|
|
|
u_long
|
|
|
|
|
pps_zero(
|
|
|
|
|
register parse_t *parseio,
|
|
|
|
|
register int status,
|
|
|
|
|
register timestamp_t *ptime
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
if (!status)
|
|
|
|
|
return pps_simple(parseio, status, ptime);
|
|
|
|
|
|
|
|
|
|
return CVT_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* timepacket
|
|
|
|
|
*
|
|
|
|
|
* process a data packet
|
|
|
|
|
*/
|
|
|
|
|
static u_long
|
|
|
|
|
timepacket(
|
|
|
|
|
register parse_t *parseio
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
register unsigned short format;
|
|
|
|
|
register time_t t;
|
|
|
|
|
u_long cvtrtc; /* current conversion result */
|
|
|
|
|
clocktime_t clock_time;
|
|
|
|
|
|
|
|
|
|
memset((char *)&clock_time, 0, sizeof clock_time);
|
|
|
|
|
format = parseio->parse_lformat;
|
|
|
|
|
|
|
|
|
|
if (format == (unsigned short)~0)
|
|
|
|
|
return CVT_NONE;
|
|
|
|
|
|
|
|
|
|
switch ((cvtrtc = clockformats[format]->convert ?
|
|
|
|
|
clockformats[format]->convert((unsigned char *)parseio->parse_ldata, parseio->parse_ldsize, (struct format *)(clockformats[format]->data), &clock_time, parseio->parse_pdata) :
|
|
|
|
|
CVT_NONE) & CVT_MASK)
|
|
|
|
|
{
|
|
|
|
|
case CVT_FAIL:
|
|
|
|
|
parseio->parse_badformat++;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case CVT_NONE:
|
|
|
|
|
/*
|
|
|
|
|
* too bad - pretend bad format
|
|
|
|
|
*/
|
|
|
|
|
parseio->parse_badformat++;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case CVT_OK:
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case CVT_SKIP:
|
|
|
|
|
return CVT_NONE;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
/* shouldn't happen */
|
|
|
|
|
#ifndef PARSEKERNEL
|
|
|
|
|
msyslog(LOG_WARNING, "parse: INTERNAL error: bad return code of convert routine \"%s\"\n", clockformats[format]->name);
|
|
|
|
|
#endif
|
|
|
|
|
return CVT_FAIL|cvtrtc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((t = parse_to_unixtime(&clock_time, &cvtrtc)) == -1)
|
|
|
|
|
{
|
|
|
|
|
return CVT_FAIL|cvtrtc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* time stamp
|
|
|
|
|
*/
|
|
|
|
|
#ifdef PARSEKERNEL
|
|
|
|
|
parseio->parse_dtime.parse_time.tv.tv_sec = t;
|
|
|
|
|
parseio->parse_dtime.parse_time.tv.tv_usec = clock_time.usecond;
|
|
|
|
|
#else
|
|
|
|
|
parseio->parse_dtime.parse_time.fp.l_ui = t + JAN_1970;
|
|
|
|
|
TVUTOTSF(clock_time.usecond, parseio->parse_dtime.parse_time.fp.l_uf);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
parseio->parse_dtime.parse_format = format;
|
|
|
|
|
|
|
|
|
|
return updatetimeinfo(parseio, clock_time.flags);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*ARGSUSED*/
|
|
|
|
|
int
|
|
|
|
|
parse_timecode(
|
|
|
|
|
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;
|
|
|
|
|
memcpy(dct->parsegettc.parse_buffer, parse->parse_ldata, dct->parsegettc.parse_count);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*ARGSUSED*/
|
|
|
|
|
int
|
|
|
|
|
parse_setfmt(
|
|
|
|
|
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))
|
|
|
|
|
{
|
|
|
|
|
if (parse->parse_pdata)
|
|
|
|
|
FREE(parse->parse_pdata, parse->parse_plen);
|
|
|
|
|
parse->parse_pdata = 0;
|
|
|
|
|
|
|
|
|
|
parse->parse_plen = clockformats[i]->plen;
|
|
|
|
|
|
|
|
|
|
if (parse->parse_plen)
|
|
|
|
|
{
|
|
|
|
|
parse->parse_pdata = MALLOC(parse->parse_plen);
|
|
|
|
|
if (!parse->parse_pdata)
|
|
|
|
|
{
|
|
|
|
|
parseprintf(DD_PARSE, ("set format failed: malloc for private data area failed\n"));
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
memset((char *)parse->parse_pdata, 0, parse->parse_plen);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (parse->parse_data)
|
|
|
|
|
FREE(parse->parse_data, (unsigned)(parse->parse_dsize * 2 + 2));
|
|
|
|
|
parse->parse_ldata = parse->parse_data = 0;
|
|
|
|
|
|
|
|
|
|
parse->parse_dsize = clockformats[i]->length;
|
|
|
|
|
|
|
|
|
|
if (parse->parse_dsize)
|
|
|
|
|
{
|
|
|
|
|
parse->parse_data = (char*)MALLOC((unsigned)(parse->parse_dsize * 2 + 2));
|
|
|
|
|
if (!parse->parse_data)
|
|
|
|
|
{
|
|
|
|
|
if (parse->parse_pdata)
|
|
|
|
|
FREE(parse->parse_pdata, parse->parse_plen);
|
|
|
|
|
parse->parse_pdata = 0;
|
|
|
|
|
|
|
|
|
|
parseprintf(DD_PARSE, ("init failed: malloc for data area failed\n"));
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* leave room for '\0'
|
|
|
|
|
*/
|
|
|
|
|
parse->parse_ldata = parse->parse_data + parse->parse_dsize + 1;
|
|
|
|
|
|
|
|
|
|
parse->parse_lformat = i;
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*ARGSUSED*/
|
|
|
|
|
int
|
|
|
|
|
parse_getfmt(
|
|
|
|
|
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;
|
|
|
|
|
memcpy(dct->parseformat.parse_buffer, clockformats[dct->parseformat.parse_format]->name, dct->parseformat.parse_count);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*ARGSUSED*/
|
|
|
|
|
int
|
|
|
|
|
parse_setcs(
|
|
|
|
|
parsectl_t *dct,
|
|
|
|
|
parse_t *parse
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
parse->parse_ioflags &= ~PARSE_IO_CSIZE;
|
|
|
|
|
parse->parse_ioflags |= dct->parsesetcs.parse_cs & PARSE_IO_CSIZE;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#else /* not (REFCLOCK && CLOCK_PARSE) */
|
|
|
|
|
int parse_bs;
|
|
|
|
|
#endif /* not (REFCLOCK && CLOCK_PARSE) */
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* History:
|
|
|
|
|
*
|
|
|
|
|
* parse.c,v
|
2000-01-28 14:55:50 +00:00
|
|
|
|
* Revision 4.14 1999/11/28 09:13:52 kardel
|
|
|
|
|
* RECON_4_0_98F
|
|
|
|
|
*
|
1999-12-09 13:01:21 +00:00
|
|
|
|
* Revision 4.13 1999/02/28 11:50:20 kardel
|
|
|
|
|
* (timepacket): removed unecessary code
|
|
|
|
|
*
|
|
|
|
|
* Revision 4.12 1999/02/21 12:17:44 kardel
|
|
|
|
|
* 4.91f reconcilation
|
|
|
|
|
*
|
|
|
|
|
* Revision 4.11 1999/02/21 11:09:47 kardel
|
|
|
|
|
* unified debug output
|
|
|
|
|
*
|
|
|
|
|
* Revision 4.10 1998/12/20 23:45:30 kardel
|
|
|
|
|
* fix types and warnings
|
|
|
|
|
*
|
|
|
|
|
* Revision 4.9 1998/08/09 22:26:06 kardel
|
|
|
|
|
* Trimble TSIP support
|
|
|
|
|
*
|
|
|
|
|
* Revision 4.8 1998/06/14 21:09:39 kardel
|
|
|
|
|
* Sun acc cleanup
|
|
|
|
|
*
|
|
|
|
|
* Revision 4.7 1998/06/13 15:19:13 kardel
|
|
|
|
|
* fix mem*() to b*() function macro emulation
|
|
|
|
|
*
|
|
|
|
|
* Revision 4.6 1998/06/13 13:24:13 kardel
|
|
|
|
|
* printf fmt
|
|
|
|
|
*
|
|
|
|
|
* Revision 4.5 1998/06/13 13:01:10 kardel
|
|
|
|
|
* printf fmt
|
|
|
|
|
*
|
|
|
|
|
* Revision 4.4 1998/06/13 12:12:10 kardel
|
|
|
|
|
* bcopy/memcpy cleanup
|
|
|
|
|
* fix SVSV name clash
|
|
|
|
|
*
|
|
|
|
|
* Revision 4.3 1998/06/12 15:22:30 kardel
|
|
|
|
|
* fix prototypes
|
|
|
|
|
*
|
|
|
|
|
* Revision 4.2 1998/06/12 09:13:27 kardel
|
|
|
|
|
* conditional compile macros fixed
|
|
|
|
|
* printf prototype
|
|
|
|
|
*
|
|
|
|
|
* Revision 4.1 1998/05/24 09:39:55 kardel
|
|
|
|
|
* implementation of the new IO handling model
|
|
|
|
|
*
|
|
|
|
|
* Revision 4.0 1998/04/10 19:45:36 kardel
|
|
|
|
|
* Start 4.0 release version numbering
|
|
|
|
|
*
|
|
|
|
|
* from V3 3.46 log info deleted 1998/04/11 kardel
|
|
|
|
|
*/
|