//132405.000,A,4809.2356,N,01704.4263,E,0.15,317.49,270115,,,A //hhmmss.XXX, void gps_parse_rmc() { // DEBUG("\nRMC\n"); gps_init_ok = true; // strcpy(gps_parser_buffer, "$GPRMC,044434.000,A,3319.1312,S,14805.03,E,24.00,37.86,090116,,,A*71"); char * ptr = find_comma(gps_parser_buffer); //UTC time uint8_t hour = atoi_n(ptr + 0, 2); uint8_t min = atoi_n(ptr + 2, 2); uint8_t sec = atoi_n(ptr + 4, 2); // DEBUG("%02d:%02d:%02d\n", hour, min, sec); ptr = find_comma(ptr); //Valid (A = valid) fc.gps_data.valid = (*ptr) == 'A'; if (fc.gps_data.valid) { if (fc.gps_data.fix_cnt < GPS_FIX_CNT_MAX) fc.gps_data.fix_cnt++; } else { fc.gps_data.fix_cnt = 0; } ptr = find_comma(ptr); uint32_t loc_deg; uint32_t loc_min; //Latitude loc_deg = atoi_n(ptr, 2); loc_min = atoi_n(ptr + 2, 6); int32_t latitude = (loc_min * 100ul) / 6; latitude = loc_deg * 10000000ul + latitude; ptr = find_comma(ptr); //Latitude sign if ((*ptr) == 'S') latitude *= -1; fc.gps_data.latitude = latitude; sprintf_P((char *)fc.gps_data.cache_igc_latitude, PSTR("%02lu%05lu%c"), loc_deg, loc_min / 10, (*ptr)); ptr = find_comma(ptr); //Longitude loc_deg = atoi_n(ptr, 3); loc_min = atoi_n(ptr + 3, 6); int32_t longitude = (loc_min * 100ul) / 6; longitude = loc_deg * 10000000ul + longitude; ptr = find_comma(ptr); // DEBUG("ptr = '%s'\n", ptr); //Longitude sign if ((*ptr) == 'W') longitude *= -1; fc.gps_data.longtitude = longitude; sprintf_P((char *)fc.gps_data.cache_igc_longtitude, PSTR("%03lu%05lu%c"), loc_deg, loc_min / 10, (*ptr)); ptr = find_comma(ptr); // DEBUG("lat+lon %07ld %08ld\n", latitude, longitude); fc.gps_data.groud_speed = atoi_f(ptr); //in knots ptr = find_comma(ptr); //Ground course fc.gps_data.heading = atoi_f(ptr); ptr = find_comma(ptr); //UTC date uint8_t day = atoi_n(ptr + 0, 2); uint8_t month = atoi_n(ptr + 2, 2); uint16_t year = atoi_n(ptr + 4, 2) + 2000; // DEBUG("%02d.%02d.%04d\n", day, month, year); fc.gps_data.utc_time = datetime_to_epoch(sec, min, hour, day, month, year); if (config.connectivity.forward_gps) { char tmp[NMEA_MAX_LEN]; sprintf(tmp, "$%s", gps_parser_buffer); bt_send(tmp); if (config.connectivity.uart_function > UART_FORWARD_OFF) uart_send(tmp); } uint16_t tdeg, tmin, tsec; int32_t tmp; switch (config.connectivity.gps_format_flags & GPS_FORMAT_MASK) { case(GPS_DDdddddd): sprintf_P((char *)fc.gps_data.cache_gui_latitude, PSTR(" %+010ld"), fc.gps_data.latitude); memcpy((void *)fc.gps_data.cache_gui_latitude, (void *)(fc.gps_data.cache_gui_latitude + 1), 3); fc.gps_data.cache_gui_latitude[3] = '.'; if (fc.gps_data.cache_gui_latitude[1] == '0') memcpy((void *)(fc.gps_data.cache_gui_latitude + 1), (void *)(fc.gps_data.cache_gui_latitude + 2), 10); sprintf_P((char *)fc.gps_data.cache_gui_longtitude, PSTR(" %+011ld"), fc.gps_data.longtitude); memcpy((void *)fc.gps_data.cache_gui_longtitude, (void *)(fc.gps_data.cache_gui_longtitude + 1), 4); fc.gps_data.cache_gui_longtitude[4] = '.'; if (fc.gps_data.cache_gui_longtitude[1] == '0') { if (fc.gps_data.cache_gui_longtitude[2] == '0') memcpy((void *)(fc.gps_data.cache_gui_longtitude + 1), (void *)(fc.gps_data.cache_gui_longtitude + 3), 10); else memcpy((void *)(fc.gps_data.cache_gui_longtitude + 1), (void *)(fc.gps_data.cache_gui_longtitude + 2), 11); } break; case(GPS_DDMMmmm): memcpy((void *)fc.gps_data.cache_gui_latitude, (void *)fc.gps_data.cache_igc_latitude, 2); fc.gps_data.cache_gui_latitude[2] = '*'; memcpy((void *)(fc.gps_data.cache_gui_latitude + 3), (void *)(fc.gps_data.cache_igc_latitude + 2), 2); fc.gps_data.cache_gui_latitude[5] = '.'; memcpy((void *)(fc.gps_data.cache_gui_latitude + 6), (void *)(fc.gps_data.cache_igc_latitude + 4), 4); fc.gps_data.cache_gui_latitude[10] = 0; memcpy((void *)fc.gps_data.cache_gui_longtitude, (void *)fc.gps_data.cache_igc_longtitude, 3); fc.gps_data.cache_gui_longtitude[3] = '*'; memcpy((void *)(fc.gps_data.cache_gui_longtitude + 4), (void *)(fc.gps_data.cache_igc_longtitude + 3), 2); fc.gps_data.cache_gui_longtitude[6] = '.'; memcpy((void *)(fc.gps_data.cache_gui_longtitude + 7), (void *)(fc.gps_data.cache_igc_longtitude + 5), 4); fc.gps_data.cache_gui_longtitude[11] = 0; break; case(GPS_DDMMSS): tdeg = abs(fc.gps_data.latitude) / 10000000ul; tmp = ((abs(fc.gps_data.latitude) % 10000000ul) * 60); tmin = tmp / 10000000ul; tsec = ((tmp % 10000000ul) * 60) / 10000000ul; sprintf_P((char *)fc.gps_data.cache_gui_latitude, PSTR("%02u*%02u'%02u\"%c"), tdeg, tmin, tsec, (*(fc.gps_data.cache_igc_latitude + 7))); tdeg = abs(fc.gps_data.longtitude) / 10000000ul; tmp = ((abs(fc.gps_data.longtitude) % 10000000ul) * 60); tmin = tmp / 10000000ul; tsec = ((tmp % 10000000ul) * 60) / 10000000ul; sprintf_P((char *)fc.gps_data.cache_gui_longtitude, PSTR("%03u*%02u'%02u\"%c"), tdeg, tmin, tsec, (*(fc.gps_data.cache_igc_longtitude + 8))); break; } // DEBUG("clat = %s\n", fc.gps_data.cache_gui_latitude); // DEBUG("clon = %s\n", fc.gps_data.cache_gui_longtitude); }
static void dump(const char *fname, const char *from, const char *to, int input_format, int output_format, int write_using_libxml2, int print_offset, const char *split_fname, int split_chunk, int verbose, FILE *cfile, const char *leader_spec) { yaz_marc_t mt = yaz_marc_create(); yaz_iconv_t cd = 0; if (yaz_marc_leader_spec(mt, leader_spec)) { fprintf(stderr, "bad leader spec: %s\n", leader_spec); yaz_marc_destroy(mt); exit(2); } if (from && to) { cd = yaz_iconv_open(to, from); if (!cd) { fprintf(stderr, "conversion from %s to %s " "unsupported\n", from, to); yaz_marc_destroy(mt); exit(2); } yaz_marc_iconv(mt, cd); } yaz_marc_enable_collection(mt); yaz_marc_xml(mt, output_format); yaz_marc_write_using_libxml2(mt, write_using_libxml2); yaz_marc_debug(mt, verbose); if (input_format == YAZ_MARC_MARCXML || input_format == YAZ_MARC_TURBOMARC || input_format == YAZ_MARC_XCHANGE) { #if YAZ_HAVE_XML2 marcdump_read_xml(mt, fname); #endif } else if (input_format == YAZ_MARC_LINE) { marcdump_read_line(mt, fname); } else if (input_format == YAZ_MARC_ISO2709) { FILE *inf = fopen(fname, "rb"); int num = 1; int marc_no = 0; int split_file_no = -1; if (!inf) { fprintf(stderr, "%s: cannot open %s:%s\n", prog, fname, strerror(errno)); exit(1); } if (cfile) fprintf(cfile, "char *marc_records[] = {\n"); for(;; marc_no++) { const char *result = 0; size_t len; size_t rlen; size_t len_result; size_t r; char buf[100001]; r = fread(buf, 1, 5, inf); if (r < 5) { if (r == 0) /* normal EOF, all good */ break; if (print_offset && verbose) { printf("<!-- Extra %ld bytes at end of file -->\n", (long) r); } break; } while (*buf < '0' || *buf > '9') { int i; long off = ftell(inf) - 5; printf("<!-- Skipping bad byte %d (0x%02X) at offset " "%ld (0x%lx) -->\n", *buf & 0xff, *buf & 0xff, off, off); for (i = 0; i<4; i++) buf[i] = buf[i+1]; r = fread(buf+4, 1, 1, inf); no_errors++; if (r < 1) break; } if (r < 1) { if (verbose || print_offset) printf("<!-- End of file with data -->\n"); break; } if (print_offset) { long off = ftell(inf) - 5; printf("<!-- Record %d offset %ld (0x%lx) -->\n", num, off, off); } len = atoi_n(buf, 5); if (len < 25 || len > 100000) { long off = ftell(inf) - 5; printf("<!-- Bad Length %ld read at offset %ld (%lx) -->\n", (long)len, (long) off, (long) off); no_errors++; break; } rlen = len - 5; r = fread(buf + 5, 1, rlen, inf); if (r < rlen) { long off = ftell(inf); printf("<!-- Premature EOF at offset %ld (%lx) -->\n", (long) off, (long) off); no_errors++; break; } while (buf[len-1] != ISO2709_RS) { if (len > sizeof(buf)-2) { r = 0; break; } r = fread(buf + len, 1, 1, inf); if (r != 1) break; len++; } if (r < 1) { printf("<!-- EOF while searching for RS -->\n"); no_errors++; break; } if (split_fname) { char fname[256]; const char *mode = 0; FILE *sf; if ((marc_no % split_chunk) == 0) { mode = "wb"; split_file_no++; } else mode = "ab"; sprintf(fname, "%.200s%07d", split_fname, split_file_no); sf = fopen(fname, mode); if (!sf) { fprintf(stderr, "Could not open %s\n", fname); split_fname = 0; } else { if (fwrite(buf, 1, len, sf) != len) { fprintf(stderr, "Could write content to %s\n", fname); split_fname = 0; no_errors++; } fclose(sf); } } len_result = rlen; r = yaz_marc_decode_buf(mt, buf, -1, &result, &len_result); if (r == -1) no_errors++; if (r > 0 && result && len_result) { if (fwrite(result, len_result, 1, stdout) != 1) { fprintf(stderr, "Write to stdout failed\n"); no_errors++; break; } } if (r > 0 && cfile) { char *p = buf; size_t i; if (marc_no) fprintf(cfile, ","); fprintf(cfile, "\n"); for (i = 0; i < r; i++) { if ((i & 15) == 0) fprintf(cfile, " \""); fprintf(cfile, "\\x%02X", p[i] & 255); if (i < r - 1 && (i & 15) == 15) fprintf(cfile, "\"\n"); } fprintf(cfile, "\"\n"); } num++; if (verbose) printf("\n"); } if (cfile) fprintf(cfile, "};\n"); fclose(inf); } { WRBUF wrbuf = wrbuf_alloc(); yaz_marc_write_trailer(mt, wrbuf); fputs(wrbuf_cstr(wrbuf), stdout); wrbuf_destroy(wrbuf); } if (cd) yaz_iconv_close(cd); yaz_marc_destroy(mt); }
int yaz_marc_read_iso2709(yaz_marc_t mt, const char *buf, int bsize) { int entry_p; int record_length; int indicator_length; int identifier_length; int end_of_directory; int base_address; int length_data_entry; int length_starting; int length_implementation; yaz_marc_reset(mt); record_length = atoi_n (buf, 5); if (record_length < 25) { yaz_marc_cprintf(mt, "Record length %d < 24", record_length); return -1; } /* ballout if bsize is known and record_length is less than that */ if (bsize != -1 && record_length > bsize) { yaz_marc_cprintf(mt, "Record appears to be larger than buffer %d < %d", record_length, bsize); return -1; } if (yaz_marc_get_debug(mt)) yaz_marc_cprintf(mt, "Record length %5d", record_length); yaz_marc_set_leader(mt, buf, &indicator_length, &identifier_length, &base_address, &length_data_entry, &length_starting, &length_implementation); /* First pass. determine length of directory & base of data */ for (entry_p = 24; buf[entry_p] != ISO2709_FS; ) { /* length of directory entry */ int l = 3 + length_data_entry + length_starting; if (entry_p + l >= record_length) { yaz_marc_cprintf(mt, "Directory offset %d: end of record." " Missing FS char", entry_p); return -1; } if (yaz_marc_get_debug(mt)) { yaz_marc_cprintf(mt, "Directory offset %d: Tag %.3s", entry_p, buf+entry_p); } /* Check for digits in length info */ while (--l >= 3) if (!isdigit(*(const unsigned char *) (buf + entry_p+l))) break; if (l >= 3) { /* Not all digits, so stop directory scan */ yaz_marc_cprintf(mt, "Directory offset %d: Bad value for data" " length and/or length starting", entry_p); break; } entry_p += 3 + length_data_entry + length_starting; } end_of_directory = entry_p; if (base_address != entry_p+1) { yaz_marc_cprintf(mt, "Base address not at end of directory," " base %d, end %d", base_address, entry_p+1); } /* Second pass. parse control - and datafields */ for (entry_p = 24; entry_p != end_of_directory; ) { int data_length; int data_offset; int end_offset; int i; char tag[4]; int identifier_flag = 0; int entry_p0 = entry_p; memcpy (tag, buf+entry_p, 3); entry_p += 3; tag[3] = '\0'; data_length = atoi_n(buf+entry_p, length_data_entry); entry_p += length_data_entry; data_offset = atoi_n(buf+entry_p, length_starting); entry_p += length_starting; i = data_offset + base_address; end_offset = i+data_length-1; if (data_length <= 0 || data_offset < 0) break; if (yaz_marc_get_debug(mt)) { yaz_marc_cprintf(mt, "Tag: %s. Directory offset %d: data-length %d," " data-offset %d", tag, entry_p0, data_length, data_offset); } if (end_offset >= record_length) { yaz_marc_cprintf(mt, "Directory offset %d: Data out of bounds %d >= %d", entry_p0, end_offset, record_length); break; } if (memcmp (tag, "00", 2)) identifier_flag = 1; /* if not 00X assume subfields */ else if (indicator_length < 4 && indicator_length > 0) { /* Danmarc 00X have subfields */ if (buf[i + indicator_length] == ISO2709_IDFS) identifier_flag = 1; else if (buf[i + indicator_length + 1] == ISO2709_IDFS) identifier_flag = 2; } if (identifier_flag) { /* datafield */ i += identifier_flag-1; if (indicator_length) { /* skip RS/FS bytes in indicator. They are not allowed there */ int j; for (j = indicator_length; --j >= 0; ) if (buf[j+i] < ' ') { j++; i += j; end_offset += j; yaz_marc_cprintf(mt, "Bad indicator data. " "Skipping %d bytes", j); break; } yaz_marc_add_datafield(mt, tag, buf+i, indicator_length); i += indicator_length; } while (i < end_offset && buf[i] != ISO2709_RS && buf[i] != ISO2709_FS) { int code_offset = i+1; i ++; while (i < end_offset && buf[i] != ISO2709_RS && buf[i] != ISO2709_IDFS && buf[i] != ISO2709_FS) i++; if (i > code_offset) yaz_marc_add_subfield(mt, buf+code_offset, i - code_offset); } } else { /* controlfield */ int i0 = i; while (i < end_offset && buf[i] != ISO2709_RS && buf[i] != ISO2709_FS) i++; yaz_marc_add_controlfield(mt, tag, buf+i0, i-i0); } if (i < end_offset) { yaz_marc_cprintf(mt, "Separator but not at end of field length=%d", data_length); } if (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS) { yaz_marc_cprintf(mt, "No separator at end of field length=%d", data_length); } } return record_length; }