Annotation of embedaddon/ntp/libparse/parse.c, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>