]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - contrib/ntp/libparse/parse.c
o Fix invalid TCP checksums with pf(4). [EN-16:02.pf]
[FreeBSD/releng/9.3.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 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__))
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 "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
68 extern clockformat_t *clockformats[];
69 extern unsigned short nformats;
70
71 static u_long timepacket (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         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*/
151 int
152 parse_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*/
174 void
175 parse_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
188 unsigned int
189 parse_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
218 unsigned int
219 parse_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
243 unsigned int
244 parse_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*/
260 int
261 parse_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*/
349 int
350 parse_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*/
380 void
381 parse_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
399 time_t
400 parse_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
498 int
499 Stoi(
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
542 int
543 Strok(
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
566 u_long
567 updatetimeinfo(
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*/
605 void
606 syn_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*/
622 u_long
623 pps_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*/
641 u_long
642 pps_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*/
660 u_long
661 pps_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  */
678 static u_long
679 timepacket(
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*/
745 int
746 parse_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*/
776 int
777 parse_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*/
846 int
847 parse_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*/
866 int
867 parse_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) */
878 int 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  */