Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / ntp / libparse / parse.c
bloba076a0f64b82dc8d4683780771c675b6c28a5930
1 /* $NetBSD: parse.c,v 1.2 2003/12/04 16:23:37 drochner Exp $ */
3 /*
4 * /src/NTP/ntp4-dev/libparse/parse.c,v 4.20 2005/08/06 17:39:40 kardel RELEASE_20050806_A
5 *
6 * parse.c,v 4.20 2005/08/06 17:39:40 kardel RELEASE_20050806_A
8 * Parser module for reference clock
10 * PARSEKERNEL define switches between two personalities of the module
11 * if PARSEKERNEL is defined this module can be used
12 * as kernel module. In this case the time stamps will be
13 * a struct timeval.
14 * when PARSEKERNEL is not defined NTP time stamps will be used.
16 * Copyright (c) 1995-2005 by Frank Kardel <kardel <AT> ntp.org>
17 * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, Germany
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions
21 * are met:
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 * 2. Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in the
26 * documentation and/or other materials provided with the distribution.
27 * 3. Neither the name of the author nor the names of its contributors
28 * may be used to endorse or promote products derived from this software
29 * without specific prior written permission.
31 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
32 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
35 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
40 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 * SUCH DAMAGE.
45 #ifdef HAVE_CONFIG_H
46 # include <config.h>
47 #endif
49 #if defined(REFCLOCK) && defined(CLOCK_PARSE)
51 #if !(defined(lint) || defined(__GNUC__))
52 static char rcsid[] = "parse.c,v 4.20 2005/08/06 17:39:40 kardel RELEASE_20050806_A";
53 #endif
55 #include "ntp_fp.h"
56 #include "ntp_unixtime.h"
57 #include "ntp_calendar.h"
58 #include "ntp_stdlib.h"
59 #include "ntp_machine.h"
60 #include "ntp.h" /* (get Y2KFixes definitions) Y2KFixes */
62 #include "parse.h"
64 #ifndef PARSESTREAM
65 # include <stdio.h>
66 #else
67 # include "sys/parsestreams.h"
68 #endif
70 extern clockformat_t *clockformats[];
71 extern unsigned short nformats;
73 static u_long timepacket P((parse_t *));
76 * strings support usually not in kernel - duplicated, but what the heck
78 static int
79 Strlen(
80 register const char *s
83 register int c;
85 c = 0;
86 if (s)
88 while (*s++)
90 c++;
93 return c;
96 static int
97 Strcmp(
98 register const char *s,
99 register const char *t
102 register int c = 0;
104 if (!s || !t || (s == t))
106 return 0;
109 while (!(c = *s++ - *t++) && *s && *t)
110 /* empty loop */;
112 return c;
116 parse_timedout(
117 parse_t *parseio,
118 timestamp_t *tstamp,
119 struct timeval *del
122 struct timeval delta;
124 #ifdef PARSEKERNEL
125 delta.tv_sec = tstamp->tv.tv_sec - parseio->parse_lastchar.tv.tv_sec;
126 delta.tv_usec = tstamp->tv.tv_usec - parseio->parse_lastchar.tv.tv_usec;
127 if (delta.tv_usec < 0)
129 delta.tv_sec -= 1;
130 delta.tv_usec += 1000000;
132 #else
133 extern long tstouslo[];
134 extern long tstousmid[];
135 extern long tstoushi[];
137 l_fp delt;
139 delt = tstamp->fp;
140 L_SUB(&delt, &parseio->parse_lastchar.fp);
141 TSTOTV(&delt, &delta);
142 #endif
144 if (timercmp(&delta, del, >))
146 parseprintf(DD_PARSE, ("parse: timedout: TRUE\n"));
147 return 1;
149 else
151 parseprintf(DD_PARSE, ("parse: timedout: FALSE\n"));
152 return 0;
156 /*ARGSUSED*/
158 parse_ioinit(
159 register parse_t *parseio
162 parseprintf(DD_PARSE, ("parse_iostart\n"));
164 parseio->parse_plen = 0;
165 parseio->parse_pdata = (void *)0;
167 parseio->parse_data = 0;
168 parseio->parse_ldata = 0;
169 parseio->parse_dsize = 0;
171 parseio->parse_badformat = 0;
172 parseio->parse_ioflags = PARSE_IO_CS7; /* usual unix default */
173 parseio->parse_index = 0;
174 parseio->parse_ldsize = 0;
176 return 1;
179 /*ARGSUSED*/
180 void
181 parse_ioend(
182 register parse_t *parseio
185 parseprintf(DD_PARSE, ("parse_ioend\n"));
187 if (parseio->parse_pdata)
188 FREE(parseio->parse_pdata, parseio->parse_plen);
190 if (parseio->parse_data)
191 FREE(parseio->parse_data, (unsigned)(parseio->parse_dsize * 2 + 2));
194 unsigned int
195 parse_restart(
196 parse_t *parseio,
197 unsigned int ch
200 unsigned int updated = PARSE_INP_SKIP;
203 * re-start packet - timeout - overflow - start symbol
206 if (parseio->parse_index)
209 * filled buffer - thus not end character found
210 * do processing now
212 parseio->parse_data[parseio->parse_index] = '\0';
213 memcpy(parseio->parse_ldata, parseio->parse_data, (unsigned)(parseio->parse_index+1));
214 parseio->parse_ldsize = parseio->parse_index;
215 updated = PARSE_INP_TIME;
218 parseio->parse_index = 1;
219 parseio->parse_data[0] = ch;
220 parseprintf(DD_PARSE, ("parse: parse_restart: buffer start (updated = %x)\n", updated));
221 return updated;
224 unsigned int
225 parse_addchar(
226 parse_t *parseio,
227 unsigned int ch
231 * add to buffer
233 if (parseio->parse_index < parseio->parse_dsize)
236 * collect into buffer
238 parseprintf(DD_PARSE, ("parse: parse_addchar: buffer[%d] = 0x%x\n", parseio->parse_index, ch));
239 parseio->parse_data[parseio->parse_index++] = ch;
240 return PARSE_INP_SKIP;
242 else
244 * buffer overflow - attempt to make the best of it
246 return parse_restart(parseio, ch);
249 unsigned int
250 parse_end(
251 parse_t *parseio
255 * message complete processing
257 parseio->parse_data[parseio->parse_index] = '\0';
258 memcpy(parseio->parse_ldata, parseio->parse_data, (unsigned)(parseio->parse_index+1));
259 parseio->parse_ldsize = parseio->parse_index;
260 parseio->parse_index = 0;
261 parseprintf(DD_PARSE, ("parse: parse_end: buffer end\n"));
262 return PARSE_INP_TIME;
265 /*ARGSUSED*/
267 parse_ioread(
268 register parse_t *parseio,
269 register unsigned int ch,
270 register timestamp_t *tstamp
273 register unsigned updated = CVT_NONE;
275 * within STREAMS CSx (x < 8) chars still have the upper bits set
276 * so we normalize the characters by masking unecessary bits off.
278 switch (parseio->parse_ioflags & PARSE_IO_CSIZE)
280 case PARSE_IO_CS5:
281 ch &= 0x1F;
282 break;
284 case PARSE_IO_CS6:
285 ch &= 0x3F;
286 break;
288 case PARSE_IO_CS7:
289 ch &= 0x7F;
290 break;
292 case PARSE_IO_CS8:
293 ch &= 0xFF;
294 break;
297 parseprintf(DD_PARSE, ("parse_ioread(0x%lx, char=0x%x, ..., ...)\n", (unsigned long)parseio, ch & 0xFF));
299 if (!clockformats[parseio->parse_lformat]->convert)
301 parseprintf(DD_PARSE, ("parse_ioread: input dropped.\n"));
302 return CVT_NONE;
305 if (clockformats[parseio->parse_lformat]->input)
307 unsigned long input_status;
309 input_status = clockformats[parseio->parse_lformat]->input(parseio, ch, tstamp);
311 if (input_status & PARSE_INP_SYNTH)
313 updated = CVT_OK;
316 if (input_status & PARSE_INP_TIME) /* time sample is available */
318 updated = timepacket(parseio);
321 if (input_status & PARSE_INP_DATA) /* got additional data */
323 updated |= CVT_ADDITIONAL;
329 * remember last character time
331 parseio->parse_lastchar = *tstamp;
333 #ifdef DEBUG
334 if ((updated & CVT_MASK) != CVT_NONE)
336 parseprintf(DD_PARSE, ("parse_ioread: time sample accumulated (status=0x%x)\n", updated));
338 #endif
340 parseio->parse_dtime.parse_status = updated;
342 return (((updated & CVT_MASK) != CVT_NONE) ||
343 ((updated & CVT_ADDITIONAL) != 0));
347 * parse_iopps
349 * take status line indication and derive synchronisation information
350 * from it.
351 * It can also be used to decode a serial serial data format (such as the
352 * ONE, ZERO, MINUTE sync data stream from DCF77)
354 /*ARGSUSED*/
356 parse_iopps(
357 register parse_t *parseio,
358 register int status,
359 register timestamp_t *ptime
362 register unsigned updated = CVT_NONE;
365 * PPS pulse information will only be delivered to ONE clock format
366 * this is either the last successful conversion module with a ppssync
367 * routine, or a fixed format with a ppssync routine
369 parseprintf(DD_PARSE, ("parse_iopps: STATUS %s\n", (status == SYNC_ONE) ? "ONE" : "ZERO"));
371 if (clockformats[parseio->parse_lformat]->syncpps)
373 updated = clockformats[parseio->parse_lformat]->syncpps(parseio, status == SYNC_ONE, ptime);
374 parseprintf(DD_PARSE, ("parse_iopps: updated = 0x%x\n", updated));
377 return (updated & CVT_MASK) != CVT_NONE;
381 * parse_iodone
383 * clean up internal status for new round
385 /*ARGSUSED*/
386 void
387 parse_iodone(
388 register parse_t *parseio
392 * we need to clean up certain flags for the next round
394 parseprintf(DD_PARSE, ("parse_iodone: DONE\n"));
395 parseio->parse_dtime.parse_state = 0; /* no problems with ISRs */
398 /*---------- conversion implementation --------------------*/
401 * convert a struct clock to UTC since Jan, 1st 1970 0:00 (the UNIX EPOCH)
403 #define days_per_year(x) ((x) % 4 ? 365 : ((x % 400) ? ((x % 100) ? 366 : 365) : 366))
405 time_t
406 parse_to_unixtime(
407 register clocktime_t *clock_time,
408 register u_long *cvtrtc
411 #define SETRTC(_X_) { if (cvtrtc) *cvtrtc = (_X_); }
412 static int days_of_month[] =
414 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
416 register int i;
417 time_t t;
419 if (clock_time->utctime)
420 return clock_time->utctime; /* if the conversion routine gets it right away - why not */
422 if ( clock_time->year < YEAR_PIVOT ) /* Y2KFixes [ */
423 clock_time->year += 100; /* convert 20xx%100 to 20xx-1900 */
424 if ( clock_time->year < YEAR_BREAK ) /* expand to full four-digits */
425 clock_time->year += 1900;
427 if (clock_time->year < 1970 ) /* Y2KFixes ] */
429 SETRTC(CVT_FAIL|CVT_BADDATE);
430 return -1;
434 * sorry, slow section here - but it's not time critical anyway
436 t = julian0(clock_time->year) - julian0(1970); /* Y2kFixes */
437 /* month */
438 if (clock_time->month <= 0 || clock_time->month > 12)
440 SETRTC(CVT_FAIL|CVT_BADDATE);
441 return -1; /* bad month */
444 #if 0 /* Y2KFixes */
445 /* adjust leap year */
446 if (clock_time->month < 3 && days_per_year(clock_time->year) == 366)
447 t--;
448 #else /* Y2KFixes [ */
449 if ( clock_time->month >= 3 && isleap_4(clock_time->year) )
450 t++; /* add one more if within leap year */
451 #endif /* Y2KFixes ] */
453 for (i = 1; i < clock_time->month; i++)
455 t += days_of_month[i];
457 /* day */
458 if (clock_time->day < 1 || ((clock_time->month == 2 && days_per_year(clock_time->year) == 366) ?
459 clock_time->day > 29 : clock_time->day > days_of_month[clock_time->month]))
461 SETRTC(CVT_FAIL|CVT_BADDATE);
462 return -1; /* bad day */
465 t += clock_time->day - 1;
466 /* hour */
467 if (clock_time->hour < 0 || clock_time->hour >= 24)
469 SETRTC(CVT_FAIL|CVT_BADTIME);
470 return -1; /* bad hour */
473 t = TIMES24(t) + clock_time->hour;
475 /* min */
476 if (clock_time->minute < 0 || clock_time->minute > 59)
478 SETRTC(CVT_FAIL|CVT_BADTIME);
479 return -1; /* bad min */
482 t = TIMES60(t) + clock_time->minute;
483 /* sec */
485 if (clock_time->second < 0 || clock_time->second > 60) /* allow for LEAPs */
487 SETRTC(CVT_FAIL|CVT_BADTIME);
488 return -1; /* bad sec */
491 t = TIMES60(t) + clock_time->second;
493 t += clock_time->utcoffset; /* warp to UTC */
495 /* done */
497 clock_time->utctime = t; /* documentray only */
499 return t;
502 /*--------------- format conversion -----------------------------------*/
505 Stoi(
506 const unsigned char *s,
507 long *zp,
508 int cnt
511 char unsigned const *b = s;
512 int f,z,v;
513 char unsigned c;
515 f=z=v=0;
517 while(*s == ' ')
518 s++;
520 if (*s == '-')
522 s++;
523 v = 1;
525 else
526 if (*s == '+')
527 s++;
529 for(;;)
531 c = *s++;
532 if (c == '\0' || c < '0' || c > '9' || (cnt && ((s-b) > cnt)))
534 if (f == 0)
536 return(-1);
538 if (v)
539 z = -z;
540 *zp = z;
541 return(0);
543 z = (z << 3) + (z << 1) + ( c - '0' );
544 f=1;
549 Strok(
550 const unsigned char *s,
551 const unsigned char *m
554 if (!s || !m)
555 return 0;
557 while(*s && *m)
559 if ((*m == ' ') ? 1 : (*s == *m))
561 s++;
562 m++;
564 else
566 return 0;
569 return !*m;
572 u_long
573 updatetimeinfo(
574 register parse_t *parseio,
575 register u_long flags
578 #ifdef PARSEKERNEL
580 int s = splhigh();
581 #endif
583 parseio->parse_lstate = parseio->parse_dtime.parse_state | flags | PARSEB_TIMECODE;
585 parseio->parse_dtime.parse_state = parseio->parse_lstate;
587 #ifdef PARSEKERNEL
588 (void)splx((unsigned int)s);
590 #endif
593 #ifdef PARSEKERNEL
594 parseprintf(DD_PARSE, ("updatetimeinfo status=0x%x, time=%x\n", parseio->parse_dtime.parse_state,
595 parseio->parse_dtime.parse_time.tv.tv_sec));
596 #else
597 parseprintf(DD_PARSE, ("updatetimeinfo status=0x%lx, time=%x\n", (long)parseio->parse_dtime.parse_state,
598 parseio->parse_dtime.parse_time.fp.l_ui));
599 #endif
601 return CVT_OK; /* everything fine and dandy... */
606 * syn_simple
608 * handle a sync time stamp
610 /*ARGSUSED*/
611 void
612 syn_simple(
613 register parse_t *parseio,
614 register timestamp_t *ts,
615 register struct format *format,
616 register u_long why
619 parseio->parse_dtime.parse_stime = *ts;
623 * pps_simple
625 * handle a pps time stamp
627 /*ARGSUSED*/
628 u_long
629 pps_simple(
630 register parse_t *parseio,
631 register int status,
632 register timestamp_t *ptime
635 parseio->parse_dtime.parse_ptime = *ptime;
636 parseio->parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
638 return CVT_NONE;
642 * pps_one
644 * handle a pps time stamp in ONE edge
646 /*ARGSUSED*/
647 u_long
648 pps_one(
649 register parse_t *parseio,
650 register int status,
651 register timestamp_t *ptime
654 if (status)
655 return pps_simple(parseio, status, ptime);
657 return CVT_NONE;
661 * pps_zero
663 * handle a pps time stamp in ZERO edge
665 /*ARGSUSED*/
666 u_long
667 pps_zero(
668 register parse_t *parseio,
669 register int status,
670 register timestamp_t *ptime
673 if (!status)
674 return pps_simple(parseio, status, ptime);
676 return CVT_NONE;
680 * timepacket
682 * process a data packet
684 static u_long
685 timepacket(
686 register parse_t *parseio
689 register unsigned short format;
690 register time_t t;
691 u_long cvtrtc; /* current conversion result */
692 clocktime_t clock_time;
694 memset((char *)&clock_time, 0, sizeof clock_time);
695 format = parseio->parse_lformat;
697 if (format == (unsigned short)~0)
698 return CVT_NONE;
700 switch ((cvtrtc = clockformats[format]->convert ?
701 clockformats[format]->convert((unsigned char *)parseio->parse_ldata, parseio->parse_ldsize, (struct format *)(clockformats[format]->data), &clock_time, parseio->parse_pdata) :
702 CVT_NONE) & CVT_MASK)
704 case CVT_FAIL:
705 parseio->parse_badformat++;
706 break;
708 case CVT_NONE:
710 * too bad - pretend bad format
712 parseio->parse_badformat++;
713 break;
715 case CVT_OK:
716 break;
718 case CVT_SKIP:
719 return CVT_NONE;
721 default:
722 /* shouldn't happen */
723 #ifndef PARSEKERNEL
724 msyslog(LOG_WARNING, "parse: INTERNAL error: bad return code of convert routine \"%s\"\n", clockformats[format]->name);
725 #endif
726 return CVT_FAIL|cvtrtc;
729 if ((t = parse_to_unixtime(&clock_time, &cvtrtc)) == -1)
731 return CVT_FAIL|cvtrtc;
735 * time stamp
737 #ifdef PARSEKERNEL
738 parseio->parse_dtime.parse_time.tv.tv_sec = t;
739 parseio->parse_dtime.parse_time.tv.tv_usec = clock_time.usecond;
740 #else
741 parseio->parse_dtime.parse_time.fp.l_ui = t + JAN_1970;
742 TVUTOTSF(clock_time.usecond, parseio->parse_dtime.parse_time.fp.l_uf);
743 #endif
745 parseio->parse_dtime.parse_format = format;
747 return updatetimeinfo(parseio, clock_time.flags);
750 /*ARGSUSED*/
752 parse_timecode(
753 parsectl_t *dct,
754 parse_t *parse
757 dct->parsegettc.parse_state = parse->parse_lstate;
758 dct->parsegettc.parse_format = parse->parse_lformat;
760 * move out current bad packet count
761 * user program is expected to sum these up
762 * this is not a problem, as "parse" module are
763 * exclusive open only
765 dct->parsegettc.parse_badformat = parse->parse_badformat;
766 parse->parse_badformat = 0;
768 if (parse->parse_ldsize <= PARSE_TCMAX)
770 dct->parsegettc.parse_count = parse->parse_ldsize;
771 memcpy(dct->parsegettc.parse_buffer, parse->parse_ldata, dct->parsegettc.parse_count);
772 return 1;
774 else
776 return 0;
781 /*ARGSUSED*/
783 parse_setfmt(
784 parsectl_t *dct,
785 parse_t *parse
788 if (dct->parseformat.parse_count <= PARSE_TCMAX)
790 if (dct->parseformat.parse_count)
792 register unsigned short i;
794 for (i = 0; i < nformats; i++)
796 if (!Strcmp(dct->parseformat.parse_buffer, clockformats[i]->name))
798 if (parse->parse_pdata)
799 FREE(parse->parse_pdata, parse->parse_plen);
800 parse->parse_pdata = 0;
802 parse->parse_plen = clockformats[i]->plen;
804 if (parse->parse_plen)
806 parse->parse_pdata = MALLOC(parse->parse_plen);
807 if (!parse->parse_pdata)
809 parseprintf(DD_PARSE, ("set format failed: malloc for private data area failed\n"));
810 return 0;
812 memset((char *)parse->parse_pdata, 0, parse->parse_plen);
815 if (parse->parse_data)
816 FREE(parse->parse_data, (unsigned)(parse->parse_dsize * 2 + 2));
817 parse->parse_ldata = parse->parse_data = 0;
819 parse->parse_dsize = clockformats[i]->length;
821 if (parse->parse_dsize)
823 parse->parse_data = (char*)MALLOC((unsigned)(parse->parse_dsize * 2 + 2));
824 if (!parse->parse_data)
826 if (parse->parse_pdata)
827 FREE(parse->parse_pdata, parse->parse_plen);
828 parse->parse_pdata = 0;
830 parseprintf(DD_PARSE, ("init failed: malloc for data area failed\n"));
831 return 0;
837 * leave room for '\0'
839 parse->parse_ldata = parse->parse_data + parse->parse_dsize + 1;
841 parse->parse_lformat = i;
843 return 1;
848 return 0;
851 /*ARGSUSED*/
853 parse_getfmt(
854 parsectl_t *dct,
855 parse_t *parse
858 if (dct->parseformat.parse_format < nformats &&
859 Strlen(clockformats[dct->parseformat.parse_format]->name) <= PARSE_TCMAX)
861 dct->parseformat.parse_count = Strlen(clockformats[dct->parseformat.parse_format]->name)+1;
862 memcpy(dct->parseformat.parse_buffer, clockformats[dct->parseformat.parse_format]->name, dct->parseformat.parse_count);
863 return 1;
865 else
867 return 0;
871 /*ARGSUSED*/
873 parse_setcs(
874 parsectl_t *dct,
875 parse_t *parse
878 parse->parse_ioflags &= ~PARSE_IO_CSIZE;
879 parse->parse_ioflags |= dct->parsesetcs.parse_cs & PARSE_IO_CSIZE;
880 return 1;
883 #else /* not (REFCLOCK && CLOCK_PARSE) */
884 int parse_bs;
885 #endif /* not (REFCLOCK && CLOCK_PARSE) */
888 * History:
890 * parse.c,v
891 * Revision 4.20 2005/08/06 17:39:40 kardel
892 * cleanup size handling wrt/ to buffer boundaries
894 * Revision 4.19 2005/04/16 17:32:10 kardel
895 * update copyright
897 * Revision 4.18 2004/11/14 16:11:05 kardel
898 * update Id tags
900 * Revision 4.17 2004/11/14 15:29:41 kardel
901 * support PPSAPI, upgrade Copyright to Berkeley style
903 * Revision 4.14 1999/11/28 09:13:52 kardel
904 * RECON_4_0_98F
906 * Revision 4.13 1999/02/28 11:50:20 kardel
907 * (timepacket): removed unecessary code
909 * Revision 4.12 1999/02/21 12:17:44 kardel
910 * 4.91f reconcilation
912 * Revision 4.11 1999/02/21 11:09:47 kardel
913 * unified debug output
915 * Revision 4.10 1998/12/20 23:45:30 kardel
916 * fix types and warnings
918 * Revision 4.9 1998/08/09 22:26:06 kardel
919 * Trimble TSIP support
921 * Revision 4.8 1998/06/14 21:09:39 kardel
922 * Sun acc cleanup
924 * Revision 4.7 1998/06/13 15:19:13 kardel
925 * fix mem*() to b*() function macro emulation
927 * Revision 4.6 1998/06/13 13:24:13 kardel
928 * printf fmt
930 * Revision 4.5 1998/06/13 13:01:10 kardel
931 * printf fmt
933 * Revision 4.4 1998/06/13 12:12:10 kardel
934 * bcopy/memcpy cleanup
935 * fix SVSV name clash
937 * Revision 4.3 1998/06/12 15:22:30 kardel
938 * fix prototypes
940 * Revision 4.2 1998/06/12 09:13:27 kardel
941 * conditional compile macros fixed
942 * printf prototype
944 * Revision 4.1 1998/05/24 09:39:55 kardel
945 * implementation of the new IO handling model
947 * Revision 4.0 1998/04/10 19:45:36 kardel
948 * Start 4.0 release version numbering
950 * from V3 3.46 log info deleted 1998/04/11 kardel