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