]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/ntp/libparse/parse.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / ntp / libparse / parse.c
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__))
50 static char rcsid[] = "parse.c,v 4.20 2005/08/06 17:39:40 kardel RELEASE_20050806_A";
51 #endif
52
53 #include "ntp_fp.h"
54 #include "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
68 extern clockformat_t *clockformats[];
69 extern unsigned short nformats;
70
71 static u_long timepacket P((parse_t *));
72
73 /*
74  * strings support usually not in kernel - duplicated, but what the heck
75  */
76 static int
77 Strlen(
78         register const char *s
79         )
80 {
81         register int c;
82
83         c = 0;
84         if (s)
85         {
86                 while (*s++)
87                 {
88                         c++;
89                 }
90         }
91         return c;
92 }
93
94 static int
95 Strcmp(
96         register const char *s,
97         register const char *t
98         )
99 {
100         register int c = 0;
101
102         if (!s || !t || (s == t))
103         {
104                 return 0;
105         }
106
107         while (!(c = *s++ - *t++) && *s && *t)
108             /* empty loop */;
109   
110         return c;
111 }
112
113 int
114 parse_timedout(
115                parse_t *parseio,
116                timestamp_t *tstamp,
117                struct timeval *del
118                )
119 {
120         struct timeval delta;
121
122 #ifdef PARSEKERNEL
123         delta.tv_sec = tstamp->tv.tv_sec - parseio->parse_lastchar.tv.tv_sec;
124         delta.tv_usec = tstamp->tv.tv_usec - parseio->parse_lastchar.tv.tv_usec;
125         if (delta.tv_usec < 0)
126         {
127                 delta.tv_sec  -= 1;
128                 delta.tv_usec += 1000000;
129         }
130 #else
131         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*/
155 int
156 parse_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*/
178 void
179 parse_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
192 unsigned int
193 parse_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         
222 unsigned int
223 parse_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         
247 unsigned int
248 parse_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*/
264 int
265 parse_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*/
353 int
354 parse_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*/
384 void
385 parse_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
403 time_t
404 parse_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
502 int
503 Stoi(
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
546 int
547 Strok(
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
570 u_long
571 updatetimeinfo(
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*/
609 void
610 syn_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*/
626 u_long
627 pps_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*/
645 u_long
646 pps_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*/
664 u_long
665 pps_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  */
682 static u_long
683 timepacket(
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*/
749 int
750 parse_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*/
780 int
781 parse_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*/
850 int
851 parse_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*/
870 int
871 parse_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) */
882 int 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  */