154359Sroberto/* 2182007Sroberto * /src/NTP/ntp4-dev/libparse/parse.c,v 4.20 2005/08/06 17:39:40 kardel RELEASE_20050806_A 3282408Scy * 4182007Sroberto * parse.c,v 4.20 2005/08/06 17:39:40 kardel RELEASE_20050806_A 554359Sroberto * 654359Sroberto * Parser module for reference clock 754359Sroberto * 854359Sroberto * PARSEKERNEL define switches between two personalities of the module 954359Sroberto * if PARSEKERNEL is defined this module can be used 1054359Sroberto * as kernel module. In this case the time stamps will be 1154359Sroberto * a struct timeval. 1254359Sroberto * when PARSEKERNEL is not defined NTP time stamps will be used. 1354359Sroberto * 14182007Sroberto * Copyright (c) 1995-2005 by Frank Kardel <kardel <AT> ntp.org> 15282408Scy * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universitaet Erlangen-Nuernberg, Germany 1654359Sroberto * 17182007Sroberto * Redistribution and use in source and binary forms, with or without 18182007Sroberto * modification, are permitted provided that the following conditions 19182007Sroberto * are met: 20182007Sroberto * 1. Redistributions of source code must retain the above copyright 21182007Sroberto * notice, this list of conditions and the following disclaimer. 22182007Sroberto * 2. Redistributions in binary form must reproduce the above copyright 23182007Sroberto * notice, this list of conditions and the following disclaimer in the 24182007Sroberto * documentation and/or other materials provided with the distribution. 25182007Sroberto * 3. Neither the name of the author nor the names of its contributors 26182007Sroberto * may be used to endorse or promote products derived from this software 27182007Sroberto * without specific prior written permission. 28182007Sroberto * 29182007Sroberto * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 30182007Sroberto * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31182007Sroberto * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32182007Sroberto * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 33182007Sroberto * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34182007Sroberto * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35182007Sroberto * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36182007Sroberto * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37182007Sroberto * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38182007Sroberto * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39182007Sroberto * SUCH DAMAGE. 40182007Sroberto * 4154359Sroberto */ 4254359Sroberto 4354359Sroberto#ifdef HAVE_CONFIG_H 4454359Sroberto# include <config.h> 4554359Sroberto#endif 4654359Sroberto 4754359Sroberto#if defined(REFCLOCK) && defined(CLOCK_PARSE) 4854359Sroberto 4954359Sroberto#if !(defined(lint) || defined(__GNUC__)) 50182007Srobertostatic char rcsid[] = "parse.c,v 4.20 2005/08/06 17:39:40 kardel RELEASE_20050806_A"; 5154359Sroberto#endif 5254359Sroberto 5354359Sroberto#include "ntp_fp.h" 54280849Scy#include "timevalops.h" 5554359Sroberto#include "ntp_calendar.h" 5654359Sroberto#include "ntp_stdlib.h" 5754359Sroberto#include "ntp_machine.h" 5854359Sroberto#include "ntp.h" /* (get Y2KFixes definitions) Y2KFixes */ 5954359Sroberto 6054359Sroberto#include "parse.h" 6154359Sroberto 6254359Sroberto#ifndef PARSESTREAM 6382498Sroberto# include <stdio.h> 6454359Sroberto#else 6582498Sroberto# include "sys/parsestreams.h" 6654359Sroberto#endif 6754359Sroberto 6854359Srobertoextern clockformat_t *clockformats[]; 6954359Srobertoextern unsigned short nformats; 7054359Sroberto 71280849Scystatic u_long timepacket (parse_t *); 7254359Sroberto 7354359Sroberto/* 7454359Sroberto * strings support usually not in kernel - duplicated, but what the heck 7554359Sroberto */ 7654359Srobertostatic int 7754359SrobertoStrlen( 7854359Sroberto register const char *s 7954359Sroberto ) 8054359Sroberto{ 8154359Sroberto register int c; 8254359Sroberto 8354359Sroberto c = 0; 8454359Sroberto if (s) 8554359Sroberto { 8654359Sroberto while (*s++) 8754359Sroberto { 8854359Sroberto c++; 8954359Sroberto } 9054359Sroberto } 9154359Sroberto return c; 9254359Sroberto} 9354359Sroberto 9454359Srobertostatic int 9554359SrobertoStrcmp( 9654359Sroberto register const char *s, 9754359Sroberto register const char *t 9854359Sroberto ) 9954359Sroberto{ 10054359Sroberto register int c = 0; 10154359Sroberto 10254359Sroberto if (!s || !t || (s == t)) 10354359Sroberto { 10454359Sroberto return 0; 10554359Sroberto } 10654359Sroberto 10754359Sroberto while (!(c = *s++ - *t++) && *s && *t) 10854359Sroberto /* empty loop */; 109282408Scy 11054359Sroberto return c; 11154359Sroberto} 11254359Sroberto 11354359Srobertoint 11454359Srobertoparse_timedout( 11554359Sroberto parse_t *parseio, 11654359Sroberto timestamp_t *tstamp, 11754359Sroberto struct timeval *del 11854359Sroberto ) 11954359Sroberto{ 12054359Sroberto struct timeval delta; 12154359Sroberto 12254359Sroberto#ifdef PARSEKERNEL 12354359Sroberto delta.tv_sec = tstamp->tv.tv_sec - parseio->parse_lastchar.tv.tv_sec; 12454359Sroberto delta.tv_usec = tstamp->tv.tv_usec - parseio->parse_lastchar.tv.tv_usec; 12554359Sroberto if (delta.tv_usec < 0) 12654359Sroberto { 12754359Sroberto delta.tv_sec -= 1; 12854359Sroberto delta.tv_usec += 1000000; 12954359Sroberto } 13054359Sroberto#else 13154359Sroberto l_fp delt; 13254359Sroberto 13354359Sroberto delt = tstamp->fp; 13454359Sroberto L_SUB(&delt, &parseio->parse_lastchar.fp); 13554359Sroberto TSTOTV(&delt, &delta); 13654359Sroberto#endif 13754359Sroberto 13854359Sroberto if (timercmp(&delta, del, >)) 13954359Sroberto { 14054359Sroberto parseprintf(DD_PARSE, ("parse: timedout: TRUE\n")); 14154359Sroberto return 1; 14254359Sroberto } 14354359Sroberto else 14454359Sroberto { 14554359Sroberto parseprintf(DD_PARSE, ("parse: timedout: FALSE\n")); 14654359Sroberto return 0; 14754359Sroberto } 14854359Sroberto} 14954359Sroberto 15054359Sroberto/*ARGSUSED*/ 15154359Srobertoint 15254359Srobertoparse_ioinit( 15354359Sroberto register parse_t *parseio 15454359Sroberto ) 15554359Sroberto{ 15654359Sroberto parseprintf(DD_PARSE, ("parse_iostart\n")); 157282408Scy 15854359Sroberto parseio->parse_plen = 0; 15954359Sroberto parseio->parse_pdata = (void *)0; 160282408Scy 16154359Sroberto parseio->parse_data = 0; 16254359Sroberto parseio->parse_ldata = 0; 16354359Sroberto parseio->parse_dsize = 0; 16454359Sroberto 16554359Sroberto parseio->parse_badformat = 0; 16654359Sroberto parseio->parse_ioflags = PARSE_IO_CS7; /* usual unix default */ 16754359Sroberto parseio->parse_index = 0; 16854359Sroberto parseio->parse_ldsize = 0; 169282408Scy 17054359Sroberto return 1; 17154359Sroberto} 17254359Sroberto 17354359Sroberto/*ARGSUSED*/ 17454359Srobertovoid 17554359Srobertoparse_ioend( 17654359Sroberto register parse_t *parseio 17754359Sroberto ) 17854359Sroberto{ 17954359Sroberto parseprintf(DD_PARSE, ("parse_ioend\n")); 18054359Sroberto 18154359Sroberto if (parseio->parse_pdata) 18254359Sroberto FREE(parseio->parse_pdata, parseio->parse_plen); 18354359Sroberto 18454359Sroberto if (parseio->parse_data) 18554359Sroberto FREE(parseio->parse_data, (unsigned)(parseio->parse_dsize * 2 + 2)); 18654359Sroberto} 18754359Sroberto 18854359Srobertounsigned int 18954359Srobertoparse_restart( 19054359Sroberto parse_t *parseio, 191282408Scy char ch 19254359Sroberto ) 19354359Sroberto{ 19454359Sroberto unsigned int updated = PARSE_INP_SKIP; 195282408Scy 19654359Sroberto /* 19754359Sroberto * re-start packet - timeout - overflow - start symbol 19854359Sroberto */ 199282408Scy 20054359Sroberto if (parseio->parse_index) 20154359Sroberto { 20254359Sroberto /* 20354359Sroberto * filled buffer - thus not end character found 20454359Sroberto * do processing now 20554359Sroberto */ 20654359Sroberto parseio->parse_data[parseio->parse_index] = '\0'; 20754359Sroberto memcpy(parseio->parse_ldata, parseio->parse_data, (unsigned)(parseio->parse_index+1)); 208182007Sroberto parseio->parse_ldsize = parseio->parse_index; 20954359Sroberto updated = PARSE_INP_TIME; 21054359Sroberto } 211282408Scy 21254359Sroberto parseio->parse_index = 1; 21354359Sroberto parseio->parse_data[0] = ch; 21454359Sroberto parseprintf(DD_PARSE, ("parse: parse_restart: buffer start (updated = %x)\n", updated)); 21554359Sroberto return updated; 21654359Sroberto} 217282408Scy 21854359Srobertounsigned int 21954359Srobertoparse_addchar( 22054359Sroberto parse_t *parseio, 221282408Scy char ch 22254359Sroberto ) 22354359Sroberto{ 22454359Sroberto /* 22554359Sroberto * add to buffer 22654359Sroberto */ 22754359Sroberto if (parseio->parse_index < parseio->parse_dsize) 22854359Sroberto { 22954359Sroberto /* 23054359Sroberto * collect into buffer 23154359Sroberto */ 23254359Sroberto parseprintf(DD_PARSE, ("parse: parse_addchar: buffer[%d] = 0x%x\n", parseio->parse_index, ch)); 233280849Scy parseio->parse_data[parseio->parse_index++] = (char)ch; 23454359Sroberto return PARSE_INP_SKIP; 23554359Sroberto } 23654359Sroberto else 23754359Sroberto /* 23854359Sroberto * buffer overflow - attempt to make the best of it 23954359Sroberto */ 24054359Sroberto return parse_restart(parseio, ch); 24154359Sroberto} 242282408Scy 24354359Srobertounsigned int 24454359Srobertoparse_end( 24554359Sroberto parse_t *parseio 24654359Sroberto ) 24754359Sroberto{ 24854359Sroberto /* 24954359Sroberto * message complete processing 25054359Sroberto */ 25154359Sroberto parseio->parse_data[parseio->parse_index] = '\0'; 25254359Sroberto memcpy(parseio->parse_ldata, parseio->parse_data, (unsigned)(parseio->parse_index+1)); 253182007Sroberto parseio->parse_ldsize = parseio->parse_index; 25454359Sroberto parseio->parse_index = 0; 25554359Sroberto parseprintf(DD_PARSE, ("parse: parse_end: buffer end\n")); 25654359Sroberto return PARSE_INP_TIME; 25754359Sroberto} 25854359Sroberto 25954359Sroberto/*ARGSUSED*/ 26054359Srobertoint 26154359Srobertoparse_ioread( 26254359Sroberto register parse_t *parseio, 263282408Scy register char ch, 26454359Sroberto register timestamp_t *tstamp 26554359Sroberto ) 26654359Sroberto{ 267282408Scy register u_int updated = CVT_NONE; 26854359Sroberto /* 26954359Sroberto * within STREAMS CSx (x < 8) chars still have the upper bits set 27054359Sroberto * so we normalize the characters by masking unecessary bits off. 27154359Sroberto */ 27254359Sroberto switch (parseio->parse_ioflags & PARSE_IO_CSIZE) 27354359Sroberto { 27454359Sroberto case PARSE_IO_CS5: 27554359Sroberto ch &= 0x1F; 27654359Sroberto break; 27754359Sroberto 27854359Sroberto case PARSE_IO_CS6: 27954359Sroberto ch &= 0x3F; 28054359Sroberto break; 28154359Sroberto 28254359Sroberto case PARSE_IO_CS7: 28354359Sroberto ch &= 0x7F; 28454359Sroberto break; 285282408Scy 28654359Sroberto case PARSE_IO_CS8: 287282408Scy ch &= (char) 0xFFU; 28854359Sroberto break; 28954359Sroberto } 29054359Sroberto 291293423Sdelphij parseprintf(DD_PARSE, ("parse_ioread(0x%p, char=0x%x, ..., ...)\n", (void*)parseio, ch & 0xFF)); 29254359Sroberto 29354359Sroberto if (!clockformats[parseio->parse_lformat]->convert) 29454359Sroberto { 29554359Sroberto parseprintf(DD_PARSE, ("parse_ioread: input dropped.\n")); 29654359Sroberto return CVT_NONE; 29754359Sroberto } 29854359Sroberto 29954359Sroberto if (clockformats[parseio->parse_lformat]->input) 30054359Sroberto { 30154359Sroberto unsigned long input_status; 30254359Sroberto 30354359Sroberto input_status = clockformats[parseio->parse_lformat]->input(parseio, ch, tstamp); 30454359Sroberto 30554359Sroberto if (input_status & PARSE_INP_SYNTH) 30654359Sroberto { 30754359Sroberto updated = CVT_OK; 30854359Sroberto } 309282408Scy 31054359Sroberto if (input_status & PARSE_INP_TIME) /* time sample is available */ 31154359Sroberto { 312282408Scy updated = (u_int) timepacket(parseio); 31354359Sroberto } 314282408Scy 31554359Sroberto if (input_status & PARSE_INP_DATA) /* got additional data */ 31654359Sroberto { 31754359Sroberto updated |= CVT_ADDITIONAL; 31854359Sroberto } 31954359Sroberto } 32054359Sroberto 321282408Scy 32254359Sroberto /* 32354359Sroberto * remember last character time 32454359Sroberto */ 32554359Sroberto parseio->parse_lastchar = *tstamp; 32654359Sroberto 32754359Sroberto#ifdef DEBUG 32854359Sroberto if ((updated & CVT_MASK) != CVT_NONE) 32954359Sroberto { 33054359Sroberto parseprintf(DD_PARSE, ("parse_ioread: time sample accumulated (status=0x%x)\n", updated)); 33154359Sroberto } 33254359Sroberto#endif 33354359Sroberto 33454359Sroberto parseio->parse_dtime.parse_status = updated; 33554359Sroberto 33654359Sroberto return (((updated & CVT_MASK) != CVT_NONE) || 33754359Sroberto ((updated & CVT_ADDITIONAL) != 0)); 33854359Sroberto} 33954359Sroberto 34054359Sroberto/* 34154359Sroberto * parse_iopps 34254359Sroberto * 34354359Sroberto * take status line indication and derive synchronisation information 34454359Sroberto * from it. 34554359Sroberto * It can also be used to decode a serial serial data format (such as the 34654359Sroberto * ONE, ZERO, MINUTE sync data stream from DCF77) 34754359Sroberto */ 34854359Sroberto/*ARGSUSED*/ 34954359Srobertoint 35054359Srobertoparse_iopps( 35154359Sroberto register parse_t *parseio, 35254359Sroberto register int status, 35354359Sroberto register timestamp_t *ptime 35454359Sroberto ) 35554359Sroberto{ 356282408Scy register u_int updated = CVT_NONE; 35754359Sroberto 35854359Sroberto /* 35954359Sroberto * PPS pulse information will only be delivered to ONE clock format 36054359Sroberto * this is either the last successful conversion module with a ppssync 36154359Sroberto * routine, or a fixed format with a ppssync routine 36254359Sroberto */ 36354359Sroberto parseprintf(DD_PARSE, ("parse_iopps: STATUS %s\n", (status == SYNC_ONE) ? "ONE" : "ZERO")); 36454359Sroberto 36554359Sroberto if (clockformats[parseio->parse_lformat]->syncpps) 36654359Sroberto { 367282408Scy updated = (u_int) clockformats[parseio->parse_lformat]->syncpps(parseio, status == SYNC_ONE, ptime); 36854359Sroberto parseprintf(DD_PARSE, ("parse_iopps: updated = 0x%x\n", updated)); 36954359Sroberto } 37054359Sroberto 37154359Sroberto return (updated & CVT_MASK) != CVT_NONE; 37254359Sroberto} 37354359Sroberto 37454359Sroberto/* 37554359Sroberto * parse_iodone 37654359Sroberto * 37754359Sroberto * clean up internal status for new round 37854359Sroberto */ 37954359Sroberto/*ARGSUSED*/ 38054359Srobertovoid 38154359Srobertoparse_iodone( 38254359Sroberto register parse_t *parseio 38354359Sroberto ) 38454359Sroberto{ 38554359Sroberto /* 38654359Sroberto * we need to clean up certain flags for the next round 38754359Sroberto */ 38854359Sroberto parseprintf(DD_PARSE, ("parse_iodone: DONE\n")); 38954359Sroberto parseio->parse_dtime.parse_state = 0; /* no problems with ISRs */ 39054359Sroberto} 39154359Sroberto 39254359Sroberto/*---------- conversion implementation --------------------*/ 39354359Sroberto 39454359Sroberto/* 39554359Sroberto * convert a struct clock to UTC since Jan, 1st 1970 0:00 (the UNIX EPOCH) 39654359Sroberto */ 39754359Sroberto#define days_per_year(x) ((x) % 4 ? 365 : ((x % 400) ? ((x % 100) ? 366 : 365) : 366)) 39854359Sroberto 39954359Srobertotime_t 40054359Srobertoparse_to_unixtime( 40154359Sroberto register clocktime_t *clock_time, 40254359Sroberto register u_long *cvtrtc 40354359Sroberto ) 40454359Sroberto{ 40554359Sroberto#define SETRTC(_X_) { if (cvtrtc) *cvtrtc = (_X_); } 406282408Scy static int days_of_month[] = 40754359Sroberto { 40854359Sroberto 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 40954359Sroberto }; 41054359Sroberto register int i; 41154359Sroberto time_t t; 412282408Scy 41354359Sroberto if (clock_time->utctime) 41454359Sroberto return clock_time->utctime; /* if the conversion routine gets it right away - why not */ 41554359Sroberto 41654359Sroberto if ( clock_time->year < YEAR_PIVOT ) /* Y2KFixes [ */ 41754359Sroberto clock_time->year += 100; /* convert 20xx%100 to 20xx-1900 */ 41854359Sroberto if ( clock_time->year < YEAR_BREAK ) /* expand to full four-digits */ 41954359Sroberto clock_time->year += 1900; 42054359Sroberto 42154359Sroberto if (clock_time->year < 1970 ) /* Y2KFixes ] */ 42254359Sroberto { 42354359Sroberto SETRTC(CVT_FAIL|CVT_BADDATE); 42454359Sroberto return -1; 42554359Sroberto } 426282408Scy 42754359Sroberto /* 42854359Sroberto * sorry, slow section here - but it's not time critical anyway 42954359Sroberto */ 43054359Sroberto t = julian0(clock_time->year) - julian0(1970); /* Y2kFixes */ 431282408Scy /* month */ 43254359Sroberto if (clock_time->month <= 0 || clock_time->month > 12) 43354359Sroberto { 43454359Sroberto SETRTC(CVT_FAIL|CVT_BADDATE); 43554359Sroberto return -1; /* bad month */ 43654359Sroberto } 43754359Sroberto 43854359Sroberto#if 0 /* Y2KFixes */ 43954359Sroberto /* adjust leap year */ 44054359Sroberto if (clock_time->month < 3 && days_per_year(clock_time->year) == 366) 44154359Sroberto t--; 44254359Sroberto#else /* Y2KFixes [ */ 44354359Sroberto if ( clock_time->month >= 3 && isleap_4(clock_time->year) ) 44454359Sroberto t++; /* add one more if within leap year */ 44554359Sroberto#endif /* Y2KFixes ] */ 44654359Sroberto 44754359Sroberto for (i = 1; i < clock_time->month; i++) 44854359Sroberto { 44954359Sroberto t += days_of_month[i]; 45054359Sroberto } 45154359Sroberto /* day */ 45254359Sroberto if (clock_time->day < 1 || ((clock_time->month == 2 && days_per_year(clock_time->year) == 366) ? 45354359Sroberto clock_time->day > 29 : clock_time->day > days_of_month[clock_time->month])) 45454359Sroberto { 45554359Sroberto SETRTC(CVT_FAIL|CVT_BADDATE); 45654359Sroberto return -1; /* bad day */ 45754359Sroberto } 45854359Sroberto 45954359Sroberto t += clock_time->day - 1; 46054359Sroberto /* hour */ 46154359Sroberto if (clock_time->hour < 0 || clock_time->hour >= 24) 46254359Sroberto { 46354359Sroberto SETRTC(CVT_FAIL|CVT_BADTIME); 46454359Sroberto return -1; /* bad hour */ 46554359Sroberto } 46654359Sroberto 46754359Sroberto t = TIMES24(t) + clock_time->hour; 46854359Sroberto 469282408Scy /* min */ 47054359Sroberto if (clock_time->minute < 0 || clock_time->minute > 59) 47154359Sroberto { 47254359Sroberto SETRTC(CVT_FAIL|CVT_BADTIME); 47354359Sroberto return -1; /* bad min */ 47454359Sroberto } 47554359Sroberto 47654359Sroberto t = TIMES60(t) + clock_time->minute; 47754359Sroberto /* sec */ 478282408Scy 47954359Sroberto if (clock_time->second < 0 || clock_time->second > 60) /* allow for LEAPs */ 48054359Sroberto { 48154359Sroberto SETRTC(CVT_FAIL|CVT_BADTIME); 48254359Sroberto return -1; /* bad sec */ 48354359Sroberto } 48454359Sroberto 48554359Sroberto t = TIMES60(t) + clock_time->second; 48654359Sroberto 48754359Sroberto t += clock_time->utcoffset; /* warp to UTC */ 48854359Sroberto 48954359Sroberto /* done */ 49054359Sroberto 49154359Sroberto clock_time->utctime = t; /* documentray only */ 49254359Sroberto 49354359Sroberto return t; 49454359Sroberto} 49554359Sroberto 49654359Sroberto/*--------------- format conversion -----------------------------------*/ 49754359Sroberto 49854359Srobertoint 49954359SrobertoStoi( 50054359Sroberto const unsigned char *s, 50154359Sroberto long *zp, 50254359Sroberto int cnt 50354359Sroberto ) 50454359Sroberto{ 50554359Sroberto char unsigned const *b = s; 50654359Sroberto int f,z,v; 50754359Sroberto char unsigned c; 50854359Sroberto 50954359Sroberto f=z=v=0; 51054359Sroberto 51154359Sroberto while(*s == ' ') 51254359Sroberto s++; 513282408Scy 51454359Sroberto if (*s == '-') 51554359Sroberto { 51654359Sroberto s++; 51754359Sroberto v = 1; 51854359Sroberto } 51954359Sroberto else 52054359Sroberto if (*s == '+') 52154359Sroberto s++; 522282408Scy 52354359Sroberto for(;;) 52454359Sroberto { 52554359Sroberto c = *s++; 52654359Sroberto if (c == '\0' || c < '0' || c > '9' || (cnt && ((s-b) > cnt))) 52754359Sroberto { 52854359Sroberto if (f == 0) 52954359Sroberto { 53054359Sroberto return(-1); 53154359Sroberto } 53254359Sroberto if (v) 53354359Sroberto z = -z; 53454359Sroberto *zp = z; 53554359Sroberto return(0); 53654359Sroberto } 53754359Sroberto z = (z << 3) + (z << 1) + ( c - '0' ); 53854359Sroberto f=1; 53954359Sroberto } 54054359Sroberto} 54154359Sroberto 54254359Srobertoint 54354359SrobertoStrok( 54454359Sroberto const unsigned char *s, 54554359Sroberto const unsigned char *m 54654359Sroberto ) 54754359Sroberto{ 54854359Sroberto if (!s || !m) 54954359Sroberto return 0; 55054359Sroberto 55154359Sroberto while(*s && *m) 55254359Sroberto { 55354359Sroberto if ((*m == ' ') ? 1 : (*s == *m)) 55454359Sroberto { 55554359Sroberto s++; 55654359Sroberto m++; 55754359Sroberto } 55854359Sroberto else 55954359Sroberto { 56054359Sroberto return 0; 56154359Sroberto } 56254359Sroberto } 56354359Sroberto return !*m; 56454359Sroberto} 56554359Sroberto 56654359Srobertou_long 56754359Srobertoupdatetimeinfo( 56854359Sroberto register parse_t *parseio, 56954359Sroberto register u_long flags 57054359Sroberto ) 57154359Sroberto{ 57254359Sroberto#ifdef PARSEKERNEL 57354359Sroberto { 57454359Sroberto int s = splhigh(); 57554359Sroberto#endif 576282408Scy 57754359Sroberto parseio->parse_lstate = parseio->parse_dtime.parse_state | flags | PARSEB_TIMECODE; 578282408Scy 57954359Sroberto parseio->parse_dtime.parse_state = parseio->parse_lstate; 58054359Sroberto 58154359Sroberto#ifdef PARSEKERNEL 58254359Sroberto (void)splx((unsigned int)s); 58354359Sroberto } 58454359Sroberto#endif 58554359Sroberto 586282408Scy 58754359Sroberto#ifdef PARSEKERNEL 58854359Sroberto parseprintf(DD_PARSE, ("updatetimeinfo status=0x%x, time=%x\n", parseio->parse_dtime.parse_state, 58954359Sroberto parseio->parse_dtime.parse_time.tv.tv_sec)); 59054359Sroberto#else 59154359Sroberto parseprintf(DD_PARSE, ("updatetimeinfo status=0x%lx, time=%x\n", (long)parseio->parse_dtime.parse_state, 59254359Sroberto parseio->parse_dtime.parse_time.fp.l_ui)); 59354359Sroberto#endif 594282408Scy 59554359Sroberto return CVT_OK; /* everything fine and dandy... */ 59654359Sroberto} 59754359Sroberto 59854359Sroberto 59954359Sroberto/* 60054359Sroberto * syn_simple 60154359Sroberto * 60254359Sroberto * handle a sync time stamp 60354359Sroberto */ 60454359Sroberto/*ARGSUSED*/ 60554359Srobertovoid 60654359Srobertosyn_simple( 60754359Sroberto register parse_t *parseio, 60854359Sroberto register timestamp_t *ts, 60954359Sroberto register struct format *format, 61054359Sroberto register u_long why 61154359Sroberto ) 61254359Sroberto{ 61354359Sroberto parseio->parse_dtime.parse_stime = *ts; 61454359Sroberto} 61554359Sroberto 61654359Sroberto/* 617282408Scy * parse_pps_fnc_t pps_simple 61854359Sroberto * 61954359Sroberto * handle a pps time stamp 62054359Sroberto */ 62154359Sroberto/*ARGSUSED*/ 62254359Srobertou_long 62354359Srobertopps_simple( 62454359Sroberto register parse_t *parseio, 62554359Sroberto register int status, 62654359Sroberto register timestamp_t *ptime 62754359Sroberto ) 62854359Sroberto{ 62954359Sroberto parseio->parse_dtime.parse_ptime = *ptime; 63054359Sroberto parseio->parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS; 631282408Scy 63254359Sroberto return CVT_NONE; 63354359Sroberto} 63454359Sroberto 63554359Sroberto/* 636282408Scy * parse_pps_fnc_t pps_one 63754359Sroberto * 63854359Sroberto * handle a pps time stamp in ONE edge 63954359Sroberto */ 64054359Sroberto/*ARGSUSED*/ 64154359Srobertou_long 64254359Srobertopps_one( 64354359Sroberto register parse_t *parseio, 64454359Sroberto register int status, 64554359Sroberto register timestamp_t *ptime 64654359Sroberto ) 64754359Sroberto{ 64854359Sroberto if (status) 64954359Sroberto return pps_simple(parseio, status, ptime); 650282408Scy 65154359Sroberto return CVT_NONE; 65254359Sroberto} 65354359Sroberto 65454359Sroberto/* 655282408Scy * parse_pps_fnc_t pps_zero 65654359Sroberto * 65754359Sroberto * handle a pps time stamp in ZERO edge 65854359Sroberto */ 65954359Sroberto/*ARGSUSED*/ 66054359Srobertou_long 66154359Srobertopps_zero( 66254359Sroberto register parse_t *parseio, 66354359Sroberto register int status, 66454359Sroberto register timestamp_t *ptime 66554359Sroberto ) 66654359Sroberto{ 66754359Sroberto if (!status) 66854359Sroberto return pps_simple(parseio, status, ptime); 669282408Scy 67054359Sroberto return CVT_NONE; 67154359Sroberto} 67254359Sroberto 67354359Sroberto/* 67454359Sroberto * timepacket 67554359Sroberto * 67654359Sroberto * process a data packet 67754359Sroberto */ 67854359Srobertostatic u_long 67954359Srobertotimepacket( 68054359Sroberto register parse_t *parseio 68154359Sroberto ) 68254359Sroberto{ 68354359Sroberto register unsigned short format; 68454359Sroberto register time_t t; 68554359Sroberto u_long cvtrtc; /* current conversion result */ 68654359Sroberto clocktime_t clock_time; 687282408Scy 68854359Sroberto memset((char *)&clock_time, 0, sizeof clock_time); 68954359Sroberto format = parseio->parse_lformat; 69054359Sroberto 69154359Sroberto if (format == (unsigned short)~0) 69254359Sroberto return CVT_NONE; 693282408Scy 69454359Sroberto switch ((cvtrtc = clockformats[format]->convert ? 69554359Sroberto clockformats[format]->convert((unsigned char *)parseio->parse_ldata, parseio->parse_ldsize, (struct format *)(clockformats[format]->data), &clock_time, parseio->parse_pdata) : 69654359Sroberto CVT_NONE) & CVT_MASK) 69754359Sroberto { 69854359Sroberto case CVT_FAIL: 69954359Sroberto parseio->parse_badformat++; 700285169Scy return cvtrtc; 701282408Scy 70254359Sroberto case CVT_NONE: 70354359Sroberto /* 70454359Sroberto * too bad - pretend bad format 70554359Sroberto */ 70654359Sroberto parseio->parse_badformat++; 707285169Scy return CVT_NONE; 708282408Scy 70954359Sroberto case CVT_OK: 71054359Sroberto break; 711282408Scy 71254359Sroberto case CVT_SKIP: 71354359Sroberto return CVT_NONE; 71454359Sroberto 71554359Sroberto default: 71654359Sroberto /* shouldn't happen */ 71754359Sroberto#ifndef PARSEKERNEL 718280849Scy msyslog(LOG_WARNING, "parse: INTERNAL error: bad return code of convert routine \"%s\"", clockformats[format]->name); 719282408Scy#endif 72054359Sroberto return CVT_FAIL|cvtrtc; 72154359Sroberto } 72254359Sroberto 72354359Sroberto if ((t = parse_to_unixtime(&clock_time, &cvtrtc)) == -1) 72454359Sroberto { 72554359Sroberto return CVT_FAIL|cvtrtc; 72654359Sroberto } 727282408Scy 72854359Sroberto /* 72954359Sroberto * time stamp 73054359Sroberto */ 73154359Sroberto#ifdef PARSEKERNEL 73254359Sroberto parseio->parse_dtime.parse_time.tv.tv_sec = t; 73354359Sroberto parseio->parse_dtime.parse_time.tv.tv_usec = clock_time.usecond; 73454359Sroberto#else 735282408Scy parseio->parse_dtime.parse_time.fp.l_ui = (uint32_t) (t + JAN_1970); 73654359Sroberto TVUTOTSF(clock_time.usecond, parseio->parse_dtime.parse_time.fp.l_uf); 73754359Sroberto#endif 73854359Sroberto 73954359Sroberto parseio->parse_dtime.parse_format = format; 74054359Sroberto 74154359Sroberto return updatetimeinfo(parseio, clock_time.flags); 74254359Sroberto} 74354359Sroberto 74454359Sroberto/*ARGSUSED*/ 74554359Srobertoint 74654359Srobertoparse_timecode( 74754359Sroberto parsectl_t *dct, 74854359Sroberto parse_t *parse 74954359Sroberto ) 75054359Sroberto{ 75154359Sroberto dct->parsegettc.parse_state = parse->parse_lstate; 75254359Sroberto dct->parsegettc.parse_format = parse->parse_lformat; 75354359Sroberto /* 75454359Sroberto * move out current bad packet count 75554359Sroberto * user program is expected to sum these up 75654359Sroberto * this is not a problem, as "parse" module are 75754359Sroberto * exclusive open only 75854359Sroberto */ 75954359Sroberto dct->parsegettc.parse_badformat = parse->parse_badformat; 76054359Sroberto parse->parse_badformat = 0; 761282408Scy 76254359Sroberto if (parse->parse_ldsize <= PARSE_TCMAX) 76354359Sroberto { 76454359Sroberto dct->parsegettc.parse_count = parse->parse_ldsize; 76554359Sroberto memcpy(dct->parsegettc.parse_buffer, parse->parse_ldata, dct->parsegettc.parse_count); 76654359Sroberto return 1; 76754359Sroberto } 76854359Sroberto else 76954359Sroberto { 77054359Sroberto return 0; 77154359Sroberto } 77254359Sroberto} 77354359Sroberto 774282408Scy 77554359Sroberto/*ARGSUSED*/ 77654359Srobertoint 77754359Srobertoparse_setfmt( 77854359Sroberto parsectl_t *dct, 77954359Sroberto parse_t *parse 78054359Sroberto ) 78154359Sroberto{ 78254359Sroberto if (dct->parseformat.parse_count <= PARSE_TCMAX) 78354359Sroberto { 78454359Sroberto if (dct->parseformat.parse_count) 78554359Sroberto { 78654359Sroberto register unsigned short i; 78754359Sroberto 78854359Sroberto for (i = 0; i < nformats; i++) 78954359Sroberto { 79054359Sroberto if (!Strcmp(dct->parseformat.parse_buffer, clockformats[i]->name)) 79154359Sroberto { 79254359Sroberto if (parse->parse_pdata) 79354359Sroberto FREE(parse->parse_pdata, parse->parse_plen); 79454359Sroberto parse->parse_pdata = 0; 795282408Scy 79654359Sroberto parse->parse_plen = clockformats[i]->plen; 79754359Sroberto 79854359Sroberto if (parse->parse_plen) 79954359Sroberto { 80054359Sroberto parse->parse_pdata = MALLOC(parse->parse_plen); 80154359Sroberto if (!parse->parse_pdata) 80254359Sroberto { 80354359Sroberto parseprintf(DD_PARSE, ("set format failed: malloc for private data area failed\n")); 80454359Sroberto return 0; 80554359Sroberto } 80654359Sroberto memset((char *)parse->parse_pdata, 0, parse->parse_plen); 80754359Sroberto } 80854359Sroberto 80954359Sroberto if (parse->parse_data) 81054359Sroberto FREE(parse->parse_data, (unsigned)(parse->parse_dsize * 2 + 2)); 81154359Sroberto parse->parse_ldata = parse->parse_data = 0; 812282408Scy 81354359Sroberto parse->parse_dsize = clockformats[i]->length; 814282408Scy 81554359Sroberto if (parse->parse_dsize) 81654359Sroberto { 81754359Sroberto parse->parse_data = (char*)MALLOC((unsigned)(parse->parse_dsize * 2 + 2)); 81854359Sroberto if (!parse->parse_data) 81954359Sroberto { 82054359Sroberto if (parse->parse_pdata) 82154359Sroberto FREE(parse->parse_pdata, parse->parse_plen); 82254359Sroberto parse->parse_pdata = 0; 823282408Scy 82454359Sroberto parseprintf(DD_PARSE, ("init failed: malloc for data area failed\n")); 82554359Sroberto return 0; 82654359Sroberto } 82754359Sroberto } 82854359Sroberto 829282408Scy 83054359Sroberto /* 83154359Sroberto * leave room for '\0' 83254359Sroberto */ 83354359Sroberto parse->parse_ldata = parse->parse_data + parse->parse_dsize + 1; 834282408Scy 83554359Sroberto parse->parse_lformat = i; 836282408Scy 83754359Sroberto return 1; 83854359Sroberto } 83954359Sroberto } 84054359Sroberto } 84154359Sroberto } 84254359Sroberto return 0; 84354359Sroberto} 84454359Sroberto 84554359Sroberto/*ARGSUSED*/ 84654359Srobertoint 84754359Srobertoparse_getfmt( 84854359Sroberto parsectl_t *dct, 84954359Sroberto parse_t *parse 85054359Sroberto ) 85154359Sroberto{ 85254359Sroberto if (dct->parseformat.parse_format < nformats && 85354359Sroberto Strlen(clockformats[dct->parseformat.parse_format]->name) <= PARSE_TCMAX) 85454359Sroberto { 855282408Scy dct->parseformat.parse_count = (unsigned short) (Strlen(clockformats[dct->parseformat.parse_format]->name) + 1); 85654359Sroberto memcpy(dct->parseformat.parse_buffer, clockformats[dct->parseformat.parse_format]->name, dct->parseformat.parse_count); 85754359Sroberto return 1; 85854359Sroberto } 85954359Sroberto else 86054359Sroberto { 86154359Sroberto return 0; 86254359Sroberto } 86354359Sroberto} 86454359Sroberto 86554359Sroberto/*ARGSUSED*/ 86654359Srobertoint 86754359Srobertoparse_setcs( 86854359Sroberto parsectl_t *dct, 86954359Sroberto parse_t *parse 87054359Sroberto ) 87154359Sroberto{ 87254359Sroberto parse->parse_ioflags &= ~PARSE_IO_CSIZE; 873282408Scy parse->parse_ioflags |= (int) (dct->parsesetcs.parse_cs & PARSE_IO_CSIZE); 87454359Sroberto return 1; 87554359Sroberto} 87654359Sroberto 87754359Sroberto#else /* not (REFCLOCK && CLOCK_PARSE) */ 87854359Srobertoint parse_bs; 87954359Sroberto#endif /* not (REFCLOCK && CLOCK_PARSE) */ 88054359Sroberto 88154359Sroberto/* 88254359Sroberto * History: 88354359Sroberto * 88454359Sroberto * parse.c,v 885182007Sroberto * Revision 4.20 2005/08/06 17:39:40 kardel 886182007Sroberto * cleanup size handling wrt/ to buffer boundaries 887182007Sroberto * 888182007Sroberto * Revision 4.19 2005/04/16 17:32:10 kardel 889182007Sroberto * update copyright 890182007Sroberto * 891182007Sroberto * Revision 4.18 2004/11/14 16:11:05 kardel 892182007Sroberto * update Id tags 893182007Sroberto * 894182007Sroberto * Revision 4.17 2004/11/14 15:29:41 kardel 895182007Sroberto * support PPSAPI, upgrade Copyright to Berkeley style 896182007Sroberto * 89756746Sroberto * Revision 4.14 1999/11/28 09:13:52 kardel 89856746Sroberto * RECON_4_0_98F 89956746Sroberto * 90054359Sroberto * Revision 4.13 1999/02/28 11:50:20 kardel 90154359Sroberto * (timepacket): removed unecessary code 90254359Sroberto * 90354359Sroberto * Revision 4.12 1999/02/21 12:17:44 kardel 90454359Sroberto * 4.91f reconcilation 90554359Sroberto * 90654359Sroberto * Revision 4.11 1999/02/21 11:09:47 kardel 90754359Sroberto * unified debug output 90854359Sroberto * 90954359Sroberto * Revision 4.10 1998/12/20 23:45:30 kardel 91054359Sroberto * fix types and warnings 91154359Sroberto * 91254359Sroberto * Revision 4.9 1998/08/09 22:26:06 kardel 91354359Sroberto * Trimble TSIP support 91454359Sroberto * 91554359Sroberto * Revision 4.8 1998/06/14 21:09:39 kardel 91654359Sroberto * Sun acc cleanup 91754359Sroberto * 91854359Sroberto * Revision 4.7 1998/06/13 15:19:13 kardel 91954359Sroberto * fix mem*() to b*() function macro emulation 92054359Sroberto * 92154359Sroberto * Revision 4.6 1998/06/13 13:24:13 kardel 92254359Sroberto * printf fmt 92354359Sroberto * 92454359Sroberto * Revision 4.5 1998/06/13 13:01:10 kardel 92554359Sroberto * printf fmt 92654359Sroberto * 92754359Sroberto * Revision 4.4 1998/06/13 12:12:10 kardel 92854359Sroberto * bcopy/memcpy cleanup 92954359Sroberto * fix SVSV name clash 93054359Sroberto * 93154359Sroberto * Revision 4.3 1998/06/12 15:22:30 kardel 93254359Sroberto * fix prototypes 93354359Sroberto * 93454359Sroberto * Revision 4.2 1998/06/12 09:13:27 kardel 93554359Sroberto * conditional compile macros fixed 93654359Sroberto * printf prototype 93754359Sroberto * 93854359Sroberto * Revision 4.1 1998/05/24 09:39:55 kardel 93954359Sroberto * implementation of the new IO handling model 94054359Sroberto * 94154359Sroberto * Revision 4.0 1998/04/10 19:45:36 kardel 94254359Sroberto * Start 4.0 release version numbering 94354359Sroberto * 94454359Sroberto * from V3 3.46 log info deleted 1998/04/11 kardel 94554359Sroberto */ 946