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