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__))
50static 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
68extern clockformat_t *clockformats[];
69extern unsigned short nformats;
70
71static u_long timepacket (parse_t *);
72
73/*
74 * strings support usually not in kernel - duplicated, but what the heck
75 */
76static int
77Strlen(
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
94static int
95Strcmp(
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
113int
114parse_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*/
151int
152parse_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*/
174void
175parse_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
188unsigned int
189parse_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
218unsigned int
219parse_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
243unsigned int
244parse_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*/
260int
261parse_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*/
349int
350parse_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*/
380void
381parse_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
399time_t
400parse_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
498int
499Stoi(
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
542int
543Strok(
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
566u_long
567updatetimeinfo(
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*/
605void
606syn_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*/
622u_long
623pps_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*/
641u_long
642pps_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*/
660u_long
661pps_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 */
678static u_long
679timepacket(
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*/
745int
746parse_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*/
776int
777parse_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*/
846int
847parse_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*/
866int
867parse_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) */
878int 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