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