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