PageRenderTime 71ms CodeModel.GetById 13ms app.highlight 52ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/ntp/libparse/parse.c

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