2 * /src/NTP/ntp-4/libparse/parse.c,v 4.14 1999/11/28 09:13:52 kardel RELEASE_19991128_A
4 * parse.c,v 4.14 1999/11/28 09:13:52 kardel RELEASE_19991128_A
6 * Parser module for reference clock
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
12 * when PARSEKERNEL is not defined NTP time stamps will be used.
14 * Copyright (c) 1992-1998 by Frank Kardel
15 * Friedrich-Alexander Universität Erlangen-Nürnberg, Germany
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
27 #if defined(REFCLOCK) && defined(CLOCK_PARSE)
29 #if !(defined(lint) || defined(__GNUC__))
30 static char rcsid[] = "parse.c,v 4.14 1999/11/28 09:13:52 kardel RELEASE_19991128_A";
33 #include <sys/types.h>
37 #include "ntp_unixtime.h"
38 #include "ntp_calendar.h"
39 #include "ntp_stdlib.h"
40 #include "ntp_machine.h"
41 #include "ntp.h" /* (get Y2KFixes definitions) Y2KFixes */
48 #include "sys/parsestreams.h"
51 extern clockformat_t *clockformats[];
52 extern unsigned short nformats;
54 static u_long timepacket P((parse_t *));
57 * strings support usually not in kernel - duplicated, but what the heck
61 register const char *s
79 register const char *s,
80 register const char *t
85 if (!s || !t || (s == t))
90 while (!(c = *s++ - *t++) && *s && *t)
103 struct timeval delta;
106 delta.tv_sec = tstamp->tv.tv_sec - parseio->parse_lastchar.tv.tv_sec;
107 delta.tv_usec = tstamp->tv.tv_usec - parseio->parse_lastchar.tv.tv_usec;
108 if (delta.tv_usec < 0)
111 delta.tv_usec += 1000000;
114 extern long tstouslo[];
115 extern long tstousmid[];
116 extern long tstoushi[];
121 L_SUB(&delt, &parseio->parse_lastchar.fp);
122 TSTOTV(&delt, &delta);
125 if (timercmp(&delta, del, >))
127 parseprintf(DD_PARSE, ("parse: timedout: TRUE\n"));
132 parseprintf(DD_PARSE, ("parse: timedout: FALSE\n"));
140 register parse_t *parseio
143 parseprintf(DD_PARSE, ("parse_iostart\n"));
145 parseio->parse_plen = 0;
146 parseio->parse_pdata = (void *)0;
148 parseio->parse_data = 0;
149 parseio->parse_ldata = 0;
150 parseio->parse_dsize = 0;
152 parseio->parse_badformat = 0;
153 parseio->parse_ioflags = PARSE_IO_CS7; /* usual unix default */
154 parseio->parse_index = 0;
155 parseio->parse_ldsize = 0;
163 register parse_t *parseio
166 parseprintf(DD_PARSE, ("parse_ioend\n"));
168 if (parseio->parse_pdata)
169 FREE(parseio->parse_pdata, parseio->parse_plen);
171 if (parseio->parse_data)
172 FREE(parseio->parse_data, (unsigned)(parseio->parse_dsize * 2 + 2));
181 unsigned int updated = PARSE_INP_SKIP;
184 * re-start packet - timeout - overflow - start symbol
187 if (parseio->parse_index)
190 * filled buffer - thus not end character found
193 parseio->parse_data[parseio->parse_index] = '\0';
194 memcpy(parseio->parse_ldata, parseio->parse_data, (unsigned)(parseio->parse_index+1));
195 parseio->parse_ldsize = parseio->parse_index+1;
196 updated = PARSE_INP_TIME;
199 parseio->parse_index = 1;
200 parseio->parse_data[0] = ch;
201 parseprintf(DD_PARSE, ("parse: parse_restart: buffer start (updated = %x)\n", updated));
214 if (parseio->parse_index < parseio->parse_dsize)
217 * collect into buffer
219 parseprintf(DD_PARSE, ("parse: parse_addchar: buffer[%d] = 0x%x\n", parseio->parse_index, ch));
220 parseio->parse_data[parseio->parse_index++] = ch;
221 return PARSE_INP_SKIP;
225 * buffer overflow - attempt to make the best of it
227 return parse_restart(parseio, ch);
236 * message complete processing
238 parseio->parse_data[parseio->parse_index] = '\0';
239 memcpy(parseio->parse_ldata, parseio->parse_data, (unsigned)(parseio->parse_index+1));
240 parseio->parse_ldsize = parseio->parse_index+1;
241 parseio->parse_index = 0;
242 parseprintf(DD_PARSE, ("parse: parse_end: buffer end\n"));
243 return PARSE_INP_TIME;
249 register parse_t *parseio,
250 register unsigned int ch,
251 register timestamp_t *tstamp
254 register unsigned updated = CVT_NONE;
256 * within STREAMS CSx (x < 8) chars still have the upper bits set
257 * so we normalize the characters by masking unecessary bits off.
259 switch (parseio->parse_ioflags & PARSE_IO_CSIZE)
278 parseprintf(DD_PARSE, ("parse_ioread(0x%lx, char=0x%x, ..., ...)\n", (unsigned long)parseio, ch & 0xFF));
280 if (!clockformats[parseio->parse_lformat]->convert)
282 parseprintf(DD_PARSE, ("parse_ioread: input dropped.\n"));
286 if (clockformats[parseio->parse_lformat]->input)
288 unsigned long input_status;
290 input_status = clockformats[parseio->parse_lformat]->input(parseio, ch, tstamp);
292 if (input_status & PARSE_INP_SYNTH)
297 if (input_status & PARSE_INP_TIME) /* time sample is available */
299 updated = timepacket(parseio);
302 if (input_status & PARSE_INP_DATA) /* got additional data */
304 updated |= CVT_ADDITIONAL;
310 * remember last character time
312 parseio->parse_lastchar = *tstamp;
315 if ((updated & CVT_MASK) != CVT_NONE)
317 parseprintf(DD_PARSE, ("parse_ioread: time sample accumulated (status=0x%x)\n", updated));
321 parseio->parse_dtime.parse_status = updated;
323 return (((updated & CVT_MASK) != CVT_NONE) ||
324 ((updated & CVT_ADDITIONAL) != 0));
330 * take status line indication and derive synchronisation information
332 * It can also be used to decode a serial serial data format (such as the
333 * ONE, ZERO, MINUTE sync data stream from DCF77)
338 register parse_t *parseio,
340 register timestamp_t *ptime
343 register unsigned updated = CVT_NONE;
346 * PPS pulse information will only be delivered to ONE clock format
347 * this is either the last successful conversion module with a ppssync
348 * routine, or a fixed format with a ppssync routine
350 parseprintf(DD_PARSE, ("parse_iopps: STATUS %s\n", (status == SYNC_ONE) ? "ONE" : "ZERO"));
352 if (clockformats[parseio->parse_lformat]->syncpps)
354 updated = clockformats[parseio->parse_lformat]->syncpps(parseio, status == SYNC_ONE, ptime);
355 parseprintf(DD_PARSE, ("parse_iopps: updated = 0x%x\n", updated));
358 return (updated & CVT_MASK) != CVT_NONE;
364 * clean up internal status for new round
369 register parse_t *parseio
373 * we need to clean up certain flags for the next round
375 parseprintf(DD_PARSE, ("parse_iodone: DONE\n"));
376 parseio->parse_dtime.parse_state = 0; /* no problems with ISRs */
379 /*---------- conversion implementation --------------------*/
382 * convert a struct clock to UTC since Jan, 1st 1970 0:00 (the UNIX EPOCH)
384 #define days_per_year(x) ((x) % 4 ? 365 : ((x % 400) ? ((x % 100) ? 366 : 365) : 366))
388 register clocktime_t *clock_time,
389 register u_long *cvtrtc
392 #define SETRTC(_X_) { if (cvtrtc) *cvtrtc = (_X_); }
393 static int days_of_month[] =
395 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
400 if (clock_time->utctime)
401 return clock_time->utctime; /* if the conversion routine gets it right away - why not */
403 if ( clock_time->year < YEAR_PIVOT ) /* Y2KFixes [ */
404 clock_time->year += 100; /* convert 20xx%100 to 20xx-1900 */
405 if ( clock_time->year < YEAR_BREAK ) /* expand to full four-digits */
406 clock_time->year += 1900;
408 if (clock_time->year < 1970 ) /* Y2KFixes ] */
410 SETRTC(CVT_FAIL|CVT_BADDATE);
415 * sorry, slow section here - but it's not time critical anyway
417 t = julian0(clock_time->year) - julian0(1970); /* Y2kFixes */
419 if (clock_time->month <= 0 || clock_time->month > 12)
421 SETRTC(CVT_FAIL|CVT_BADDATE);
422 return -1; /* bad month */
426 /* adjust leap year */
427 if (clock_time->month < 3 && days_per_year(clock_time->year) == 366)
429 #else /* Y2KFixes [ */
430 if ( clock_time->month >= 3 && isleap_4(clock_time->year) )
431 t++; /* add one more if within leap year */
432 #endif /* Y2KFixes ] */
434 for (i = 1; i < clock_time->month; i++)
436 t += days_of_month[i];
439 if (clock_time->day < 1 || ((clock_time->month == 2 && days_per_year(clock_time->year) == 366) ?
440 clock_time->day > 29 : clock_time->day > days_of_month[clock_time->month]))
442 SETRTC(CVT_FAIL|CVT_BADDATE);
443 return -1; /* bad day */
446 t += clock_time->day - 1;
448 if (clock_time->hour < 0 || clock_time->hour >= 24)
450 SETRTC(CVT_FAIL|CVT_BADTIME);
451 return -1; /* bad hour */
454 t = TIMES24(t) + clock_time->hour;
457 if (clock_time->minute < 0 || clock_time->minute > 59)
459 SETRTC(CVT_FAIL|CVT_BADTIME);
460 return -1; /* bad min */
463 t = TIMES60(t) + clock_time->minute;
466 if (clock_time->second < 0 || clock_time->second > 60) /* allow for LEAPs */
468 SETRTC(CVT_FAIL|CVT_BADTIME);
469 return -1; /* bad sec */
472 t = TIMES60(t) + clock_time->second;
474 t += clock_time->utcoffset; /* warp to UTC */
478 clock_time->utctime = t; /* documentray only */
483 /*--------------- format conversion -----------------------------------*/
487 const unsigned char *s,
492 char unsigned const *b = s;
513 if (c == '\0' || c < '0' || c > '9' || (cnt && ((s-b) > cnt)))
524 z = (z << 3) + (z << 1) + ( c - '0' );
531 const unsigned char *s,
532 const unsigned char *m
540 if ((*m == ' ') ? 1 : (*s == *m))
555 register parse_t *parseio,
556 register u_long flags
564 parseio->parse_lstate = parseio->parse_dtime.parse_state | flags | PARSEB_TIMECODE;
566 parseio->parse_dtime.parse_state = parseio->parse_lstate;
569 (void)splx((unsigned int)s);
575 parseprintf(DD_PARSE, ("updatetimeinfo status=0x%x, time=%x\n", parseio->parse_dtime.parse_state,
576 parseio->parse_dtime.parse_time.tv.tv_sec));
578 parseprintf(DD_PARSE, ("updatetimeinfo status=0x%lx, time=%x\n", (long)parseio->parse_dtime.parse_state,
579 parseio->parse_dtime.parse_time.fp.l_ui));
582 return CVT_OK; /* everything fine and dandy... */
589 * handle a sync time stamp
594 register parse_t *parseio,
595 register timestamp_t *ts,
596 register struct format *format,
600 parseio->parse_dtime.parse_stime = *ts;
606 * handle a pps time stamp
611 register parse_t *parseio,
613 register timestamp_t *ptime
616 parseio->parse_dtime.parse_ptime = *ptime;
617 parseio->parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
625 * handle a pps time stamp in ONE edge
630 register parse_t *parseio,
632 register timestamp_t *ptime
636 return pps_simple(parseio, status, ptime);
644 * handle a pps time stamp in ZERO edge
649 register parse_t *parseio,
651 register timestamp_t *ptime
655 return pps_simple(parseio, status, ptime);
663 * process a data packet
667 register parse_t *parseio
670 register unsigned short format;
672 u_long cvtrtc; /* current conversion result */
673 clocktime_t clock_time;
675 memset((char *)&clock_time, 0, sizeof clock_time);
676 format = parseio->parse_lformat;
678 if (format == (unsigned short)~0)
681 switch ((cvtrtc = clockformats[format]->convert ?
682 clockformats[format]->convert((unsigned char *)parseio->parse_ldata, parseio->parse_ldsize, (struct format *)(clockformats[format]->data), &clock_time, parseio->parse_pdata) :
683 CVT_NONE) & CVT_MASK)
686 parseio->parse_badformat++;
691 * too bad - pretend bad format
693 parseio->parse_badformat++;
703 /* shouldn't happen */
705 msyslog(LOG_WARNING, "parse: INTERNAL error: bad return code of convert routine \"%s\"\n", clockformats[format]->name);
707 return CVT_FAIL|cvtrtc;
710 if ((t = parse_to_unixtime(&clock_time, &cvtrtc)) == -1)
712 return CVT_FAIL|cvtrtc;
719 parseio->parse_dtime.parse_time.tv.tv_sec = t;
720 parseio->parse_dtime.parse_time.tv.tv_usec = clock_time.usecond;
722 parseio->parse_dtime.parse_time.fp.l_ui = t + JAN_1970;
723 TVUTOTSF(clock_time.usecond, parseio->parse_dtime.parse_time.fp.l_uf);
726 parseio->parse_dtime.parse_format = format;
728 return updatetimeinfo(parseio, clock_time.flags);
738 dct->parsegettc.parse_state = parse->parse_lstate;
739 dct->parsegettc.parse_format = parse->parse_lformat;
741 * move out current bad packet count
742 * user program is expected to sum these up
743 * this is not a problem, as "parse" module are
744 * exclusive open only
746 dct->parsegettc.parse_badformat = parse->parse_badformat;
747 parse->parse_badformat = 0;
749 if (parse->parse_ldsize <= PARSE_TCMAX)
751 dct->parsegettc.parse_count = parse->parse_ldsize;
752 memcpy(dct->parsegettc.parse_buffer, parse->parse_ldata, dct->parsegettc.parse_count);
769 if (dct->parseformat.parse_count <= PARSE_TCMAX)
771 if (dct->parseformat.parse_count)
773 register unsigned short i;
775 for (i = 0; i < nformats; i++)
777 if (!Strcmp(dct->parseformat.parse_buffer, clockformats[i]->name))
779 if (parse->parse_pdata)
780 FREE(parse->parse_pdata, parse->parse_plen);
781 parse->parse_pdata = 0;
783 parse->parse_plen = clockformats[i]->plen;
785 if (parse->parse_plen)
787 parse->parse_pdata = MALLOC(parse->parse_plen);
788 if (!parse->parse_pdata)
790 parseprintf(DD_PARSE, ("set format failed: malloc for private data area failed\n"));
793 memset((char *)parse->parse_pdata, 0, parse->parse_plen);
796 if (parse->parse_data)
797 FREE(parse->parse_data, (unsigned)(parse->parse_dsize * 2 + 2));
798 parse->parse_ldata = parse->parse_data = 0;
800 parse->parse_dsize = clockformats[i]->length;
802 if (parse->parse_dsize)
804 parse->parse_data = (char*)MALLOC((unsigned)(parse->parse_dsize * 2 + 2));
805 if (!parse->parse_data)
807 if (parse->parse_pdata)
808 FREE(parse->parse_pdata, parse->parse_plen);
809 parse->parse_pdata = 0;
811 parseprintf(DD_PARSE, ("init failed: malloc for data area failed\n"));
818 * leave room for '\0'
820 parse->parse_ldata = parse->parse_data + parse->parse_dsize + 1;
822 parse->parse_lformat = i;
839 if (dct->parseformat.parse_format < nformats &&
840 Strlen(clockformats[dct->parseformat.parse_format]->name) <= PARSE_TCMAX)
842 dct->parseformat.parse_count = Strlen(clockformats[dct->parseformat.parse_format]->name)+1;
843 memcpy(dct->parseformat.parse_buffer, clockformats[dct->parseformat.parse_format]->name, dct->parseformat.parse_count);
859 parse->parse_ioflags &= ~PARSE_IO_CSIZE;
860 parse->parse_ioflags |= dct->parsesetcs.parse_cs & PARSE_IO_CSIZE;
864 #else /* not (REFCLOCK && CLOCK_PARSE) */
866 #endif /* not (REFCLOCK && CLOCK_PARSE) */
872 * Revision 4.14 1999/11/28 09:13:52 kardel
875 * Revision 4.13 1999/02/28 11:50:20 kardel
876 * (timepacket): removed unecessary code
878 * Revision 4.12 1999/02/21 12:17:44 kardel
879 * 4.91f reconcilation
881 * Revision 4.11 1999/02/21 11:09:47 kardel
882 * unified debug output
884 * Revision 4.10 1998/12/20 23:45:30 kardel
885 * fix types and warnings
887 * Revision 4.9 1998/08/09 22:26:06 kardel
888 * Trimble TSIP support
890 * Revision 4.8 1998/06/14 21:09:39 kardel
893 * Revision 4.7 1998/06/13 15:19:13 kardel
894 * fix mem*() to b*() function macro emulation
896 * Revision 4.6 1998/06/13 13:24:13 kardel
899 * Revision 4.5 1998/06/13 13:01:10 kardel
902 * Revision 4.4 1998/06/13 12:12:10 kardel
903 * bcopy/memcpy cleanup
904 * fix SVSV name clash
906 * Revision 4.3 1998/06/12 15:22:30 kardel
909 * Revision 4.2 1998/06/12 09:13:27 kardel
910 * conditional compile macros fixed
913 * Revision 4.1 1998/05/24 09:39:55 kardel
914 * implementation of the new IO handling model
916 * Revision 4.0 1998/04/10 19:45:36 kardel
917 * Start 4.0 release version numbering
919 * from V3 3.46 log info deleted 1998/04/11 kardel