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