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