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