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