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
Strlen(register const char * s)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
Strcmp(register const char * s,register const char * t)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
parse_timedout(parse_t * parseio,timestamp_t * tstamp,struct timeval * del)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
parse_ioinit(register parse_t * parseio)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
parse_ioend(register parse_t * parseio)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
parse_restart(parse_t * parseio,char ch)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
parse_addchar(parse_t * parseio,char ch)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
parse_end(parse_t * parseio)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
parse_ioread(register parse_t * parseio,register char ch,register timestamp_t * tstamp)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
parse_iopps(register parse_t * parseio,register int status,register timestamp_t * ptime)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
parse_iodone(register parse_t * parseio)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
parse_to_unixtime(register clocktime_t * clock_time,register u_long * cvtrtc)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
Stoi(const unsigned char * s,long * zp,int cnt)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
Strok(const unsigned char * s,const unsigned char * m)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
updatetimeinfo(register parse_t * parseio,register u_long flags)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
syn_simple(register parse_t * parseio,register timestamp_t * ts,register struct format * format,register u_long why)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
pps_simple(register parse_t * parseio,register int status,register timestamp_t * ptime)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
pps_one(register parse_t * parseio,register int status,register timestamp_t * ptime)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
pps_zero(register parse_t * parseio,register int status,register timestamp_t * ptime)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
timepacket(register parse_t * parseio)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
parse_timecode(parsectl_t * dct,parse_t * parse)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
parse_setfmt(parsectl_t * dct,parse_t * parse)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
parse_getfmt(parsectl_t * dct,parse_t * parse)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
parse_setcs(parsectl_t * dct,parse_t * parse)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 NONEMPTY_TRANSLATION_UNIT
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 */
946