Browse Source

Imported Upstream version 3.10

master
Bernd Zeimetz 7 years ago
parent
commit
baf7bec962
100 changed files with 8902 additions and 4853 deletions
  1. +5
    -0
      .splintrc
  2. +1
    -0
      AUTHORS
  3. +8
    -0
      HACKING
  4. +3
    -6
      INSTALL
  5. +20
    -6
      NEWS
  6. +473
    -327
      SConstruct
  7. +48
    -23
      TODO
  8. +2
    -0
      Tachometer.c
  9. +106
    -22
      ais_json.c
  10. +209
    -24
      ais_json.i
  11. +14
    -7
      bits.c
  12. +1
    -0
      bits.h
  13. +3
    -1
      bsd_base64.c
  14. +95
    -27
      build.txt
  15. +11
    -4
      cgps.c
  16. +11
    -0
      contrib/README
  17. +2
    -2
      contrib/binlog.c
  18. +6
    -30
      contrib/binreplay.c
  19. +4
    -3
      contrib/motosend.c
  20. +10
    -0
      contrib/ntpoffset
  21. +98
    -0
      contrib/ppscheck.c
  22. +59
    -28
      contrib/webgps.py
  23. +1
    -1
      control
  24. +2
    -0
      crc24q.c
  25. +6
    -1
      devtools/ais.py
  26. +39
    -12
      devtools/striplog
  27. +156
    -53
      devtools/tablegen.py
  28. +1
    -1
      doc/Makefile
  29. +303
    -170
      driver_ais.c
  30. +41
    -28
      driver_evermore.c
  31. +156
    -111
      driver_garmin.c
  32. +55
    -33
      driver_garmin_txt.c
  33. +124
    -78
      driver_geostar.c
  34. +48
    -41
      driver_italk.c
  35. +67
    -67
      driver_navcom.c
  36. +176
    -58
      driver_nmea0183.c
  37. +630
    -148
      driver_nmea2000.c
  38. +48
    -83
      driver_oncore.c
  39. +33
    -36
      driver_proto.c
  40. +71
    -2
      driver_rtcm2.c
  41. +3
    -2
      driver_rtcm3.c
  42. +351
    -185
      driver_sirf.c
  43. +35
    -33
      driver_superstar2.c
  44. +292
    -159
      driver_tsip.c
  45. +358
    -180
      driver_ubx.c
  46. +42
    -78
      driver_zodiac.c
  47. +303
    -325
      drivers.c
  48. +7
    -8
      gps.1
  49. +196
    -67
      gps.h
  50. +1
    -0
      gps.xml
  51. +22
    -8
      gps/client.py
  52. +153
    -43
      gps/fake.py
  53. +16
    -2
      gps/gps.py
  54. +114
    -0
      gps2udp.1
  55. +501
    -0
      gps2udp.c
  56. +130
    -0
      gps2udp.xml
  57. +2
    -0
      gps_json.h
  58. +2
    -1
      gps_maskdump.c
  59. +131
    -37
      gpscap.ini
  60. +6
    -6
      gpscap.py
  61. +5
    -5
      gpscat
  62. +2
    -3
      gpscat.1
  63. +1
    -0
      gpsclient.c
  64. +11
    -10
      gpsctl.1
  65. +236
    -211
      gpsctl.c
  66. +15
    -12
      gpsctl.xml
  67. +10
    -164
      gpsd.8
  68. +557
    -636
      gpsd.c
  69. +213
    -76
      gpsd.h-tail
  70. +22
    -144
      gpsd.xml
  71. +36
    -11
      gpsd_json.5
  72. +592
    -229
      gpsd_json.c
  73. +33
    -16
      gpsd_json.xml
  74. +9
    -4
      gpsdctl.8
  75. +11
    -3
      gpsdctl.c
  76. +11
    -1
      gpsdctl.xml
  77. +7
    -4
      gpsdecode.1
  78. +47
    -20
      gpsdecode.c
  79. +5
    -0
      gpsdecode.xml
  80. +26
    -9
      gpsfake
  81. +27
    -7
      gpsfake.1
  82. +40
    -3
      gpsfake.xml
  83. +6
    -1
      gpsinit
  84. +2
    -3
      gpsinit.8
  85. +20
    -15
      gpsmon.1
  86. +939
    -608
      gpsmon.c
  87. +38
    -13
      gpsmon.xml
  88. +3
    -3
      gpspacket.c
  89. +8
    -6
      gpspipe.1
  90. +9
    -1
      gpspipe.c
  91. +6
    -0
      gpspipe.xml
  92. +47
    -14
      gpsprof
  93. +11
    -5
      gpsprof.1
  94. +19
    -9
      gpsprof.xml
  95. +3
    -2
      gpsutils.c
  96. +15
    -8
      gpxlogger.c
  97. +22
    -16
      hex.c
  98. +17
    -11
      isgps.c
  99. +8
    -2
      json.c
  100. +2
    -1
      json.h

+ 5
- 0
.splintrc View File

@@ -18,3 +18,8 @@
-DCRTSCTS=0x00020000
-DONLCR=0x00000002
-D__gnuc_va_list=va_list
-D__signed__=signed
-D__pid_t=int
-D__size_t=size_t
-Dpps_handle_t=int


+ 1
- 0
AUTHORS View File

@@ -7,3 +7,4 @@ Jeff Francis <jeff@gritch.org>
Amaury Jacquot <sxpert@esitcom.org>
Chris Kuethe <chris.kuethe@gmail.com>
Ville Nuorvala <vnuorval@tcs.hut.fi>
Fulup Ar Foll <fulup@sinagot.net>

+ 8
- 0
HACKING View File

@@ -2,3 +2,11 @@ For the gpsd project, the information that was traditionally placed in
this file is in the repository as:

www/hacking.html

If you only have www/hacking.html.in, run

scons www

This builds www/hacking.html with some magic cookies usefully substituted.



+ 3
- 6
INSTALL View File

@@ -85,7 +85,7 @@ various additional features have additional prerequisites:
|pgtk-2/cairo bindings | the main test client, xgps, needs this
|==========================================================================

Some ncurses packages comntain the terminfo library; some break it out
Some ncurses packages contain the terminfo library; some break it out
separately as libtinfo5 or libtinfo.

The Python code in GPSD is actually compatible back to Python 2.4 except that
@@ -157,8 +157,5 @@ first time it's invoked, it will generate a file called
'gpsd_config.inc' in that directory containing configuration
information; edit to taste.

4. Note for people using gpsd as time source for ntpd: In case you're
using dhcp3-client to configure your system, make sure you disable
/etc/dhcp3/dhclient-exit-hooks.d/ntp, as dhclient would restart
ntpd with an automatically created ntp.conf otherwise - and gpsd
would not be able to talk with ntpd anymore.
For special instructions related to using GPSD for time service, see the
GPSD Time Service HOWTO in the distribution or on the web.

+ 20
- 6
NEWS View File

@@ -1,3 +1,16 @@
GPSD project news

* Fri 22 Oct 2013 Eric S. Raymond <esr@snark.thyrsus.com> - 3.10
AIS: Adds gps2udp, an AIS data relay, split24 option supports
passing through Type 24 halves; support for Inland AIS; "scaled" no
longer controls dumping of controlled-vocabulary fields; instead,
the're always dumped numerically and as text, with text in an
attribute name generated by appending "_text" to the name of the
base attribute. The packetizer's handling of write boundaries not
coinciding with packet boundaries is improved. Better support for
mode and speed switching in the UBX driver. PPS message now ships
nsec. PPS events are visible in gpsmon. Time-reporting fix to TSIP.

* Wed 1 May 2013 Eric S. Raymond <esr@snark.thyrsus.com> - 3.9
Note to packagers: this is an urgent release that fixes a possible
DoS or security hole! Armor the AIS driver against an implausible
@@ -8,10 +21,11 @@

* Mon 25 Feb 2013 Eric S. Raymond <esr@snark.thyrsus.com> - 3.8
Fix various minor errors in the AIVDM/AIVDO description. Repair the
xmlto support in the build system. Add two more regression tests. Significant
improvements to NMEA2000 support. Upgrade the PHP client to v3 of the
Google Maps API. Support for the Telit SL869 chipset. Added a nautical-style
display to xgpsspeed. Minor improvements to leapsecond.py.
xmlto support in the build system. Add two more regression
tests. Significant improvements to NMEA2000 support. Upgrade the PHP
client to v3 of the Google Maps API. Support for the Telit SL869
chipset. Added a nautical-style display to xgpsspeed. Minor
improvements to leapsecond.py.

* Mon 02 Jul 2012 Eric S. Raymond <esr@snark.thyrsus.com> - 3.7
Snap release to get the midnight change in the default leap-second
@@ -45,7 +59,7 @@
* Sat Oct 29 2011 Eric S. Raymond <esr@snark.thyrsus.com> - 3.3
Improvements to build and release-procedure documentation. Make
sirf=no build work again. Main reason for this release is to make
chrpath a mandatory build depedency and explain why in the build
chrpath a mandatory build dependency and explain why in the build
documentation.

* Wed Oct 25 2011 Eric S. Raymond <esr@snark.thyrsus.com> - 3.2
@@ -286,7 +300,7 @@

* Sun Mar 12 2006 Eric S. Raymond <esr@snark.thyrsus.com> - 2.32-1
Cleanup of the xgps layout, and minor memory-leak fixes for xgps. Fix
to cope with Antares uBlox by Andreas Stricker. Minor fix to libgps
to cope with Antares u-blox by Andreas Stricker. Minor fix to libgps
cgpxlogger. Merge cgpxlogger and gpxlogger documentation onto
the xgps(1) manual page and rename it gps(1).



+ 473
- 327
SConstruct
File diff suppressed because it is too large
View File


+ 48
- 23
TODO View File

@@ -16,6 +16,44 @@ See the GPSD bug tracker on the project website, but don't be
surprised if it's empty or very sparse. Our rate of new defects per
month is quite low.

*** Client bugs

**** In gpsmon's PPS Offset field

resently PPS Offset is displayed in direct mode for NMEA, SiRF, and
UBX devices. Others should probably do likewise, notably the
Motorola Oncore and Garmin drivers.

**** gpsmon driver switching and blocking on error

Hal Murray reports:

If I run .gpsmon /dev/ttyUSB0

It starts up in NMEA0183 mode as I expect.
"i" switches to SiRF, again, as I expect.

"n" switches the display to NMEA layout, but the header still says SiRF.
Another "n" now says: Device type has no mode switcher.
At this point, "i" doesn't do anything. (no pause either)

The second 'n' is losing information that it shouldn't.

If I start over and feed it an "f", it starts blinking "Unknown command "f"
The logging and display update stops. After I type another character, it
clears the blinking error message and stars logging/updating again.

Display update should not stop while this is going on.

*** Speed, mode and rate-changes in client-mode gpsmon.

Are not implemented. In theory they could be.

*** Speed, mode and rate-changes in client-mode gpsctl.

Baud rate and mode changes work in direct mode but are not
reliable in client mode.

*** Dispatcher/network issues

**** Reading AISHub data via UDP confuses xgps with short writes
@@ -26,17 +64,17 @@ packet aggregation issue as it doesn't happen with test logs.

*** Driver issues

**** gpsctl -b should work on UBX, but does not.

Presently this means there's no way to kick a UBX into returning
binary data. Chris Kuethe is supposed to fix this one.

**** RTCM3 analysis is incomplete

We can presently decode RTCM3 messages of type 1004, 1005, 1006, 1008, 1012,
1013, and 1029. This is not the complete set. We need more test data with
different types in them, and a copy of the RTCM3 standard at latest revision
(all we have is revision 3).
We can presently decode RTCM3 messages of type 1001-1014, 1029, and
1033. This is not the complete set. We need more test data with
different types in them, and a copy of the RTCM3 standard at latest
revision (all we have is revision 3).

The support for unpacking RTCM3 sentences in the client library is
limited to 1001, 1002, 1007, 1008, 1009, 1010, 1014, and 1033. There
are some design issues with the baby JSON parser that are going to
make extending this set difficult.

**** Reporting code for specialized Type 6 and 8 AIS messages is incomplete.

@@ -49,19 +87,6 @@ message 6 and 8 subtypes - specifically, 6/23, 8/21, 8/22, 8/24, and

We'd need machinery to shift a byte array 30 bits left...

**** JSON passthrough for AIS

Roy Barkas wants to be able to pass custom JSON up to GPSD in an
armored AIS sentence, so all his clients will get it. See
http://lists.nongnu.org/archive/html/gpsd-dev/2013-01/msg00022.html
for the full proposal.

** Ports

*** Windows port

Partially complete. David Ludlow <dave@adsllc.com> is working on it.

** To do:

*** Make subframe reports available in the C API.
@@ -83,7 +108,7 @@ shouldn't be difficult.

*** Enable flocktest on the Debian server farm

Debian server farm boxes have a screwy chrooted envorinment setup.
Debian server farm boxes have a screwy chrooted environment setup.
flocktest needs to be modified to deal with it.

*** Finish gpssim


+ 2
- 0
Tachometer.c View File

@@ -579,11 +579,13 @@ static void Destroy(Widget w)

/* Exported Procedures */

// cppcheck-suppress unusedFunction
int TachometerGetValue(Widget w)
{
return (((TachometerWidget) w)->tachometer.value);
}

// cppcheck-suppress unusedFunction
int TachometerSetValue(Widget w, int i)
{
int old;


+ 106
- 22
ais_json.c View File

@@ -122,7 +122,7 @@ int json_ais_read(const char *buf,
&ais->type5.minute);
}
} else if (strstr(buf, "\"type\":6,") != NULL) {
bool imo = false;
bool structured = false;
if (strstr(buf, "\"dac\":1,") != NULL) {
if (strstr(buf, "\"fid\":12,") != NULL) {
status = json_read_object(buf, json_ais6_fid12, endptr);
@@ -148,15 +148,15 @@ int json_ais_read(const char *buf,
&ais->type6.dac1fid12.nhour,
&ais->type6.dac1fid12.nminute);
}
imo = true;
structured = true;
}
else if (strstr(buf, "\"fid\":15,") != NULL) {
status = json_read_object(buf, json_ais6_fid15, endptr);
imo = true;
structured = true;
}
else if (strstr(buf, "\"fid\":16,") != NULL) {
status = json_read_object(buf, json_ais6_fid16, endptr);
imo = true;
structured = true;
}
else if (strstr(buf, "\"fid\":18,") != NULL) {
status = json_read_object(buf, json_ais6_fid18, endptr);
@@ -171,7 +171,7 @@ int json_ais_read(const char *buf,
&ais->type6.dac1fid18.hour,
&ais->type6.dac1fid18.minute);
}
imo = true;
structured = true;
}
else if (strstr(buf, "\"fid\":20,") != NULL) {
status = json_read_object(buf, json_ais6_fid20, endptr);
@@ -187,11 +187,11 @@ int json_ais_read(const char *buf,
&ais->type6.dac1fid20.hour,
&ais->type6.dac1fid20.minute);
}
imo = true;
structured = true;
}
else if (strstr(buf, "\"fid\":25,") != NULL) {
status = json_read_object(buf, json_ais6_fid25, endptr);
imo = true;
structured = true;
}
else if (strstr(buf, "\"fid\":28,") != NULL) {
status = json_read_object(buf, json_ais6_fid28, endptr);
@@ -207,24 +207,62 @@ int json_ais_read(const char *buf,
&ais->type6.dac1fid28.hour,
&ais->type6.dac1fid28.minute);
}
imo = true;
structured = true;
}
else if (strstr(buf, "\"fid\":30,") != NULL) {
status = json_read_object(buf, json_ais6_fid30, endptr);
imo = true;
structured = true;
}
else if (strstr(buf, "\"fid\":32,") != NULL || strstr(buf, "\"fid\":14,") != NULL) {
status = json_read_object(buf, json_ais6_fid32, endptr);
imo = true;
structured = true;
}
}
else if (strstr(buf, "\"dac\":235,") != NULL || strstr(buf, "\"dac\":250,") != NULL) {
if (strstr(buf, "\"fid\":10,") != NULL) {
status = json_read_object(buf, json_ais6_fid10, endptr);
imo = true;
structured = true;
}
}
if (!imo) {
else if (strstr(buf, "\"dac\":200,") != NULL) {
if (strstr(buf, "\"fid\":21,") != NULL) {
status = json_read_object(buf, json_ais6_fid21, endptr);
structured = true;
if (status == 0) {
ais->type6.dac200fid21.month = AIS_MONTH_NOT_AVAILABLE;
ais->type6.dac200fid21.day = AIS_DAY_NOT_AVAILABLE;
ais->type6.dac200fid21.hour = AIS_HOUR_NOT_AVAILABLE;
ais->type6.dac200fid21.minute = AIS_MINUTE_NOT_AVAILABLE;
// cppcheck-suppress uninitvar
(void)sscanf(eta, "%02u-%02uT%02u:%02u",
&ais->type6.dac200fid21.month,
&ais->type6.dac200fid21.day,
&ais->type6.dac200fid21.hour,
&ais->type6.dac200fid21.minute);
}
}
else if (strstr(buf, "\"fid\":22,") != NULL) {
status = json_read_object(buf, json_ais6_fid22, endptr);
structured = true;
if (status == 0) {
ais->type6.dac200fid22.month = AIS_MONTH_NOT_AVAILABLE;
ais->type6.dac200fid22.day = AIS_DAY_NOT_AVAILABLE;
ais->type6.dac200fid22.hour = AIS_HOUR_NOT_AVAILABLE;
ais->type6.dac200fid22.minute = AIS_MINUTE_NOT_AVAILABLE;
// cppcheck-suppress uninitvar
(void)sscanf(rta, "%02u-%02uT%02u:%02u",
&ais->type6.dac200fid22.month,
&ais->type6.dac200fid22.day,
&ais->type6.dac200fid22.hour,
&ais->type6.dac200fid22.minute);
}
}
else if (strstr(buf, "\"fid\":55,") != NULL) {
status = json_read_object(buf, json_ais6_fid55, endptr);
structured = true;
}
}
if (!structured) {
status = json_read_object(buf, json_ais6, endptr);
if (status == 0)
lenhex_unpack(data, &ais->type6.bitcount,
@@ -234,7 +272,7 @@ int json_ais_read(const char *buf,
|| strstr(buf, "\"type\":13,") != NULL) {
status = json_read_object(buf, json_ais7, endptr);
} else if (strstr(buf, "\"type\":8,") != NULL) {
bool imo = false;
bool structured = false;
if (strstr(buf, "\"dac\":1,") != NULL) {
if (strstr(buf, "\"fid\":11,") != NULL) {
status = json_read_object(buf, json_ais8_fid11, endptr);
@@ -248,7 +286,7 @@ int json_ais_read(const char *buf,
&ais->type8.dac1fid11.hour,
&ais->type8.dac1fid11.minute);
}
imo = true;
structured = true;
}
else if (strstr(buf, "\"fid\":13,") != NULL) {
status = json_read_object(buf, json_ais8_fid13, endptr);
@@ -274,19 +312,55 @@ int json_ais_read(const char *buf,
&ais->type8.dac1fid13.thour,
&ais->type8.dac1fid13.tminute);
}
imo = true;
structured = true;
}
else if (strstr(buf, "\"fid\":15,") != NULL) {
status = json_read_object(buf, json_ais8_fid15, endptr);
imo = true;
structured = true;
}
else if (strstr(buf, "\"fid\":16,") != NULL) {
status = json_read_object(buf, json_ais8_fid16, endptr);
structured = true;
}
else if (strstr(buf, "\"fid\":17,") != NULL) {
status = json_read_object(buf, json_ais8_fid17, endptr);
imo = true;
structured = true;
}
else if (strstr(buf, "\"fid\":19,") != NULL) {
status = json_read_object(buf, json_ais8_fid19, endptr);
imo = true;
structured = true;
}
else if (strstr(buf, "\"fid\":23,") != NULL) {
status = json_read_object(buf, json_ais8_fid23, endptr);
ais->type8.dac200fid23.start_year = AIS_YEAR_NOT_AVAILABLE;
ais->type8.dac200fid23.start_month = AIS_MONTH_NOT_AVAILABLE;
ais->type8.dac200fid23.start_day = AIS_DAY_NOT_AVAILABLE;
ais->type8.dac200fid23.start_hour = AIS_HOUR_NOT_AVAILABLE;
ais->type8.dac200fid23.start_minute = AIS_MINUTE_NOT_AVAILABLE;
ais->type8.dac200fid23.end_year = AIS_YEAR_NOT_AVAILABLE;
ais->type8.dac200fid23.end_month = AIS_MONTH_NOT_AVAILABLE;
ais->type8.dac200fid23.end_day = AIS_DAY_NOT_AVAILABLE;
ais->type8.dac200fid23.end_hour = AIS_HOUR_NOT_AVAILABLE;
ais->type8.dac200fid23.end_minute = AIS_MINUTE_NOT_AVAILABLE;
// cppcheck-suppress uninitvar
(void)sscanf(start, "%09u-%02u-%02uT%02u:%02u",
&ais->type8.dac200fid23.start_year,
&ais->type8.dac200fid23.start_month,
&ais->type8.dac200fid23.start_day,
&ais->type8.dac200fid23.start_hour,
&ais->type8.dac200fid23.start_minute);
// cppcheck-suppress uninitvar
(void)sscanf(end, "%09u-%02u-%02uT%02u:%02u",
&ais->type8.dac200fid23.end_year,
&ais->type8.dac200fid23.end_month,
&ais->type8.dac200fid23.end_day,
&ais->type8.dac200fid23.end_hour,
&ais->type8.dac200fid23.end_minute);
structured = true;
}
else if (strstr(buf, "\"fid\":24,") != NULL) {
status = json_read_object(buf, json_ais8_fid24, endptr);
structured = true;
}
else if (strstr(buf, "\"fid\":27,") != NULL) {
status = json_read_object(buf, json_ais8_fid27, endptr);
@@ -302,11 +376,11 @@ int json_ais_read(const char *buf,
&ais->type8.dac1fid27.hour,
&ais->type8.dac1fid27.minute);
}
imo = true;
structured = true;
}
else if (strstr(buf, "\"fid\":29,") != NULL) {
status = json_read_object(buf, json_ais8_fid29, endptr);
imo = true;
structured = true;
}
else if (strstr(buf, "\"fid\":31,") != NULL) {
status = json_read_object(buf, json_ais8_fid31, endptr);
@@ -320,10 +394,20 @@ int json_ais_read(const char *buf,
&ais->type8.dac1fid31.hour,
&ais->type8.dac1fid31.minute);
}
imo = true;
structured = true;
}
}
else if (strstr(buf, "\"dac\":200,") != NULL) {
if (strstr(buf, "\"fid\":10,") != NULL) {
status = json_read_object(buf, json_ais8_fid10, endptr);
structured = true;
}
if (strstr(buf, "\"fid\":40,") != NULL) {
status = json_read_object(buf, json_ais8_fid40, endptr);
structured = true;
}
}
if (!imo) {
if (!structured) {
status = json_read_object(buf, json_ais8, endptr);
if (status == 0)
lenhex_unpack(data, &ais->type8.bitcount,


+ 209
- 24
ais_json.i View File

@@ -10,6 +10,7 @@
AIS_HEADER
{"status", t_uinteger, .addr.uinteger = &ais->type1.status,
.dflt.uinteger = 0},
{"status_text", t_ignore},
{"turn", t_integer, .addr.integer = &ais->type1.turn,
.dflt.integer = AIS_TURN_NOT_AVAILABLE},
{"speed", t_uinteger, .addr.uinteger = &ais->type1.speed,
@@ -48,6 +49,7 @@
.dflt.integer = AIS_LAT_NOT_AVAILABLE},
{"epfd", t_uinteger, .addr.uinteger = &ais->type4.epfd,
.dflt.uinteger = 0},
{"epfd_text", t_ignore},
{"raim", t_boolean, .addr.boolean = &ais->type4.raim,
.dflt.boolean = false},
{"radio", t_uinteger, .addr.uinteger = &ais->type4.radio,
@@ -68,6 +70,7 @@
.len = sizeof(ais->type5.shipname)},
{"shiptype", t_uinteger, .addr.uinteger = &ais->type5.shiptype,
.dflt.uinteger = 0},
{"shiptype_text", t_ignore},
{"to_bow", t_uinteger, .addr.uinteger = &ais->type5.to_bow,
.dflt.uinteger = 0},
{"to_stern", t_uinteger, .addr.uinteger = &ais->type5.to_stern,
@@ -78,6 +81,7 @@
.dflt.uinteger = 0},
{"epfd", t_uinteger, .addr.uinteger = &ais->type5.epfd,
.dflt.uinteger = 0},
{"epfd_text", t_ignore},
{"eta", t_string, .addr.string = eta,
.len = sizeof(eta)},
{"draught", t_uinteger, .addr.uinteger = &ais->type5.draught,
@@ -109,8 +113,10 @@
.dflt.uinteger = 0},
{"racon", t_uinteger, .addr.uinteger = &ais->type6.dac235fid10.racon,
.dflt.uinteger = 0},
{"racon_text", t_ignore},
{"light", t_uinteger, .addr.uinteger = &ais->type6.dac235fid10.light,
.dflt.uinteger = 0},
{"light_text", t_ignore},
{"alarm", t_boolean, .addr.boolean = &ais->type6.dac235fid10.alarm,
.dflt.boolean = false},
{"stat_ext", t_uinteger, .addr.uinteger = &ais->type6.dac235fid10.stat_ext,
@@ -161,26 +167,6 @@
{NULL}
};

const struct json_attr_t json_ais6_fid25_cargos_subtype[] = {
{"code", t_uinteger,STRUCTOBJECT(struct cargo_t, code),
.dflt.uinteger = 0},
{"subtype", t_uinteger,STRUCTOBJECT(struct cargo_t, subtype),
.dflt.uinteger = 0},
{NULL}
};
/*@-type@*//* STRUCTARRAY confuses splint */
const struct json_attr_t json_ais6_fid25[] = {
AIS_HEADER
AIS_TYPE6
{"unit", t_uinteger, .addr.uinteger = &ais->type6.dac1fid25.unit,
.dflt.uinteger = 0},
{"amount", t_uinteger, .addr.uinteger = &ais->type6.dac1fid25.amount,
.dflt.uinteger = 0},
{"cargos", t_array, STRUCTARRAY(ais->type6.dac1fid25.cargos, json_ais6_fid25_cargos_subtype, &ais->type6.dac1fid25.ncargos)},
{NULL}
};
/*@+type@*/

char arrival[JSON_VAL_MAX+1];
const struct json_attr_t json_ais6_fid18[] = {
AIS_HEADER
@@ -212,6 +198,7 @@
.dflt.uinteger = 0},
{"position", t_uinteger, .addr.uinteger = &ais->type6.dac1fid20.position,
.dflt.uinteger = 0},
{"position_text", t_ignore},
{"arrival", t_string, .addr.string = arrival,
.len = sizeof(arrival)},
{"availability", t_uinteger, .addr.uinteger = &ais->type6.dac1fid20.availability,
@@ -277,6 +264,69 @@
{NULL}
};

const struct json_attr_t json_ais6_fid21[] = {
AIS_HEADER
AIS_TYPE6
{"country", t_string, .addr.string = ais->type6.dac200fid21.country,
.len = sizeof(ais->type6.dac200fid21.country)},
{"locode", t_string, .addr.string = ais->type6.dac200fid21.locode,
.len = sizeof(ais->type6.dac200fid21.locode)},
{"section", t_string, .addr.string = ais->type6.dac200fid21.section,
.len = sizeof(ais->type6.dac200fid21.section)},
{"terminal", t_string, .addr.string = ais->type6.dac200fid21.terminal,
.len = sizeof(ais->type6.dac200fid21.terminal)},
{"hectometre", t_string, .addr.string = ais->type6.dac200fid21.hectometre,
.len = sizeof(ais->type6.dac200fid21.hectometre)},
{"eta", t_string, .addr.string = eta,
.len = sizeof(eta)},
{"tugs", t_uinteger, .addr.uinteger = &ais->type6.dac200fid21.tugs,
.dflt.uinteger = 0},
{"airdraught", t_uinteger, .addr.uinteger = &ais->type6.dac200fid21.airdraught,
.dflt.uinteger = 0},
{NULL}
};

char rta[JSON_VAL_MAX+1];
const struct json_attr_t json_ais6_fid22[] = {
AIS_HEADER
AIS_TYPE6
{"country", t_string, .addr.string = ais->type6.dac200fid22.country,
.len = sizeof(ais->type6.dac200fid22.country)},
{"locode", t_string, .addr.string = ais->type6.dac200fid22.locode,
.len = sizeof(ais->type6.dac200fid22.locode)},
{"section", t_string, .addr.string = ais->type6.dac200fid22.section,
.len = sizeof(ais->type6.dac200fid22.section)},
{"terminal", t_string, .addr.string = ais->type6.dac200fid22.terminal,
.len = sizeof(ais->type6.dac200fid22.terminal)},
{"hectometre", t_string, .addr.string = ais->type6.dac200fid22.hectometre,
.len = sizeof(ais->type6.dac200fid22.hectometre)},
{"rta", t_string, .addr.string = rta,
.len = sizeof(rta)},
{"status", t_uinteger, .addr.uinteger = &ais->type6.dac200fid22.status,
.dflt.uinteger = DAC200FID22_STATUS_NOT_AVAILABLE},
{NULL}
};

const struct json_attr_t json_ais6_fid25_cargos_subtype[] = {
{"code", t_uinteger,STRUCTOBJECT(struct cargo_t, code),
.dflt.uinteger = 0},
{"subtype", t_uinteger,STRUCTOBJECT(struct cargo_t, subtype),
.dflt.uinteger = 0},
{NULL}
};
/*@-type@*//* STRUCTARRAY confuses splint */
const struct json_attr_t json_ais6_fid25[] = {
AIS_HEADER
AIS_TYPE6
{"unit", t_uinteger, .addr.uinteger = &ais->type6.dac1fid25.unit,
.dflt.uinteger = 0},
{"amount", t_uinteger, .addr.uinteger = &ais->type6.dac1fid25.amount,
.dflt.uinteger = 0},
{"cargos", t_array, STRUCTARRAY(ais->type6.dac1fid25.cargos, json_ais6_fid25_cargos_subtype, &ais->type6.dac1fid25.ncargos)},
{NULL}
};
/*@+type@*/

char start[JSON_VAL_MAX+1];
const struct json_attr_t json_ais6_fid28_waypoints_subtype[] = {
{"lon", t_integer, STRUCTOBJECT(struct waypoint_t, lon),
@@ -295,6 +345,7 @@
.dflt.uinteger = 0},
{"rtype", t_uinteger, .addr.uinteger = &ais->type6.dac1fid28.rtype,
.dflt.uinteger = 0},
{"rtype_text", t_ignore},
{"start", t_string, .addr.string = start,
.len = sizeof(start)},
{"duration", t_uinteger, .addr.uinteger = &ais->type6.dac1fid28.duration,
@@ -346,6 +397,18 @@
};
/*@+type@*/

const struct json_attr_t json_ais6_fid55[] = {
AIS_HEADER
AIS_TYPE6
{"crew", t_uinteger, .addr.uinteger = &ais->type6.dac200fid55.crew,
.dflt.uinteger = DAC200FID55_COUNT_NOT_AVAILABLE},
{"passengers", t_uinteger, .addr.uinteger = &ais->type6.dac200fid55.passengers,
.dflt.uinteger = DAC200FID55_COUNT_NOT_AVAILABLE},
{"personnel", t_uinteger, .addr.uinteger = &ais->type6.dac200fid55.personnel,
.dflt.uinteger = DAC200FID55_COUNT_NOT_AVAILABLE},
{NULL}
};

const struct json_attr_t json_ais7[] = {
AIS_HEADER
{"mmsi1", t_uinteger, .addr.uinteger = &ais->type7.mmsi1,
@@ -367,6 +430,35 @@
{NULL}
};

const struct json_attr_t json_ais8_fid10[] = {
AIS_HEADER
AIS_TYPE8
{"vin", t_string, .addr.string = ais->type8.dac200fid10.vin,
.len = sizeof(ais->type8.dac200fid10.vin)},
{"length", t_uinteger, .addr.uinteger = &ais->type8.dac200fid10.length,
.dflt.uinteger = 0},
{"beam", t_uinteger, .addr.uinteger = &ais->type8.dac200fid10.beam,
.dflt.uinteger = 0},
{"type", t_uinteger, .addr.uinteger = &ais->type8.dac200fid10.type,
.dflt.uinteger = 0},
{"type_text", t_ignore},
{"hazard", t_uinteger, .addr.uinteger = &ais->type8.dac200fid10.hazard,
.dflt.uinteger = 0},
{"hazard_text", t_ignore},
{"draught", t_uinteger, .addr.uinteger = &ais->type8.dac200fid10.draught,
.dflt.uinteger = 0},
{"loaded", t_uinteger, .addr.uinteger = &ais->type8.dac200fid10.loaded,
.dflt.uinteger = 0},
{"loaded_text", t_ignore},
{"speed_q", t_boolean, .addr.boolean = &ais->type8.dac200fid10.speed_q,
.dflt.boolean = false},
{"course_q", t_boolean, .addr.boolean = &ais->type8.dac200fid10.course_q,
.dflt.boolean = false},
{"heading_q", t_boolean, .addr.boolean = &ais->type8.dac200fid10.heading_q,
.dflt.boolean = false},
{NULL}
};

const struct json_attr_t json_ais8_fid11[] = {
AIS_HEADER
AIS_TYPE8
@@ -434,22 +526,26 @@
.dflt.uinteger = DAC1FID11_WATERTEMP_NOT_AVAILABLE},
{"preciptype", t_uinteger, .addr.uinteger = &ais->type8.dac1fid11.preciptype,
.dflt.uinteger = DAC1FID11_PRECIPTYPE_NOT_AVAILABLE},
{"preciptype_text", t_ignore},
{"salinity", t_uinteger, .addr.uinteger = &ais->type8.dac1fid11.salinity,
.dflt.uinteger = DAC1FID11_SALINITY_NOT_AVAILABLE},
{"ice", t_uinteger, .addr.uinteger = &ais->type8.dac1fid11.ice,
.dflt.uinteger = DAC1FID11_ICE_NOT_AVAILABLE},
{"ice_text", t_ignore},
{NULL}
};

char closefrom[JSON_VAL_MAX+1];
char closeto[JSON_VAL_MAX+1];
const struct json_attr_t json_ais8_fid13[] = {
AIS_HEADER
AIS_TYPE8
{"reason", t_string, .addr.string = ais->type8.dac1fid13.reason,
.len = sizeof(ais->type8.dac1fid13.reason)},
{"closefrom", t_string, .addr.string = ais->type8.dac1fid13.closefrom,
.len = sizeof(ais->type8.dac1fid13.closefrom)},
{"closeto", t_string, .addr.string = ais->type8.dac1fid13.closeto,
.len = sizeof(ais->type8.dac1fid13.closeto)},
{"closefrom", t_string, .addr.string = closefrom,
.len = sizeof(closefrom)},
{"closeto", t_string, .addr.string = closeto,
.len = sizeof(closeto)},
{"radius", t_uinteger, .addr.uinteger = &ais->type8.dac1fid13.radius,
.dflt.uinteger = AIS_DAC1FID13_RADIUS_NOT_AVAILABLE},
{"extunit", t_uinteger, .addr.uinteger = &ais->type8.dac1fid13.extunit,
@@ -481,6 +577,14 @@
{NULL}
};

const struct json_attr_t json_ais8_fid16[] = {
AIS_HEADER
AIS_TYPE8
{"persons", t_uinteger, .addr.uinteger = &ais->type8.dac1fid16.persons,
.dflt.uinteger = 0},
{NULL}
};

const struct json_attr_t json_ais8_fid17_targets_subtype[] = {
{"idtype", t_uinteger,STRUCTOBJECT(struct target_t, idtype),
.dflt.uinteger = DAC1FID17_IDTYPE_OTHER},
@@ -528,15 +632,67 @@
.dflt.uinteger = 0},
{"signal", t_uinteger, .addr.uinteger = &ais->type8.dac1fid19.signal,
.dflt.uinteger = 0},
{"signal_text", t_ignore},
{"hour", t_uinteger, .addr.uinteger = &ais->type8.dac1fid19.hour,
.dflt.uinteger = AIS_HOUR_NOT_AVAILABLE},
{"minute", t_uinteger, .addr.uinteger = &ais->type8.dac1fid19.minute,
.dflt.uinteger = AIS_MINUTE_NOT_AVAILABLE},
{"nextsignal", t_uinteger, .addr.uinteger = &ais->type8.dac1fid19.nextsignal,
.dflt.uinteger = 0},
{"nextsignal_type", t_ignore},
{NULL}
};

char end[JSON_VAL_MAX+1];
const struct json_attr_t json_ais8_fid23[] = {
AIS_HEADER
AIS_TYPE8
{"start", t_string, .addr.string = start,
.len = sizeof(start)},
{"end", t_string, .addr.string = end,
.len = sizeof(end)},
{"start_lon", t_integer, .addr.integer = &ais->type8.dac200fid23.start_lon,
.dflt.integer = AIS_LON4_NOT_AVAILABLE},
{"start_lat", t_integer, .addr.integer = &ais->type8.dac200fid23.start_lat,
.dflt.integer = AIS_LAT4_NOT_AVAILABLE},
{"end_lon", t_integer, .addr.integer = &ais->type8.dac200fid23.end_lon,
.dflt.integer = AIS_LON4_NOT_AVAILABLE},
{"end_lat", t_integer, .addr.integer = &ais->type8.dac200fid23.end_lat,
.dflt.integer = AIS_LAT4_NOT_AVAILABLE},
{"type", t_uinteger, .addr.uinteger = &ais->type8.dac200fid23.type,
.dflt.uinteger = DAC200FID23_TYPE_UNKNOWN},
{"type_text", t_ignore},
{"min", t_integer, .addr.integer = &ais->type8.dac200fid23.min,
.dflt.integer = DAC200FID23_MIN_UNKNOWN},
{"max", t_integer, .addr.integer = &ais->type8.dac200fid23.max,
.dflt.integer = DAC200FID23_MAX_UNKNOWN},
{"intensity", t_uinteger, .addr.uinteger = &ais->type8.dac200fid23.intensity,
.dflt.uinteger = DAC200FID23_CLASS_UNKNOWN},
{"intensity_text", t_ignore},
{"wind", t_uinteger, .addr.uinteger = &ais->type8.dac200fid23.wind,
.dflt.uinteger = DAC200FID23_WIND_UNKNOWN},
{"wind_text", t_ignore},
{NULL}
};

const struct json_attr_t json_ais8_fid24_gauges_subtype[] = {
{"id", t_uinteger,STRUCTOBJECT(struct gauge_t, id),
.dflt.uinteger = DAC200FID24_GAUGE_ID_UNKNOWN},
{"level", t_integer, STRUCTOBJECT(struct gauge_t, level),
.dflt.integer = DAC200FID24_GAUGE_LEVEL_UNKNOWN},
{NULL}
};
/*@-type@*//* STRUCTARRAY confuses splint */
const struct json_attr_t json_ais8_fid24[] = {
AIS_HEADER
AIS_TYPE8
{"country", t_string, .addr.string = ais->type8.dac200fid24.country,
.len = sizeof(ais->type8.dac200fid24.country)},
{"gauges", t_array, STRUCTARRAY(ais->type8.dac200fid24.gauges, json_ais8_fid24_gauges_subtype, &ais->type8.dac200fid24.ngauges)},
{NULL}
};
/*@+type@*/

const struct json_attr_t json_ais8_fid27_waypoints_subtype[] = {
{"lon", t_integer, STRUCTOBJECT(struct waypoint_t, lon),
.dflt.integer = AIS_LON4_NOT_AVAILABLE},
@@ -554,6 +710,7 @@
.dflt.uinteger = 0},
{"rtype", t_uinteger, .addr.uinteger = &ais->type8.dac1fid27.rtype,
.dflt.uinteger = 0},
{"rtype_text", t_ignore},
{"start", t_string, .addr.string = start,
.len = sizeof(start)},
{"duration", t_uinteger, .addr.uinteger = &ais->type8.dac1fid27.duration,
@@ -644,6 +801,7 @@
.dflt.integer = DAC1FID31_WATERTEMP_NOT_AVAILABLE},
{"preciptype", t_uinteger, .addr.uinteger = &ais->type8.dac1fid31.preciptype,
.dflt.uinteger = DAC1FID31_PRECIPTYPE_NOT_AVAILABLE},
{"preciptype_text", t_ignore},
{"salinity", t_uinteger, .addr.uinteger = &ais->type8.dac1fid31.salinity,
.dflt.uinteger = DAC1FID31_SALINITY_NOT_AVAILABLE},
{"ice", t_uinteger, .addr.uinteger = &ais->type8.dac1fid31.ice,
@@ -651,6 +809,22 @@
{NULL}
};

const struct json_attr_t json_ais8_fid40[] = {
AIS_HEADER
AIS_TYPE8
{"form", t_uinteger, .addr.uinteger = &ais->type8.dac200fid40.form,
.dflt.uinteger = DAC200FID40_FORM_UNKNOWN},
{"facing", t_uinteger, .addr.uinteger = &ais->type8.dac200fid40.facing,
.dflt.uinteger = DAC200FID40_FACING_UNKNOWN},
{"direction", t_uinteger, .addr.uinteger = &ais->type8.dac200fid40.direction,
.dflt.uinteger = DAC200FID40_DIRECTION_UNKNOWN},
{"direction_text", t_ignore},
{"status", t_uinteger, .addr.uinteger = &ais->type8.dac200fid40.status,
.dflt.uinteger = DAC200FID40_STATUS_UNKNOWN},
{"status_text", t_ignore},
{NULL}
};

const struct json_attr_t json_ais9[] = {
AIS_HEADER
{"alt", t_uinteger, .addr.uinteger = &ais->type9.alt,
@@ -815,6 +989,7 @@
.len = sizeof(ais->type19.shipname)},
{"shiptype", t_uinteger, .addr.uinteger = &ais->type19.shiptype,
.dflt.uinteger = 0},
{"shiptype_text", t_ignore},
{"to_bow", t_uinteger, .addr.uinteger = &ais->type19.to_bow,
.dflt.uinteger = 0},
{"to_stern", t_uinteger, .addr.uinteger = &ais->type19.to_stern,
@@ -825,6 +1000,7 @@
.dflt.uinteger = 0},
{"epfd", t_uinteger, .addr.uinteger = &ais->type19.epfd,
.dflt.uinteger = 0},
{"epfd_text", t_ignore},
{"raim", t_boolean, .addr.boolean = &ais->type19.raim,
.dflt.boolean = false},
{"dte", t_uinteger, .addr.uinteger = &ais->type19.dte,
@@ -875,6 +1051,7 @@
AIS_HEADER
{"aid_type", t_uinteger, .addr.uinteger = &ais->type21.aid_type,
.dflt.uinteger = 0},
{"aid_type_text", t_ignore},
{"name", t_string, .addr.string = ais->type21.name,
.len = sizeof(ais->type21.name)},
{"accuracy", t_boolean, .addr.boolean = &ais->type21.accuracy,
@@ -893,6 +1070,7 @@
.dflt.uinteger = 0},
{"epfd", t_uinteger, .addr.uinteger = &ais->type21.epfd,
.dflt.uinteger = 0},
{"epfd_text", t_ignore},
{"second", t_uinteger, .addr.uinteger = &ais->type21.second,
.dflt.uinteger = 0},
{"regional", t_uinteger, .addr.uinteger = &ais->type21.regional,
@@ -951,8 +1129,10 @@
.dflt.integer = AIS_GNS_LAT_NOT_AVAILABLE},
{"stationtype", t_uinteger, .addr.uinteger = &ais->type23.stationtype,
.dflt.uinteger = 0},
{"stationtype_text", t_ignore},
{"shiptype", t_uinteger, .addr.uinteger = &ais->type23.shiptype,
.dflt.uinteger = 0},
{"shiptype_text", t_ignore},
{"txrx", t_uinteger, .addr.uinteger = &ais->type23.txrx,
.dflt.uinteger = 0},
{"interval", t_uinteger, .addr.uinteger = &ais->type23.interval,
@@ -968,8 +1148,13 @@
.len = sizeof(ais->type24.shipname)},
{"shiptype", t_uinteger, .addr.uinteger = &ais->type24.shiptype,
.dflt.uinteger = 0},
{"shiptype_text", t_ignore},
{"vendorid", t_string, .addr.string = ais->type24.vendorid,
.len = sizeof(ais->type24.vendorid)},
{"model", t_uinteger, .addr.uinteger = &ais->type24.model,
.dflt.uinteger = 0},
{"serial", t_uinteger, .addr.uinteger = &ais->type24.serial,
.dflt.uinteger = 0},
{"callsign", t_string, .addr.string = ais->type24.callsign,
.len = sizeof(ais->type24.callsign)},
{"mothership_mmsi",t_uinteger, .addr.uinteger = &ais->type24.mothership_mmsi,


+ 14
- 7
bits.c View File

@@ -115,19 +115,28 @@ double getbed64(const char *buf, int off)
return l_d.d;
}

/*@-shiftimplementation@*/
void putbef32(char *buf, int off, float val)
{
union int_float i_f;

i_f.f = val;
/* this would be a putbe32 call if not for a signedness issue */
buf[off] = (char)(((i_f.i) >> 16) >> 8);
/*@-shiftimplementation +ignoresigns@*/
putbe32(buf, off, i_f.i);
/*@+shiftimplementation -ignoresigns@*/
}
/*@+shiftimplementation@*/

#ifdef __UNUSED__
// cppcheck-suppress unusedFunction
void putbed64(char *buf, int off, double val)
{
union long_double l_d;

l_d.d = val;
/*@-shiftimplementation +ignoresigns@*/
putbe32(buf, (off), (l_d.l) >> 32);
putbe32(buf, (off)+4, (l_d.l));
/*@+shiftimplementation -ignoresigns@*/
}

u_int16_t swap_u16(u_int16_t i)
/* byte-swap a 16-bit unsigned int */
{
@@ -139,7 +148,6 @@ u_int16_t swap_u16(u_int16_t i)
return (c1 << 8) + c2;
}

// cppcheck-suppress unusedFunction
u_int32_t swap_u32(u_int32_t i)
/* byte-swap a 32-bit unsigned int */
{
@@ -153,7 +161,6 @@ u_int32_t swap_u32(u_int32_t i)
return ((u_int32_t)c1 << 24) + ((u_int32_t)c2 << 16) + ((u_int32_t)c3 << 8) + c4;
}

// cppcheck-suppress unusedFunction
u_int64_t swap_u64(u_int64_t i)
/* byte-swap a 64-bit unsigned int */
{


+ 1
- 0
bits.h View File

@@ -48,6 +48,7 @@ extern double getbed64(const char *, int);
#define putbe32(buf,off,l) do {putbe16(buf, (off), (l) >> 16); putbe16(buf, (off)+2, (l));} while (0)

extern void putbef32(char *, int, float);
extern void putbed64(char *, int, double);

/* bitfield extraction */
extern uint64_t ubits(unsigned char buf[], unsigned int, unsigned int, bool);


+ 3
- 1
bsd_base64.c View File

@@ -130,7 +130,6 @@ b64_ntop(unsigned char const *src, size_t srclength, char *target,
size_t datalength = 0;
unsigned char input[3];
unsigned char output[4];
size_t i;

while (2 < srclength) {
input[0] = *src++;
@@ -157,6 +156,7 @@ b64_ntop(unsigned char const *src, size_t srclength, char *target,

/* Now we worry about padding. */
if (0 != srclength) {
size_t i;
/* Get what's left. */
input[0] = input[1] = input[2] = '\0';
for (i = 0; i < srclength; i++)
@@ -185,6 +185,7 @@ b64_ntop(unsigned char const *src, size_t srclength, char *target,
return (datalength);
}

#ifdef __UNUSED__
/*@ -matchanyintegral +type @*/

/* skips all whitespace anywhere.
@@ -311,5 +312,6 @@ int b64_pton(char const *src, unsigned char *target, size_t targsize)
}

/*@ +matchanyintegral -charint @*/
#endif /* __UNUSED__ */

#endif /* !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) */

+ 95
- 27
build.txt View File

@@ -1,7 +1,9 @@
= Building GPSD from source ==

This is a guide to building GPSD from a bare source tree. It includes
guidance on how to cross-build the package.
guidance on how to cross-build the package.

Some hints for people building binary packages are in packaging/readme.txt.

(This file is marked up in asciidoc.)

@@ -10,7 +12,7 @@ guidance on how to cross-build the package.
Under Linux, assuming you have all your build prerequisites in place,
this line will do:

scons && scons testregress && sudo scons udev-install
scons && scons check && sudo scons udev-install

If you get any errors, you need to read the detailed instructions that follow.

@@ -18,26 +20,29 @@ If you get any errors, you need to read the detailed instructions that follow.

Necessary components for any build:

|==============================================================================
|============================================================================
|C compiler | gpsd and client library are written in C
|Python | some code is generated from python scripts
|scons | for executing the build recipe
|chrpath | needed with scons for RPATH setting
|==============================================================================
|============================================================================

=== C compiler ===

C99 conformance is required in the compiler. The C code depends on one
non-C99 feature: anonymous unions. We could eliminate these, but the
cost would be source-level interface breakage if we have to move
structure members in and out of unions.
non-C99 feature (supported by GCC, clang, and pretty much any C
compiler that also speaks C++): anonymous unions. We could eliminate
these, but the cost would be source-level interface breakage if we
have to move structure members in and out of unions.

GPSD is normally built and tested with GCC. The shared-memory
interface relies on one GCCism, but the code is otherwise pretty
compiler-agnostic. It is reported that clang produces a gpsd that
passes all regression tests. If -Wmissing-field-initializers or
its non-gcc equivalent is set you will get a lot of warnings;
this is due to generated code and cannot be fixed.
GPSD is normally built and tested with GCC. If the option
-Wmissing-field-initializers or its non-gcc equivalent is set you will
get a lot of warnings; this is due to generated code and cannot be
fixed.

The shared-memory interface relies on one GCCism, but the code is
otherwise pretty compiler-agnostic. It is reported that clang
produces a gpsd that passes all regression tests.

Older versions of gcc don't recognize Wno-missing-field-initializers;
this has been reported from GCC 3.4.6. We don't recommend building
@@ -60,6 +65,13 @@ extensions. Usually these are called "python" and "python-dev". You
will know you are missing the latter if your compilation fails
because of a missing Python.h.

The xgps test client requires the following Python extensions:

|============================================================================
|gobject | GNOME object introspection library
|pygtk | Python bindings for GTK
|===========================================================================

=== Scons ===

You will need scons version 2.0.1 or later to build the code. The
@@ -111,6 +123,7 @@ various additional capabilities and extensions:
|C++ compiler | allows building libgpsmm C++ wrapper for client library
|Qt 4.53+ | allows building libQgpsmm C++ wrapper for client library
|libcap | Capabilities library, allows 1PPS support under Linux
|curses | curses screen-painting library, allows building cgps
|============================================================================

If you have libusb-1.0.0 or later, the GPSD build will autodetect
@@ -129,14 +142,19 @@ For working with DBUS, you'll need the DBUS development
headers and libraries installed. Under Debian/Ubuntu these
are the packages libdbus-1-dev and libdbus-glib-1-dev.

Under Ubuntu, the ncurses package you want is libncurses5-dev.
Depending on how your distribution packages ncurses you may
also require libtinfo5, a separate terminfo library.
Under Ubuntu, the ncurses package you want is libncurses5-dev. Under
Fedora, it's ncurses-devel. Depending on how your distribution
packages ncurses you may also require libtinfo5, a separate terminfo
library.

On some recent versions of Ubuntu (notably 11.10) there is a packaging
defect that may cause your build to blow up in SCons. It's a missing
package info file for the tinfo library. To fix this, install the file
packaging/tinfo.pc in /usr/lib/pkgconfig/tinfo.pc.
packaging/tinfo.pc in /usr/lib/pkgconfig/tinfo.pc. 13.10 fixed this.

We've seen a report that compiling on the Raspberry Pi fails with
a complaint about curses.h not being found. You need to install
Raspbian's curses development library if this happens.

For building from the source tree, or if you change the man page
source, xslt and docbook xsl style files are used to generate nroff
@@ -147,6 +165,7 @@ process:
|libxslt | xsltproc is used to build man pages from xml
|docbook-xsl | style file for xml to man translation
|xmlto | DocBook formatter program
|asciidoc | DocBook front end with lighter markup
|============================================================================

The build degrades gracefully in the absence of any of these. You should
@@ -167,7 +186,7 @@ will need some subset of the following modules:
|cdc_am | USB Communication Device Class Abstract Control Model interface
|============================================================================

These are listed in rough order of devices covered as of 2011; the
These are listed in rough order of devices covered as of 2013; the
PL23203 by itself accounts for over 70% of deployed USB mice. We
recommend building with pl2303, ftdi_sio, cypress_m8, and cp210x.

@@ -217,10 +236,10 @@ won't try building the documentation. The actual fix is to install
DocBook on your machine so there will be a local copy of the
stylesheet where xmlto can find it.

After building, please run 'scons testregress' to test the correctness
After building, please run 'scons check' to test the correctness
of the build. It is not necessary to install first, but you do need
to have "." in your $PATH to run regressions uninstalled. Python is
required for regression tests. If any of the tests fail, you probavly
required for regression tests. If any of the tests fail, you probably
have a toolchain issue. The most common such problem is issues with
strict C99 conformance in floating-point libraries.

@@ -239,6 +258,39 @@ included with the distribution. To install it, copy the file
'gpsd.php' to your HTML document directory. Then see the
post-installation instructions in INSTALL for how to configure it.

== The leapseconds cache ==

Early in your build, the recipe will try to go over the Internet to
one of several sources of current data on the leap-second offset in
order to ensure that the file leapseconds.cache is up to date. This,
in turn, is used to build a timebase.h include file.

This procedure may fail if you are building inside an intranet that
requires an authenticating web proxy. If that occurs, it will time
out with a warning and a suggestion to use the leapfetch=no build
option.

Building with leapfetch=no may, in unusual circumstances, result in
reported GPS time being off by a second or more. The circumstances
are:

1. It has been less than 20 minutes since power-up; the GPS has
not yet received the current leapsecond offset as part of the
periodic ephemeris download.

2. One or more leap-second offset increments have been issued between
when your GPSD source tree was cloned from the repository (or
leapsecond.cache was later updated) and now. Leap-second
increments, compensating for minute and unpredictable changes in
the Earth's rotation, are occasionally issued by international time
authorities.

Note that the same failure can occur with any GPSD installation. But
by refreshing leapseconds.cache you reduce the error window for
leap-second offset bumps to affect your installation so that it begins
as late as possible, at your build time rather than from when the
source tree was copied.

== Optional features ==

By giving command-line options to scons you can configure certain rarely-used
@@ -266,17 +318,29 @@ status of Qt supported platforms as of version 4.6.

== Port and toolchain testing ==

'scons testregress' will run a comprehensive regression-test suite.
You should do this, at minimum, every time you build from source
on a new machine type. GPSD does enough bit-twiddling and floating
point that it is very sensitive to toolchain problems; you'll want to
be sure those aren't going to bite you in production.
'scons check' will run a comprehensive regression-test suite. You
should do this, at minimum, every time you build from source on a new
machine type. GPSD does enough bit-twiddling and floating point that
it is very sensitive to toolchain problems; you'll want to be sure
those aren't going to bite you in production.

So the tests will run fast and be easy to do often, we make the test
framework shove data through the pty and socket layers *way* faster
than would ever occur in production. If you get regression-test
failures that aren't repeatable and look like the test framework is
sporadically failing to feed the last line or two of test loads, try
increasing the delay constants in fake.py. If you have to do this,
please report your experience to the GPSD maintainers.

For instructions on how to live-test the software, see the file INSTALL.

== Reverting to a clean state ==

The scons equivalent of 'make clean' is 'scons -c'. This will revert
your source tree to a clean state as though you had just cloned or
downloaded it.
your source tree to a clean state nearly as though you had just cloned or
downloaded it; some scons housekeeping stuff is left in place. If you
interrupted a regression test, 'distclean' will remove generated test
programs.

== Cross-building ==

@@ -351,6 +415,8 @@ When you are cross-compiling, you'll need chrpath at version 0.14 or
later for cross-architecture support. If it's not yet packaged for
your environment, see http://alioth.debian.org/projects/chrpath/

You may also find it useful to set manbuild=no.

== Autostarting the daemon ==

The preferred way to start gpsd is on-demand by a hotplug script
@@ -363,3 +429,5 @@ If you for some reason need to start gpsd unconditionally at
boot time (in particular, if you need to support RS232 devices)
there's a model init.d script under packaging/deb and a systemd
setup under systemd/.

// end

+ 11
- 4
cgps.c View File

@@ -96,6 +96,7 @@
#ifndef S_SPLINT_S
#include <unistd.h>
#endif /* S_SPLINT_S */
#include <ctype.h>

#include "gpsd_config.h"
#include "gps.h"
@@ -410,7 +411,7 @@ static void update_compass_panel(struct gps_data_t *gpsdata)
static void update_gps_panel(struct gps_data_t *gpsdata)
/* This gets called once for each new GPS sentence. */
{
int i, j, n;
int i, j;
int newstate;
char scr[128], *s;
bool usedflags[MAXCHANNELS];
@@ -444,7 +445,7 @@ static void update_gps_panel(struct gps_data_t *gpsdata)
SATELLITES_WIDTH - 3, scr);
}
} else {
n = 0;
int n = 0;
for (i = 0; i < MAX_POSSIBLE_SATS; i++) {
if (n < display_sats) {
if ((i < gpsdata->satellites_visible)
@@ -639,9 +640,14 @@ static void update_gps_panel(struct gps_data_t *gpsdata)
}

/* Be quiet if the user requests silence. */
/*@-modobserver@*/
if (!silent_flag && raw_flag && (s = (char *)gps_data(gpsdata)) != NULL) {
(void)waddstr(messages, s);
char *p;
for (p = s + strlen(s); --p > s && isspace(*p); *p = '\0')
;
(void)wprintw(messages, "%s\n", s);
}
/*@+modobserver@*/

/* Reset the status_timer if the state has changed. */
if (newstate != state) {
@@ -682,7 +688,6 @@ static void usage(char *prog)
int main(int argc, char *argv[])
{
int option;
int c;
unsigned int flags = WATCH_ENABLE;

/*@ -observertrans @*/
@@ -808,6 +813,8 @@ int main(int argc, char *argv[])

/* heart of the client */
for (;;) {
int c;

if (!gps_waiting(&gpsdata, 5000000)) {
die(GPS_TIMEOUT);
} else {


+ 11
- 0
contrib/README View File

@@ -41,3 +41,14 @@ display the satellite view properly. webgps.py can be called with the argument
"c" to run continously, with an integer duration and a unit suffix to run this
long (units allowed are "s", "m", "h" and "d", e.g. "4h"), or without argument
to create a snapshot of the current sat view.

ntpoffset generate an estimate of your GPS's offset from a peerstats
file. For instructions on how to use this script, see the GPSD Time
Service HOWTO in this distrubution.

ppscheck watches a specified serial device for changes in handshake lines
CD, RI, and CTS by running ioctl(...., TIOCMIWAIT, ...) in a loop. When it
sees a state change it emits a timestamped line of output dumping the state
of the handshake signals. It's useful for checking whether a device is
emitting 1PPS. There is troubleshooting advice in the header comment.

+ 2
- 2
contrib/binlog.c View File

@@ -16,7 +16,7 @@
void spinner(int );

int main(int argc, char **argv) {
int speed, n, l, ifd, ofd;
int speed, n, ifd, ofd;
struct termios term;
char buf[BUFSIZ];

@@ -58,7 +58,7 @@ int main(int argc, char **argv) {
tcflush(ifd, TCIOFLUSH);
n = 0;
while (1){
l = read(ifd, buf, BUFSIZ);
int l = read(ifd, buf, BUFSIZ);
if (l > 0)
assert(write(ofd, buf, l) > 0);
usleep(1000);


+ 6
- 30
contrib/binreplay.c View File

@@ -1,5 +1,7 @@
/* This file is Copyright (c)2010 by the GPSD project
* BSD terms apply: see the file COPYING in the distribution root for details.
*
* Stuff the contents of a specified file into a specified tty.
*/
#include <sys/types.h>
#include <sys/mman.h>
@@ -28,7 +30,7 @@ int main( int argc, char **argv){
struct termios term;
char *buf, tn[32];
int ifd, ofd, sfd;
int dflag = 0, c, sleeptime, len, rate = 0, speed = 0;
int dflag = 0, c, sleeptime, len, speed = 0;

while((c = getopt(argc, argv, "d:r:s:")) != -1) {
switch(c){
@@ -36,24 +38,6 @@ int main( int argc, char **argv){
dflag = 1;
strncpy(tn, optarg, sizeof(tn)-1);
break;
case 'r':
rate = atoi(optarg);
switch (rate) {
case 230400:
case 115200:
case 57600:
case 38400:
case 28800:
case 19200:
case 14400:
case 9600:
case 4800:
break;
default:
fprintf(stderr, "invalid data rate: %d\n", rate);
return 1;
}
break;
case 's':
speed = atoi(optarg);
switch (speed) {
@@ -82,16 +66,8 @@ int main( int argc, char **argv){
if (argc != 1)
usage();

if (rate > speed){
printf("data rate cannot be higher than port speed.\n");
return 1;
}

if (0 == rate && 0 != speed)
rate = speed;

if (0 == rate && 0 == speed)
rate = speed = 4800;
if (0 == speed)
speed = 4800;

printf("opening %s\n", argv[0]);
if ((ifd = open(argv[0], O_RDONLY, 0444)) == -1)
@@ -165,6 +141,6 @@ void spinner(int n){
}

void usage(void){
fprintf(stderr, "usage: binreplay [-d <device>] [-r <data_rate>] [-s <port_speed>] <file>\n");
fprintf(stderr, "usage: binreplay [-d <device>] [-s <port_speed>] <file>\n");
exit(1);
}

+ 4
- 3
contrib/motosend.c View File

@@ -166,8 +166,9 @@ char *gpsd_hexdump(char *binbuf, size_t binbuflen)
return hexbuf;
}

int gpsd_hexpack(char *src, char *dst, int len){
int i, k, l;
int gpsd_hexpack(char *src, char *dst, int len)
{
int i, l;

l = (int)(strlen(src) / 2);
if ((l < 1) || (l > len))
@@ -175,7 +176,7 @@ int gpsd_hexpack(char *src, char *dst, int len){

bzero(dst, len);
for (i = 0; i < l; i++)
if ((k = hex2bin(src+i*2)) != -1)
if (hex2bin(src+i*2) != -1)
dst[i] = (char)(k & 0xff);
else
return -1;


+ 10
- 0
contrib/ntpoffset View File

@@ -0,0 +1,10 @@
#!/bin/sh
#
# Generate an estimate of your GPS's offset from a peerstats file
# For instructions on how to use this script, see the GPSD Time
# Service HOWTO in this distrubution.
#
awk '
/127\.127\.28\.0/ { sum += $5 * 1000; cnt++; }
END { print sum / cnt; }
' </var/log/ntpstats/peerstats

+ 98
- 0
contrib/ppscheck.c View File

@@ -0,0 +1,98 @@
/*
* Watch a specified serial port for transitions that might be 1PPS.
*
* Each output line is the second and nanosecond parts of a timestamp
* followed by the names of handshake signals then asserted. Off
* transitions may generate lines with no signals aserted.
*
* If you don't see output within a second, use gpsmon or some other
* equivalent tool to check that your device has satellite lock and is
* getting fixes before giving up on the possibility of 1PPS.
*
* Also, check your cable. Cheap DB9 to DB9 cables such as those
* issued with UPSes often carry TXD/RXD/SG only, omitting handshake
* lines such as DCD. Suspect this especially if the cable jacket
* looks too skinny to hold more than three leads!
*
* This code requires only ANSI/POSIX. If it doesn't compile and run
* on your Unix there is something very wrong with your Unix.
*
* This code by ESR, Copyright (C) 2013, under BSD terms.
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifndef S_SPLINT_S
#include <unistd.h>
#endif /* S_SPLINT_S */
#include <fcntl.h> /* needed for open() and friends */
#include <sys/ioctl.h>
#include <errno.h>
#include <time.h>

struct assoc {
int mask;
char *string;
};

/*
* Possible pins for PPS: DCD, CTS, RTS, RI, DSR. Pinouts:
*
* DB9 DB25 Name Full name
* --- ---- ---- --------------------
* 3 2 TXD --> Transmit Data
* 2 3 RXD <-- Receive Data
* 7 4 RTS --> Request To Send
* 8 5 CTS <-- Clear To Send
* 6 6 DSR <-- Data Set Ready
* 4 20 DTR --> Data Terminal Ready
* 1 8 DCD <-- Data Carrier Detect
* 9 22 RI <-- Ring Indicator
* 5 7 GND Signal ground
*/
const static struct assoc hlines[] = {
{TIOCM_CD, "TIOCM_CD"},
{TIOCM_RI, "TIOCM_RI"},
{TIOCM_DSR, "TIOCM_DSR"},
{TIOCM_CTS, "TIOCM_CTS"},
};

int main(int argc, char *argv[])
{
struct timespec ts;
int fd = open(argv[1], O_RDONLY);

if (fd == -1) {
(void)fprintf(stderr,
"open(%s) failed: %d %.40s\n",
argv[1], errno, strerror(errno));
return 1;
}

for (;;) {
if (ioctl(fd, TIOCMIWAIT, TIOCM_CD|TIOCM_DSR|TIOCM_CAR|TIOCM_RI|TIOCM_CTS) != 0) {
(void)fprintf(stderr,
"PPS ioctl(TIOCMIWAIT) failed: %d %.40s\n",
errno, strerror(errno));
break;
} else {
const struct assoc *sp;
int handshakes;

(void)clock_gettime(CLOCK_REALTIME, &ts);
(void)ioctl(fd, TIOCMGET, &handshakes);
(void)fprintf(stdout, "%10ld %10ld", ts.tv_sec, ts.tv_nsec);
for (sp = hlines;
sp < hlines + sizeof(hlines)/sizeof(hlines[0]);
sp++)
if ((handshakes & sp->mask) != 0) {
(void)fputc(' ', stdout);
(void)fputs(sp->string, stdout);
}
(void)fputc('\n', stdout);
}
}
}

/* end */

+ 59
- 28
contrib/webgps.py View File

@@ -1,14 +1,47 @@
#!/usr/bin/env python
# encoding: utf-8

# webgps.py
#
# This is a Python port of webgps.c from http://www.wireless.org.au/~jhecker/gpsd/
# by Beat Bolli <me+gps@drbeat.li>
#
"""webgps.py

This is a Python port of webgps.c from http://www.wireless.org.au/~jhecker/gpsd/
by Beat Bolli <me+gps@drbeat.li>

It creates a skyview of the currently visible GPS satellites and their tracks
over a time period.

Usage:
./webgps.py [duration]

duration may be
- a number of seconds
- a number followed by a time unit ('s' for secinds, 'm' for minutes,
'h' for hours or 'd' for days, e.g. '4h' for a duration of four hours)
- the letter 'c' for continuous operation

If duration is missing, the current skyview is generated and webgps.py exits
immediately. This is the same as giving a duration of 0.

If a duration is given, webgps.py runs for this duration and generates the
tracks of the GPS satellites in view. If the duration is the letter 'c',
the script never exits and continuously updates the skyview.

webgps.py generates two files: a HTML5 file that can be browsed, and a
JavaScript file that contains the drawing commands for the skyview. The HTML5
file auto-refreshes every five minutes. The generated file names are
"gpsd-<duration>.html" and "gpsd-<duration>.js".

If webgps.py is interrupted with Ctrl-C before the duration is over, it saves
the current tracks into the file "tracks.p". This is a Python "pickle" file.
If this file is present on start of webgps.py, it is loaded. This allows to
restart webgps.py without losing accumulated satellite tracks.
"""

import time, calendar, math, socket, sys, os, select, pickle
from gps import *
try:
from gps import *
except ImportError:
sys.path.append('..')
from gps import *

TRACKMAX = 1024
STALECOUNT = 10
@@ -42,6 +75,10 @@ class Track:
return 1
return 0

def track(self):
'''Return the track as canvas drawing operations.'''
return 'M(%d,%d); ' % self.posn[0] + ''.join(['L(%d,%d); ' % p for p in self.posn[1:]])

class SatTracks(gps):
'''gpsd client writing HTML5 and <canvas> output.'''

@@ -192,17 +229,11 @@ function draw_satview() {
ctx.strokeStyle = 'red';
""");

def M(p):
return 'M(%d,%d); ' % p
def L(p):
return 'L(%d,%d); ' % p

# Draw the tracks
for t in self.sattrack.values():
if t.posn:
fh.write(" ctx.globalAlpha = %s; ctx.beginPath(); %s%sctx.stroke();\n" % (
t.stale == 0 and '0.66' or '1', M(t.posn[0]),
''.join([L(p) for p in t.posn[1:]])
fh.write(" ctx.globalAlpha = %s; ctx.beginPath(); %sctx.stroke();\n" % (
t.stale == 0 and '0.66' or '1', t.track()
))

fh.write("""
@@ -250,14 +281,14 @@ function draw_satview() {
t = self.sattrack[prn]
except KeyError:
self.sattrack[prn] = t = Track(prn)
self.needsupdate += t.add(x, y)
if t.add(x, y):
self.needsupdate = 1

def update_tracks(self):
self.make_stale()
for s in self.satellites:
x, y = polartocart(s.elevation, s.azimuth)
if self.insert_sat(s.PRN, x, y):
self.needsupdate = 1
self.insert_sat(s.PRN, x, y)
self.delete_stale()

def generate_html(self, htmlfile, jsfile):
@@ -273,7 +304,8 @@ function draw_satview() {
def run(self, suffix, period):
jsfile = 'gpsd' + suffix + '.js'
htmlfile = 'gpsd' + suffix + '.html'
end = time.time() + period
if period is not None:
end = time.time() + period
self.needsupdate = 1
self.stream(WATCH_ENABLE | WATCH_NEWSTYLE)
for report in self:
@@ -284,8 +316,10 @@ function draw_satview() {
self.generate_js(jsfile)
self.needsupdate = 0
self.generate_html(htmlfile, jsfile)
if period <= 0 and self.fix.mode >= MODE_2D \
or period > 0 and time.time() > end:
if period is not None and (
period <= 0 and self.fix.mode >= MODE_2D or
period > 0 and time.time() > end
):
break

def main():
@@ -294,17 +328,14 @@ def main():
factors = {
's': 1, 'm': 60, 'h': 60 * 60, 'd': 24 * 60 * 60
}
arg = argv and argv[0] or ''
arg = argv and argv[0] or '0'
if arg[-1:] in factors.keys():
period = int(arg[:-1]) * factors[arg[-1]]
elif arg == 'c':
period = None
elif arg:
period = int(arg)
period = None
else:
period = 0
if arg:
arg = '-' + arg
period = int(arg)
prefix = '-' + arg

sat = SatTracks()

@@ -316,7 +347,7 @@ def main():
p.close()

try:
sat.run(arg, period)
sat.run(prefix, period)
except KeyboardInterrupt:
# save the tracks
p = open(pfile, 'w')


+ 1
- 1
control View File

@@ -3,7 +3,7 @@

Package: gpsd

Description: monitoring daemon for GPSes, AIS radios, and other navigation aids
Description: A monitoring daemon for GPSes, AIS radios, and other nav sensors.
gpsd is a userland daemon acting as a translator between GPS and
AIS receivers and their clients. gpsd listens on port 2947 for clients
requesting position/time/velocity information. The receivers are


+ 2
- 0
crc24q.c View File

@@ -159,6 +159,7 @@ unsigned crc24q_hash(unsigned char *data, int len)
#define MID(x) (unsigned char)(((x) >> 8) & 0xff)
#define HI(x) (unsigned char)(((x) >> 16) & 0xff)

#ifdef __UNUSED__
void crc24q_sign(unsigned char *data, int len)
{
unsigned crc = crc24q_hash(data, len);
@@ -167,6 +168,7 @@ void crc24q_sign(unsigned char *data, int len)
data[len + 1] = MID(crc);
data[len + 2] = LO(crc);
}
#endif /* __UNUSED__ */

bool crc24q_check(unsigned char *data, int len)
{


+ 6
- 1
devtools/ais.py View File

@@ -1237,7 +1237,12 @@ if __name__ == "__main__":
sys.stdout.write(raw)
if not bogon:
if json:
print "{" + ",".join(map(lambda x: '"' + x[0].name + '":' + str(x[1]), parsed)) + "}"
def quotify(x):
if type(x) == type(""):
return '"' + str(x) + '"'
else:
return str(x)
print "{" + ",".join(map(lambda x: '"' + x[0].name + '":' + quotify(x[1]), parsed)) + "}"
elif dsv:
print "|".join(map(lambda x: str(x[1]), parsed))
elif histogram:


+ 39
- 12
devtools/striplog View File

@@ -2,7 +2,7 @@
#
# striplog -- strip leading lines from logs
#
# striplog -1 strips the first line only.
# striplog -j strips JSON leader sentences.
# striplog with no option strips all leading lines beginning with #
#
# This file is Copyright (c) 2010 by the GPSD project
@@ -10,19 +10,46 @@
#
import getopt, sys

firstline = False
(options, argumwnts) = getopt.getopt(sys.argv[1:], "1")
secondline = firstline = stripjson = False
stripval = 0
(options, arguments) = getopt.getopt(sys.argv[1:], "12n:j")
for (switch, val) in options:
if (switch == '-1'):
firstline = True
if (switch == '-2'):
secondline = True
if (switch == '-n'):
stripval = int(val)
if (switch == '-j'):
stripjson = True

if firstline:
sys.stdin.readline()
else:
while True:
line = sys.stdin.readline()
if line[0] != '#':
break
sys.stdout.write(line)
try:
if firstline:
sys.stdin.readline()
elif secondline:
sys.stdin.readline()
sys.stdin.readline()
elif stripval:
for _dummy in range(stripval):
sys.stdin.readline()
elif stripjson:
while True:
line = sys.stdin.readline()
if line.startswith('{"class":"VERSION"') \
or line.startswith('{"class":"DEVICE"') \
or line.startswith('{"class":"DEVICES"') \
or line.startswith('{"class":"WATCH"'):
continue
else:
break
sys.stdout.write(line)
else:
while True:
line = sys.stdin.readline()
if line[0] != '#':
break
sys.stdout.write(line)

sys.stdout.write(sys.stdin.read())
sys.stdout.write(sys.stdin.read())
except KeyboardInterrupt:
pass

+ 156
- 53
devtools/tablegen.py View File

@@ -6,10 +6,12 @@
# correct offsets in the tables themselves.
#
# Requires the AIVDM.txt file on standard input. Takes a single argument,
# the line number of a table start. Things you can generate:
# which must match a string in a //: Type comment. Things you can generate:
#
# * -t: A corrected version of the table. It will redo all the offsets to be
# in conformance with the bit widths.
# in conformance with the bit widths. (The other options rely only on the
# bit widths). If the old and new tables are different, an error message
# describing the corrections will be emitted to standard error.
#
# * -s: A structure definition capturing the message info, with member
# names extracted from the table and types computed from it.
@@ -26,8 +28,9 @@
# generate the specification structure for a JSON parse that reads JSON
# into an instance of the message structure.
#
# * -a: Generate all of -s, -d, -c, and -r, , not to stdout but to
# files named with the argument as a distinguishing part of the stem.
# * -a: Generate all of -s, -d, -c, and -r, and -t, not to stdout but to
# files named with 'tablegen' as a distinguishing part of the stem.
# The stem name can be overridden with the -o option.
#
# This generates almost all the code required to support a new message type.
# It's not quite "Look, ma, no handhacking!" You'll need to add default
@@ -46,13 +49,21 @@
# of fields in the table. This may be useful for dealing with groups of
# messages that have a common head section.
#
# This code interprets magic comments in the input
#
# //: Type
# The token following "Type" is the name of the table
# //: xxxx vocabulary
# A subtable describing a controlled vocabulary for field xxxx in the
# preceding table.
#
# TO-DO: generate code for ais.py.

import sys, getopt

def correct_table(wfp):
# Writes the corrected table.
print >>sys.stderr, "Total bits:", base
print >>sys.stderr, "Total bits:", base
for (i, t) in enumerate(table):
if offsets[i].strip():
print >>wfp, "|" + offsets[i] + t[owidth+1:].rstrip()
@@ -62,7 +73,8 @@ def correct_table(wfp):
def make_driver_code(wfp):
# Writes calls to bit-extraction macros.
# Requires UBITS, SBITS, UCHARS to act as they do in the AIVDM driver.
# Also relies on ais_context->bitlen to be the message bit length.
# Also relies on bitlen to be the message bit length, and i to be
# available as abn index variable.
record = after is None
arrayname = None
base = '\t'
@@ -92,16 +104,16 @@ def make_driver_code(wfp):
print >>wfp, '#define ELEMENT_SIZE %s' % trailing
if explicit:
lengthfield = last
print >>wfp, indent + "for (ind = 0; ind < %s; ind++) {" % lengthfield
print >>wfp, indent + "for (i = 0; i < %s; i++) {" % lengthfield
else:
lengthfield = "n" + arrayname
print >>wfp, indent + "for (ind = 0; ARRAY_BASE + (ELEMENT_SIZE*ind) <= ais_context->bitlen; ind++) {"
print >>wfp, indent + "for (i = 0; ARRAY_BASE + (ELEMENT_SIZE*i) < bitlen; i++) {"