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__))
52static 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
70extern clockformat_t *clockformats[];
71extern unsigned short nformats;
72
73static u_long timepacket (parse_t *);
74
75/*
76 * strings support usually not in kernel - duplicated, but what the heck
77 */
78static int
79Strlen(
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
96static int
97Strcmp(
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
115int
116parse_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*/
153int
154parse_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*/
176void
177parse_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
190unsigned int
191parse_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
220unsigned int
221parse_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
245unsigned int
246parse_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*/
262int
263parse_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*/
351int
352parse_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*/
382void
383parse_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
401time_t
402parse_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
500int
501Stoi(
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
544int
545Strok(
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
568u_long
569updatetimeinfo(
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*/
607void
608syn_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*/
624u_long
625pps_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*/
643u_long
644pps_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*/
662u_long
663pps_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 */
680static u_long
681timepacket(
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*/
747int
748parse_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*/
778int
779parse_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*/
848int
849parse_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*/
868int
869parse_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) */
880int 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