xref: /netbsd/external/bsd/ntp/dist/libparse/parse.c (revision 4e3b3909)
1*4e3b3909Schristos /*	$NetBSD: parse.c,v 1.4 2015/07/10 14:20:32 christos Exp $	*/
2abb0f93cSkardel 
3abb0f93cSkardel /*
4abb0f93cSkardel  * /src/NTP/ntp4-dev/libparse/parse.c,v 4.20 2005/08/06 17:39:40 kardel RELEASE_20050806_A
5abb0f93cSkardel  *
6abb0f93cSkardel  * parse.c,v 4.20 2005/08/06 17:39:40 kardel RELEASE_20050806_A
7abb0f93cSkardel  *
8abb0f93cSkardel  * Parser module for reference clock
9abb0f93cSkardel  *
10abb0f93cSkardel  * PARSEKERNEL define switches between two personalities of the module
11abb0f93cSkardel  * if PARSEKERNEL is defined this module can be used
12abb0f93cSkardel  * as kernel module. In this case the time stamps will be
13abb0f93cSkardel  * a struct timeval.
14abb0f93cSkardel  * when PARSEKERNEL is not defined NTP time stamps will be used.
15abb0f93cSkardel  *
16abb0f93cSkardel  * Copyright (c) 1995-2005 by Frank Kardel <kardel <AT> ntp.org>
1750cc4415Schristos  * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universitaet Erlangen-Nuernberg, Germany
18abb0f93cSkardel  *
19abb0f93cSkardel  * Redistribution and use in source and binary forms, with or without
20abb0f93cSkardel  * modification, are permitted provided that the following conditions
21abb0f93cSkardel  * are met:
22abb0f93cSkardel  * 1. Redistributions of source code must retain the above copyright
23abb0f93cSkardel  *    notice, this list of conditions and the following disclaimer.
24abb0f93cSkardel  * 2. Redistributions in binary form must reproduce the above copyright
25abb0f93cSkardel  *    notice, this list of conditions and the following disclaimer in the
26abb0f93cSkardel  *    documentation and/or other materials provided with the distribution.
27abb0f93cSkardel  * 3. Neither the name of the author nor the names of its contributors
28abb0f93cSkardel  *    may be used to endorse or promote products derived from this software
29abb0f93cSkardel  *    without specific prior written permission.
30abb0f93cSkardel  *
31abb0f93cSkardel  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
32abb0f93cSkardel  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33abb0f93cSkardel  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34abb0f93cSkardel  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
35abb0f93cSkardel  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36abb0f93cSkardel  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37abb0f93cSkardel  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38abb0f93cSkardel  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39abb0f93cSkardel  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
40abb0f93cSkardel  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41abb0f93cSkardel  * SUCH DAMAGE.
42abb0f93cSkardel  *
43abb0f93cSkardel  */
44abb0f93cSkardel 
45abb0f93cSkardel #ifdef HAVE_CONFIG_H
46abb0f93cSkardel # include <config.h>
47abb0f93cSkardel #endif
48abb0f93cSkardel 
49abb0f93cSkardel #if defined(REFCLOCK) && defined(CLOCK_PARSE)
50abb0f93cSkardel 
51abb0f93cSkardel #if	!(defined(lint) || defined(__GNUC__))
52abb0f93cSkardel static char rcsid[] = "parse.c,v 4.20 2005/08/06 17:39:40 kardel RELEASE_20050806_A";
53abb0f93cSkardel #endif
54abb0f93cSkardel 
55abb0f93cSkardel #include "ntp_fp.h"
562b3787f6Schristos #include "timevalops.h"
57abb0f93cSkardel #include "ntp_calendar.h"
58abb0f93cSkardel #include "ntp_stdlib.h"
59abb0f93cSkardel #include "ntp_machine.h"
60abb0f93cSkardel #include "ntp.h"		/* (get Y2KFixes definitions) 	Y2KFixes */
61abb0f93cSkardel 
62abb0f93cSkardel #include "parse.h"
63abb0f93cSkardel 
64abb0f93cSkardel #ifndef PARSESTREAM
65abb0f93cSkardel # include <stdio.h>
66abb0f93cSkardel #else
67abb0f93cSkardel # include "sys/parsestreams.h"
68abb0f93cSkardel #endif
69abb0f93cSkardel 
70abb0f93cSkardel extern clockformat_t *clockformats[];
71abb0f93cSkardel extern unsigned short nformats;
72abb0f93cSkardel 
73abb0f93cSkardel static u_long timepacket (parse_t *);
74abb0f93cSkardel 
75abb0f93cSkardel /*
76abb0f93cSkardel  * strings support usually not in kernel - duplicated, but what the heck
77abb0f93cSkardel  */
78abb0f93cSkardel static int
79abb0f93cSkardel Strlen(
80abb0f93cSkardel 	register const char *s
81abb0f93cSkardel 	)
82abb0f93cSkardel {
83abb0f93cSkardel 	register int c;
84abb0f93cSkardel 
85abb0f93cSkardel 	c = 0;
86abb0f93cSkardel 	if (s)
87abb0f93cSkardel 	{
88abb0f93cSkardel 		while (*s++)
89abb0f93cSkardel 		{
90abb0f93cSkardel 			c++;
91abb0f93cSkardel 		}
92abb0f93cSkardel 	}
93abb0f93cSkardel 	return c;
94abb0f93cSkardel }
95abb0f93cSkardel 
96abb0f93cSkardel static int
97abb0f93cSkardel Strcmp(
98abb0f93cSkardel 	register const char *s,
99abb0f93cSkardel 	register const char *t
100abb0f93cSkardel 	)
101abb0f93cSkardel {
102abb0f93cSkardel 	register int c = 0;
103abb0f93cSkardel 
104abb0f93cSkardel 	if (!s || !t || (s == t))
105abb0f93cSkardel 	{
106abb0f93cSkardel 		return 0;
107abb0f93cSkardel 	}
108abb0f93cSkardel 
109abb0f93cSkardel 	while (!(c = *s++ - *t++) && *s && *t)
110abb0f93cSkardel 	    /* empty loop */;
111abb0f93cSkardel 
112abb0f93cSkardel 	return c;
113abb0f93cSkardel }
114abb0f93cSkardel 
115abb0f93cSkardel int
116abb0f93cSkardel parse_timedout(
117abb0f93cSkardel 	       parse_t *parseio,
118abb0f93cSkardel 	       timestamp_t *tstamp,
119abb0f93cSkardel 	       struct timeval *del
120abb0f93cSkardel 	       )
121abb0f93cSkardel {
122abb0f93cSkardel 	struct timeval delta;
123abb0f93cSkardel 
124abb0f93cSkardel #ifdef PARSEKERNEL
125abb0f93cSkardel 	delta.tv_sec = tstamp->tv.tv_sec - parseio->parse_lastchar.tv.tv_sec;
126abb0f93cSkardel 	delta.tv_usec = tstamp->tv.tv_usec - parseio->parse_lastchar.tv.tv_usec;
127abb0f93cSkardel 	if (delta.tv_usec < 0)
128abb0f93cSkardel 	{
129abb0f93cSkardel 		delta.tv_sec  -= 1;
130abb0f93cSkardel 		delta.tv_usec += 1000000;
131abb0f93cSkardel 	}
132abb0f93cSkardel #else
133abb0f93cSkardel 	l_fp delt;
134abb0f93cSkardel 
135abb0f93cSkardel 	delt = tstamp->fp;
136abb0f93cSkardel 	L_SUB(&delt, &parseio->parse_lastchar.fp);
137abb0f93cSkardel 	TSTOTV(&delt, &delta);
138abb0f93cSkardel #endif
139abb0f93cSkardel 
140abb0f93cSkardel 	if (timercmp(&delta, del, >))
141abb0f93cSkardel 	{
142abb0f93cSkardel 		parseprintf(DD_PARSE, ("parse: timedout: TRUE\n"));
143abb0f93cSkardel 		return 1;
144abb0f93cSkardel 	}
145abb0f93cSkardel 	else
146abb0f93cSkardel 	{
147abb0f93cSkardel 		parseprintf(DD_PARSE, ("parse: timedout: FALSE\n"));
148abb0f93cSkardel 		return 0;
149abb0f93cSkardel 	}
150abb0f93cSkardel }
151abb0f93cSkardel 
152abb0f93cSkardel /*ARGSUSED*/
153abb0f93cSkardel int
154abb0f93cSkardel parse_ioinit(
155abb0f93cSkardel 	register parse_t *parseio
156abb0f93cSkardel 	)
157abb0f93cSkardel {
158abb0f93cSkardel 	parseprintf(DD_PARSE, ("parse_iostart\n"));
159abb0f93cSkardel 
160abb0f93cSkardel 	parseio->parse_plen = 0;
161abb0f93cSkardel 	parseio->parse_pdata = (void *)0;
162abb0f93cSkardel 
163abb0f93cSkardel 	parseio->parse_data = 0;
164abb0f93cSkardel 	parseio->parse_ldata = 0;
165abb0f93cSkardel 	parseio->parse_dsize = 0;
166abb0f93cSkardel 
167abb0f93cSkardel 	parseio->parse_badformat = 0;
168abb0f93cSkardel 	parseio->parse_ioflags   = PARSE_IO_CS7;	/* usual unix default */
169abb0f93cSkardel 	parseio->parse_index     = 0;
170abb0f93cSkardel 	parseio->parse_ldsize    = 0;
171abb0f93cSkardel 
172abb0f93cSkardel 	return 1;
173abb0f93cSkardel }
174abb0f93cSkardel 
175abb0f93cSkardel /*ARGSUSED*/
176abb0f93cSkardel void
177abb0f93cSkardel parse_ioend(
178abb0f93cSkardel 	register parse_t *parseio
179abb0f93cSkardel 	)
180abb0f93cSkardel {
181abb0f93cSkardel 	parseprintf(DD_PARSE, ("parse_ioend\n"));
182abb0f93cSkardel 
183abb0f93cSkardel 	if (parseio->parse_pdata)
184abb0f93cSkardel 	    FREE(parseio->parse_pdata, parseio->parse_plen);
185abb0f93cSkardel 
186abb0f93cSkardel 	if (parseio->parse_data)
187abb0f93cSkardel 	    FREE(parseio->parse_data, (unsigned)(parseio->parse_dsize * 2 + 2));
188abb0f93cSkardel }
189abb0f93cSkardel 
190abb0f93cSkardel unsigned int
191abb0f93cSkardel parse_restart(
192abb0f93cSkardel 	      parse_t *parseio,
19350cc4415Schristos 	      char ch
194abb0f93cSkardel 	      )
195abb0f93cSkardel {
196abb0f93cSkardel 	unsigned int updated = PARSE_INP_SKIP;
197abb0f93cSkardel 
198abb0f93cSkardel 	/*
199abb0f93cSkardel 	 * re-start packet - timeout - overflow - start symbol
200abb0f93cSkardel 	 */
201abb0f93cSkardel 
202abb0f93cSkardel 	if (parseio->parse_index)
203abb0f93cSkardel 	{
204abb0f93cSkardel 		/*
205abb0f93cSkardel 		 * filled buffer - thus not end character found
206abb0f93cSkardel 		 * do processing now
207abb0f93cSkardel 		 */
208abb0f93cSkardel 		parseio->parse_data[parseio->parse_index] = '\0';
209abb0f93cSkardel 		memcpy(parseio->parse_ldata, parseio->parse_data, (unsigned)(parseio->parse_index+1));
210abb0f93cSkardel 		parseio->parse_ldsize = parseio->parse_index;
211abb0f93cSkardel 		updated = PARSE_INP_TIME;
212abb0f93cSkardel 	}
213abb0f93cSkardel 
214abb0f93cSkardel 	parseio->parse_index = 1;
215abb0f93cSkardel 	parseio->parse_data[0] = ch;
216abb0f93cSkardel 	parseprintf(DD_PARSE, ("parse: parse_restart: buffer start (updated = %x)\n", updated));
217abb0f93cSkardel 	return updated;
218abb0f93cSkardel }
219abb0f93cSkardel 
220abb0f93cSkardel unsigned int
221abb0f93cSkardel parse_addchar(
222abb0f93cSkardel 	      parse_t *parseio,
22350cc4415Schristos 	      char ch
224abb0f93cSkardel 	      )
225abb0f93cSkardel {
226abb0f93cSkardel 	/*
227abb0f93cSkardel 	 * add to buffer
228abb0f93cSkardel 	 */
229abb0f93cSkardel 	if (parseio->parse_index < parseio->parse_dsize)
230abb0f93cSkardel 	{
231abb0f93cSkardel 		/*
232abb0f93cSkardel 		 * collect into buffer
233abb0f93cSkardel 		 */
234abb0f93cSkardel 		parseprintf(DD_PARSE, ("parse: parse_addchar: buffer[%d] = 0x%x\n", parseio->parse_index, ch));
235abb0f93cSkardel 		parseio->parse_data[parseio->parse_index++] = (char)ch;
236abb0f93cSkardel 		return PARSE_INP_SKIP;
237abb0f93cSkardel 	}
238abb0f93cSkardel 	else
239abb0f93cSkardel 		/*
240abb0f93cSkardel 		 * buffer overflow - attempt to make the best of it
241abb0f93cSkardel 		 */
242abb0f93cSkardel 		return parse_restart(parseio, ch);
243abb0f93cSkardel }
244abb0f93cSkardel 
245abb0f93cSkardel unsigned int
246abb0f93cSkardel parse_end(
247abb0f93cSkardel 	  parse_t *parseio
248abb0f93cSkardel 	  )
249abb0f93cSkardel {
250abb0f93cSkardel 	/*
251abb0f93cSkardel 	 * message complete processing
252abb0f93cSkardel 	 */
253abb0f93cSkardel 	parseio->parse_data[parseio->parse_index] = '\0';
254abb0f93cSkardel 	memcpy(parseio->parse_ldata, parseio->parse_data, (unsigned)(parseio->parse_index+1));
255abb0f93cSkardel 	parseio->parse_ldsize = parseio->parse_index;
256abb0f93cSkardel 	parseio->parse_index = 0;
257abb0f93cSkardel 	parseprintf(DD_PARSE, ("parse: parse_end: buffer end\n"));
258abb0f93cSkardel 	return PARSE_INP_TIME;
259abb0f93cSkardel }
260abb0f93cSkardel 
261abb0f93cSkardel /*ARGSUSED*/
262abb0f93cSkardel int
263abb0f93cSkardel parse_ioread(
264abb0f93cSkardel 	register parse_t *parseio,
26550cc4415Schristos 	register char ch,
266abb0f93cSkardel 	register timestamp_t *tstamp
267abb0f93cSkardel 	)
268abb0f93cSkardel {
26950cc4415Schristos 	register u_int updated = CVT_NONE;
270abb0f93cSkardel 	/*
271abb0f93cSkardel 	 * within STREAMS CSx (x < 8) chars still have the upper bits set
272abb0f93cSkardel 	 * so we normalize the characters by masking unecessary bits off.
273abb0f93cSkardel 	 */
274abb0f93cSkardel 	switch (parseio->parse_ioflags & PARSE_IO_CSIZE)
275abb0f93cSkardel 	{
276abb0f93cSkardel 	    case PARSE_IO_CS5:
277abb0f93cSkardel 		ch &= 0x1F;
278abb0f93cSkardel 		break;
279abb0f93cSkardel 
280abb0f93cSkardel 	    case PARSE_IO_CS6:
281abb0f93cSkardel 		ch &= 0x3F;
282abb0f93cSkardel 		break;
283abb0f93cSkardel 
284abb0f93cSkardel 	    case PARSE_IO_CS7:
285abb0f93cSkardel 		ch &= 0x7F;
286abb0f93cSkardel 		break;
287abb0f93cSkardel 
288abb0f93cSkardel 	    case PARSE_IO_CS8:
28950cc4415Schristos 		ch &= (char) 0xFFU;
290abb0f93cSkardel 		break;
291abb0f93cSkardel 	}
292abb0f93cSkardel 
293abb0f93cSkardel 	parseprintf(DD_PARSE, ("parse_ioread(0x%lx, char=0x%x, ..., ...)\n", (unsigned long)parseio, ch & 0xFF));
294abb0f93cSkardel 
295abb0f93cSkardel 	if (!clockformats[parseio->parse_lformat]->convert)
296abb0f93cSkardel 	{
297abb0f93cSkardel 		parseprintf(DD_PARSE, ("parse_ioread: input dropped.\n"));
298abb0f93cSkardel 		return CVT_NONE;
299abb0f93cSkardel 	}
300abb0f93cSkardel 
301abb0f93cSkardel 	if (clockformats[parseio->parse_lformat]->input)
302abb0f93cSkardel 	{
303abb0f93cSkardel 		unsigned long input_status;
304abb0f93cSkardel 
305abb0f93cSkardel 		input_status = clockformats[parseio->parse_lformat]->input(parseio, ch, tstamp);
306abb0f93cSkardel 
307abb0f93cSkardel 		if (input_status & PARSE_INP_SYNTH)
308abb0f93cSkardel 		{
309abb0f93cSkardel 			updated = CVT_OK;
310abb0f93cSkardel 		}
311abb0f93cSkardel 
312abb0f93cSkardel 		if (input_status & PARSE_INP_TIME)	/* time sample is available */
313abb0f93cSkardel 		{
31450cc4415Schristos 			updated = (u_int) timepacket(parseio);
315abb0f93cSkardel 		}
316abb0f93cSkardel 
317abb0f93cSkardel 		if (input_status & PARSE_INP_DATA) /* got additional data */
318abb0f93cSkardel 		{
319abb0f93cSkardel 			updated |= CVT_ADDITIONAL;
320abb0f93cSkardel 		}
321abb0f93cSkardel 	}
322abb0f93cSkardel 
323abb0f93cSkardel 
324abb0f93cSkardel 	/*
325abb0f93cSkardel 	 * remember last character time
326abb0f93cSkardel 	 */
327abb0f93cSkardel 	parseio->parse_lastchar = *tstamp;
328abb0f93cSkardel 
329abb0f93cSkardel #ifdef DEBUG
330abb0f93cSkardel 	if ((updated & CVT_MASK) != CVT_NONE)
331abb0f93cSkardel 	{
332abb0f93cSkardel 		parseprintf(DD_PARSE, ("parse_ioread: time sample accumulated (status=0x%x)\n", updated));
333abb0f93cSkardel 	}
334abb0f93cSkardel #endif
335abb0f93cSkardel 
336abb0f93cSkardel 	parseio->parse_dtime.parse_status = updated;
337abb0f93cSkardel 
338abb0f93cSkardel 	return (((updated & CVT_MASK) != CVT_NONE) ||
339abb0f93cSkardel 		((updated & CVT_ADDITIONAL) != 0));
340abb0f93cSkardel }
341abb0f93cSkardel 
342abb0f93cSkardel /*
343abb0f93cSkardel  * parse_iopps
344abb0f93cSkardel  *
345abb0f93cSkardel  * take status line indication and derive synchronisation information
346abb0f93cSkardel  * from it.
347abb0f93cSkardel  * It can also be used to decode a serial serial data format (such as the
348abb0f93cSkardel  * ONE, ZERO, MINUTE sync data stream from DCF77)
349abb0f93cSkardel  */
350abb0f93cSkardel /*ARGSUSED*/
351abb0f93cSkardel int
352abb0f93cSkardel parse_iopps(
353abb0f93cSkardel 	register parse_t *parseio,
354abb0f93cSkardel 	register int status,
355abb0f93cSkardel 	register timestamp_t *ptime
356abb0f93cSkardel 	)
357abb0f93cSkardel {
35850cc4415Schristos 	register u_int updated = CVT_NONE;
359abb0f93cSkardel 
360abb0f93cSkardel 	/*
361abb0f93cSkardel 	 * PPS pulse information will only be delivered to ONE clock format
362abb0f93cSkardel 	 * this is either the last successful conversion module with a ppssync
363abb0f93cSkardel 	 * routine, or a fixed format with a ppssync routine
364abb0f93cSkardel 	 */
365abb0f93cSkardel 	parseprintf(DD_PARSE, ("parse_iopps: STATUS %s\n", (status == SYNC_ONE) ? "ONE" : "ZERO"));
366abb0f93cSkardel 
367abb0f93cSkardel 	if (clockformats[parseio->parse_lformat]->syncpps)
368abb0f93cSkardel 	{
36950cc4415Schristos 		updated = (u_int) clockformats[parseio->parse_lformat]->syncpps(parseio, status == SYNC_ONE, ptime);
370abb0f93cSkardel 		parseprintf(DD_PARSE, ("parse_iopps: updated = 0x%x\n", updated));
371abb0f93cSkardel 	}
372abb0f93cSkardel 
373abb0f93cSkardel 	return (updated & CVT_MASK) != CVT_NONE;
374abb0f93cSkardel }
375abb0f93cSkardel 
376abb0f93cSkardel /*
377abb0f93cSkardel  * parse_iodone
378abb0f93cSkardel  *
379abb0f93cSkardel  * clean up internal status for new round
380abb0f93cSkardel  */
381abb0f93cSkardel /*ARGSUSED*/
382abb0f93cSkardel void
383abb0f93cSkardel parse_iodone(
384abb0f93cSkardel 	register parse_t *parseio
385abb0f93cSkardel 	)
386abb0f93cSkardel {
387abb0f93cSkardel 	/*
388abb0f93cSkardel 	 * we need to clean up certain flags for the next round
389abb0f93cSkardel 	 */
390abb0f93cSkardel 	parseprintf(DD_PARSE, ("parse_iodone: DONE\n"));
391abb0f93cSkardel 	parseio->parse_dtime.parse_state = 0; /* no problems with ISRs */
392abb0f93cSkardel }
393abb0f93cSkardel 
394abb0f93cSkardel /*---------- conversion implementation --------------------*/
395abb0f93cSkardel 
396abb0f93cSkardel /*
397abb0f93cSkardel  * convert a struct clock to UTC since Jan, 1st 1970 0:00 (the UNIX EPOCH)
398abb0f93cSkardel  */
399abb0f93cSkardel #define days_per_year(x)	((x) % 4 ? 365 : ((x % 400) ? ((x % 100) ? 366 : 365) : 366))
400abb0f93cSkardel 
401abb0f93cSkardel time_t
402abb0f93cSkardel parse_to_unixtime(
403abb0f93cSkardel 	register clocktime_t   *clock_time,
404abb0f93cSkardel 	register u_long *cvtrtc
405abb0f93cSkardel 	)
406abb0f93cSkardel {
407abb0f93cSkardel #define SETRTC(_X_)	{ if (cvtrtc) *cvtrtc = (_X_); }
408abb0f93cSkardel 	static int days_of_month[] =
409abb0f93cSkardel 	{
410abb0f93cSkardel 		0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
411abb0f93cSkardel 	};
412abb0f93cSkardel 	register int i;
413abb0f93cSkardel 	time_t t;
414abb0f93cSkardel 
415abb0f93cSkardel 	if (clock_time->utctime)
416abb0f93cSkardel 	    return clock_time->utctime;	/* if the conversion routine gets it right away - why not */
417abb0f93cSkardel 
418abb0f93cSkardel 	if ( clock_time->year < YEAR_PIVOT )			/* Y2KFixes [ */
419abb0f93cSkardel 	    clock_time->year += 100;	/* convert 20xx%100 to 20xx-1900 */
420abb0f93cSkardel 	if ( clock_time->year < YEAR_BREAK )	/* expand to full four-digits */
421abb0f93cSkardel 	    clock_time->year += 1900;
422abb0f93cSkardel 
423abb0f93cSkardel 	if (clock_time->year < 1970 )				/* Y2KFixes ] */
424abb0f93cSkardel 	{
425abb0f93cSkardel 		SETRTC(CVT_FAIL|CVT_BADDATE);
426abb0f93cSkardel 		return -1;
427abb0f93cSkardel 	}
428abb0f93cSkardel 
429abb0f93cSkardel 	/*
430abb0f93cSkardel 	 * sorry, slow section here - but it's not time critical anyway
431abb0f93cSkardel 	 */
432abb0f93cSkardel 	t = julian0(clock_time->year) - julian0(1970);		/* Y2kFixes */
433abb0f93cSkardel 				/* month */
434abb0f93cSkardel 	if (clock_time->month <= 0 || clock_time->month > 12)
435abb0f93cSkardel 	{
436abb0f93cSkardel 		SETRTC(CVT_FAIL|CVT_BADDATE);
437abb0f93cSkardel 		return -1;		/* bad month */
438abb0f93cSkardel 	}
439abb0f93cSkardel 
440abb0f93cSkardel #if 0								/* Y2KFixes */
441abb0f93cSkardel 				/* adjust leap year */
442abb0f93cSkardel 	if (clock_time->month < 3 && days_per_year(clock_time->year) == 366)
443abb0f93cSkardel 	    t--;
444abb0f93cSkardel #else								/* Y2KFixes [ */
445abb0f93cSkardel 	if ( clock_time->month >= 3  &&  isleap_4(clock_time->year) )
446abb0f93cSkardel 	    t++;		/* add one more if within leap year */
447abb0f93cSkardel #endif								/* Y2KFixes ] */
448abb0f93cSkardel 
449abb0f93cSkardel 	for (i = 1; i < clock_time->month; i++)
450abb0f93cSkardel 	{
451abb0f93cSkardel 		t += days_of_month[i];
452abb0f93cSkardel 	}
453abb0f93cSkardel 				/* day */
454abb0f93cSkardel 	if (clock_time->day < 1 || ((clock_time->month == 2 && days_per_year(clock_time->year) == 366) ?
455abb0f93cSkardel 			       clock_time->day > 29 : clock_time->day > days_of_month[clock_time->month]))
456abb0f93cSkardel 	{
457abb0f93cSkardel 		SETRTC(CVT_FAIL|CVT_BADDATE);
458abb0f93cSkardel 		return -1;		/* bad day */
459abb0f93cSkardel 	}
460abb0f93cSkardel 
461abb0f93cSkardel 	t += clock_time->day - 1;
462abb0f93cSkardel 				/* hour */
463abb0f93cSkardel 	if (clock_time->hour < 0 || clock_time->hour >= 24)
464abb0f93cSkardel 	{
465abb0f93cSkardel 		SETRTC(CVT_FAIL|CVT_BADTIME);
466abb0f93cSkardel 		return -1;		/* bad hour */
467abb0f93cSkardel 	}
468abb0f93cSkardel 
469abb0f93cSkardel 	t = TIMES24(t) + clock_time->hour;
470abb0f93cSkardel 
471abb0f93cSkardel 				/* min */
472abb0f93cSkardel 	if (clock_time->minute < 0 || clock_time->minute > 59)
473abb0f93cSkardel 	{
474abb0f93cSkardel 		SETRTC(CVT_FAIL|CVT_BADTIME);
475abb0f93cSkardel 		return -1;		/* bad min */
476abb0f93cSkardel 	}
477abb0f93cSkardel 
478abb0f93cSkardel 	t = TIMES60(t) + clock_time->minute;
479abb0f93cSkardel 				/* sec */
480abb0f93cSkardel 
481abb0f93cSkardel 	if (clock_time->second < 0 || clock_time->second > 60)	/* allow for LEAPs */
482abb0f93cSkardel 	{
483abb0f93cSkardel 		SETRTC(CVT_FAIL|CVT_BADTIME);
484abb0f93cSkardel 		return -1;		/* bad sec */
485abb0f93cSkardel 	}
486abb0f93cSkardel 
487abb0f93cSkardel 	t  = TIMES60(t) + clock_time->second;
488abb0f93cSkardel 
489abb0f93cSkardel 	t += clock_time->utcoffset;	/* warp to UTC */
490abb0f93cSkardel 
491abb0f93cSkardel 				/* done */
492abb0f93cSkardel 
493abb0f93cSkardel 	clock_time->utctime = t;		/* documentray only */
494abb0f93cSkardel 
495abb0f93cSkardel 	return t;
496abb0f93cSkardel }
497abb0f93cSkardel 
498abb0f93cSkardel /*--------------- format conversion -----------------------------------*/
499abb0f93cSkardel 
500abb0f93cSkardel int
501abb0f93cSkardel Stoi(
502abb0f93cSkardel 	const unsigned char *s,
503abb0f93cSkardel 	long *zp,
504abb0f93cSkardel 	int cnt
505abb0f93cSkardel 	)
506abb0f93cSkardel {
507abb0f93cSkardel 	char unsigned const *b = s;
508abb0f93cSkardel 	int f,z,v;
509abb0f93cSkardel 	char unsigned c;
510abb0f93cSkardel 
511abb0f93cSkardel 	f=z=v=0;
512abb0f93cSkardel 
513abb0f93cSkardel 	while(*s == ' ')
514abb0f93cSkardel 	    s++;
515abb0f93cSkardel 
516abb0f93cSkardel 	if (*s == '-')
517abb0f93cSkardel 	{
518abb0f93cSkardel 		s++;
519abb0f93cSkardel 		v = 1;
520abb0f93cSkardel 	}
521abb0f93cSkardel 	else
522abb0f93cSkardel 	    if (*s == '+')
523abb0f93cSkardel 		s++;
524abb0f93cSkardel 
525abb0f93cSkardel 	for(;;)
526abb0f93cSkardel 	{
527abb0f93cSkardel 		c = *s++;
528abb0f93cSkardel 		if (c == '\0' || c < '0' || c > '9' || (cnt && ((s-b) > cnt)))
529abb0f93cSkardel 		{
530abb0f93cSkardel 			if (f == 0)
531abb0f93cSkardel 			{
532abb0f93cSkardel 				return(-1);
533abb0f93cSkardel 			}
534abb0f93cSkardel 			if (v)
535abb0f93cSkardel 			    z = -z;
536abb0f93cSkardel 			*zp = z;
537abb0f93cSkardel 			return(0);
538abb0f93cSkardel 		}
539abb0f93cSkardel 		z = (z << 3) + (z << 1) + ( c - '0' );
540abb0f93cSkardel 		f=1;
541abb0f93cSkardel 	}
542abb0f93cSkardel }
543abb0f93cSkardel 
544abb0f93cSkardel int
545abb0f93cSkardel Strok(
546abb0f93cSkardel 	const unsigned char *s,
547abb0f93cSkardel 	const unsigned char *m
548abb0f93cSkardel 	)
549abb0f93cSkardel {
550abb0f93cSkardel 	if (!s || !m)
551abb0f93cSkardel 	    return 0;
552abb0f93cSkardel 
553abb0f93cSkardel 	while(*s && *m)
554abb0f93cSkardel 	{
555abb0f93cSkardel 		if ((*m == ' ') ? 1 : (*s == *m))
556abb0f93cSkardel 		{
557abb0f93cSkardel 			s++;
558abb0f93cSkardel 			m++;
559abb0f93cSkardel 		}
560abb0f93cSkardel 		else
561abb0f93cSkardel 		{
562abb0f93cSkardel 			return 0;
563abb0f93cSkardel 		}
564abb0f93cSkardel 	}
565abb0f93cSkardel 	return !*m;
566abb0f93cSkardel }
567abb0f93cSkardel 
568abb0f93cSkardel u_long
569abb0f93cSkardel updatetimeinfo(
570abb0f93cSkardel 	       register parse_t *parseio,
571abb0f93cSkardel 	       register u_long   flags
572abb0f93cSkardel 	       )
573abb0f93cSkardel {
574abb0f93cSkardel #ifdef PARSEKERNEL
575abb0f93cSkardel 	{
576abb0f93cSkardel 		int s = splhigh();
577abb0f93cSkardel #endif
578abb0f93cSkardel 
579abb0f93cSkardel 		parseio->parse_lstate          = parseio->parse_dtime.parse_state | flags | PARSEB_TIMECODE;
580abb0f93cSkardel 
581abb0f93cSkardel 		parseio->parse_dtime.parse_state = parseio->parse_lstate;
582abb0f93cSkardel 
583abb0f93cSkardel #ifdef PARSEKERNEL
584abb0f93cSkardel 		(void)splx((unsigned int)s);
585abb0f93cSkardel 	}
586abb0f93cSkardel #endif
587abb0f93cSkardel 
588abb0f93cSkardel 
589abb0f93cSkardel #ifdef PARSEKERNEL
590abb0f93cSkardel 	parseprintf(DD_PARSE, ("updatetimeinfo status=0x%x, time=%x\n", parseio->parse_dtime.parse_state,
591abb0f93cSkardel 			       parseio->parse_dtime.parse_time.tv.tv_sec));
592abb0f93cSkardel #else
593abb0f93cSkardel 	parseprintf(DD_PARSE, ("updatetimeinfo status=0x%lx, time=%x\n", (long)parseio->parse_dtime.parse_state,
594abb0f93cSkardel 	                       parseio->parse_dtime.parse_time.fp.l_ui));
595abb0f93cSkardel #endif
596abb0f93cSkardel 
597abb0f93cSkardel 	return CVT_OK;		/* everything fine and dandy... */
598abb0f93cSkardel }
599abb0f93cSkardel 
600abb0f93cSkardel 
601abb0f93cSkardel /*
602abb0f93cSkardel  * syn_simple
603abb0f93cSkardel  *
604abb0f93cSkardel  * handle a sync time stamp
605abb0f93cSkardel  */
606abb0f93cSkardel /*ARGSUSED*/
607abb0f93cSkardel void
608abb0f93cSkardel syn_simple(
609abb0f93cSkardel 	register parse_t *parseio,
610abb0f93cSkardel 	register timestamp_t *ts,
611abb0f93cSkardel 	register struct format *format,
612abb0f93cSkardel 	register u_long why
613abb0f93cSkardel 	)
614abb0f93cSkardel {
615abb0f93cSkardel 	parseio->parse_dtime.parse_stime = *ts;
616abb0f93cSkardel }
617abb0f93cSkardel 
618abb0f93cSkardel /*
61950cc4415Schristos  * parse_pps_fnc_t pps_simple
620abb0f93cSkardel  *
621abb0f93cSkardel  * handle a pps time stamp
622abb0f93cSkardel  */
623abb0f93cSkardel /*ARGSUSED*/
624abb0f93cSkardel u_long
625abb0f93cSkardel pps_simple(
626abb0f93cSkardel 	register parse_t *parseio,
627abb0f93cSkardel 	register int status,
628abb0f93cSkardel 	register timestamp_t *ptime
629abb0f93cSkardel 	)
630abb0f93cSkardel {
631abb0f93cSkardel 	parseio->parse_dtime.parse_ptime  = *ptime;
632abb0f93cSkardel 	parseio->parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
633abb0f93cSkardel 
634abb0f93cSkardel 	return CVT_NONE;
635abb0f93cSkardel }
636abb0f93cSkardel 
637abb0f93cSkardel /*
63850cc4415Schristos  * parse_pps_fnc_t pps_one
639abb0f93cSkardel  *
640abb0f93cSkardel  * handle a pps time stamp in ONE edge
641abb0f93cSkardel  */
642abb0f93cSkardel /*ARGSUSED*/
643abb0f93cSkardel u_long
644abb0f93cSkardel pps_one(
645abb0f93cSkardel 	register parse_t *parseio,
646abb0f93cSkardel 	register int status,
647abb0f93cSkardel 	register timestamp_t *ptime
648abb0f93cSkardel 	)
649abb0f93cSkardel {
650abb0f93cSkardel 	if (status)
651abb0f93cSkardel 		return pps_simple(parseio, status, ptime);
652abb0f93cSkardel 
653abb0f93cSkardel 	return CVT_NONE;
654abb0f93cSkardel }
655abb0f93cSkardel 
656abb0f93cSkardel /*
65750cc4415Schristos  * parse_pps_fnc_t pps_zero
658abb0f93cSkardel  *
659abb0f93cSkardel  * handle a pps time stamp in ZERO edge
660abb0f93cSkardel  */
661abb0f93cSkardel /*ARGSUSED*/
662abb0f93cSkardel u_long
663abb0f93cSkardel pps_zero(
664abb0f93cSkardel 	register parse_t *parseio,
665abb0f93cSkardel 	register int status,
666abb0f93cSkardel 	register timestamp_t *ptime
667abb0f93cSkardel 	)
668abb0f93cSkardel {
669abb0f93cSkardel 	if (!status)
670abb0f93cSkardel 		return pps_simple(parseio, status, ptime);
671abb0f93cSkardel 
672abb0f93cSkardel 	return CVT_NONE;
673abb0f93cSkardel }
674abb0f93cSkardel 
675abb0f93cSkardel /*
676abb0f93cSkardel  * timepacket
677abb0f93cSkardel  *
678abb0f93cSkardel  * process a data packet
679abb0f93cSkardel  */
680abb0f93cSkardel static u_long
681abb0f93cSkardel timepacket(
682abb0f93cSkardel 	register parse_t *parseio
683abb0f93cSkardel 	)
684abb0f93cSkardel {
685abb0f93cSkardel 	register unsigned short format;
686abb0f93cSkardel 	register time_t t;
687abb0f93cSkardel 	u_long cvtrtc;		/* current conversion result */
688abb0f93cSkardel 	clocktime_t clock_time;
689abb0f93cSkardel 
690abb0f93cSkardel 	memset((char *)&clock_time, 0, sizeof clock_time);
691abb0f93cSkardel 	format = parseio->parse_lformat;
692abb0f93cSkardel 
693abb0f93cSkardel 	if (format == (unsigned short)~0)
694abb0f93cSkardel 		return CVT_NONE;
695abb0f93cSkardel 
696abb0f93cSkardel 	switch ((cvtrtc = clockformats[format]->convert ?
697abb0f93cSkardel 		 clockformats[format]->convert((unsigned char *)parseio->parse_ldata, parseio->parse_ldsize, (struct format *)(clockformats[format]->data), &clock_time, parseio->parse_pdata) :
698abb0f93cSkardel 		 CVT_NONE) & CVT_MASK)
699abb0f93cSkardel 	{
700abb0f93cSkardel 	case CVT_FAIL:
701abb0f93cSkardel 		parseio->parse_badformat++;
702*4e3b3909Schristos 		return cvtrtc;
703abb0f93cSkardel 
704abb0f93cSkardel 	case CVT_NONE:
705abb0f93cSkardel 		/*
706abb0f93cSkardel 		 * too bad - pretend bad format
707abb0f93cSkardel 		 */
708abb0f93cSkardel 		parseio->parse_badformat++;
709*4e3b3909Schristos 		return CVT_NONE;
710abb0f93cSkardel 
711abb0f93cSkardel 	case CVT_OK:
712abb0f93cSkardel 		break;
713abb0f93cSkardel 
714abb0f93cSkardel 	case CVT_SKIP:
715abb0f93cSkardel 		return CVT_NONE;
716abb0f93cSkardel 
717abb0f93cSkardel 	default:
718abb0f93cSkardel 		/* shouldn't happen */
719abb0f93cSkardel #ifndef PARSEKERNEL
7202b3787f6Schristos 		msyslog(LOG_WARNING, "parse: INTERNAL error: bad return code of convert routine \"%s\"", clockformats[format]->name);
721abb0f93cSkardel #endif
722abb0f93cSkardel 		return CVT_FAIL|cvtrtc;
723abb0f93cSkardel 	}
724abb0f93cSkardel 
725abb0f93cSkardel 	if ((t = parse_to_unixtime(&clock_time, &cvtrtc)) == -1)
726abb0f93cSkardel 	{
727abb0f93cSkardel 		return CVT_FAIL|cvtrtc;
728abb0f93cSkardel 	}
729abb0f93cSkardel 
730abb0f93cSkardel 	/*
731abb0f93cSkardel 	 * time stamp
732abb0f93cSkardel 	 */
733abb0f93cSkardel #ifdef PARSEKERNEL
734abb0f93cSkardel 	parseio->parse_dtime.parse_time.tv.tv_sec  = t;
735abb0f93cSkardel 	parseio->parse_dtime.parse_time.tv.tv_usec = clock_time.usecond;
736abb0f93cSkardel #else
73750cc4415Schristos 	parseio->parse_dtime.parse_time.fp.l_ui = (uint32_t) (t + JAN_1970);
738abb0f93cSkardel 	TVUTOTSF(clock_time.usecond, parseio->parse_dtime.parse_time.fp.l_uf);
739abb0f93cSkardel #endif
740abb0f93cSkardel 
741abb0f93cSkardel 	parseio->parse_dtime.parse_format       = format;
742abb0f93cSkardel 
743abb0f93cSkardel 	return updatetimeinfo(parseio, clock_time.flags);
744abb0f93cSkardel }
745abb0f93cSkardel 
746abb0f93cSkardel /*ARGSUSED*/
747abb0f93cSkardel int
748abb0f93cSkardel parse_timecode(
749abb0f93cSkardel 	parsectl_t *dct,
750abb0f93cSkardel 	parse_t    *parse
751abb0f93cSkardel 	)
752abb0f93cSkardel {
753abb0f93cSkardel 	dct->parsegettc.parse_state  = parse->parse_lstate;
754abb0f93cSkardel 	dct->parsegettc.parse_format = parse->parse_lformat;
755abb0f93cSkardel 	/*
756abb0f93cSkardel 	 * move out current bad packet count
757abb0f93cSkardel 	 * user program is expected to sum these up
758abb0f93cSkardel 	 * this is not a problem, as "parse" module are
759abb0f93cSkardel 	 * exclusive open only
760abb0f93cSkardel 	 */
761abb0f93cSkardel 	dct->parsegettc.parse_badformat = parse->parse_badformat;
762abb0f93cSkardel 	parse->parse_badformat = 0;
763abb0f93cSkardel 
764abb0f93cSkardel 	if (parse->parse_ldsize <= PARSE_TCMAX)
765abb0f93cSkardel 	{
766abb0f93cSkardel 		dct->parsegettc.parse_count = parse->parse_ldsize;
767abb0f93cSkardel 		memcpy(dct->parsegettc.parse_buffer, parse->parse_ldata, dct->parsegettc.parse_count);
768abb0f93cSkardel 		return 1;
769abb0f93cSkardel 	}
770abb0f93cSkardel 	else
771abb0f93cSkardel 	{
772abb0f93cSkardel 		return 0;
773abb0f93cSkardel 	}
774abb0f93cSkardel }
775abb0f93cSkardel 
776abb0f93cSkardel 
777abb0f93cSkardel /*ARGSUSED*/
778abb0f93cSkardel int
779abb0f93cSkardel parse_setfmt(
780abb0f93cSkardel 	parsectl_t *dct,
781abb0f93cSkardel 	parse_t    *parse
782abb0f93cSkardel 	)
783abb0f93cSkardel {
784abb0f93cSkardel 	if (dct->parseformat.parse_count <= PARSE_TCMAX)
785abb0f93cSkardel 	{
786abb0f93cSkardel 		if (dct->parseformat.parse_count)
787abb0f93cSkardel 		{
788abb0f93cSkardel 			register unsigned short i;
789abb0f93cSkardel 
790abb0f93cSkardel 			for (i = 0; i < nformats; i++)
791abb0f93cSkardel 			{
792abb0f93cSkardel 				if (!Strcmp(dct->parseformat.parse_buffer, clockformats[i]->name))
793abb0f93cSkardel 				{
794abb0f93cSkardel 					if (parse->parse_pdata)
795abb0f93cSkardel 						FREE(parse->parse_pdata, parse->parse_plen);
796abb0f93cSkardel 					parse->parse_pdata = 0;
797abb0f93cSkardel 
798abb0f93cSkardel 					parse->parse_plen = clockformats[i]->plen;
799abb0f93cSkardel 
800abb0f93cSkardel 					if (parse->parse_plen)
801abb0f93cSkardel 					{
802abb0f93cSkardel 						parse->parse_pdata = MALLOC(parse->parse_plen);
803abb0f93cSkardel 						if (!parse->parse_pdata)
804abb0f93cSkardel 						{
805abb0f93cSkardel 							parseprintf(DD_PARSE, ("set format failed: malloc for private data area failed\n"));
806abb0f93cSkardel 							return 0;
807abb0f93cSkardel 						}
808abb0f93cSkardel 						memset((char *)parse->parse_pdata, 0, parse->parse_plen);
809abb0f93cSkardel 					}
810abb0f93cSkardel 
811abb0f93cSkardel 					if (parse->parse_data)
812abb0f93cSkardel 						FREE(parse->parse_data, (unsigned)(parse->parse_dsize * 2 + 2));
813abb0f93cSkardel 					parse->parse_ldata = parse->parse_data = 0;
814abb0f93cSkardel 
815abb0f93cSkardel 					parse->parse_dsize = clockformats[i]->length;
816abb0f93cSkardel 
817abb0f93cSkardel 					if (parse->parse_dsize)
818abb0f93cSkardel 					{
819abb0f93cSkardel 						parse->parse_data = (char*)MALLOC((unsigned)(parse->parse_dsize * 2 + 2));
820abb0f93cSkardel 						if (!parse->parse_data)
821abb0f93cSkardel 						{
822abb0f93cSkardel 							if (parse->parse_pdata)
823abb0f93cSkardel 								FREE(parse->parse_pdata, parse->parse_plen);
824abb0f93cSkardel 							parse->parse_pdata = 0;
825abb0f93cSkardel 
826abb0f93cSkardel 							parseprintf(DD_PARSE, ("init failed: malloc for data area failed\n"));
827abb0f93cSkardel 							return 0;
828abb0f93cSkardel 						}
829abb0f93cSkardel 					}
830abb0f93cSkardel 
831abb0f93cSkardel 
832abb0f93cSkardel 					/*
833abb0f93cSkardel 					 * leave room for '\0'
834abb0f93cSkardel 					 */
835abb0f93cSkardel 					parse->parse_ldata     = parse->parse_data + parse->parse_dsize + 1;
836abb0f93cSkardel 
837abb0f93cSkardel 					parse->parse_lformat  = i;
838abb0f93cSkardel 
839abb0f93cSkardel 					return 1;
840abb0f93cSkardel 				}
841abb0f93cSkardel 			}
842abb0f93cSkardel 		}
843abb0f93cSkardel 	}
844abb0f93cSkardel 	return 0;
845abb0f93cSkardel }
846abb0f93cSkardel 
847abb0f93cSkardel /*ARGSUSED*/
848abb0f93cSkardel int
849abb0f93cSkardel parse_getfmt(
850abb0f93cSkardel 	parsectl_t *dct,
851abb0f93cSkardel 	parse_t    *parse
852abb0f93cSkardel 	)
853abb0f93cSkardel {
854abb0f93cSkardel 	if (dct->parseformat.parse_format < nformats &&
855abb0f93cSkardel 	    Strlen(clockformats[dct->parseformat.parse_format]->name) <= PARSE_TCMAX)
856abb0f93cSkardel 	{
85750cc4415Schristos 		dct->parseformat.parse_count = (unsigned short) (Strlen(clockformats[dct->parseformat.parse_format]->name) + 1);
858abb0f93cSkardel 		memcpy(dct->parseformat.parse_buffer, clockformats[dct->parseformat.parse_format]->name, dct->parseformat.parse_count);
859abb0f93cSkardel 		return 1;
860abb0f93cSkardel 	}
861abb0f93cSkardel 	else
862abb0f93cSkardel 	{
863abb0f93cSkardel 		return 0;
864abb0f93cSkardel 	}
865abb0f93cSkardel }
866abb0f93cSkardel 
867abb0f93cSkardel /*ARGSUSED*/
868abb0f93cSkardel int
869abb0f93cSkardel parse_setcs(
870abb0f93cSkardel 	parsectl_t *dct,
871abb0f93cSkardel 	parse_t    *parse
872abb0f93cSkardel 	)
873abb0f93cSkardel {
874abb0f93cSkardel 	parse->parse_ioflags &= ~PARSE_IO_CSIZE;
87550cc4415Schristos 	parse->parse_ioflags |= (int) (dct->parsesetcs.parse_cs & PARSE_IO_CSIZE);
876abb0f93cSkardel 	return 1;
877abb0f93cSkardel }
878abb0f93cSkardel 
879abb0f93cSkardel #else /* not (REFCLOCK && CLOCK_PARSE) */
880abb0f93cSkardel int parse_bs;
881abb0f93cSkardel #endif /* not (REFCLOCK && CLOCK_PARSE) */
882abb0f93cSkardel 
883abb0f93cSkardel /*
884abb0f93cSkardel  * History:
885abb0f93cSkardel  *
886abb0f93cSkardel  * parse.c,v
887abb0f93cSkardel  * Revision 4.20  2005/08/06 17:39:40  kardel
888abb0f93cSkardel  * cleanup size handling wrt/ to buffer boundaries
889abb0f93cSkardel  *
890abb0f93cSkardel  * Revision 4.19  2005/04/16 17:32:10  kardel
891abb0f93cSkardel  * update copyright
892abb0f93cSkardel  *
893abb0f93cSkardel  * Revision 4.18  2004/11/14 16:11:05  kardel
894abb0f93cSkardel  * update Id tags
895abb0f93cSkardel  *
896abb0f93cSkardel  * Revision 4.17  2004/11/14 15:29:41  kardel
897abb0f93cSkardel  * support PPSAPI, upgrade Copyright to Berkeley style
898abb0f93cSkardel  *
899abb0f93cSkardel  * Revision 4.14  1999/11/28 09:13:52  kardel
900abb0f93cSkardel  * RECON_4_0_98F
901abb0f93cSkardel  *
902abb0f93cSkardel  * Revision 4.13  1999/02/28 11:50:20  kardel
903abb0f93cSkardel  * (timepacket): removed unecessary code
904abb0f93cSkardel  *
905abb0f93cSkardel  * Revision 4.12  1999/02/21 12:17:44  kardel
906abb0f93cSkardel  * 4.91f reconcilation
907abb0f93cSkardel  *
908abb0f93cSkardel  * Revision 4.11  1999/02/21 11:09:47  kardel
909abb0f93cSkardel  * unified debug output
910abb0f93cSkardel  *
911abb0f93cSkardel  * Revision 4.10  1998/12/20 23:45:30  kardel
912abb0f93cSkardel  * fix types and warnings
913abb0f93cSkardel  *
914abb0f93cSkardel  * Revision 4.9  1998/08/09 22:26:06  kardel
915abb0f93cSkardel  * Trimble TSIP support
916abb0f93cSkardel  *
917abb0f93cSkardel  * Revision 4.8  1998/06/14 21:09:39  kardel
918abb0f93cSkardel  * Sun acc cleanup
919abb0f93cSkardel  *
920abb0f93cSkardel  * Revision 4.7  1998/06/13 15:19:13  kardel
921abb0f93cSkardel  * fix mem*() to b*() function macro emulation
922abb0f93cSkardel  *
923abb0f93cSkardel  * Revision 4.6  1998/06/13 13:24:13  kardel
924abb0f93cSkardel  * printf fmt
925abb0f93cSkardel  *
926abb0f93cSkardel  * Revision 4.5  1998/06/13 13:01:10  kardel
927abb0f93cSkardel  * printf fmt
928abb0f93cSkardel  *
929abb0f93cSkardel  * Revision 4.4  1998/06/13 12:12:10  kardel
930abb0f93cSkardel  * bcopy/memcpy cleanup
931abb0f93cSkardel  * fix SVSV name clash
932abb0f93cSkardel  *
933abb0f93cSkardel  * Revision 4.3  1998/06/12 15:22:30  kardel
934abb0f93cSkardel  * fix prototypes
935abb0f93cSkardel  *
936abb0f93cSkardel  * Revision 4.2  1998/06/12 09:13:27  kardel
937abb0f93cSkardel  * conditional compile macros fixed
938abb0f93cSkardel  * printf prototype
939abb0f93cSkardel  *
940abb0f93cSkardel  * Revision 4.1  1998/05/24 09:39:55  kardel
941abb0f93cSkardel  * implementation of the new IO handling model
942abb0f93cSkardel  *
943abb0f93cSkardel  * Revision 4.0  1998/04/10 19:45:36  kardel
944abb0f93cSkardel  * Start 4.0 release version numbering
945abb0f93cSkardel  *
946abb0f93cSkardel  * from V3 3.46 log info deleted 1998/04/11 kardel
947abb0f93cSkardel  */
948