Merge branch 'master' of http://olsr.org/git/olsrd
authorHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Mon, 31 Mar 2014 09:18:51 +0000 (11:18 +0200)
committerHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Mon, 31 Mar 2014 09:18:51 +0000 (11:18 +0200)
65 files changed:
README-Olsr-Extensions
android/linux/if_tunnel.h
android/linux/ip6_tunnel.h
doc/SmartGateway/.gitignore [new file with mode: 0644]
doc/SmartGateway/SmartGatewayCost.gnuplot [new file with mode: 0644]
doc/SmartGateway/watchAndPlot.bash [new file with mode: 0755]
files/olsrd.conf.default.full
files/olsrd.conf.default.lq
files/olsrd.conf.default.lq-fisheye
files/sgw_policy_routing_setup.sh
lib/httpinfo/src/olsrd_httpinfo.c
lib/jsoninfo/src/olsrd_jsoninfo.c
lib/p2pd/README
lib/p2pd/src/olsrd_plugin.c
lib/p2pd/src/p2pd.c
lib/p2pd/src/p2pd.h
lib/pud/nmealib/COPYRIGHT [new file with mode: 0644]
lib/pud/nmealib/Makefile
lib/pud/nmealib/Makefile.inc
lib/pud/nmealib/doc/nmea.doxygen
lib/pud/nmealib/include/nmea/context.h
lib/pud/nmealib/include/nmea/conversions.h
lib/pud/nmealib/include/nmea/generate.h
lib/pud/nmealib/include/nmea/generator.h
lib/pud/nmealib/include/nmea/gmath.h
lib/pud/nmealib/include/nmea/info.h
lib/pud/nmealib/include/nmea/parse.h
lib/pud/nmealib/include/nmea/parser.h
lib/pud/nmealib/include/nmea/sentence.h
lib/pud/nmealib/include/nmea/tok.h
lib/pud/nmealib/samples/Makefile [deleted file]
lib/pud/nmealib/samples/generate/main.c [deleted file]
lib/pud/nmealib/samples/generator/main.c [deleted file]
lib/pud/nmealib/samples/math/main.c [deleted file]
lib/pud/nmealib/samples/parse/main.c [deleted file]
lib/pud/nmealib/samples/parse_file/gpslog.txt [deleted file]
lib/pud/nmealib/samples/parse_file/main.c [deleted file]
lib/pud/nmealib/src/context.c
lib/pud/nmealib/src/conversions.c
lib/pud/nmealib/src/generate.c
lib/pud/nmealib/src/generator.c
lib/pud/nmealib/src/gmath.c
lib/pud/nmealib/src/info.c
lib/pud/nmealib/src/parse.c
lib/pud/nmealib/src/parser.c
lib/pud/nmealib/src/sentence.c
lib/pud/nmealib/src/tok.c
lib/pud/src/configuration.c
lib/pud/src/receiver.c
lib/sgwdynspeed/src/speedFile.c
lib/txtinfo/src/olsrd_txtinfo.c
make/getmingwversion.bash
src/cfgparser/cfgfile_gen.c
src/cfgparser/olsrd_conf.c
src/cfgparser/oparse.y
src/cfgparser/oscan.lex
src/common/autobuf.c
src/gateway.c
src/gateway.h
src/gateway_costs.c
src/gateway_costs.h
src/gateway_default_handler.c
src/gateway_list.c
src/gateway_list.h
src/olsr_cfg.h

index 51baf28..103fb46 100644 (file)
@@ -264,22 +264,23 @@ All other parameters will be ignored if SmartGateway is set to "no"
    This setting is only relevant when SmartGatewayUseCount is larger than 1;
    a value of 0 will result in the tunnels not being taken down proactively.
    The default setting is 0.
-3- SmartGatewayPolicyRoutingScript controles the policy routing script that is
+3- SmartGatewayPolicyRoutingScript controls the policy routing script that is
    executed during startup and shutdown of olsrd. The script is only executed
    when SmartGatewayUseCount is set to a value larger than 1. The script must
-   setup policy routing rules such that multi-gateway mode works. A sample
+   setup policy routing rules such that multi-gateway mode works. A reference
    script is included.
-   The default setting is 'not set'.
+   The default setting is <not set>.
 4- SmartGatewayEgressInterfaces determines the egress interfaces that are part
    of the multi-gateway setup and therefore only relevant when
    SmartGatewayUseCount is larger than 1 (in which case it must be explicitly
    set).
-   The default setting is 'not set'.
-5- SmartGatewayMarkOffsetEgress and SmartGatewayMarkOffsetTunnels determine
-   the ranges of policy routing rule markings that are used in a multi-gateway
-   setup. The ranges are not allowed to overlap. Both settings are only
-   relevant when a multi-gateway setup is used.
-   The default settings are 91 and 101 respectively.
+   The default setting is <not set>.
+5- SmartGatewayTablesOffset and SmartGatewayRulesOffset determine the ranges of
+   policy routing rule markings that are used in a multi-gateway setup (see the
+   policy routing script for an explanation).
+   The default settings are 90 and 0 respectively. The value of 0 for
+   SmartGatewayRulesOffset will automatically align the table and rule numbers
+   for the server tunnel, egress interfaces and gateway tunnel interfaces.
 6- SmartGatewayAllowNAT controls whether you want to allow the selection
    of an outgoing ipv4 gateway with NAT (Network Address Translation).
    The default setting is "yes".
@@ -338,10 +339,12 @@ All other parameters will be ignored if SmartGateway is set to "no"
 
      ** Recommended Configuration Parameter Settings
      ===============================================
-     SmartGatewayWeightExitLinkUp   = 1 (default is 1)
-     SmartGatewayWeightExitLinkDown = 1 (default is 1)
-     SmartGatewayWeightEtx          = 1 (default is 1)
-     SmartGatewayDividerEtx         = 4 (default is 0)
+     (assuming LinkQualityAlgorithm "etx_ffeth")
+
+     SmartGatewayWeightExitLinkUp   = 1    (default is 1)
+     SmartGatewayWeightExitLinkDown = 1    (default is 1)
+     SmartGatewayWeightEtx          = 1    (default is 1)
+     SmartGatewayDividerEtx         = 4096 (default is 0)
 
 
     5.3) Uplink Side
index a1acfa9..b522a06 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/types.h>
 #include <asm/byteorder.h>
+#include <net/if.h>
 
 #ifdef __KERNEL__
 #include <linux/ip.h>
index 9bcc323..b3597d7 100644 (file)
@@ -2,6 +2,7 @@
 #define _IP6_TUNNEL_H
 
 #include <linux/types.h>
+#include <net/if.h>
 
 #define IPV6_TLV_TNL_ENCAP_LIMIT 4
 #define IPV6_DEFAULT_TNL_ENCAP_LIMIT 4
diff --git a/doc/SmartGateway/.gitignore b/doc/SmartGateway/.gitignore
new file mode 100644 (file)
index 0000000..d8c3b27
--- /dev/null
@@ -0,0 +1 @@
+/*.svg
diff --git a/doc/SmartGateway/SmartGatewayCost.gnuplot b/doc/SmartGateway/SmartGatewayCost.gnuplot
new file mode 100644 (file)
index 0000000..5168c0d
--- /dev/null
@@ -0,0 +1,42 @@
+sizex=1920
+sizey=1080
+
+set terminal svg dynamic enhanced fname 'Helvetica' fsize 16 mousing name "SmartGatewayCost" butt solid size sizex,sizey
+set output 'SmartGatewayCost.svg'
+
+set grid xtics lt 0 lw 1 lc rgb "#bbbbbb"
+set grid ytics lt 0 lw 1 lc rgb "#bbbbbb"
+set grid ztics lt 0 lw 1 lc rgb "#bbbbbb"
+
+set dummy x,y
+set isosamples 100, 100
+
+
+set title "Smart Gateway Cost (Symmetric Link)" 
+
+#                     WexitU   WexitD   Wetx
+# path_cost_weight =  ------ + ------ + ---- * path_cost
+#                     exitUm   exitDm   Detx
+
+WexitU=1.0
+WexitD=1.0
+Wetx=1.0
+Detx=4096.0
+
+set xlabel "Uplink / Downlink (Mbps)" 
+xlow=0.0
+xhigh=1.0
+set xlabel  offset character 0, 0, 0 font "Helvetica" textcolor lt -1 norotate
+set xrange [ xlow : xhigh ] noreverse nowriteback
+
+set ylabel "Path Cost ( = ETX * 1024 )"
+ylow=1000.0
+yhigh=10000.0
+set ylabel  offset character 0, 0, 0 font "Helvetica" textcolor lt -1 rotate by -270
+set yrange [ ylow : yhigh ] noreverse nowriteback
+
+
+set zlabel "Costs" 
+set zlabel  offset character -2, 0, 0 font "" textcolor lt -1 norotate
+
+splot (WexitU/x)+(WexitD/x)+((Wetx/Detx)*y)
diff --git a/doc/SmartGateway/watchAndPlot.bash b/doc/SmartGateway/watchAndPlot.bash
new file mode 100755 (executable)
index 0000000..da05038
--- /dev/null
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+set -e
+set -u
+
+ifsOld="$IFS"
+IFS=$'\n'
+gnuplotfiles=( $(ls -1 *.gnuplot | sort) )
+IFS="$ifsOld"
+gnuplotfilestimes=()
+
+# init time stamps
+declare -i index=0
+while [[ $index -lt ${#gnuplotfiles[*]} ]]; do
+  gnuplotfilestimes[$index]=1
+  index+=1
+done
+
+
+declare -i tim=0
+while true; do
+  index=0
+  while [[ $index -lt ${#gnuplotfiles[*]} ]]; do
+    tim=$(stat -c "%Y" "${gnuplotfiles[index]}")
+    if [[ $tim -ne ${gnuplotfilestimes[index]} ]]; then
+      gnuplot "${gnuplotfiles[index]}"
+      gnuplotfilestimes[$index]=$tim
+    fi
+    index+=1
+  done
+  sleep 1
+done
index 21fd505..2e2e648 100644 (file)
 
 # SmartGatewayEgressInterfaces ""
 
-# Determines the offset of the smart gateway egress interfaces mark that are
-# used in the policy routing rules in a multi-gateway setup. Only relevant
-# when a multi-gateway setup is used.
-# (default is 91)
+# Determines the routing tables offset for multi-gateway policy routing tables
+# See the policy routing script for an explanation.
+# (default is 90)
 
-# SmartGatewayMarkOffsetEgress 91
+# SmartGatewayTablesOffset 90
 
-# Determines the offset of the smart gateway tunnel interfaces mark that are
-# used in the policy routing rules in a multi-gateway setup. Only relevant
-# when a multi-gateway setup is used.
-# The ranges [egress offset, egress offset + egress count] and
-# [tunnel offset, tunnel offset + use count] are not allowed to overlap.
-# (default is 101)
+# Determines the policy routing rules offset for multi-gateway policy routing
+# rules. See the policy routing script for an explanation.
+# (default is 0, which indicates that the rules and tables should be aligned and
+# puts this value at SmartGatewayTablesOffset - # egress interfaces -
+# # olsr interfaces)
 
-# SmartGatewayMarkOffsetTunnels 101
+# SmartGatewayRulesOffset 87
 
 # Allows the selection of a smartgateway with NAT (only for IPv4)
 # (default is "yes")
index 078e2f9..e694e3d 100644 (file)
 
 # SmartGatewayEgressInterfaces ""
 
-# Determines the offset of the smart gateway egress interfaces mark that are
-# used in the policy routing rules in a multi-gateway setup. Only relevant
-# when a multi-gateway setup is used.
-# (default is 91)
+# Determines the routing tables offset for multi-gateway policy routing tables
+# See the policy routing script for an explanation.
+# (default is 90)
 
-# SmartGatewayMarkOffsetEgress 91
+# SmartGatewayTablesOffset 90
 
-# Determines the offset of the smart gateway tunnel interfaces mark that are
-# used in the policy routing rules in a multi-gateway setup. Only relevant
-# when a multi-gateway setup is used.
-# The ranges [egress offset, egress offset + egress count] and
-# [tunnel offset, tunnel offset + use count] are not allowed to overlap.
-# (default is 101)
+# Determines the policy routing rules offset for multi-gateway policy routing
+# rules. See the policy routing script for an explanation.
+# (default is 0, which indicates that the rules and tables should be aligned and
+# puts this value at SmartGatewayTablesOffset - # egress interfaces -
+# # olsr interfaces)
 
-# SmartGatewayMarkOffsetTunnels 101
+# SmartGatewayRulesOffset 87
 
 # Allows the selection of a smartgateway with NAT (only for IPv4)
 # (default is "yes")
index 64e30d8..2b5587b 100644 (file)
 
 # SmartGatewayEgressInterfaces ""
 
-# Determines the offset of the smart gateway egress interfaces mark that are
-# used in the policy routing rules in a multi-gateway setup. Only relevant
-# when a multi-gateway setup is used.
-# (default is 91)
+# Determines the routing tables offset for multi-gateway policy routing tables
+# See the policy routing script for an explanation.
+# (default is 90)
 
-# SmartGatewayMarkOffsetEgress 91
+# SmartGatewayTablesOffset 90
 
-# Determines the offset of the smart gateway tunnel interfaces mark that are
-# used in the policy routing rules in a multi-gateway setup. Only relevant
-# when a multi-gateway setup is used.
-# The ranges [egress offset, egress offset + egress count] and
-# [tunnel offset, tunnel offset + use count] are not allowed to overlap.
-# (default is 101)
+# Determines the policy routing rules offset for multi-gateway policy routing
+# rules. See the policy routing script for an explanation.
+# (default is 0, which indicates that the rules and tables should be aligned and
+# puts this value at SmartGatewayTablesOffset - # egress interfaces -
+# # olsr interfaces)
 
-# SmartGatewayMarkOffsetTunnels 101
+# SmartGatewayRulesOffset 87
 
 # Allows the selection of a smartgateway with NAT (only for IPv4)
 # (default is "yes")
index 7648fe1..8fdc4a1 100755 (executable)
@@ -3,6 +3,27 @@
 set -e
 set -u
 
+
+###############################################################################
+#
+# OVERVIEW
+#
+###############################################################################
+
+# Tables (from SmartGatewayTablesOffset):
+#                                               +-----------------+-----------------+---------------+
+#                                               | sgwsrvtun table | egressif tables | sgwtun tables |
+#                                               +-----------------+-----------------+---------------+
+# Example:                                              90               91 92            93 94 ...
+#
+#
+# Rules (from SmartGatewayRulesOffset):
+# +-----------------------+---------------------+-----------------+-----------------+---------------+
+# | egressif bypass rules | olsrif bypass rules | sgwsrvtun rule  | egressif rules  | sgwtun rules  |
+# +-----------------------+---------------------+-----------------+-----------------+---------------+
+# Example:  84 85               86 87 88 89             90               91 92            93 94 ...
+
+
 ###############################################################################
 #
 # SETTINGS
@@ -21,6 +42,12 @@ declare MODE_SGWTUN="sgwtun"
 declare ADDMODE_ADD="add"
 declare ADDMODE_DEL="del"
 
+declare -i MODE_GENERIC_ARGC=0
+declare -i MODE_OLSRIF_ARGC=2
+declare -i MODE_EGRESSIF_ARGC=4
+declare -i MODE_SGWSRVTUN_ARGC=3
+declare -i MODE_SGWTUN_ARGC=3
+
 
 ###############################################################################
 #
@@ -31,24 +58,26 @@ declare ADDMODE_DEL="del"
 function usage() {
   echo ""
   echo "The script was called as:"
-  echo "  ${script} ${arguments[@]:-}"
+  echo "  $script ${arguments[@]:-}"
   echo ""
   echo "Usage:"
-  echo "  ${script} ipVersion mode addMode [ifname [ifmark]]"
-  echo "    - ipVersion: ${IPVERSION_4} or ${IPVERSION_6}"
-  echo "    - mode     : ${MODE_GENERIC}, ${MODE_OLSRIF}, ${MODE_SGWSRVTUN}, ${MODE_EGRESSIF} or ${MODE_SGWTUN}"
-  echo "    - addMode  : ${ADDMODE_ADD} or ${ADDMODE_DEL}"
-  echo "    - ifname   : an interface name, not relevant for generic mode"
-  echo "    - ifmark   : an interface marking (number), only relevant for ${MODE_EGRESSIF} and ${MODE_SGWTUN} modes"
+  echo "  $script ipVersion mode addMode ifName tableNr ruleNr bypassRuleNr"
+  echo "    - ipVersion   : $IPVERSION_4 or $IPVERSION_6"
+  echo "    - mode        : $MODE_GENERIC, $MODE_OLSRIF, $MODE_EGRESSIF, $MODE_SGWSRVTUN or $MODE_SGWTUN"
+  echo "    - addMode     : $ADDMODE_ADD or $ADDMODE_DEL"
+  echo "    - ifName      : the interface name       , only relevant for modes $MODE_EGRESSIF, $MODE_SGWSRVTUN, $MODE_SGWTUN"
+  echo "    - tableNr     : the routing table number , only relevant for modes $MODE_EGRESSIF, $MODE_SGWSRVTUN, $MODE_SGWTUN"
+  echo "    - ruleNr      : the ip rule number       , only relevant for modes $MODE_EGRESSIF, $MODE_SGWSRVTUN, $MODE_SGWTUN"
+  echo "    - bypassRuleNr: the bypass ip rule number, only relevant for mode  $MODE_EGRESSIF, $MODE_OLSRIF"
 }
 
 function error() {
   local -i firstLine=1
-  while [ ${#} -gt 0 ]; do
-    if [ ${firstLine} -eq 1 ]; then
-      echo "Error: ${1}"
+  while [ $# -gt 0 ]; do
+    if [ $firstLine -eq 1 ]; then
+      echo "Error: $1"
     else
-      echo "       ${1}"
+      echo "       $1"
     fi
     firstLine=0
     shift 1
@@ -63,26 +92,45 @@ function error() {
 ###############################################################################
 
 function generic() {
-  "${IPTABLES}" ${IPTABLES_ARGS} -t mangle "${ADDMODE_IPTABLES}" OUTPUT -j CONNMARK --restore-mark
+  "$IPTABLES" $IPTABLES_ARGS -t mangle "$ADDMODE_IPTABLES" PREROUTING  -m conntrack ! --ctstate NEW -j CONNMARK --restore-mark
+  "$IPTABLES" $IPTABLES_ARGS -t mangle "$ADDMODE_IPTABLES" OUTPUT      -m conntrack ! --ctstate NEW -j CONNMARK --restore-mark
 }
 
 function olsrif() {
-  "${IPTABLES}" ${IPTABLES_ARGS} -t mangle "${ADDMODE_IPTABLES}" PREROUTING -i "${1}" -j CONNMARK --restore-mark
-}
+  local interfaceName="$1"
+  local bypassRuleNr="$2"
 
-function sgwsrvtun() {
-  "${IPTABLES}" ${IPTABLES_ARGS} -t mangle "${ADDMODE_IPTABLES}" PREROUTING -i "${1}" -j CONNMARK --restore-mark
+  "$IP"       $IP_ARGS        rule      "$ADDMODE_IP" iif    "$interfaceName" table main       priority "$bypassRuleNr"
 }
 
 function egressif() {
-  "${IPTABLES}" ${IPTABLES_ARGS} -t mangle "${ADDMODE_IPTABLES}" POSTROUTING -m conntrack --ctstate NEW -o "${1}" -j CONNMARK --set-mark "${2}"
-  "${IPTABLES}" ${IPTABLES_ARGS} -t mangle "${ADDMODE_IPTABLES}" INPUT       -m conntrack --ctstate NEW -i "${1}" -j CONNMARK --set-mark "${2}"
-  "${IP}" ${IP_ARGS} rule "${ADDMODE_IP}" fwmark "${2}" table "${2}" pref "${2}"
+  local interfaceName="$1"
+  local tableNr="$2"
+  local ruleNr="$3"
+  local bypassRuleNr="$4"
+
+  "$IPTABLES" $IPTABLES_ARGS -t mangle "$ADDMODE_IPTABLES" POSTROUTING -m conntrack --ctstate NEW -o "$interfaceName" -j CONNMARK --set-mark "$ruleNr"
+  "$IPTABLES" $IPTABLES_ARGS -t mangle "$ADDMODE_IPTABLES" INPUT       -m conntrack --ctstate NEW -i "$interfaceName" -j CONNMARK --set-mark "$ruleNr"
+  "$IP"       $IP_ARGS       rule      "$ADDMODE_IP" fwmark "$ruleNr"        table "$tableNr" priority "$ruleNr"
+  "$IP"       $IP_ARGS       rule      "$ADDMODE_IP" iif    "$interfaceName" table main       priority "$bypassRuleNr"
+}
+
+function sgwsrvtun() {
+  local interfaceName="$1"
+  local tableNr="$2"
+  local ruleNr="$3"
+
+  "$IPTABLES" $IPTABLES_ARGS -t mangle "$ADDMODE_IPTABLES" PREROUTING  -m conntrack --ctstate NEW -i "$interfaceName" -j CONNMARK --set-mark "$ruleNr"
+  "$IP"       $IP_ARGS       rule      "$ADDMODE_IP" fwmark "$ruleNr" table "$tableNr" priority "$ruleNr"
 }
 
 function sgwtun() {
-  "${IPTABLES}" ${IPTABLES_ARGS} -t mangle "${ADDMODE_IPTABLES}" POSTROUTING -m conntrack --ctstate NEW -o "${1}" -j CONNMARK --set-mark "${2}"
-  "${IP}" ${IP_ARGS} rule "${ADDMODE_IP}" fwmark "${2}" table "${2}" pref "${2}"
+  local interfaceName="$1"
+  local tableNr="$2"
+  local ruleNr="$3"
+
+  "$IPTABLES" $IPTABLES_ARGS -t mangle "$ADDMODE_IPTABLES" POSTROUTING -m conntrack --ctstate NEW -o "$interfaceName" -j CONNMARK --set-mark "$ruleNr"
+  "$IP"       $IP_ARGS       rule      "$ADDMODE_IP" fwmark "$ruleNr" table "$tableNr" priority "$ruleNr"
 }
 
 
@@ -92,58 +140,77 @@ function sgwtun() {
 #
 ###############################################################################
 
-declare script="${0}"
+declare script="$0"
 declare -a arguments=( ${@} )
-declare -i argc=${#}
+declare -i argc=$#
 
 # we always need 3 arguments, check it
-if [ ${argc} -lt 3 ]; then
+if [ $argc -lt 3 ]; then
   error "Need at least 3 arguments"
   usage
   exit 1
 fi
 
 # get first 3 arguments
-declare ipVersion=${1}
-declare mode="${2}"
-declare addMode="${3}"
+declare ipVersion=$1
+declare mode="$2"
+declare addMode="$3"
 shift 3
-argc=${#}
+argc=$#
 
 # check IP version argument
-if [ ! "${ipVersion}" == "${IPVERSION_4}" ] && \
-   [ ! "${ipVersion}" == "${IPVERSION_6}" ]; then
+if [ ! "$ipVersion" == "$IPVERSION_4" ] && \
+   [ ! "$ipVersion" == "$IPVERSION_6" ]; then
   error "Illegal IP version"
   usage
   exit 1
 fi
 
 # check mode argument
-if [ ! "${mode}" == "${MODE_GENERIC}" ] && \
-   [ ! "${mode}" == "${MODE_OLSRIF}" ] && \
-   [ ! "${mode}" == "${MODE_SGWSRVTUN}" ] && \
-   [ ! "${mode}" == "${MODE_EGRESSIF}" ] && \
-   [ ! "${mode}" == "${MODE_SGWTUN}" ]; then
+if [ ! "$mode" == "$MODE_GENERIC" ] && \
+   [ ! "$mode" == "$MODE_OLSRIF" ] && \
+   [ ! "$mode" == "$MODE_SGWSRVTUN" ] && \
+   [ ! "$mode" == "$MODE_EGRESSIF" ] && \
+   [ ! "$mode" == "$MODE_SGWTUN" ]; then
   error "Illegal mode"
   usage
   exit 1
 fi
 
 # check addMode argument
-if [ ! "${addMode}" == "${ADDMODE_ADD}" ] && \
-   [ ! "${addMode}" == "${ADDMODE_DEL}" ]; then
+if [ ! "$addMode" == "$ADDMODE_ADD" ] && \
+   [ ! "$addMode" == "$ADDMODE_DEL" ]; then
   error "Illegal addMode"
   usage
   exit 1
 fi
 
 # check argument count for all modes
-if ([ "${mode}" == "${MODE_GENERIC}" ]   && [ ${argc} -ne 0 ]) || \
-   ([ "${mode}" == "${MODE_OLSRIF}" ]    && [ ${argc} -ne 1 ]) || \
-   ([ "${mode}" == "${MODE_SGWSRVTUN}" ] && [ ${argc} -ne 1 ]) || \
-   ([ "${mode}" == "${MODE_EGRESSIF}"  ] && [ ${argc} -ne 2 ]) || \
-   ([ "${mode}" == "${MODE_SGWTUN}"  ]   && [ ${argc} -ne 2 ]); then
-  error "Not enough arguments or too many arguments"
+if ([ "$mode" == "$MODE_GENERIC" ]   && [ $argc -lt $MODE_GENERIC_ARGC   ]) || \
+   ([ "$mode" == "$MODE_OLSRIF" ]    && [ $argc -lt $MODE_OLSRIF_ARGC    ]) || \
+   ([ "$mode" == "$MODE_EGRESSIF"  ] && [ $argc -lt $MODE_EGRESSIF_ARGC  ]) || \
+   ([ "$mode" == "$MODE_SGWSRVTUN" ] && [ $argc -lt $MODE_SGWSRVTUN_ARGC ]) || \
+   ([ "$mode" == "$MODE_SGWTUN"  ]   && [ $argc -lt $MODE_SGWTUN_ARGC    ]); then
+  if [ $argc -eq 0 ]; then
+    error "Not enough arguments arguments ($argc) for mode $mode"
+  else
+    error "Not enough arguments arguments ($argc) for mode $mode" "Arguments: ${@}"
+  fi
+  usage
+  exit 1
+fi
+
+# check argument count for all modes
+if ([ "$mode" == "$MODE_GENERIC" ]   && [ $argc -gt $MODE_GENERIC_ARGC   ]) || \
+   ([ "$mode" == "$MODE_OLSRIF" ]    && [ $argc -gt $MODE_OLSRIF_ARGC    ]) || \
+   ([ "$mode" == "$MODE_EGRESSIF"  ] && [ $argc -gt $MODE_EGRESSIF_ARGC  ]) || \
+   ([ "$mode" == "$MODE_SGWSRVTUN" ] && [ $argc -gt $MODE_SGWSRVTUN_ARGC ]) || \
+   ([ "$mode" == "$MODE_SGWTUN"  ]   && [ $argc -gt $MODE_SGWTUN_ARGC    ]); then
+  if [ $argc -eq 0 ]; then
+    error "Not enough arguments arguments ($argc) for mode $mode"
+  else
+    error "Not enough arguments arguments ($argc) for mode $mode" "Arguments: ${@}"
+  fi
   usage
   exit 1
 fi
@@ -153,7 +220,7 @@ declare IPTABLES="iptables"
 declare IPTABLES_ARGS=""
 declare IP="ip"
 declare IP_ARGS="-4"
-if [ "${ipVersion}" == "${IPVERSION_6}" ]; then
+if [ "$ipVersion" == "$IPVERSION_6" ]; then
   IPTABLES="ip6tables"
   IPTABLES_ARGS=""
   IP="ip"
@@ -162,11 +229,11 @@ fi
 
 # process addMode argument
 declare ADDMODE_IPTABLES="-D"
-declare ADDMODE_IP="del"
-if [ "${addMode}" == "${ADDMODE_ADD}" ]; then
+declare ADDMODE_IP="delete"
+if [ "$addMode" == "$ADDMODE_ADD" ]; then
   # first call the delete mode to remove any left-over rules
   set +e
-  "${mode}" "${@}" 2> /dev/null
+  "$mode" "${@}" 2> /dev/null
   set -e
 
   ADDMODE_IPTABLES="-I"
@@ -174,4 +241,4 @@ if [ "${addMode}" == "${ADDMODE_ADD}" ]; then
 fi
 
 # call the mode
-"${mode}" "${@}"
+"$mode" "${@}"
index 6bee0e4..ae833cf 100644 (file)
@@ -1553,6 +1553,7 @@ static void sgw_ipvx(struct autobuf *abuf, bool ipv6) {
     abuf_puts(abuf, "      <th><center>Prefix</center></th>\n");
     abuf_puts(abuf, "      <th><center>Uplink (kbps)</center></th>\n");
     abuf_puts(abuf, "      <th><center>Downlink (kbps)</center></th>\n");
+    abuf_puts(abuf, "      <th><center>Path Cost</center></th>\n");
     abuf_puts(abuf, "      <th><center>IPv4</center></th>\n");
     abuf_puts(abuf, "      <th><center>IPv4 NAT</center></th>\n");
     abuf_puts(abuf, "      <th><center>IPv6</center></th>\n");
@@ -1574,14 +1575,27 @@ static void sgw_ipvx(struct autobuf *abuf, bool ipv6) {
 
         if (!gw->gw) {
           int i;
-          for (i = 0; i < 7; i++) {
+          for (i = 0; i < 8; i++) {
             abuf_puts(abuf, "      <td></td>\n");
           }
         } else {
+          struct tc_entry* tc = olsr_lookup_tc_entry(&gw->gw->originator);
+          olsr_linkcost etx = ROUTE_COST_BROKEN;
+          if (tc) {
+            etx = tc->path_cost;
+          }
+
           abuf_appendf(abuf, "      <td>%s</td>\n", inet_ntop(ipv6 ? AF_INET6 : AF_INET, &gw->gw->originator, buf, sizeof(buf)));
           abuf_appendf(abuf, "      <td>%s</td>\n", olsr_ip_prefix_to_string(&gw->gw->external_prefix));
           abuf_appendf(abuf, "      <td>%u</td>\n", gw->gw->uplink);
           abuf_appendf(abuf, "      <td>%u</td>\n", gw->gw->downlink);
+
+          if (tc->path_cost == ROUTE_COST_BROKEN) {
+            abuf_appendf(abuf, "      <td>Unreachable</td>\n");
+          } else {
+            abuf_appendf(abuf, "      <td>%u</td>\n", etx);
+          }
+
           abuf_appendf(abuf, "      <td>%s</td>\n", gw->gw->ipv4 ? "yes" : "no");
           abuf_appendf(abuf, "      <td>%s</td>\n", gw->gw->ipv4nat ? "yes" : "no");
           abuf_appendf(abuf, "      <td>%s</td>\n", gw->gw->ipv6 ? "yes" : "no");
@@ -1598,7 +1612,7 @@ static void sgw_ipvx(struct autobuf *abuf, bool ipv6) {
         if (!gw->gw) {
           abuf_puts(abuf, "      <td></td>\n");
         } else {
-          abuf_appendf(abuf, "      <td>%llu</td>\n", (long long unsigned int)gw->path_cost);
+          abuf_appendf(abuf, "      <td>%llu</td>\n", (long long unsigned int)gw->gw->path_cost);
         }
         abuf_puts(abuf, "    </tr>\n");
       }
index 966292c..9ad76d0 100644 (file)
@@ -1006,8 +1006,8 @@ ipc_print_config(struct autobuf *abuf)
       abuf_json_string(abuf, "smartGatewayEgressInterfaces", egressbuf.buf);
       abuf_free(&egressbuf);
     }
-    abuf_json_int(abuf, "smartGatewayMarkOffsetEgress", olsr_cnf->smart_gw_mark_offset_egress);
-    abuf_json_int(abuf, "smartGatewayMarkOffsetTunnels", olsr_cnf->smart_gw_mark_offset_tunnels);
+    abuf_json_int(abuf, "smartGatewayTablesOffset", olsr_cnf->smart_gw_offset_tables);
+    abuf_json_int(abuf, "smartGatewayRulesOffset", olsr_cnf->smart_gw_offset_rules);
     abuf_json_boolean(abuf, "smartGatewayAllowNat", olsr_cnf->smart_gw_allow_nat);
     abuf_json_boolean(abuf, "smartGatewayUplinkNat", olsr_cnf->smart_gw_uplink_nat);
     abuf_json_int(abuf, "smartGatewayPeriod", olsr_cnf->smart_gw_period);
index c89f292..b5c44a5 100644 (file)
@@ -67,6 +67,8 @@ PlParam     "P2pdTtl"     "5"
 PlParam     "UdpDestPort" "255.255.255.255 1211"
 #   MDNS multicast (draft-cheshire-dnsext-multicastdns)
 PlParam     "UdpDestPort" "224.0.0.251 5353"
+# Set to 1 to decrement the TTL on the packet going into the OLSR network (default 0)
+#PlParam     "UseTTLDecrement" "0"
 }
 
 Where eth0 and eth1 are the names of the interfaces where you want to capture
index 737cef8..da2d9c0 100644 (file)
@@ -112,6 +112,7 @@ static const struct olsrd_plugin_parameters plugin_parameters[] = {
   {.name = "P2pdTtl", .set_plugin_parameter = &SetP2pdTtl, .data = NULL },
   {.name = "UdpDestPort",.set_plugin_parameter = &AddUdpDestPort,.data = NULL},
   {.name = "UseHashFilter",.set_plugin_parameter = &SetP2pdUseHashFilter,.data = NULL},
+  {.name = "UseTTLDecrement",.set_plugin_parameter = &SetP2pdUseTtlDecrement,.data = NULL},
 };
 
 /* -------------------------------------------------------------------------
index b696c4f..44abcfe 100644 (file)
@@ -85,6 +85,7 @@
 
 int P2pdTtl                        = 0;
 int P2pdUseHash                    = 0;  /* Switch off hash filter by default */
+int P2pdUseTtlDecrement            = 0;  /* No TTL decrement by default */
 int P2pdDuplicateTimeout           = P2PD_VALID_TIME;
 
 /* List of UDP destination address and port information */
@@ -603,6 +604,46 @@ InUdpDestPortList(int ip_version, union olsr_ip_addr *addr, uint16_t port)
   return false;
 }
 
+/*
+ * Function for checksum calculation.
+ * From the RFC, the checksum algorithm is:
+ *   "The checksum field is the 16 bit one's complement of the one's
+ *   complement sum of all 16 bit words in the header. For purposes of
+ *   computing the checksum, the value of the checksum field is zero."
+ *
+ * For example, consider Hex 4500003044224000800600008c7c19acae241e2b (20 bytes IP header):
+ * - Step 1) 4500 + 0030 + 4422 + 4000 + 8006 + 0000 + 8c7c + 19ac + ae24 + 1e2b = 0002`BBCF (16-bit sum)
+ * - Step 2) 0002 + BBCF = BBD1 = 1011101111010001 (1's complement 16-bit sum)
+ * - Step 3) ~BBD1 = 0100010000101110 = 442E (1's complement of 1's complement 16-bit sum)
+ */
+static void recomputeIPv4HeaderChecksum(struct ip *header) {
+  uint32_t sum;
+  uint32_t nwords;
+  u_short *headerWords;
+
+  if (!header) {
+    return;
+  }
+
+  header->ip_sum = 0;
+  nwords = header->ip_hl << 1;
+  headerWords = (u_short *) header;
+
+  /* step 1 */
+  for (sum = 0; nwords > 0; nwords--) {
+    sum += ntohs(*headerWords);
+    headerWords++;
+  }
+
+  /* step 2 */
+  sum = (sum >> 16) + (sum & 0xffff);
+
+  /* step 3 */
+  sum = ~sum & 0xffff;
+
+  header->ip_sum = (u_short) (sum);
+}
+
 /* -------------------------------------------------------------------------
  * Function   : P2pdPacketCaptured
  * Description: Handle a captured IP packet
@@ -622,6 +663,8 @@ P2pdPacketCaptured(unsigned char *encapsulationUdpData, int nBytes)
   struct ip *ipHeader;         /* The IP header inside the captured IP packet */
   struct ip6_hdr *ipHeader6;   /* The IP header inside the captured IP packet */
   struct udphdr *udpHeader;
+  uint8_t * ttl = NULL;
+  int recomputeChecksum = 0;
   u_int16_t destPort;
 
   if ((encapsulationUdpData[0] & 0xf0) == 0x40) {       //IPV4
@@ -662,6 +705,9 @@ P2pdPacketCaptured(unsigned char *encapsulationUdpData, int nBytes)
 #endif /* INCLUDE_DEBUG_OUTPUT */
        return;
     }
+
+    ttl = &ipHeader->ip_ttl;
+    recomputeChecksum = 1;
   }                            //END IPV4
   else if ((encapsulationUdpData[0] & 0xf0) == 0x60) {  //IPv6
 
@@ -703,11 +749,29 @@ P2pdPacketCaptured(unsigned char *encapsulationUdpData, int nBytes)
 #endif /* INCLUDE_DEBUG_OUTPUT */
       return;
     }
+
+    ttl = &ipHeader6->ip6_ctlun.ip6_un1.ip6_un1_hlim;
+    recomputeChecksum = 0;
   }                             //END IPV6
   else {
     return;                     //Is not IP packet
   }
 
+  if (P2pdUseTtlDecrement) {
+    assert(ttl);
+    if (!*ttl) {
+      return;
+    }
+    *ttl -= 1;
+    if (!*ttl) {
+      return;
+    }
+
+    if (recomputeChecksum) {
+      recomputeIPv4HeaderChecksum(ipHeader);
+    }
+  }
+
   // send the packet to OLSR forward mechanism
   olsr_p2pd_gen(encapsulationUdpData, nBytes);
 }                               /* P2pdPacketCaptured */
@@ -861,6 +925,27 @@ SetP2pdUseHashFilter(const char *value,
   return 0;
 }
 
+/* -------------------------------------------------------------------------
+ * Function   : SetP2pdUseTtlDecrement
+ * Description: Set the TTL decrement lag for this plug-in
+ * Input      : value - parameter value to evaluate
+ *              data  - data associated with this parameter (unused in this app)
+ *              addon - additional parameter data
+ * Output     : none
+ * Return     : Always 0
+ * Data Used  : P2pdUseTtlDecrement
+ * ------------------------------------------------------------------------- */
+int
+SetP2pdUseTtlDecrement(const char *value,
+                     void *data __attribute__ ((unused)),
+                     set_plugin_parameter_addon addon __attribute__ ((unused)))
+{
+  assert(value != NULL);
+  P2pdUseTtlDecrement = atoi(value);
+
+  return 0;
+}
+
 /* -------------------------------------------------------------------------
  * Function   : AddUdpDestPort
  * Description: Set the UDP destination/port combination as an entry in the
index 4f90bbf..5d1762f 100644 (file)
@@ -99,6 +99,7 @@ int AddUdpDestPort(const char *value, void *data __attribute__ ((unused)), set_p
 bool InUdpDestPortList(int ip_version, union olsr_ip_addr *addr, uint16_t port);
 int SetP2pdTtl(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)));
 int SetP2pdUseHashFilter(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)));
+int SetP2pdUseTtlDecrement(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)));
 bool p2pd_message_seen(struct node **head, struct node **tail, union olsr_message *m);
 void p2pd_store_message(struct node **head, struct node **tail, union olsr_message *m);
 bool p2pd_is_duplicate_message(union olsr_message *msg);
diff --git a/lib/pud/nmealib/COPYRIGHT b/lib/pud/nmealib/COPYRIGHT
new file mode 100644 (file)
index 0000000..b3e55da
--- /dev/null
@@ -0,0 +1,10 @@
+----------
+Copyrights
+----------
+
+Copyrights may apply to all sources or to parts, use our Git repository to
+find out which parts have copyrights by whom.
+
+* Copyright (c) 2008      Timur Sinitsyn
+* Copyright (c) 2011-2014 Ferry Huberts
+* Copyright (c) 2014      Tobias Simon
\ No newline at end of file
index 2cbe920..201dc35 100644 (file)
@@ -55,9 +55,6 @@ ifeq ($(VERBOSE),0)
 endif
        $(MAKECMDPREFIX)$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
 
-samples: all
-       $(MAKECMDPREFIX)$(MAKE) -C samples all
-
 
 #
 # Phony Targets
@@ -70,7 +67,6 @@ all-before:
 
 clean:
        $(MAKECMDPREFIX)$(MAKE) -C doc clean
-       $(MAKECMDPREFIX)$(MAKE) -C samples clean
        $(MAKECMDPREFIX)rm -frv build lib
 
 doc:
index 28d90cf..5d5b4a4 100644 (file)
@@ -31,7 +31,7 @@ endif
 
 # we expect the version to be like 'v0.5.3-27-g0c2727a' and then strip the 'v',
 # and the '-27-g0c2727a' parts
-VERSION=1.0.4
+VERSION=2.0.0
 
 # protect against no version number
 ifeq ($(strip $(VERSION)),)
index 9954954..eb6d5b7 100644 (file)
-# Doxyfile 1.8.1.1
+# Doxyfile 1.8.6
 
 # This file describes the settings to be used by the documentation system
 # doxygen (www.doxygen.org) for a project.
 #
-# All text after a hash (#) is considered a comment and will be ignored.
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
 # The format is:
-#       TAG = value [value, ...]
-# For lists items can also be appended using:
-#       TAG += value [value, ...]
-# Values that contain spaces should be placed between quotes (").
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
 
 #---------------------------------------------------------------------------
 # Project related configuration options
 #---------------------------------------------------------------------------
 
 # This tag specifies the encoding used for all characters in the config file
-# that follow. The default is UTF-8 which is also the encoding used for all
-# text before the first occurrence of this tag. Doxygen uses libiconv (or the
-# iconv built into libc) for the transcoding. See
-# http://www.gnu.org/software/libiconv for the list of possible encodings.
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
 
 DOXYFILE_ENCODING      = UTF-8
 
-# The PROJECT_NAME tag is a single word (or sequence of words) that should
-# identify the project. Note that if you do not use Doxywizard you need
-# to put quotes around the project name if it contains spaces.
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
 
 PROJECT_NAME           = "NMEAlib"
 
-# The PROJECT_NUMBER tag can be used to enter a project or revision number.
-# This could be handy for archiving the generated documentation or
-# if some version control system is used.
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
 
 PROJECT_NUMBER         =
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
-# for a project that appears at the top of each page and should give viewer
-# quick idea about the purpose of the project. Keep the description short.
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
 
 PROJECT_BRIEF          =
 
-# With the PROJECT_LOGO tag one can specify an logo or icon that is
-# included in the documentation. The maximum height of the logo should not
-# exceed 55 pixels and the maximum width should not exceed 200 pixels.
-# Doxygen will copy the logo to the output directory.
+# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
+# the documentation. The maximum height of the logo should not exceed 55 pixels
+# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
+# to the output directory.
 
 PROJECT_LOGO           =
 
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
-# base path where the generated documentation will be put.
-# If a relative path is entered, it will be relative to the location
-# where doxygen was started. If left blank the current directory will be used.
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
 
 OUTPUT_DIRECTORY       =
 
-# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
-# 4096 sub-directories (in 2 levels) under the output directory of each output
-# format and will distribute the generated files over these directories.
-# Enabling this option can be useful when feeding doxygen a huge amount of
-# source files, where putting all generated files in the same directory would
-# otherwise cause performance problems for the file system.
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
 
 CREATE_SUBDIRS         = NO
 
 # The OUTPUT_LANGUAGE tag is used to specify the language in which all
 # documentation generated by doxygen is written. Doxygen will use this
 # information to generate all constant output in the proper language.
-# The default language is English, other supported languages are:
-# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
-# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
-# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
-# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
-# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
-# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
 
 OUTPUT_LANGUAGE        = English
 
-# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
-# include brief member descriptions after the members that are listed in
-# the file and class documentation (similar to JavaDoc).
-# Set to NO to disable this.
+# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
 
 BRIEF_MEMBER_DESC      = YES
 
-# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
-# the brief description of a member or function before the detailed description.
-# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
 # brief descriptions will be completely suppressed.
+# The default value is: YES.
 
 REPEAT_BRIEF           = YES
 
-# This tag implements a quasi-intelligent brief description abbreviator
-# that is used to form the text in various listings. Each string
-# in this list, if found as the leading text of the brief description, will be
-# stripped from the text and the result after processing the whole list, is
-# used as the annotated text. Otherwise, the brief description is used as-is.
-# If left blank, the following values are used ("$name" is automatically
-# replaced with the name of the entity): "The $name class" "The $name widget"
-# "The $name file" "is" "provides" "specifies" "contains"
-# "represents" "a" "an" "the"
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
 
 ABBREVIATE_BRIEF       =
 
 # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
-# Doxygen will generate a detailed section even if there is only a brief
+# doxygen will generate a detailed section even if there is only a brief
 # description.
+# The default value is: NO.
 
 ALWAYS_DETAILED_SEC    = NO
 
@@ -112,169 +123,204 @@ ALWAYS_DETAILED_SEC    = NO
 # inherited members of a class in the documentation of that class as if those
 # members were ordinary class members. Constructors, destructors and assignment
 # operators of the base classes will not be shown.
+# The default value is: NO.
 
 INLINE_INHERITED_MEMB  = NO
 
-# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
-# path before files name in the file list and in the header files. If set
-# to NO the shortest path that makes the file name unique will be used.
+# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
 
 FULL_PATH_NAMES        = NO
 
-# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
-# can be used to strip a user-defined part of the path. Stripping is
-# only done if one of the specified strings matches the left-hand part of
-# the path. The tag can be used to show relative paths in the file list.
-# If left blank the directory from which doxygen is run is used as the
-# path to strip.
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
 
 STRIP_FROM_PATH        =
 
-# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
-# the path mentioned in the documentation of a class, which tells
-# the reader which header file to include in order to use a class.
-# If left blank only the name of the header file containing the class
-# definition is used. Otherwise one should specify the include paths that
-# are normally passed to the compiler using the -I flag.
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
 
 STRIP_FROM_INC_PATH    =
 
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
-# (but less readable) file names. This can be useful if your file system
-# doesn't support long names like on DOS, Mac, or CD-ROM.
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
 
 SHORT_NAMES            = NO
 
-# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
-# will interpret the first line (until the first dot) of a JavaDoc-style
-# comment as the brief description. If set to NO, the JavaDoc
-# comments will behave just like regular Qt-style comments
-# (thus requiring an explicit @brief command for a brief description.)
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
 
 JAVADOC_AUTOBRIEF      = YES
 
-# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
-# interpret the first line (until the first dot) of a Qt-style
-# comment as the brief description. If set to NO, the comments
-# will behave just like regular Qt-style comments (thus requiring
-# an explicit \brief command for a brief description.)
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
 
 QT_AUTOBRIEF           = NO
 
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
-# treat a multi-line C++ special comment block (i.e. a block of //! or ///
-# comments) as a brief description. This used to be the default behaviour.
-# The new default is to treat a multi-line C++ comment block as a detailed
-# description. Set this tag to YES if you prefer the old behaviour instead.
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
 
 MULTILINE_CPP_IS_BRIEF = NO
 
-# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
-# member inherits the documentation from any documented member that it
-# re-implements.
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
 
 INHERIT_DOCS           = YES
 
-# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
-# a new page for each member. If set to NO, the documentation of a member will
-# be part of the file/class/namespace that contains it.
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
+# new page for each member. If set to NO, the documentation of a member will be
+# part of the file/class/namespace that contains it.
+# The default value is: NO.
 
 SEPARATE_MEMBER_PAGES  = NO
 
-# The TAB_SIZE tag can be used to set the number of spaces in a tab.
-# Doxygen uses this value to replace tabs by spaces in code fragments.
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
 
 TAB_SIZE               = 2
 
-# This tag can be used to specify a number of aliases that acts
-# as commands in the documentation. An alias has the form "name=value".
-# For example adding "sideeffect=\par Side Effects:\n" will allow you to
-# put the command \sideeffect (or @sideeffect) in the documentation, which
-# will result in a user-defined paragraph with heading "Side Effects:".
-# You can put \n's in the value part of an alias to insert newlines.
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
 
 ALIASES                =
 
 # This tag can be used to specify a number of word-keyword mappings (TCL only).
-# A mapping has the form "name=value". For example adding
-# "class=itcl::class" will allow you to use the command class in the
-# itcl::class meaning.
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
 
 TCL_SUBST              =
 
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
-# sources only. Doxygen will then generate output that is more tailored for C.
-# For instance, some of the names that are used will be different. The list
-# of all members will be omitted, etc.
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
 
 OPTIMIZE_OUTPUT_FOR_C  = YES
 
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
-# sources only. Doxygen will then generate output that is more tailored for
-# Java. For instance, namespaces will be presented as packages, qualified
-# scopes will look different, etc.
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
 
 OPTIMIZE_OUTPUT_JAVA   = NO
 
 # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
-# sources only. Doxygen will then generate output that is more tailored for
-# Fortran.
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
 
 OPTIMIZE_FOR_FORTRAN   = NO
 
 # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
-# sources. Doxygen will then generate output that is tailored for
-# VHDL.
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
 
 OPTIMIZE_OUTPUT_VHDL   = NO
 
 # Doxygen selects the parser to use depending on the extension of the files it
-# parses. With this tag you can assign which parser to use for a given extension.
-# Doxygen has a built-in mapping, but you can override or extend it using this
-# tag. The format is ext=language, where ext is a file extension, and language
-# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C,
-# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make
 # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
-# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions
-# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+# (default is Fortran), use: inc=Fortran f=C.
+#
+# Note For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
 
 EXTENSION_MAPPING      =
 
-# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
-# comments according to the Markdown format, which allows for more readable
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
 # documentation. See http://daringfireball.net/projects/markdown/ for details.
-# The output of markdown processing is further processed by doxygen, so you
-# can mix doxygen, HTML, and XML commands with Markdown formatting.
-# Disable only in case of backward compatibilities issues.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
 
 MARKDOWN_SUPPORT       = YES
 
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT       = YES
+
 # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
-# to include (a tag file for) the STL sources as input, then you should
-# set this tag to YES in order to let doxygen match functions declarations and
-# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
-# func(std::string) {}). This also makes the inheritance and collaboration
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
 # diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
 
 BUILTIN_STL_SUPPORT    = NO
 
 # If you use Microsoft's C++/CLI language, you should set this option to YES to
 # enable parsing support.
+# The default value is: NO.
 
 CPP_CLI_SUPPORT        = NO
 
-# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
-# Doxygen will parse them like normal C++ but will assume all classes use public
-# instead of private inheritance when no explicit protection keyword is present.
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
 
 SIP_SUPPORT            = NO
 
-# For Microsoft's IDL there are propget and propput attributes to indicate getter
-# and setter methods for a property. Setting this option to YES (the default)
-# will make doxygen replace the get and set methods by a property in the
-# documentation. This will only work if the methods are indeed getting or
-# setting a simple type. If this is not the case, or you want to show the
-# methods anyway, you should set this option to NO.
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
 
 IDL_PROPERTY_SUPPORT   = YES
 
@@ -282,67 +328,61 @@ IDL_PROPERTY_SUPPORT   = YES
 # tag is set to YES, then doxygen will reuse the documentation of the first
 # member in the group (if any) for the other members of the group. By default
 # all members of a group must be documented explicitly.
+# The default value is: NO.
 
 DISTRIBUTE_GROUP_DOC   = NO
 
-# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
-# the same type (for instance a group of public functions) to be put as a
-# subgroup of that type (e.g. under the Public Functions section). Set it to
-# NO to prevent subgrouping. Alternatively, this can be done per class using
-# the \nosubgrouping command.
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
 
 SUBGROUPING            = YES
 
-# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
-# unions are shown inside the group in which they are included (e.g. using
-# @ingroup) instead of on a separate page (for HTML and Man pages) or
-# section (for LaTeX and RTF).
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
 
 INLINE_GROUPED_CLASSES = NO
 
-# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
-# unions with only public data fields will be shown inline in the documentation
-# of the scope in which they are defined (i.e. file, namespace, or group
-# documentation), provided this scope is documented. If set to NO (the default),
-# structs, classes, and unions are shown on a separate page (for HTML and Man
-# pages) or section (for LaTeX and RTF).
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
 
 INLINE_SIMPLE_STRUCTS  = NO
 
-# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
-# is documented as struct, union, or enum with the name of the typedef. So
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
 # typedef struct TypeS {} TypeT, will appear in the documentation as a struct
 # with name TypeT. When disabled the typedef will appear as a member of a file,
-# namespace, or class. And the struct will be named TypeS. This can typically
-# be useful for C code in case the coding convention dictates that all compound
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
 # types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
 
 TYPEDEF_HIDES_STRUCT   = NO
 
-# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
-# determine which symbols to keep in memory and which to flush to disk.
-# When the cache is full, less often used symbols will be written to disk.
-# For small to medium size projects (<1000 input files) the default value is
-# probably good enough. For larger projects a too small cache size can cause
-# doxygen to be busy swapping symbols to and from disk most of the time
-# causing a significant performance penalty.
-# If the system has enough physical memory increasing the cache will improve the
-# performance by keeping more symbols in memory. Note that the value works on
-# a logarithmic scale so increasing the size by one will roughly double the
-# memory usage. The cache size is given by this formula:
-# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
-# corresponding to a cache size of 2^16 = 65536 symbols.
-
-SYMBOL_CACHE_SIZE      = 0
-
-# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be
-# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
-# their name and scope. Since this can be an expensive process and often the
-# same symbol appear multiple times in the code, doxygen keeps a cache of
-# pre-resolved symbols. If the cache is too small doxygen will become slower.
-# If the cache is too large, memory is wasted. The cache size is given by this
-# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0,
-# corresponding to a cache size of 2^16 = 65536 symbols.
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
 
 LOOKUP_CACHE_SIZE      = 0
 
@@ -351,341 +391,392 @@ LOOKUP_CACHE_SIZE      = 0
 #---------------------------------------------------------------------------
 
 # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
-# documentation are documented, even if no documentation was available.
-# Private class members and static file members will be hidden unless
-# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
 
 EXTRACT_ALL            = YES
 
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
-# will be included in the documentation.
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
 
 EXTRACT_PRIVATE        = YES
 
-# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal scope will be included in the documentation.
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
 
 EXTRACT_PACKAGE        = NO
 
-# If the EXTRACT_STATIC tag is set to YES all static members of a file
-# will be included in the documentation.
+# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
 
 EXTRACT_STATIC         = YES
 
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
-# defined locally in source files will be included in the documentation.
-# If set to NO only classes defined in header files are included.
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
 
 EXTRACT_LOCAL_CLASSES  = YES
 
-# This flag is only useful for Objective-C code. When set to YES local
-# methods, which are defined in the implementation section but not in
-# the interface are included in the documentation.
-# If set to NO (the default) only methods in the interface are included.
+# This flag is only useful for Objective-C code. When set to YES local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO only methods in the interface are
+# included.
+# The default value is: NO.
 
 EXTRACT_LOCAL_METHODS  = YES
 
 # If this flag is set to YES, the members of anonymous namespaces will be
 # extracted and appear in the documentation as a namespace called
-# 'anonymous_namespace{file}', where file will be replaced with the base
-# name of the file that contains the anonymous namespace. By default
-# anonymous namespaces are hidden.
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
 
 EXTRACT_ANON_NSPACES   = YES
 
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
-# undocumented members of documented classes, files or namespaces.
-# If set to NO (the default) these members will be included in the
-# various overviews, but no documentation section is generated.
-# This option has no effect if EXTRACT_ALL is enabled.
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
 
 HIDE_UNDOC_MEMBERS     = NO
 
-# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
-# undocumented classes that are normally visible in the class hierarchy.
-# If set to NO (the default) these classes will be included in the various
-# overviews. This option has no effect if EXTRACT_ALL is enabled.
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO these classes will be included in the various overviews. This option has
+# no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
 
 HIDE_UNDOC_CLASSES     = NO
 
-# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
-# friend (class|struct|union) declarations.
-# If set to NO (the default) these declarations will be included in the
-# documentation.
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO these declarations will be
+# included in the documentation.
+# The default value is: NO.
 
 HIDE_FRIEND_COMPOUNDS  = NO
 
-# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
-# documentation blocks found inside the body of a function.
-# If set to NO (the default) these blocks will be appended to the
-# function's detailed documentation block.
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
 
 HIDE_IN_BODY_DOCS      = NO
 
-# The INTERNAL_DOCS tag determines if documentation
-# that is typed after a \internal command is included. If the tag is set
-# to NO (the default) then the documentation will be excluded.
-# Set it to YES to include the internal documentation.
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
 
 INTERNAL_DOCS          = NO
 
-# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
-# file names in lower-case letters. If set to YES upper-case letters are also
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES upper-case letters are also
 # allowed. This is useful if you have classes or files whose names only differ
 # in case and if your file system supports case sensitive file names. Windows
 # and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
 
 CASE_SENSE_NAMES       = YES
 
-# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
-# will show members with their full class and namespace scopes in the
-# documentation. If set to YES the scope will be hidden.
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES the
+# scope will be hidden.
+# The default value is: NO.
 
 HIDE_SCOPE_NAMES       = NO
 
-# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
-# will put a list of the files that are included by a file in the documentation
-# of that file.
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
 
 SHOW_INCLUDE_FILES     = YES
 
-# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
-# will list include files with double quotes in the documentation
-# rather than with sharp brackets.
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC  = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
 
 FORCE_LOCAL_INCLUDES   = NO
 
-# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
-# is inserted in the documentation for inline members.
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
 
 INLINE_INFO            = YES
 
-# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
-# will sort the (detailed) documentation of file and class members
-# alphabetically by member name. If set to NO the members will appear in
-# declaration order.
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order.
+# The default value is: YES.
 
 SORT_MEMBER_DOCS       = YES
 
-# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
-# brief documentation of file, namespace and class members alphabetically
-# by member name. If set to NO (the default) the members will appear in
-# declaration order.
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
 
 SORT_BRIEF_DOCS        = NO
 
-# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
-# will sort the (brief and detailed) documentation of class members so that
-# constructors and destructors are listed first. If set to NO (the default)
-# the constructors will appear in the respective orders defined by
-# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
-# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
-# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
 
 SORT_MEMBERS_CTORS_1ST = NO
 
-# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
-# hierarchy of group names into alphabetical order. If set to NO (the default)
-# the group names will appear in their defined order.
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
 
 SORT_GROUP_NAMES       = NO
 
-# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
-# sorted by fully-qualified names, including namespaces. If set to
-# NO (the default), the class list will be sorted only by class name,
-# not including the namespace part.
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
 # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
-# Note: This option applies only to the class list, not to the
-# alphabetical list.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
 
 SORT_BY_SCOPE_NAME     = NO
 
-# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
-# do proper type resolution of all parameters of a function it will reject a
-# match between the prototype and the implementation of a member function even
-# if there is only one candidate or it is obvious which candidate to choose
-# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
-# will still accept a match between prototype and implementation in such cases.
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
 
 STRICT_PROTO_MATCHING  = NO
 
-# The GENERATE_TODOLIST tag can be used to enable (YES) or
-# disable (NO) the todo list. This list is created by putting \todo
-# commands in the documentation.
+# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
+# todo list. This list is created by putting \todo commands in the
+# documentation.
+# The default value is: YES.
 
 GENERATE_TODOLIST      = YES
 
-# The GENERATE_TESTLIST tag can be used to enable (YES) or
-# disable (NO) the test list. This list is created by putting \test
-# commands in the documentation.
+# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
+# test list. This list is created by putting \test commands in the
+# documentation.
+# The default value is: YES.
 
 GENERATE_TESTLIST      = YES
 
-# The GENERATE_BUGLIST tag can be used to enable (YES) or
-# disable (NO) the bug list. This list is created by putting \bug
-# commands in the documentation.
+# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
 
 GENERATE_BUGLIST       = YES
 
-# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
-# disable (NO) the deprecated list. This list is created by putting
-# \deprecated commands in the documentation.
+# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
 
 GENERATE_DEPRECATEDLIST= YES
 
-# The ENABLED_SECTIONS tag can be used to enable conditional
-# documentation sections, marked by \if sectionname ... \endif.
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
 
 ENABLED_SECTIONS       =
 
-# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
-# the initial value of a variable or macro consists of for it to appear in
-# the documentation. If the initializer consists of more lines than specified
-# here it will be hidden. Use a value of 0 to hide initializers completely.
-# The appearance of the initializer of individual variables and macros in the
-# documentation can be controlled using \showinitializer or \hideinitializer
-# command in the documentation regardless of this setting.
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
 
 MAX_INITIALIZER_LINES  = 30
 
-# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
-# at the bottom of the documentation of classes and structs. If set to YES the
-# list will mention the files that were used to generate the documentation.
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES the list
+# will mention the files that were used to generate the documentation.
+# The default value is: YES.
 
 SHOW_USED_FILES        = YES
 
-# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
-# This will remove the Files entry from the Quick Index and from the
-# Folder Tree View (if specified). The default is YES.
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
 
 SHOW_FILES             = YES
 
-# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
-# Namespaces page.
-# This will remove the Namespaces entry from the Quick Index
-# and from the Folder Tree View (if specified). The default is YES.
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
 
 SHOW_NAMESPACES        = YES
 
 # The FILE_VERSION_FILTER tag can be used to specify a program or script that
 # doxygen should invoke to get the current version for each file (typically from
 # the version control system). Doxygen will invoke the program by executing (via
-# popen()) the command <command> <input-file>, where <command> is the value of
-# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
-# provided by doxygen. Whatever the program writes to standard output
-# is used as the file version. See the manual for examples.
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
 
 FILE_VERSION_FILTER    =
 
 # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
 # by doxygen. The layout file controls the global structure of the generated
 # output files in an output format independent way. To create the layout file
-# that represents doxygen's defaults, run doxygen with the -l option.
-# You can optionally specify a file name after the option, if omitted
-# DoxygenLayout.xml will be used as the name of the layout file.
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
 
 LAYOUT_FILE            =
 
-# The CITE_BIB_FILES tag can be used to specify one or more bib files
-# containing the references data. This must be a list of .bib files. The
-# .bib extension is automatically appended if omitted. Using this command
-# requires the bibtex tool to be installed. See also
-# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
-# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
-# feature you need bibtex and perl available in the search path.
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. Do not use file names with spaces, bibtex cannot handle them. See
+# also \cite for info how to create references.
 
 CITE_BIB_FILES         =
 
 #---------------------------------------------------------------------------
-# configuration options related to warning and progress messages
+# Configuration options related to warning and progress messages
 #---------------------------------------------------------------------------
 
-# The QUIET tag can be used to turn on/off the messages that are generated
-# by doxygen. Possible values are YES and NO. If left blank NO is used.
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
 
 QUIET                  = YES
 
 # The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated by doxygen. Possible values are YES and NO. If left blank
-# NO is used.
+# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
 
 WARNINGS               = YES
 
-# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
-# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
-# automatically be disabled.
+# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
 
 WARN_IF_UNDOCUMENTED   = YES
 
-# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
-# potential errors in the documentation, such as not documenting some
-# parameters in a documented function, or documenting parameters that
-# don't exist or using markup commands wrongly.
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
 
 WARN_IF_DOC_ERROR      = YES
 
-# The WARN_NO_PARAMDOC option can be enabled to get warnings for
-# functions that are documented, but have no documentation for their parameters
-# or return value. If set to NO (the default) doxygen will only warn about
-# wrong or incomplete parameter documentation, but not about the absence of
-# documentation.
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO doxygen will only warn about wrong or incomplete parameter
+# documentation, but not about the absence of documentation.
+# The default value is: NO.
 
 WARN_NO_PARAMDOC       = YES
 
-# The WARN_FORMAT tag determines the format of the warning messages that
-# doxygen can produce. The string should contain the $file, $line, and $text
-# tags, which will be replaced by the file and line number from which the
-# warning originated and the warning text. Optionally the format may contain
-# $version, which will be replaced by the version of the file (if it could
-# be obtained via FILE_VERSION_FILTER)
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
 
 WARN_FORMAT            = "$file:$line: $text"
 
-# The WARN_LOGFILE tag can be used to specify a file to which warning
-# and error messages should be written. If left blank the output is written
-# to stderr.
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
 
 WARN_LOGFILE           =
 
 #---------------------------------------------------------------------------
-# configuration options related to the input files
+# Configuration options related to the input files
 #---------------------------------------------------------------------------
 
-# The INPUT tag can be used to specify the files and/or directories that contain
-# documented source files. You may enter file names like "myfile.cpp" or
-# directories like "/usr/src/myproject". Separate the files or directories
-# with spaces.
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
 
 INPUT                  = ../src \
                          ../include/nmea
 
 # This tag can be used to specify the character encoding of the source files
-# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
-# also the default input encoding. Doxygen uses libiconv (or the iconv built
-# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
-# the list of possible encodings.
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
 
 INPUT_ENCODING         = UTF-8
 
 # If the value of the INPUT tag contains directories, you can use the
-# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
-# blank the following patterns are tested:
-# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
-# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
-# *.f90 *.f *.for *.vhd *.vhdl
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
 
 FILE_PATTERNS          = *.c \
                          *.h
 
-# The RECURSIVE tag can be used to turn specify whether or not subdirectories
-# should be searched for input files as well. Possible values are YES and NO.
-# If left blank NO is used.
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
 
 RECURSIVE              = YES
 
 # The EXCLUDE tag can be used to specify files and/or directories that should be
 # excluded from the INPUT source files. This way you can easily exclude a
 # subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
 # Note that relative paths are relative to the directory from which doxygen is
 # run.
 
@@ -694,14 +785,16 @@ EXCLUDE                =
 # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
 # directories that are symbolic links (a Unix file system feature) are excluded
 # from the input.
+# The default value is: NO.
 
 EXCLUDE_SYMLINKS       = NO
 
 # If the value of the INPUT tag contains directories, you can use the
 # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
-# certain files from those directories. Note that the wildcards are matched
-# against the file with absolute path, so to exclude all test directories
-# for example use the pattern */test/*
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
 
 EXCLUDE_PATTERNS       =
 
@@ -710,755 +803,1080 @@ EXCLUDE_PATTERNS       =
 # output. The symbol name can be a fully qualified name, a word, or if the
 # wildcard * is used, a substring. Examples: ANamespace, AClass,
 # AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
 
 EXCLUDE_SYMBOLS        =
 
-# The EXAMPLE_PATH tag can be used to specify one or more files or
-# directories that contain example code fragments that are included (see
-# the \include command).
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
 
 EXAMPLE_PATH           =
 
 # If the value of the EXAMPLE_PATH tag contains directories, you can use the
-# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
-# blank all files are included.
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
 
 EXAMPLE_PATTERNS       =
 
 # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
-# searched for input files to be used with the \include or \dontinclude
-# commands irrespective of the value of the RECURSIVE tag.
-# Possible values are YES and NO. If left blank NO is used.
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
 
 EXAMPLE_RECURSIVE      = NO
 
-# The IMAGE_PATH tag can be used to specify one or more files or
-# directories that contain image that are included in the documentation (see
-# the \image command).
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
 
 IMAGE_PATH             =
 
 # The INPUT_FILTER tag can be used to specify a program that doxygen should
 # invoke to filter for each input file. Doxygen will invoke the filter program
-# by executing (via popen()) the command <filter> <input-file>, where <filter>
-# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
-# input file. Doxygen will then use the output that the filter program writes
-# to standard output.
-# If FILTER_PATTERNS is specified, this tag will be
-# ignored.
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
 
 INPUT_FILTER           =
 
 # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
-# basis.
-# Doxygen will compare the file name with each pattern and apply the
-# filter if there is a match.
-# The filters are a list of the form:
-# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
-# info on how filters are used. If FILTER_PATTERNS is empty or if
-# non of the patterns match the file name, INPUT_FILTER is applied.
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
 
 FILTER_PATTERNS        =
 
 # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
-# INPUT_FILTER) will be used to filter the input files when producing source
-# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# INPUT_FILTER ) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
 
 FILTER_SOURCE_FILES    = NO
 
 # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
-# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
-# and it is also possible to disable source filtering for a specific pattern
-# using *.ext= (so without naming a filter). This option only has effect when
-# FILTER_SOURCE_FILES is enabled.
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
 
 FILTER_SOURCE_PATTERNS =
 
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
 #---------------------------------------------------------------------------
-# configuration options related to source browsing
+# Configuration options related to source browsing
 #---------------------------------------------------------------------------
 
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will
-# be generated. Documented entities will be cross-referenced with these sources.
-# Note: To get rid of all source code in the generated output, make sure also
-# VERBATIM_HEADERS is set to NO.
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
 
 SOURCE_BROWSER         = YES
 
-# Setting the INLINE_SOURCES tag to YES will include the body
-# of functions and classes directly in the documentation.
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
 
 INLINE_SOURCES         = NO
 
-# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
-# doxygen to hide any special comment blocks from generated source code
-# fragments. Normal C, C++ and Fortran comments will always remain visible.
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
 
 STRIP_CODE_COMMENTS    = NO
 
-# If the REFERENCED_BY_RELATION tag is set to YES
-# then for each documented function all documented
-# functions referencing it will be listed.
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
 
 REFERENCED_BY_RELATION = YES
 
-# If the REFERENCES_RELATION tag is set to YES
-# then for each documented function all documented entities
-# called/used by that function will be listed.
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
 
 REFERENCES_RELATION    = YES
 
-# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
-# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
-# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
-# link to the source code.
-# Otherwise they will link to the documentation.
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
 
 REFERENCES_LINK_SOURCE = YES
 
-# If the USE_HTAGS tag is set to YES then the references to source code
-# will point to the HTML generated by the htags(1) tool instead of doxygen
-# built-in source browser. The htags tool is part of GNU's global source
-# tagging system (see http://www.gnu.org/software/global/global.html). You
-# will need version 4.8.6 or higher.
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS        = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
 
 USE_HTAGS              = NO
 
-# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
-# will generate a verbatim copy of the header file for each class for
-# which an include is specified. Set to NO to disable this.
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
 
 VERBATIM_HEADERS       = YES
 
 #---------------------------------------------------------------------------
-# configuration options related to the alphabetical class index
+# Configuration options related to the alphabetical class index
 #---------------------------------------------------------------------------
 
-# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
-# of all compounds will be generated. Enable this if the project
-# contains a lot of classes, structs, unions or interfaces.
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
 
 ALPHABETICAL_INDEX     = YES
 
-# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
-# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
-# in which this list will be split (can be a number in the range [1..20])
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
 
 COLS_IN_ALPHA_INDEX    = 2
 
-# In case all classes in a project start with a common prefix, all
-# classes will be put under the same header in the alphabetical index.
-# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
-# should be ignored while generating the index headers.
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
 
 IGNORE_PREFIX          =
 
 #---------------------------------------------------------------------------
-# configuration options related to the HTML output
+# Configuration options related to the HTML output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
-# generate HTML output.
+# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# The default value is: YES.
 
 GENERATE_HTML          = YES
 
-# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `html' will be used as the default path.
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 HTML_OUTPUT            = html
 
-# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
-# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
-# doxygen will generate files with .html extension.
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 HTML_FILE_EXTENSION    = .html
 
-# The HTML_HEADER tag can be used to specify a personal HTML header for
-# each generated HTML page. If it is left blank doxygen will generate a
-# standard header. Note that when using a custom header you are responsible
-#  for the proper inclusion of any scripts and style sheets that doxygen
-# needs, which is dependent on the configuration options used.
-# It is advised to generate a default header using "doxygen -w html
-# header.html footer.html stylesheet.css YourConfigFile" and then modify
-# that header. Note that the header is subject to change so you typically
-# have to redo this when upgrading to a newer version of doxygen or when
-# changing the value of configuration settings such as GENERATE_TREEVIEW!
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 HTML_HEADER            =
 
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for
-# each generated HTML page. If it is left blank doxygen will generate a
-# standard footer.
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 HTML_FOOTER            =
 
-# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
-# style sheet that is used by each HTML page. It can be used to
-# fine-tune the look of the HTML output. If the tag is left blank doxygen
-# will generate a default style sheet. Note that doxygen will try to copy
-# the style sheet file to the HTML output directory, so don't put your own
-# style sheet in the HTML output directory as well, or it will be erased!
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 HTML_STYLESHEET        =
 
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user-
+# defined cascading style sheet that is included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefor more robust against future updates.
+# Doxygen will copy the style sheet file to the output directory. For an example
+# see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET  =
+
 # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
 # other source files which should be copied to the HTML output directory. Note
 # that these files will be copied to the base HTML output directory. Use the
-# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
-# files. In the HTML_STYLESHEET file, use the file name only. Also note that
-# the files will be copied as-is; there are no commands or markers available.
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 HTML_EXTRA_FILES       =
 
-# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
-# Doxygen will adjust the colors in the style sheet and background images
-# according to this color. Hue is specified as an angle on a colorwheel,
-# see http://en.wikipedia.org/wiki/Hue for more information.
-# For instance the value 0 represents red, 60 is yellow, 120 is green,
-# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
-# The allowed range is 0 to 359.
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the stylesheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 HTML_COLORSTYLE_HUE    = 220
 
-# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
-# the colors in the HTML output. For a value of 0 the output will use
-# grayscales only. A value of 255 will produce the most vivid colors.
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 HTML_COLORSTYLE_SAT    = 100
 
-# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
-# the luminance component of the colors in the HTML output. Values below
-# 100 gradually make the output lighter, whereas values above 100 make
-# the output darker. The value divided by 100 is the actual gamma applied,
-# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
-# and 100 does not change the gamma.
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 HTML_COLORSTYLE_GAMMA  = 80
 
 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
-# page will contain the date and time when the page was generated. Setting
-# this to NO can help when comparing the output of multiple runs.
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 HTML_TIMESTAMP         = YES
 
 # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
 # documentation will contain sections that can be hidden and shown after the
 # page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 HTML_DYNAMIC_SECTIONS  = NO
 
-# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of
-# entries shown in the various tree structured indices initially; the user
-# can expand and collapse entries dynamically later on. Doxygen will expand
-# the tree to such a level that at most the specified number of entries are
-# visible (unless a fully collapsed tree already exceeds this amount).
-# So setting the number of entries 1 will produce a full collapsed tree by
-# default. 0 is a special value representing an infinite number of entries
-# and will result in a full expanded tree by default.
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 HTML_INDEX_NUM_ENTRIES = 100
 
-# If the GENERATE_DOCSET tag is set to YES, additional index files
-# will be generated that can be used as input for Apple's Xcode 3
-# integrated development environment, introduced with OSX 10.5 (Leopard).
-# To create a documentation set, doxygen will generate a Makefile in the
-# HTML output directory. Running make will produce the docset in that
-# directory and running "make install" will install the docset in
-# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
-# it at startup.
-# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
 # for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 GENERATE_DOCSET        = NO
 
-# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
-# feed. A documentation feed provides an umbrella under which multiple
-# documentation sets from a single provider (such as a company or product suite)
-# can be grouped.
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
 
 DOCSET_FEEDNAME        = "Doxygen generated docs"
 
-# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
-# should uniquely identify the documentation set bundle. This should be a
-# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
-# will append .docset to the name.
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
 
 DOCSET_BUNDLE_ID       = org.doxygen.Project
 
-# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
 # the documentation publisher. This should be a reverse domain-name style
 # string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
 
 DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
 
-# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
 
 DOCSET_PUBLISHER_NAME  = Publisher
 
-# If the GENERATE_HTMLHELP tag is set to YES, additional index files
-# will be generated that can be used as input for tools like the
-# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
-# of the generated HTML documentation.
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 GENERATE_HTMLHELP      = NO
 
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
-# be used to specify the file name of the resulting .chm file. You
-# can add a path in front of the file if the result should not be
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
 # written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
 CHM_FILE               = nmealib.chm
 
-# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
-# be used to specify the location (absolute path including file name) of
-# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
-# the HTML help compiler on the generated index.hhp.
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
 HHC_LOCATION           =
 
-# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
-# controls if a separate .chi index file is generated (YES) or that
-# it should be included in the master .chm file (NO).
+# The GENERATE_CHI flag controls if a separate .chi index file is generated (
+# YES) or that it should be included in the master .chm file ( NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
 GENERATE_CHI           = NO
 
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
-# is used to encode HtmlHelp index (hhk), content (hhc) and project file
-# content.
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
 CHM_INDEX_ENCODING     =
 
-# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
-# controls whether a binary table of contents is generated (YES) or a
-# normal table of contents (NO) in the .chm file.
+# The BINARY_TOC flag controls whether a binary table of contents is generated (
+# YES) or a normal table of contents ( NO) in the .chm file.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
 BINARY_TOC             = NO
 
-# The TOC_EXPAND flag can be set to YES to add extra items for group members
-# to the contents of the HTML help documentation and to the tree view.
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
 TOC_EXPAND             = YES
 
 # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
-# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
-# that can be used as input for Qt's qhelpgenerator to generate a
-# Qt Compressed Help (.qch) of the generated HTML documentation.
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 GENERATE_QHP           = NO
 
-# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
-# be used to specify the file name of the resulting .qch file.
-# The path specified is relative to the HTML output folder.
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
 
 QCH_FILE               =
 
-# The QHP_NAMESPACE tag specifies the namespace to use when generating
-# Qt Help Project output. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#namespace
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
 
 QHP_NAMESPACE          = org.doxygen.Project
 
-# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
-# Qt Help Project output. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
 
 QHP_VIRTUAL_FOLDER     = doc
 
-# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
-# add. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#custom-filters
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
 
 QHP_CUST_FILTER_NAME   =
 
-# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
-# custom filter to add. For more information please see
-# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
-# Qt Help Project / Custom Filters</a>.
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
 
 QHP_CUST_FILTER_ATTRS  =
 
 # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
-# project's
-# filter section matches.
-# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
-# Qt Help Project / Filter Attributes</a>.
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
 
 QHP_SECT_FILTER_ATTRS  =
 
-# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
-# be used to specify the location of Qt's qhelpgenerator.
-# If non-empty doxygen will try to run qhelpgenerator on the generated
-# .qhp file.
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
 
 QHG_LOCATION           =
 
-# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
-#  will be generated, which together with the HTML files, form an Eclipse help
-# plugin. To install this plugin and make it available under the help contents
-# menu in Eclipse, the contents of the directory containing the HTML and XML
-# files needs to be copied into the plugins directory of eclipse. The name of
-# the directory within the plugins directory should be the same as
-# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
-# the help appears.
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 GENERATE_ECLIPSEHELP   = NO
 
-# A unique identifier for the eclipse help plugin. When installing the plugin
-# the directory name containing the HTML and XML files should also have
-# this name.
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
 
 ECLIPSE_DOC_ID         = org.doxygen.Project
 
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
-# at top of each HTML page. The value NO (the default) enables the index and
-# the value YES disables it. Since the tabs have the same information as the
-# navigation tree you can set this option to NO if you already set
-# GENERATE_TREEVIEW to YES.
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 DISABLE_INDEX          = NO
 
 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
-# structure should be generated to display hierarchical information.
-# If the tag value is set to YES, a side panel will be generated
-# containing a tree-like index structure (just like the one that
-# is generated for HTML Help). For this to work a browser that supports
-# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
-# Windows users are probably better off using the HTML help feature.
-# Since the tree basically has the same information as the tab index you
-# could consider to set DISABLE_INDEX to NO when enabling this option.
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 GENERATE_TREEVIEW      = YES
 
-# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
-# (range [0,1..20]) that doxygen will group on one line in the generated HTML
-# documentation. Note that a value of 0 will completely suppress the enum
-# values from appearing in the overview section.
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 ENUM_VALUES_PER_LINE   = 4
 
-# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
-# used to set the initial width (in pixels) of the frame in which the tree
-# is shown.
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 TREEVIEW_WIDTH         = 250
 
-# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
-# links to external symbols imported via tag files in a separate window.
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 EXT_LINKS_IN_WINDOW    = NO
 
-# Use this tag to change the font size of Latex formulas included
-# as images in the HTML documentation. The default is 10. Note that
-# when you change the font size after a successful doxygen run you need
-# to manually remove any form_*.png images from the HTML output directory
-# to force them to be regenerated.
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 FORMULA_FONTSIZE       = 10
 
 # Use the FORMULA_TRANPARENT tag to determine whether or not the images
-# generated for formulas are transparent PNGs. Transparent PNGs are
-# not supported properly for IE 6.0, but are supported on all modern browsers.
-# Note that when changing this option you need to delete any form_*.png files
-# in the HTML output before the changes have effect.
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 FORMULA_TRANSPARENT    = YES
 
-# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
-# (see http://www.mathjax.org) which uses client side Javascript for the
-# rendering instead of using prerendered bitmaps. Use this if you do not
-# have LaTeX installed or if you want to formulas look prettier in the HTML
-# output. When enabled you may also need to install MathJax separately and
-# configure the path to it using the MATHJAX_RELPATH option.
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 USE_MATHJAX            = NO
 
-# When MathJax is enabled you need to specify the location relative to the
-# HTML output directory using the MATHJAX_RELPATH option. The destination
-# directory should contain the MathJax.js script. For instance, if the mathjax
-# directory is located at the same level as the HTML output directory, then
-# MATHJAX_RELPATH should be ../mathjax. The default value points to
-# the MathJax Content Delivery Network so you can quickly see the result without
-# installing MathJax.
-# However, it is strongly recommended to install a local
-# copy of MathJax from http://www.mathjax.org before deployment.
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT         = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
 
 MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
 
-# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
-# names that should be enabled during MathJax rendering.
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
 
 MATHJAX_EXTENSIONS     =
 
-# When the SEARCHENGINE tag is enabled doxygen will generate a search box
-# for the HTML output. The underlying search engine uses javascript
-# and DHTML and should work on any modern browser. Note that when using
-# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
-# (GENERATE_DOCSET) there is already a search function so this one should
-# typically be disabled. For large projects the javascript based search engine
-# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE       =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 SEARCHENGINE           = YES
 
 # When the SERVER_BASED_SEARCH tag is enabled the search engine will be
-# implemented using a PHP enabled web server instead of at the web client
-# using Javascript. Doxygen will generate the search PHP script and index
-# file to put on the web server. The advantage of the server
-# based approach is that it scales better to large projects and allows
-# full text search. The disadvantages are that it is more difficult to setup
-# and does not have live searching capabilities.
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavours of web server based searching depending on the
+# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
+# searching and an index file used by the script. When EXTERNAL_SEARCH is
+# enabled the indexing and searching needs to be provided by external tools. See
+# the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
 
 SERVER_BASED_SEARCH    = NO
 
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH        = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL       =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE        = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID     =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS  =
+
 #---------------------------------------------------------------------------
-# configuration options related to the LaTeX output
+# Configuration options related to the LaTeX output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
-# generate Latex output.
+# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# The default value is: YES.
 
 GENERATE_LATEX         = YES
 
-# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `latex' will be used as the default path.
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 LATEX_OUTPUT           = latex
 
 # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
-# invoked. If left blank `latex' will be used as the default command name.
-# Note that when enabling USE_PDFLATEX this option is only used for
-# generating bitmaps for formulas in the HTML output, but not in the
-# Makefile that is written to the output directory.
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 LATEX_CMD_NAME         = latex
 
-# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
-# generate index for LaTeX. If left blank `makeindex' will be used as the
-# default command name.
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 MAKEINDEX_CMD_NAME     = makeindex
 
-# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
-# LaTeX documents. This may be useful for small projects and may help to
-# save some trees in general.
+# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 COMPACT_LATEX          = NO
 
-# The PAPER_TYPE tag can be used to set the paper type that is used
-# by the printer. Possible values are: a4, letter, legal and
-# executive. If left blank a4wide will be used.
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 PAPER_TYPE             = a4wide
 
-# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
-# packages that should be included in the LaTeX output.
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 EXTRA_PACKAGES         =
 
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
-# the generated latex document. The header should contain everything until
-# the first chapter. If it is left blank doxygen will generate a
-# standard header. Notice: only use this tag if you know what you are doing!
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will
+# replace them by respectively the title of the page, the current date and time,
+# only the current date, the version number of doxygen, the project name (see
+# PROJECT_NAME), or the project number (see PROJECT_NUMBER).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 LATEX_HEADER           =
 
-# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
-# the generated latex document. The footer should contain everything after
-# the last chapter. If it is left blank doxygen will generate a
-# standard footer. Notice: only use this tag if you know what you are doing!
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 LATEX_FOOTER           =
 
-# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
-# is prepared for conversion to pdf (using ps2pdf). The pdf file will
-# contain links (just like the HTML output) instead of page references
-# This makes the output suitable for online browsing using a pdf viewer.
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES      =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 PDF_HYPERLINKS         = YES
 
-# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
-# plain latex in the generated Makefile. Set this option to YES to get a
+# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES to get a
 # higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 USE_PDFLATEX           = YES
 
-# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
-# command to the generated LaTeX files. This will instruct LaTeX to keep
-# running if errors occur, instead of asking the user for help.
-# This option is also used when generating formulas in HTML.
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 LATEX_BATCHMODE        = YES
 
-# If LATEX_HIDE_INDICES is set to YES then doxygen will not
-# include the index chapters (such as File Index, Compound Index, etc.)
-# in the output.
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 LATEX_HIDE_INDICES     = NO
 
-# If LATEX_SOURCE_CODE is set to YES then doxygen will include
-# source code with syntax highlighting in the LaTeX output.
-# Note that which sources are shown also depends on other settings
-# such as SOURCE_BROWSER.
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 LATEX_SOURCE_CODE      = NO
 
 # The LATEX_BIB_STYLE tag can be used to specify the style to use for the
-# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
-# http://en.wikipedia.org/wiki/BibTeX for more info.
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 LATEX_BIB_STYLE        = plain
 
 #---------------------------------------------------------------------------
-# configuration options related to the RTF output
+# Configuration options related to the RTF output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
-# The RTF output is optimized for Word 97 and may not look very pretty with
-# other RTF readers or editors.
+# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
 
 GENERATE_RTF           = NO
 
-# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `rtf' will be used as the default path.
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
 
 RTF_OUTPUT             = rtf
 
-# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
-# RTF documents. This may be useful for small projects and may help to
-# save some trees in general.
+# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
 
 COMPACT_RTF            = NO
 
-# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
-# will contain hyperlink fields. The RTF file will
-# contain links (just like the HTML output) instead of page references.
-# This makes the output suitable for online browsing using WORD or other
-# programs which support those fields.
-# Note: wordpad (write) and others do not support links.
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
 
 RTF_HYPERLINKS         = YES
 
-# Load style sheet definitions from file. Syntax is similar to doxygen's
-# config file, i.e. a series of assignments. You only have to provide
-# replacements, missing definitions are set to their default value.
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
 
 RTF_STYLESHEET_FILE    =
 
-# Set optional variables used in the generation of an rtf document.
-# Syntax is similar to doxygen's config file.
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
 
 RTF_EXTENSIONS_FILE    =
 
 #---------------------------------------------------------------------------
-# configuration options related to the man page output
+# Configuration options related to the man page output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
-# generate man pages
+# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
 
 GENERATE_MAN           = YES
 
-# The MAN_OUTPUT tag is used to specify where the man pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `man' will be used as the default path.
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
 
 MAN_OUTPUT             = man
 
-# The MAN_EXTENSION tag determines the extension that is added to
-# the generated man pages (default is the subroutine's section .3)
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
 
 MAN_EXTENSION          = .3
 
-# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
-# then it will generate one additional man file for each entity
-# documented in the real man page(s). These additional files
-# only source the real man page, but without them the man command
-# would be unable to find the correct page. The default is NO.
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
 
 MAN_LINKS              = YES
 
 #---------------------------------------------------------------------------
-# configuration options related to the XML output
+# Configuration options related to the XML output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_XML tag is set to YES Doxygen will
-# generate an XML file that captures the structure of
-# the code including all documentation.
+# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
 
 GENERATE_XML           = NO
 
-# The XML_OUTPUT tag is used to specify where the XML pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `xml' will be used as the default path.
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
 
 XML_OUTPUT             = xml
 
-# The XML_SCHEMA tag can be used to specify an XML schema,
-# which can be used by a validating XML parser to check the
-# syntax of the XML files.
+# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a
+# validating XML parser to check the syntax of the XML files.
+# This tag requires that the tag GENERATE_XML is set to YES.
 
 XML_SCHEMA             =
 
-# The XML_DTD tag can be used to specify an XML DTD,
-# which can be used by a validating XML parser to check the
-# syntax of the XML files.
+# The XML_DTD tag can be used to specify a XML DTD, which can be used by a
+# validating XML parser to check the syntax of the XML files.
+# This tag requires that the tag GENERATE_XML is set to YES.
 
 XML_DTD                =
 
-# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
-# dump the program listings (including syntax highlighting
-# and cross-referencing information) to the XML output. Note that
-# enabling this will significantly increase the size of the XML output.
+# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
 
 XML_PROGRAMLISTING     = YES
 
 #---------------------------------------------------------------------------
-# configuration options for the AutoGen Definitions output
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK       = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT         = docbook
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
-# generate an AutoGen Definitions (see autogen.sf.net) file
-# that captures the structure of the code including all
-# documentation. Note that this feature is still experimental
-# and incomplete at the moment.
+# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
+# Definitions (see http://autogen.sf.net) file that captures the structure of
+# the code including all documentation. Note that this feature is still
+# experimental and incomplete at the moment.
+# The default value is: NO.
 
 GENERATE_AUTOGEN_DEF   = NO
 
 #---------------------------------------------------------------------------
-# configuration options related to the Perl module output
+# Configuration options related to the Perl module output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_PERLMOD tag is set to YES Doxygen will
-# generate a Perl module file that captures the structure of
-# the code including all documentation. Note that this
-# feature is still experimental and incomplete at the
-# moment.
+# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
 
 GENERATE_PERLMOD       = NO
 
-# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
-# the necessary Makefile rules, Perl scripts and LaTeX code to be able
-# to generate PDF and DVI output from the Perl module output.
+# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
 
 PERLMOD_LATEX          = NO
 
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
-# nicely formatted so it can be parsed by a human reader.
-# This is useful
-# if you want to understand what is going on.
-# On the other hand, if this
-# tag is set to NO the size of the Perl module output will be much smaller
-# and Perl will parse it just the same.
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
 
 PERLMOD_PRETTY         = YES
 
-# The names of the make variables in the generated doxyrules.make file
-# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
-# This is useful so different doxyrules.make files included by the same
-# Makefile don't overwrite each other's variables.
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
 
 PERLMOD_MAKEVAR_PREFIX =
 
@@ -1466,106 +1884,128 @@ PERLMOD_MAKEVAR_PREFIX =
 # Configuration options related to the preprocessor
 #---------------------------------------------------------------------------
 
-# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
-# evaluate all C-preprocessor directives found in the sources and include
-# files.
+# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
 
 ENABLE_PREPROCESSING   = YES
 
-# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
-# names in the source code. If set to NO (the default) only conditional
-# compilation will be performed. Macro expansion can be done in a controlled
-# way by setting EXPAND_ONLY_PREDEF to YES.
+# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
+# in the source code. If set to NO only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
 MACRO_EXPANSION        = YES
 
-# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
-# then the macro expansion is limited to the macros specified with the
-# PREDEFINED and EXPAND_AS_DEFINED tags.
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
 EXPAND_ONLY_PREDEF     = YES
 
-# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
-# pointed to by INCLUDE_PATH will be searched when a #include is found.
+# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
 SEARCH_INCLUDES        = YES
 
 # The INCLUDE_PATH tag can be used to specify one or more directories that
-# contain include files that are not input files but should be processed by
-# the preprocessor.
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
 
 INCLUDE_PATH           =
 
 # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
 # patterns (like *.h and *.hpp) to filter out the header-files in the
-# directories. If left blank, the patterns specified with FILE_PATTERNS will
-# be used.
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
 INCLUDE_FILE_PATTERNS  =
 
-# The PREDEFINED tag can be used to specify one or more macro names that
-# are defined before the preprocessor is started (similar to the -D option of
-# gcc). The argument of the tag is a list of macros of the form: name
-# or name=definition (no spaces). If the definition and the = are
-# omitted =1 is assumed. To prevent a macro definition from being
-# undefined via #undef or recursively expanded use the := operator
-# instead of the = operator.
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
 PREDEFINED             = "__attribute__(x)="
 
-# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
-# this tag can be used to specify a list of macro names that should be expanded.
-# The macro definition that is found in the sources will be used.
-# Use the PREDEFINED tag if you want to use a different macro definition that
-# overrules the definition found in the source code.
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
 EXPAND_AS_DEFINED      =
 
-# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
-# doxygen's preprocessor will remove all references to function-like macros
-# that are alone on a line, have an all uppercase name, and do not end with a
-# semicolon, because these will confuse the parser if not removed.
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all refrences to function-like macros that are alone on a line, have an
+# all uppercase name, and do not end with a semicolon. Such function macros are
+# typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
 SKIP_FUNCTION_MACROS   = YES
 
 #---------------------------------------------------------------------------
-# Configuration::additions related to external references
+# Configuration options related to external references
 #---------------------------------------------------------------------------
 
-# The TAGFILES option can be used to specify one or more tagfiles. For each
-# tag file the location of the external documentation should be added. The
-# format of a tag file without this location is as follows:
-#
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
 # TAGFILES = file1 file2 ...
 # Adding location for the tag files is done as follows:
-#
 # TAGFILES = file1=loc1 "file2 = loc2" ...
-# where "loc1" and "loc2" can be relative or absolute paths
-# or URLs. Note that each tag file must have a unique name (where the name does
-# NOT include the path). If a tag file is not located in the directory in which
-# doxygen is run, you must also specify the path to the tagfile here.
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have an unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
 
 TAGFILES               =
 
-# When a file name is specified after GENERATE_TAGFILE, doxygen will create
-# a tag file that is based on the input files it reads.
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
 
 GENERATE_TAGFILE       =
 
-# If the ALLEXTERNALS tag is set to YES all external classes will be listed
-# in the class index. If set to NO only the inherited external classes
-# will be listed.
+# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
+# class index. If set to NO only the inherited external classes will be listed.
+# The default value is: NO.
 
 ALLEXTERNALS           = NO
 
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
-# in the modules index. If set to NO, only the current project's groups will
-# be listed.
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
+# the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
 
 EXTERNAL_GROUPS        = YES
 
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES         = YES
+
 # The PERL_PATH should be the absolute path and name of the perl script
-# interpreter (i.e. the result of `which perl').
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
 
 PERL_PATH              = /usr/bin/perl
 
@@ -1573,222 +2013,293 @@ PERL_PATH              = /usr/bin/perl
 # Configuration options related to the dot tool
 #---------------------------------------------------------------------------
 
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
-# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
-# or super classes. Setting the tag to NO turns the diagrams off. Note that
-# this option also works with HAVE_DOT disabled, but it is recommended to
-# install and use dot, since it yields more powerful graphs.
+# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
 
 CLASS_DIAGRAMS         = YES
 
 # You can define message sequence charts within doxygen comments using the \msc
-# command. Doxygen will then run the mscgen tool (see
-# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
 # documentation. The MSCGEN_PATH tag allows you to specify the directory where
 # the mscgen tool resides. If left empty the tool is assumed to be found in the
 # default search path.
 
 MSCGEN_PATH            =
 
-# If set to YES, the inheritance and collaboration graphs will hide
-# inheritance and usage relations if the target is undocumented
-# or is not a class.
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH               =
+
+# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
 
 HIDE_UNDOC_RELATIONS   = YES
 
 # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
-# available from the path. This tool is part of Graphviz, a graph visualization
-# toolkit from AT&T and Lucent Bell Labs. The other options in this section
-# have no effect if this option is set to NO (the default)
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
 
 HAVE_DOT               = YES
 
-# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
-# allowed to run in parallel. When set to 0 (the default) doxygen will
-# base this on the number of processors available in the system. You can set it
-# explicitly to a value larger than 0 to get control over the balance
-# between CPU load and processing speed.
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 DOT_NUM_THREADS        = 0
 
-# By default doxygen will use the Helvetica font for all dot files that
-# doxygen generates. When you want a differently looking font you can specify
-# the font name using DOT_FONTNAME. You need to make sure dot is able to find
-# the font, which can be done by putting it in a standard location or by setting
-# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
-# directory containing the font.
+# When you want a differently looking font n the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
-DOT_FONTNAME           = FreeSans.ttf
+DOT_FONTNAME           = Helvetica
 
-# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
-# The default size is 10pt.
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 DOT_FONTSIZE           = 10
 
-# By default doxygen will tell dot to use the Helvetica font.
-# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
-# set the path where dot can find it.
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 DOT_FONTPATH           =
 
-# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect inheritance relations. Setting this tag to YES will force the
-# CLASS_DIAGRAMS tag to NO.
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 CLASS_GRAPH            = YES
 
-# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect implementation dependencies (inheritance, containment, and
-# class references variables) of the class with other documented classes.
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 COLLABORATION_GRAPH    = YES
 
-# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for groups, showing the direct groups dependencies
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 GROUP_GRAPHS           = YES
 
 # If the UML_LOOK tag is set to YES doxygen will generate inheritance and
 # collaboration diagrams in a style similar to the OMG's Unified Modeling
 # Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 UML_LOOK               = YES
 
-# If the UML_LOOK tag is enabled, the fields and methods are shown inside
-# the class node. If there are many fields or methods and many nodes the
-# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
-# threshold limits the number of items for each type to make the size more
-# managable. Set this to 0 for no limit. Note that the threshold may be
-# exceeded by 50% before the limit is enforced.
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 UML_LIMIT_NUM_FIELDS   = 10
 
-# If set to YES, the inheritance and collaboration graphs will show the
-# relations between templates and their instances.
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 TEMPLATE_RELATIONS     = YES
 
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
-# tags are set to YES then doxygen will generate a graph for each documented
-# file showing the direct and indirect include dependencies of the file with
-# other documented files.
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 INCLUDE_GRAPH          = YES
 
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
-# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
-# documented header file showing the documented files that directly or
-# indirectly include this file.
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 INCLUDED_BY_GRAPH      = YES
 
-# If the CALL_GRAPH and HAVE_DOT options are set to YES then
-# doxygen will generate a call dependency graph for every global function
-# or class method. Note that enabling this option will significantly increase
-# the time of a run. So in most cases it will be better to enable call graphs
-# for selected functions only using the \callgraph command.
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 CALL_GRAPH             = YES
 
-# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
-# doxygen will generate a caller dependency graph for every global function
-# or class method. Note that enabling this option will significantly increase
-# the time of a run. So in most cases it will be better to enable caller
-# graphs for selected functions only using the \callergraph command.
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 CALLER_GRAPH           = YES
 
-# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
-# will generate a graphical hierarchy of all classes instead of a textual one.
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 GRAPHICAL_HIERARCHY    = YES
 
-# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES
-# then doxygen will show the dependencies a directory has on other directories
-# in a graphical way. The dependency relations are determined by the #include
-# relations between the files in the directories.
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 DIRECTORY_GRAPH        = YES
 
 # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot. Possible values are svg, png, jpg, or gif.
-# If left blank png will be used. If you choose svg you need to set
-# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
-# visible in IE 9+ (other browsers do not have this requirement).
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 DOT_IMAGE_FORMAT       = png
 
 # If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
 # enable generation of interactive SVG images that allow zooming and panning.
-# Note that this requires a modern browser other than Internet Explorer.
-# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
-# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
-# visible. Older versions of IE do not have SVG support.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 INTERACTIVE_SVG        = NO
 
-# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
 # found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 DOT_PATH               =
 
 # The DOTFILE_DIRS tag can be used to specify one or more directories that
-# contain dot files that are included in the documentation (see the
-# \dotfile command).
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 DOTFILE_DIRS           =
 
 # The MSCFILE_DIRS tag can be used to specify one or more directories that
-# contain msc files that are included in the documentation (see the
-# \mscfile command).
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
 
 MSCFILE_DIRS           =
 
-# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
-# nodes that will be shown in the graph. If the number of nodes in a graph
-# becomes larger than this value, doxygen will truncate the graph, which is
-# visualized by representing a node as a red box. Note that doxygen if the
-# number of direct children of the root node in a graph is already larger than
-# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
-# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS           =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 DOT_GRAPH_MAX_NODES    = 50
 
-# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
-# graphs generated by dot. A depth value of 3 means that only nodes reachable
-# from the root by following a path via at most 3 edges will be shown. Nodes
-# that lay further from the root node will be omitted. Note that setting this
-# option to 1 or 2 may greatly reduce the computation time needed for large
-# code bases. Also note that the size of a graph can be further restricted by
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
 # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 MAX_DOT_GRAPH_DEPTH    = 0
 
 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
-# background. This is disabled by default, because dot on Windows does not
-# seem to support this out of the box. Warning: Depending on the platform used,
-# enabling this option may lead to badly anti-aliased labels on the edges of
-# a graph (i.e. they become hard to read).
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 DOT_TRANSPARENT        = YES
 
 # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
 # files in one run (i.e. multiple -o and -T options on the command line). This
-# makes dot run faster, but since only newer versions of dot (>1.8.10)
-# support this, this feature is disabled by default.
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 DOT_MULTI_TARGETS      = YES
 
-# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
-# generate a legend page explaining the meaning of the various boxes and
-# arrows in the dot generated graphs.
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 GENERATE_LEGEND        = YES
 
-# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
-# remove the intermediate dot files that are used to generate
-# the various graphs.
+# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 DOT_CLEANUP            = YES
index 7599b57..73ce64f 100644 (file)
@@ -1,9 +1,6 @@
 /*
  * This file is part of nmealib.
  *
- * Copyright (c) 2008 Timur Sinitsyn
- * Copyright (c) 2011 Ferry Huberts
- *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
index bd12ff7..55cc4ad 100644 (file)
@@ -1,9 +1,6 @@
 /*
  * This file is part of nmealib.
  *
- * Copyright (c) 2008 Timur Sinitsyn
- * Copyright (c) 2011 Ferry Huberts
- *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
index c0c6d04..4c9af70 100644 (file)
@@ -1,9 +1,6 @@
 /*
  * This file is part of nmealib.
  *
- * Copyright (c) 2008 Timur Sinitsyn
- * Copyright (c) 2011 Ferry Huberts
- *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
index a692434..b214dfc 100644 (file)
@@ -1,9 +1,6 @@
 /*
  * This file is part of nmealib.
  *
- * Copyright (c) 2008 Timur Sinitsyn
- * Copyright (c) 2011 Ferry Huberts
- *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
index fd7470c..0c24725 100644 (file)
@@ -1,9 +1,6 @@
 /*
  * This file is part of nmealib.
  *
- * Copyright (c) 2008 Timur Sinitsyn
- * Copyright (c) 2011 Ferry Huberts
- *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
index e761d00..398e197 100644 (file)
@@ -1,9 +1,6 @@
 /*
  * This file is part of nmealib.
  *
- * Copyright (c) 2008 Timur Sinitsyn
- * Copyright (c) 2011 Ferry Huberts
- *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
index 93dc0bf..c2fb093 100644 (file)
@@ -1,9 +1,6 @@
 /*
  * This file is part of nmealib.
  *
- * Copyright (c) 2008 Timur Sinitsyn
- * Copyright (c) 2011 Ferry Huberts
- *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
 extern "C" {
 #endif /* __cplusplus */
 
-bool nmea_parse_sentence_has_invalid_chars(const char * str, const size_t str_len, const char * strName, char * report,
-               const size_t reportSize);
+const char * isInvalidNMEACharacter(const char * c);
+const char * nmea_parse_sentence_has_invalid_chars(const char * s, const size_t len);
 
-int nmea_parse_get_sentence_type(const char *s, const int len);
-int nmea_parse_get_sentence_length(const char *s, const int len, int *checksum);
+enum nmeaPACKTYPE nmea_parse_get_sentence_type(const char *s, const int len);
 
-int nmea_parse_GPGGA(const char *s, const int len, nmeaGPGGA *pack);
-int nmea_parse_GPGSA(const char *s, const int len, nmeaGPGSA *pack);
-int nmea_parse_GPGSV(const char *s, const int len, nmeaGPGSV *pack);
-int nmea_parse_GPRMC(const char *s, const int len, nmeaGPRMC *pack);
-int nmea_parse_GPVTG(const char *s, const int len, nmeaGPVTG *pack);
+int nmea_parse_GPGGA(const char *s, const int len, bool has_checksum, nmeaGPGGA *pack);
+int nmea_parse_GPGSA(const char *s, const int len, bool has_checksum, nmeaGPGSA *pack);
+int nmea_parse_GPGSV(const char *s, const int len, bool has_checksum, nmeaGPGSV *pack);
+int nmea_parse_GPRMC(const char *s, const int len, bool has_checksum, nmeaGPRMC *pack);
+int nmea_parse_GPVTG(const char *s, const int len, bool has_checksum, nmeaGPVTG *pack);
 
 #ifdef  __cplusplus
 }
index 87596ef..3fbc615 100644 (file)
@@ -1,9 +1,6 @@
 /*
  * This file is part of nmealib.
  *
- * Copyright (c) 2008 Timur Sinitsyn
- * Copyright (c) 2011 Ferry Huberts
- *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
 #define __NMEA_PARSER_H__
 
 #include <nmea/info.h>
+#include <nmea/sentence.h>
 
 #ifdef  __cplusplus
 extern "C" {
 #endif /* __cplusplus */
 
+/* we need to be able to parse much longer sentences than specified in the (original) specification */
+#define SENTENCE_SIZE (4096 * 1)
+
+typedef enum _sentence_parser_state {
+  SKIP_UNTIL_START,
+  READ_SENTENCE,
+  READ_CHECKSUM,
+  READ_EOL
+} sentence_parser_state;
+
 /**
- * Description of a parser node / packet
+ * NMEA frame parser structure
  */
-typedef struct _nmeaParserNODE {
-       int packType;                                           /**< the type of the packet (see nmeaPACKTYPE) */
-       void *pack;                         /**< the packet (a pointer to a malloced sentence sctucture) */
-       struct _nmeaParserNODE *next_node;  /**< pointer to the next node / packet */
-} nmeaParserNODE;
+typedef struct _sentencePARSER {
+    int sentence_checksum;
+    int calculated_checksum;
+
+    char sentence_checksum_chars[2];
+    char sentence_checksum_chars_count;
+
+    char sentence_eol_chars_count;
+
+    bool has_checksum;
+
+    sentence_parser_state state;
+} sentencePARSER;
 
 /**
- * The parser data.
+ * parsed NMEA data and frame parser state
  */
 typedef struct _nmeaPARSER {
-       nmeaParserNODE *top_node; /**< the first node / packet */
-       nmeaParserNODE *end_node; /**< the last node / packet */
-       char *buffer;             /**< the buffer containing the string to parse */
-       int buff_size;            /**< the size of the buffer */
-       int buff_use;             /**< the number of bytes in the buffer */
+    struct {
+        unsigned int length;
+        char buffer[SENTENCE_SIZE];
+    } buffer;
+
+    union {
+        nmeaGPGGA gpgga;
+        nmeaGPGSA gpgsa;
+        nmeaGPGSV gpgsv;
+        nmeaGPRMC gprmc;
+        nmeaGPVTG gpvtg;
+    } sentence;
+
+    sentencePARSER sentence_parser;
 } nmeaPARSER;
 
 int nmea_parser_init(nmeaPARSER *parser);
-void nmea_parser_destroy(nmeaPARSER *parser);
-int nmea_parse(nmeaPARSER *parser, const char *buff, const int buff_sz, nmeaINFO *info);
-
-int nmea_parser_push(nmeaPARSER *parser, const char *buff, int buff_sz);
-int nmea_parser_top(const nmeaPARSER *parser);
-int nmea_parser_pop(nmeaPARSER *parser, void **pack_ptr);
-int nmea_parser_peek(const nmeaPARSER *parser, void **pack_ptr);
-int nmea_parser_drop(nmeaPARSER *parser);
-void nmea_parser_buff_clear(nmeaPARSER *parser);
-void nmea_parser_queue_clear(nmeaPARSER *parser);
+int nmea_parse(nmeaPARSER * parser, const char * s, int len, nmeaINFO * info);
 
 #ifdef  __cplusplus
 }
index eee47ab..dbfd133 100644 (file)
@@ -1,9 +1,6 @@
 /*
  * This file is part of nmealib.
  *
- * Copyright (c) 2008 Timur Sinitsyn
- * Copyright (c) 2011 Ferry Huberts
- *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
index ea69082..20c66d6 100644 (file)
@@ -1,9 +1,6 @@
 /*
  * This file is part of nmealib.
  *
- * Copyright (c) 2008 Timur Sinitsyn
- * Copyright (c) 2011 Ferry Huberts
- *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
diff --git a/lib/pud/nmealib/samples/Makefile b/lib/pud/nmealib/samples/Makefile
deleted file mode 100644 (file)
index ac2b4c6..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-include ../Makefile.inc
-
-#
-# Settings
-#
-
-SAMPLES = generate generator math parse parse_file
-SMPLS = $(SAMPLES:%=../build/samples/%)
-SMPLOBJ = $(SAMPLES:%=%/main.o)
-
-LIBRARIES = -lm -L../lib -lnmea
-INCLUDES = -I ../include
-
-
-#
-# Targets
-#
-
-all: all-before samples
-
-remake: clean all
-
-samples: $(SMPLS)
-
-../build/samples/%: %/main.o
-ifeq ($(VERBOSE),0)
-       @echo "[LD] $@"
-endif
-       $(MAKECMDPREFIX)$(CC) $(CFLAGS) $< $(LIBRARIES) -o $@
-
-%/main.o: %/main.c Makefile ../Makefile.inc
-ifeq ($(VERBOSE),0)
-       @echo "[CC] $<"
-endif
-       $(MAKECMDPREFIX)$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
-
-
-#
-# Phony Targets
-#
-
-.PHONY: all all-before clean samples
-
-all-before:
-       $(MAKECMDPREFIX)mkdir -p ../build/samples
-
-clean:
-       $(MAKECMDPREFIX)rm -f $(SMPLOBJ) $(SMPLS)
diff --git a/lib/pud/nmealib/samples/generate/main.c b/lib/pud/nmealib/samples/generate/main.c
deleted file mode 100644 (file)
index 3b93a21..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * This file is part of nmealib.
- *
- * Copyright (c) 2008 Timur Sinitsyn
- * Copyright (c) 2011 Ferry Huberts
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <nmea/info.h>
-
-#include <nmea/gmath.h>
-#include <nmea/generate.h>
-
-#include <stdio.h>
-#include <unistd.h>
-
-int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused))) {
-       nmeaINFO info;
-       char buff[2048];
-       int gen_sz;
-       int it;
-
-       nmea_zero_INFO(&info);
-
-       info.sig = 3;
-       info.fix = 3;
-       info.lat = 5000.0;
-       info.lon = 3600.0;
-       info.speed = 2.14 * NMEA_TUS_MS;
-       info.elv = 10.86;
-       info.track = 45;
-       info.mtrack = 55;
-       info.magvar = 55;
-       info.HDOP = 2.3;
-       info.VDOP = 1.2;
-       info.PDOP = 2.594224354;
-
-       nmea_INFO_set_present(&info.present, SIG);
-       nmea_INFO_set_present(&info.present, FIX);
-       nmea_INFO_set_present(&info.present, LAT);
-       nmea_INFO_set_present(&info.present, LON);
-       nmea_INFO_set_present(&info.present, SPEED);
-       nmea_INFO_set_present(&info.present, ELV);
-       nmea_INFO_set_present(&info.present, TRACK);
-       nmea_INFO_set_present(&info.present, MTRACK);
-       nmea_INFO_set_present(&info.present, MAGVAR);
-       nmea_INFO_set_present(&info.present, HDOP);
-       nmea_INFO_set_present(&info.present, VDOP);
-       nmea_INFO_set_present(&info.present, PDOP);
-
-       info.satinfo.inuse = NMEA_MAXSAT;
-       nmea_INFO_set_present(&info.present, SATINUSECOUNT);
-       for (it = 0; it < NMEA_MAXSAT; it++) {
-               info.satinfo.in_use[it] = it + 1;
-       }
-       nmea_INFO_set_present(&info.present, SATINUSE);
-
-       info.satinfo.inview = NMEA_MAXSAT;
-       for (it = 0; it < NMEA_MAXSAT; it++) {
-               info.satinfo.sat[it].id = it + 1;
-               info.satinfo.sat[it].elv = (it * 10);
-               info.satinfo.sat[it].azimuth = it + 1;
-               info.satinfo.sat[it].sig = 99 - it;
-       }
-       nmea_INFO_set_present(&info.present, SATINVIEW);
-
-       for (it = 0; it < 10; it++) {
-               gen_sz = nmea_generate(&buff[0], 2048, &info, GPGGA | GPGSA | GPGSV | GPRMC | GPVTG);
-
-               buff[gen_sz] = 0;
-               printf("%s\n", &buff[0]);
-
-               usleep(500000);
-
-               info.speed += .1;
-       }
-
-       return 0;
-}
diff --git a/lib/pud/nmealib/samples/generator/main.c b/lib/pud/nmealib/samples/generator/main.c
deleted file mode 100644 (file)
index 957489a..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * This file is part of nmealib.
- *
- * Copyright (c) 2008 Timur Sinitsyn
- * Copyright (c) 2011 Ferry Huberts
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <nmea/generator.h>
-#include <nmea/sentence.h>
-
-#include <stdio.h>
-#include <unistd.h>
-
-int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused))) {
-       nmeaGENERATOR *gen;
-       nmeaINFO info;
-       char buff[2048];
-       int gen_sz;
-       int it;
-
-       nmea_zero_INFO(&info);
-
-       nmea_INFO_set_present(&info.present, PDOP);
-       nmea_INFO_set_present(&info.present, HDOP);
-       nmea_INFO_set_present(&info.present, VDOP);
-       nmea_INFO_set_present(&info.present, ELV);
-
-       if (0 == (gen = nmea_create_generator(NMEA_GEN_ROTATE, &info)))
-               return -1;
-
-       for (it = 0; it < 10000; it++) {
-               gen_sz = nmea_generate_from(&buff[0], 2048, &info, gen, GPGGA | GPGSA | GPGSV | GPRMC | GPVTG);
-
-               buff[gen_sz] = 0;
-               printf("%s\n", &buff[0]);
-
-               usleep(500000);
-       }
-
-       nmea_gen_destroy(gen);
-
-       return 0;
-}
diff --git a/lib/pud/nmealib/samples/math/main.c b/lib/pud/nmealib/samples/math/main.c
deleted file mode 100644 (file)
index cda96dd..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*\r
- * This file is part of nmealib.\r
- *\r
- * Copyright (c) 2008 Timur Sinitsyn\r
- * Copyright (c) 2011 Ferry Huberts\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program. If not, see <http://www.gnu.org/licenses/>.\r
- */\r
-\r
-#include <nmea/info.h>\r
-#include <nmea/parser.h>\r
-#include <nmea/gmath.h>\r
-\r
-#include <stdio.h>\r
-#include <string.h>\r
-\r
-#define NUM_POINTS 4\r
-\r
-int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused))) {\r
-       const char *buff[] = { "$GPRMC,213916.199,A,4221.0377,N,07102.9778,W,0.00,,010207,,,A*6A\r\n",\r
-                       "$GPRMC,213917.199,A,4221.0510,N,07102.9549,W,0.23,175.43,010207,,,A*77\r\n",\r
-                       "$GPRMC,213925.000,A,4221.1129,N,07102.9146,W,0.00,,010207,,,A*68\r\n",\r
-                       "$GPRMC,111609.14,A,5001.27,N,3613.06,E,11.2,0.0,261206,0.0,E*50\r\n" };\r
-\r
-       nmeaPOS pos[NUM_POINTS], pos_moved[NUM_POINTS][2];\r
-       double dist[NUM_POINTS][2];\r
-       double azimuth[NUM_POINTS][2], azimuth_moved[NUM_POINTS];\r
-       int result[2];\r
-       int it = 0;\r
-\r
-       nmeaPARSER parser;\r
-       nmea_parser_init(&parser);\r
-\r
-       for (it = 0; it < NUM_POINTS; it++) {\r
-               nmeaINFO info;\r
-               nmea_zero_INFO(&info);\r
-               (void) nmea_parse(&parser, buff[it], (int) strlen(buff[it]), &info);\r
-               nmea_info2pos(&info, &pos[it]);\r
-       }\r
-\r
-       nmea_parser_destroy(&parser);\r
-\r
-       for (it = 0; it < NUM_POINTS; it++) {\r
-               dist[it][0] = nmea_distance(&pos[0], &pos[it]);\r
-               dist[it][1] = nmea_distance_ellipsoid(&pos[0], &pos[it], &azimuth[it][0], &azimuth[it][1]);\r
-       }\r
-\r
-       for (it = 0; it < NUM_POINTS; it++) {\r
-               result[0] = nmea_move_horz(&pos[0], &pos_moved[it][0], azimuth[it][0], dist[it][0]);\r
-               result[1] = nmea_move_horz_ellipsoid(&pos[0], &pos_moved[it][1], azimuth[it][0], dist[it][0],\r
-                               &azimuth_moved[it]);\r
-\r
-       }\r
-\r
-       /* Output of results */\r
-       printf("Coordinate points:\n");\r
-       for (it = 0; it < NUM_POINTS; it++) {\r
-               printf("P%d in radians: lat:%9.6lf lon:%9.6lf  \tin degree: lat:%+010.6lf° lon:%+011.6lf°\n", it, pos[it].lat,\r
-                               pos[it].lon, nmea_radian2degree(pos[it].lat), nmea_radian2degree(pos[it].lon));\r
-       }\r
-\r
-       printf("\nCalculation results:\n");\r
-       for (it = 0; it < NUM_POINTS; it++) {\r
-               printf("\n");\r
-               printf("Distance P0 to P%d\ton spheroid:  %14.3lf m\n", it, dist[it][0]);\r
-               printf("Distance P0 to P%d\ton ellipsoid: %14.3lf m\n", it, dist[it][1]);\r
-               printf("Azimuth  P0 to P%d\tat start: %8.3lf°\tat end: %8.3lf°\n", it, nmea_radian2degree(azimuth[it][0]),\r
-                               nmea_radian2degree(azimuth[it][1]));\r
-               printf("Move     P0 to P%d\t         \tAzimuth at end: %8.3lf°\n", it, nmea_radian2degree(azimuth_moved[it]));\r
-               printf("Move     P0 to P%d\ton spheroid:  %3s lat:%+010.6lf° lon:%+011.6lf°\n", it,\r
-                               result[0] == 1 ? "OK" : "nOK", nmea_radian2degree(pos_moved[it][0].lat),\r
-                               nmea_radian2degree(pos_moved[it][0].lon));\r
-               printf("Move     P0 to P%d\ton ellipsoid: %3s lat:%+010.6lf° lon:%+011.6lf°\n", it,\r
-                               result[0] == 1 ? "OK" : "nOK", nmea_radian2degree(pos_moved[it][1].lat),\r
-                               nmea_radian2degree(pos_moved[it][1].lon));\r
-               printf("Move     P0 to P%d\toriginal:         lat:%+010.6lf° lon:%+011.6lf°\n", it,\r
-                               nmea_radian2degree(pos[it].lat), nmea_radian2degree(pos[it].lon));\r
-       }\r
-\r
-       return 0;\r
-}\r
diff --git a/lib/pud/nmealib/samples/parse/main.c b/lib/pud/nmealib/samples/parse/main.c
deleted file mode 100644 (file)
index f950415..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * This file is part of nmealib.
- *
- * Copyright (c) 2008 Timur Sinitsyn
- * Copyright (c) 2011 Ferry Huberts
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <nmea/info.h>
-#include <nmea/parser.h>
-#include <nmea/gmath.h>
-
-#include <stdio.h>
-#include <string.h>
-
-int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused))) {
-       const char *buff[] = { "$GPRMC,173843,A,3349.896,N,11808.521,W,000.0,360.0,230108,013.4,E*69\r\n",
-                       "$GPGGA,111609.14,5001.27,N,3613.06,E,3,08,0.0,10.2,M,0.0,M,0.0,0000*70\r\n",
-                       "$GPGSV,2,1,08,01,05,005,80,02,05,050,80,03,05,095,80,04,05,140,80*7f\r\n",
-                       "$GPGSV,2,2,08,05,05,185,80,06,05,230,80,07,05,275,80,08,05,320,80*71\r\n",
-                       "$GPGSA,A,3,01,02,03,04,05,06,07,08,00,00,00,00,0.0,0.0,0.0*3a\r\n",
-                       "$GPRMC,111609.14,A,5001.27,N,3613.06,E,11.2,0.0,261206,0.0,E*50\r\n",
-                       "$GPVTG,217.5,T,208.8,M,000.00,N,000.01,K*4C\r\n" };
-
-       int it;
-       nmeaINFO info;
-       nmeaPARSER parser;
-       nmeaPOS dpos;
-
-       nmea_zero_INFO(&info);
-       nmea_parser_init(&parser);
-
-       for (it = 0; it < 6; it++) {
-               nmea_parse(&parser, buff[it], (int) strlen(buff[it]), &info);
-
-               nmea_info2pos(&info, &dpos);
-               printf("%03d, Lat: %f, Lon: %f, Sig: %d, Fix: %d\n", it, dpos.lat, dpos.lon, info.sig, info.fix);
-       }
-
-       nmea_parser_destroy(&parser);
-
-       return 0;
-}
diff --git a/lib/pud/nmealib/samples/parse_file/gpslog.txt b/lib/pud/nmealib/samples/parse_file/gpslog.txt
deleted file mode 100644 (file)
index f6086da..0000000
+++ /dev/null
@@ -1,311 +0,0 @@
-$PSRFTXTVersion GSW3.2.1PAT_3.1.00.12-SDK001P1.00c *3F\r
-$PSRFTXTHTC GPS_ART_321000_GEN*20\r
-$PSRFTXTTOW:  258712*32\r
-$PSRFTXTWK:   1412*4F\r
-$PSRFTXTPOS:  1518885 -4470072 4274168*24\r
-$PSRFTXTCLK:  94817*02\r
-$PSRFTXTCHNL: 12*5F\r
-$PSRFTXTBaud rate: 57600 *51\r
-$GPGGA,213638.949,,,,,0,00,,,M,0.0,M,,0000*5F\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213638.949,V,,,,,,,010207,,,N*40\r
-$GPGGA,213639.897,,,,,0,00,,,M,0.0,M,,0000*5C\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213639.897,V,,,,,,,010207,,,N*43\r
-$GPGGA,213640.886,,,,,0,00,,,M,0.0,M,,0000*52\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213640.886,V,,,,,,,010207,,,N*4D\r
-$GPGGA,213641.886,,,,,0,00,,,M,0.0,M,,0000*53\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213641.886,V,,,,,,,010207,,,N*4C\r
-$GPGGA,213642.897,,,,,0,00,,,M,0.0,M,,0000*50\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPGSV,3,1,12,20,00,000,,10,00,000,,25,00,000,,27,00,000,*79\r
-$GPGSV,3,2,12,22,00,000,,07,00,000,,21,00,000,,24,00,000,*79\r
-$GPGSV,3,3,12,16,00,000,,28,00,000,,26,00,000,,29,00,000,*78\r
-$GPRMC,213642.897,V,,,,,,,010207,,,N*4F\r
-$GPGGA,213643.886,,,,,0,00,,,M,0.0,M,,0000*51\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213643.886,V,,,,,,,010207,,,N*4E\r
-$GPGGA,213644.886,,,,,0,00,,,M,0.0,M,,0000*56\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213644.886,V,,,,,,,010207,,,N*49\r
-$GPGGA,213645.897,,,,,0,00,,,M,0.0,M,,0000*57\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213645.897,V,,,,,,,010207,,,N*48\r
-$GPGGA,213646.886,,,,,0,00,,,M,0.0,M,,0000*54\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213646.886,V,,,,,,,010207,,,N*4B\r
-$GPGGA,213647.886,,,,,0,00,,,M,0.0,M,,0000*55\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPGSV,3,1,12,20,00,000,,10,00,000,,25,00,000,,27,00,000,*79\r
-$GPGSV,3,2,12,22,00,000,,07,00,000,,21,00,000,,24,00,000,*79\r
-$GPGSV,3,3,12,16,00,000,,28,00,000,,26,00,000,,29,00,000,*78\r
-$GPRMC,213647.886,V,,,,,,,010207,,,N*4A\r
-$GPGGA,213648.897,,,,,0,00,,,M,0.0,M,,0000*5A\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213648.897,V,,,,,,,010207,,,N*45\r
-$GPGGA,213649.886,,,,,0,00,,,M,0.0,M,,0000*5B\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213649.886,V,,,,,,,010207,,,N*44\r
-$GPGGA,213650.886,,,,,0,00,,,M,0.0,M,,0000*53\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213650.886,V,,,,,,,010207,,,N*4C\r
-$GPGGA,213651.897,,,,,0,00,,,M,0.0,M,,0000*52\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213651.897,V,,,,,,,010207,,,N*4D\r
-$GPGGA,213652.886,,,,,0,00,,,M,0.0,M,,0000*51\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPGSV,3,1,12,20,00,000,,10,00,000,,25,00,000,,27,00,000,*79\r
-$GPGSV,3,2,12,22,00,000,,07,00,000,,21,00,000,,24,00,000,*79\r
-$GPGSV,3,3,12,16,00,000,,28,00,000,,26,00,000,,29,00,000,*78\r
-$GPRMC,213652.886,V,,,,,,,010207,,,N*4E\r
-$GPGGA,213653.886,,,,,0,00,,,M,0.0,M,,0000*50\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213653.886,V,,,,,,,010207,,,N*4F\r
-$GPGGA,213654.898,,,,,0,00,,,M,0.0,M,,0000*58\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213654.898,V,,,,,,,010207,,,N*47\r
-$GPGGA,213655.886,,,,,0,00,,,M,0.0,M,,0000*56\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213655.886,V,,,,,,,010207,,,N*49\r
-$GPGGA,213656.886,,,,,0,00,,,M,0.0,M,,0000*55\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213656.886,V,,,,,,,010207,,,N*4A\r
-$GPGGA,213657.897,,,,,0,00,,,M,0.0,M,,0000*54\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPGSV,3,1,12,20,00,000,,10,00,000,,25,00,000,,27,00,000,*79\r
-$GPGSV,3,2,12,22,00,000,,07,00,000,,21,00,000,,24,00,000,*79\r
-$GPGSV,3,3,12,16,00,000,,28,00,000,,26,00,000,,29,00,000,*78\r
-$GPRMC,213657.897,V,,,,,,,010207,,,N*4B\r
-$GPGGA,213658.886,,,,,0,00,,,M,0.0,M,,0000*5B\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213658.886,V,,,,,,,010207,,,N*44\r
-$GPGGA,213659.886,,,,,0,00,,,M,0.0,M,,0000*5A\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213659.886,V,,,,,,,010207,,,N*45\r
-$GPGGA,213700.880,,,,,0,00,,,M,0.0,M,,0000*51\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213700.880,V,,,,,,,010207,,,N*4E\r
-$GPGGA,213701.880,,,,,0,00,,,M,0.0,M,,0000*50\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213701.880,V,,,,,,,010207,,,N*4F\r
-$GPGGA,213702.880,,,,,0,00,,,M,0.0,M,,0000*53\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPGSV,3,1,10,24,83,052,,29,63,170,,26,55,179,,10,46,055,*70\r
-$GPGSV,3,2,10,06,41,282,,02,23,120,,21,21,303,,08,16,068,*73\r
-$GPGSV,3,3,10,27,10,042,,18,08,257,*7B\r
-$GPRMC,213702.880,V,,,,,,,010207,,,N*4C\r
-$GPGGA,213703.880,,,,,0,00,,,M,0.0,M,,0000*52\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213703.880,V,,,,,,,010207,,,N*4D\r
-$GPGGA,213704.880,,,,,0,00,,,M,0.0,M,,0000*55\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213704.880,V,,,,,,,010207,,,N*4A\r
-$GPGGA,213705.879,,,,,0,00,,,M,0.0,M,,0000*52\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213705.879,V,,,,,,,010207,,,N*4D\r
-$GPGGA,213706.879,,,,,0,00,,,M,0.0,M,,0000*51\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213706.879,V,,,,,,,010207,,,N*4E\r
-$GPGGA,213707.879,,,,,0,00,,,M,0.0,M,,0000*50\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPGSV,3,1,10,24,83,052,,29,63,170,,26,55,179,,10,46,055,*70\r
-$GPGSV,3,2,10,06,41,282,,02,23,120,,21,21,303,,08,16,068,*73\r
-$GPGSV,3,3,10,27,10,042,,18,08,257,*7B\r
-$GPRMC,213707.879,V,,,,,,,010207,,,N*4F\r
-$GPGGA,213708.879,,,,,0,00,,,M,0.0,M,,0000*5F\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213708.879,V,,,,,,,010207,,,N*40\r
-$GPGGA,213709.879,,,,,0,00,,,M,0.0,M,,0000*5E\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213709.879,V,,,,,,,010207,,,N*41\r
-$GPGGA,213710.879,,,,,0,00,,,M,0.0,M,,0000*56\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213710.879,V,,,,,,,010207,,,N*49\r
-$GPGGA,213711.879,,,,,0,00,,,M,0.0,M,,0000*57\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213711.879,V,,,,,,,010207,,,N*48\r
-$GPGGA,213712.879,,,,,0,00,,,M,0.0,M,,0000*54\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPGSV,3,1,10,24,83,052,,29,63,170,,26,55,179,,10,46,055,*70\r
-$GPGSV,3,2,10,06,41,282,,02,23,120,,21,21,303,,08,16,068,*73\r
-$GPGSV,3,3,10,27,10,042,,18,08,257,*7B\r
-$GPRMC,213712.879,V,,,,,,,010207,,,N*4B\r
-$GPGGA,213713.879,,,,,0,00,,,M,0.0,M,,0000*55\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213713.879,V,,,,,,,010207,,,N*4A\r
-$GPGGA,213714.879,,,,,0,00,,,M,0.0,M,,0000*52\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213714.879,V,,,,,,,010207,,,N*4D\r
-$GPGGA,213715.879,,,,,0,00,,,M,0.0,M,,0000*53\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213715.879,V,,,,,,,010207,,,N*4C\r
-$GPGGA,213716.879,,,,,0,00,,,M,0.0,M,,0000*50\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213716.879,V,,,,,,,010207,,,N*4F\r
-$GPGGA,213717.879,,,,,0,00,,,M,0.0,M,,0000*51\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPGSV,3,1,10,24,83,052,,29,63,170,,26,55,179,25,10,46,055,*77\r
-$GPGSV,3,2,10,06,41,282,35,02,23,120,,21,21,303,,08,16,068,*75\r
-$GPGSV,3,3,10,27,10,042,,18,08,257,*7B\r
-$GPRMC,213717.879,V,,,,,,,010207,,,N*4E\r
-$GPGGA,213718.879,,,,,0,00,,,M,0.0,M,,0000*5E\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213718.879,V,,,,,,,010207,,,N*41\r
-$GPGGA,213719.879,,,,,0,00,,,M,0.0,M,,0000*5F\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213719.879,V,,,,,,,010207,,,N*40\r
-$GPGGA,213720.879,,,,,0,00,,,M,0.0,M,,0000*55\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213720.879,V,,,,,,,010207,,,N*4A\r
-$GPGGA,213721.879,,,,,0,00,,,M,0.0,M,,0000*54\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213721.879,V,,,,,,,010207,,,N*4B\r
-$GPGGA,213722.879,,,,,0,00,,,M,0.0,M,,0000*57\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPGSV,3,1,10,24,83,052,,29,63,170,,26,55,179,31,10,46,055,*72\r
-$GPGSV,3,2,10,06,41,282,34,02,23,120,,21,21,303,,08,16,068,*74\r
-$GPGSV,3,3,10,27,10,042,,18,08,257,*7B\r
-$GPRMC,213722.879,V,,,,,,,010207,,,N*48\r
-$GPGGA,213723.990,,,,,0,00,,,M,0.0,M,,0000*50\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213723.990,V,,,,,,,010207,,,N*4F\r
-$GPGGA,213724.990,,,,,0,00,,,M,0.0,M,,0000*57\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213724.990,V,,,,,,,010207,,,N*48\r
-$GPGGA,213725.990,,,,,0,00,,,M,0.0,M,,0000*56\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213725.990,V,,,,,,,010207,,,N*49\r
-$GPGGA,213726.990,,,,,0,00,,,M,0.0,M,,0000*55\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213726.990,V,,,,,,,010207,,,N*4A\r
-$GPGGA,213727.990,,,,,0,00,,,M,0.0,M,,0000*54\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPGSV,3,1,10,24,83,052,,29,63,170,,26,55,179,30,10,46,055,*73\r
-$GPGSV,3,2,10,06,41,282,34,02,23,120,,21,21,303,,08,16,068,*74\r
-$GPGSV,3,3,10,27,10,042,,18,08,257,*7B\r
-$GPRMC,213727.990,V,,,,,,,010207,,,N*4B\r
-$GPGGA,213728.990,,,,,0,00,,,M,0.0,M,,0000*5B\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213728.990,V,,,,,,,010207,,,N*44\r
-$GPGGA,213729.990,,,,,0,00,,,M,0.0,M,,0000*5A\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213729.990,V,,,,,,,010207,,,N*45\r
-$GPGGA,213730.990,,,,,0,00,,,M,0.0,M,,0000*52\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213730.990,V,,,,,,,010207,,,N*4D\r
-$GPGGA,213731.990,,,,,0,00,,,M,0.0,M,,0000*53\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213731.990,V,,,,,,,010207,,,N*4C\r
-$GPGGA,213732.990,,,,,0,00,,,M,0.0,M,,0000*50\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPGSV,3,1,10,24,83,052,,29,63,170,,26,55,179,27,10,46,055,*75\r
-$GPGSV,3,2,10,06,41,282,35,02,23,120,,21,21,303,,08,16,068,*75\r
-$GPGSV,3,3,10,27,10,042,,18,08,257,*7B\r
-$GPRMC,213732.990,V,,,,,,,010207,,,N*4F\r
-$GPGGA,213733.990,,,,,0,00,,,M,0.0,M,,0000*51\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213733.990,V,,,,,,,010207,,,N*4E\r
-$GPGGA,213734.990,,,,,0,00,,,M,0.0,M,,0000*56\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213734.990,V,,,,,,,010207,,,N*49\r
-$GPGGA,213735.990,,,,,0,00,,,M,0.0,M,,0000*57\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213735.990,V,,,,,,,010207,,,N*48\r
-$GPGGA,213736.990,,,,,0,00,,,M,0.0,M,,0000*54\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213736.990,V,,,,,,,010207,,,N*4B\r
-$GPGGA,213737.990,,,,,0,00,,,M,0.0,M,,0000*55\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPGSV,3,1,10,24,83,052,,29,63,170,,26,55,179,28,10,46,055,*7A\r
-$GPGSV,3,2,10,06,41,282,34,02,23,120,,21,21,303,,08,16,068,*74\r
-$GPGSV,3,3,10,27,10,042,,18,08,257,*7B\r
-$GPRMC,213737.990,V,,,,,,,010207,,,N*4A\r
-$GPGGA,213738.990,,,,,0,00,,,M,0.0,M,,0000*5A\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213738.990,V,,,,,,,010207,,,N*45\r
-$GPGGA,213739.990,,,,,0,00,,,M,0.0,M,,0000*5B\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213739.990,V,,,,,,,010207,,,N*44\r
-$GPGGA,213740.990,,,,,0,00,,,M,0.0,M,,0000*55\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213740.990,V,,,,,,,010207,,,N*4A\r
-$GPGGA,213741.990,,,,,0,00,,,M,0.0,M,,0000*54\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213741.990,V,,,,,,,010207,,,N*4B\r
-$GPGGA,213742.990,,,,,0,00,,,M,0.0,M,,0000*57\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPGSV,3,1,10,24,83,052,,29,63,170,,26,55,179,28,10,46,055,*7A\r
-$GPGSV,3,2,10,06,41,282,34,02,23,120,,21,21,303,,08,16,068,*74\r
-$GPGSV,3,3,10,27,10,042,,18,08,257,*7B\r
-$GPRMC,213742.990,V,,,,,,,010207,,,N*48\r
-$GPGGA,213743.990,,,,,0,00,,,M,0.0,M,,0000*56\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213743.990,V,,,,,,,010207,,,N*49\r
-$GPGGA,213744.990,,,,,0,00,,,M,0.0,M,,0000*51\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213744.990,V,,,,,,,010207,,,N*4E\r
-$GPGGA,213745.990,,,,,0,00,,,M,0.0,M,,0000*50\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213745.990,V,,,,,,,010207,,,N*4F\r
-$GPGGA,213746.990,,,,,0,00,,,M,0.0,M,,0000*53\r
-$PSRFTXTVersion GSW3.2.1PAT_3.1.00.12-SDK001P1.00c *3F\r
-$PSRFTXTHTC GPS_ART_321000_GEN*20\r
-$PSRFTXTTOW:  423546*3B\r
-$PSRFTXTWK:   1412*4F\r
-$PSRFTXTPOS:  1533096 -4464909 4274442*2A\r
-$PSRFTXTCLK:  94810*05\r
-$PSRFTXTCHNL: 12*5F\r
-$PSRFTXTBaud rate: 57600 *51\r
-$GPGGA,213912.270,,,,,0,00,,,M,0.0,M,,0000*59\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213912.270,V,,,,,,,010207,,,N*46\r
-$GPGGA,213913.211,,,,,0,00,,,M,0.0,M,,0000*5F\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213913.211,V,,,,,,,010207,,,N*40\r
-$GPGGA,213914.200,,,,,0,00,,,M,0.0,M,,0000*58\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213914.200,V,,,,,,,010207,,,N*47\r
-$GPGGA,213915.196,,,,,0,00,,,M,0.0,M,,0000*55\r
-$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r
-$GPRMC,213915.196,V,,,,,,,010207,,,N*4A\r
-$GPGGA,213916.199,4221.0377,N,07102.9778,W,1,03,13.4,-32.4,M,-33.7,M,,0000*45\r
-$GPGSA,A,2,26,07,06,,,,,,,,,,13.4,13.4,1.0*37\r
-$GPGSV,3,1,11,26,55,180,28,06,46,258,33,07,43,272,30,21,22,304,*77\r
-$GPGSV,3,2,11,24,83,061,,29,64,170,,10,45,056,,02,23,121,*7F\r
-$GPGSV,3,3,11,08,17,067,,27,10,041,,18,05,257,*4B\r
-$GPRMC,213916.199,A,4221.0377,N,07102.9778,W,0.00,,010207,,,A*6A\r
-$GPGGA,213917.199,4221.0510,N,07102.9549,W,1,04,3.9,-65.2,M,-33.7,M,,0000*7C\r
-$GPGSA,A,3,26,07,06,21,,,,,,,,,4.1,3.9,1.0*3A\r
-$GPRMC,213917.199,A,4221.0510,N,07102.9549,W,0.23,175.43,010207,,,A*77\r
-$GPGGA,213918.199,4221.0853,N,07102.9382,W,1,04,3.9,50.0,M,-33.7,M,,0000*51\r
-$GPGSA,A,3,26,07,06,21,,,,,,,,,4.1,3.9,1.0*3A\r
-$GPRMC,213918.199,A,4221.0853,N,07102.9382,W,0.95,326.55,010207,,,A*7D\r
-$GPGGA,213919.000,4221.0975,N,07102.9300,W,1,04,3.9,86.2,M,-33.7,M,,0000*57\r
-$GPGSA,A,3,26,07,06,21,,,,,,,,,4.1,3.9,1.0*3A\r
-$GPRMC,213919.000,A,4221.0975,N,07102.9300,W,0.55,332.53,010207,,,A*7D\r
-$GPGGA,213920.000,4221.1129,N,07102.9146,W,1,04,3.9,129.7,M,-33.7,M,,0000*6C\r
-$GPGSA,A,3,26,07,06,21,,,,,,,,,4.1,3.9,1.0*3A\r
-$GPRMC,213920.000,A,4221.1129,N,07102.9146,W,0.00,,010207,,,A*6D\r
-$GPGGA,213921.000,4221.1129,N,07102.9146,W,1,04,3.9,129.7,M,-33.7,M,,0000*6D\r
-$GPGSA,A,3,26,07,06,21,,,,,,,,,4.1,3.9,1.0*3A\r
-$GPGSV,3,1,11,26,55,180,29,06,46,258,26,07,43,272,33,21,22,304,26*75\r
-$GPGSV,3,2,11,24,83,061,,29,64,170,,10,45,056,,02,23,121,*7F\r
-$GPGSV,3,3,11,08,17,067,28,27,10,041,,18,05,257,*41\r
-$GPRMC,213921.000,A,4221.1129,N,07102.9146,W,0.00,,010207,,,A*6C\r
-$GPGGA,213922.000,4221.1129,N,07102.9146,W,1,04,3.9,129.7,M,-33.7,M,,0000*6E\r
-$GPGSA,A,3,26,07,06,21,,,,,,,,,4.1,3.9,1.0*3A\r
-$GPRMC,213922.000,A,4221.1129,N,07102.9146,W,0.00,,010207,,,A*6F\r
-$GPGGA,213923.000,4221.1129,N,07102.9146,W,1,04,3.9,129.7,M,-33.7,M,,0000*6F\r
-$GPGSA,A,3,26,07,06,21,,,,,,,,,4.1,3.9,1.0*3A\r
-$GPRMC,213923.000,A,4221.1129,N,07102.9146,W,0.00,,010207,,,A*6E\r
-$GPGGA,213924.000,4221.1129,N,07102.9146,W,1,04,3.9,129.7,M,-33.7,M,,0000*68\r
-$GPGSA,A,3,26,07,06,21,,,,,,,,,4.0,3.9,1.0*3B\r
-$GPRMC,213924.000,A,4221.1129,N,07102.9146,W,0.00,,010207,,,A*69\r
-$GPGGA,213925.000,4221.1129,N,07102.9146,W,1,04,3.9,129.7,M,-33.7,M,,0000*69\r
-$GPGSA,A,3,26,07,06,21,,,,,,,,,4.0,3.9,1.0*3B\r
-$GPRMC,213925.000,A,4221.1129,N,07102.9146,W,0.00,,010207,,,A*68\r
-$GPGGA,213926.000,4221.1112,N,07102.9177,W,1,04,3.9,136.5,M,-33.7,M,,0000*6C\r
-\r
-\r
diff --git a/lib/pud/nmealib/samples/parse_file/main.c b/lib/pud/nmealib/samples/parse_file/main.c
deleted file mode 100644 (file)
index 3836657..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * This file is part of nmealib.
- *
- * Copyright (c) 2008 Timur Sinitsyn
- * Copyright (c) 2011 Ferry Huberts
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <nmea/info.h>
-#include <nmea/context.h>
-#include <nmea/parser.h>
-#include <nmea/gmath.h>
-
-#include <stdio.h>
-#include <unistd.h>
-#include <libgen.h>
-#include <string.h>
-
-static const char * traceStr = "Trace: ";
-static const char * errorStr = "Error: ";
-static const char * eol = "\n";
-
-static void trace(const char *str, int str_size) {
-       write(1, traceStr, strlen(traceStr));
-       write(1, str, str_size);
-       write(1, eol, strlen(eol));
-}
-static void error(const char *str, int str_size) {
-       write(1, errorStr, strlen(errorStr));
-       write(1, str, str_size);
-       write(1, eol, strlen(eol));
-}
-
-int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused))) {
-       char fn[2048];
-       const char * filename = &fn[0];
-       const char * deffile;
-       const char * dn;
-       nmeaINFO info;
-       nmeaPARSER parser;
-       FILE *file;
-       char buff[2048];
-       int size, it = 0;
-       nmeaPOS dpos;
-
-       if (argc <= 1) {
-               dn = dirname(argv[0]);
-               deffile="/../../samples/parse_file/gpslog.txt";
-       } else {
-               dn="";
-               deffile = argv[1];
-       }
-       snprintf(&fn[0], sizeof(fn),"%s%s", dn, deffile);
-       printf("Using file %s\n", filename);
-
-       file = fopen(filename, "rb");
-
-       if (!file) {
-               printf("Could not open file %s\n", filename);
-               return -1;
-       }
-
-       nmea_context_set_trace_func(&trace);
-       nmea_context_set_error_func(&error);
-
-       nmea_zero_INFO(&info);
-       nmea_parser_init(&parser);
-
-       while (!feof(file)) {
-               size = (int) fread(&buff[0], 1, 100, file);
-
-               nmea_parse(&parser, &buff[0], size, &info);
-               nmea_info2pos(&info, &dpos);
-
-               printf("*** %03d, Lat: %f, Lon: %f, Sig: %d, Fix: %d\n", it++, dpos.lat, dpos.lon, info.sig, info.fix);
-       }
-
-       fseek(file, 0, SEEK_SET);
-
-       /*
-        }
-        */
-
-       nmea_parser_destroy(&parser);
-       fclose(file);
-
-       return 0;
-}
index b583de5..77e3021 100644 (file)
@@ -1,9 +1,6 @@
 /*
  * This file is part of nmealib.
  *
- * Copyright (c) 2008 Timur Sinitsyn
- * Copyright (c) 2011 Ferry Huberts
- *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
index edfc960..dc6b730 100644 (file)
@@ -1,9 +1,6 @@
 /*
  * This file is part of nmealib.
  *
- * Copyright (c) 2008 Timur Sinitsyn
- * Copyright (c) 2011 Ferry Huberts
- *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
@@ -154,7 +151,6 @@ void nmea_GPGSA2info(const nmeaGPGSA *pack, nmeaINFO *info) {
                info->fix = pack->fix_type;
        }
        if (nmea_INFO_is_present(pack->present, SATINUSE)) {
-               assert(sizeof(info->satinfo.in_use) == sizeof(info->satinfo.in_use));
                info->satinfo.inuse = 0;
                for (i = 0; i < NMEA_MAXSAT; i++) {
                        info->satinfo.in_use[i] = pack->sat_prn[i];
index cd425f6..27d82c0 100644 (file)
@@ -1,9 +1,6 @@
 /*
  * This file is part of nmealib.
  *
- * Copyright (c) 2008 Timur Sinitsyn
- * Copyright (c) 2011 Ferry Huberts
- *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
index bc590e5..ddff086 100644 (file)
@@ -1,9 +1,6 @@
 /*
  * This file is part of nmealib.
  *
- * Copyright (c) 2008 Timur Sinitsyn
- * Copyright (c) 2011 Ferry Huberts
- *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
index 3e6cefc..074b042 100644 (file)
@@ -1,9 +1,6 @@
 /*
  * This file is part of nmealib.
  *
- * Copyright (c) 2008 Timur Sinitsyn
- * Copyright (c) 2011 Ferry Huberts
- *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
index 98d310e..113b70e 100644 (file)
@@ -1,9 +1,6 @@
 /*
  * This file is part of nmealib.
  *
- * Copyright (c) 2008 Timur Sinitsyn
- * Copyright (c) 2011 Ferry Huberts
- *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
index ff3065a..2b11b92 100644 (file)
@@ -1,9 +1,6 @@
 /*
  * This file is part of nmealib.
  *
- * Copyright (c) 2008 Timur Sinitsyn
- * Copyright (c) 2011 Ferry Huberts
- *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * @return true on success, false otherwise
  */
 static bool _nmea_parse_time(const char *s, const int len, nmeaTIME *t) {
-       assert(s);
-       assert(t);
-
-       if (len == (sizeof("hhmmss") - 1)) {
-               t->hsec = 0;
-               return (3 == nmea_scanf(s, len, "%2d%2d%2d", &t->hour, &t->min, &t->sec));
-       }
-
-       if (len == (sizeof("hhmmss.s") - 1)) {
-               if (4 == nmea_scanf(s, len, "%2d%2d%2d.%d", &t->hour, &t->min, &t->sec, &t->hsec)) {
-                       t->hsec *= 10;
-                       return true;
-               }
-               return false;
-       }
-
-       if (len == (sizeof("hhmmss.ss") - 1)) {
-               return (4 == nmea_scanf(s, len, "%2d%2d%2d.%d", &t->hour, &t->min, &t->sec, &t->hsec));
-       }
-
-       if (len == (sizeof("hhmmss.sss") - 1)) {
-               if ((4 == nmea_scanf(s, len, "%2d%2d%2d.%d", &t->hour, &t->min, &t->sec, &t->hsec))) {
-                       t->hsec = (t->hsec + 9) / 10;
-                       return true;
-               }
-               return false;
-       }
-
-       nmea_error("Parse error: invalid time format in %s", s);
-       return false;
+  assert(s);
+  assert(t);
+
+  if (len == (sizeof("hhmmss") - 1)) {
+    t->hsec = 0;
+    return (3 == nmea_scanf(s, len, "%2d%2d%2d", &t->hour, &t->min, &t->sec));
+  }
+
+  if (len == (sizeof("hhmmss.s") - 1)) {
+    if (4 == nmea_scanf(s, len, "%2d%2d%2d.%d", &t->hour, &t->min, &t->sec, &t->hsec)) {
+      t->hsec *= 10;
+      return true;
+    }
+    return false;
+  }
+
+  if (len == (sizeof("hhmmss.ss") - 1)) {
+    return (4 == nmea_scanf(s, len, "%2d%2d%2d.%d", &t->hour, &t->min, &t->sec, &t->hsec));
+  }
+
+  if (len == (sizeof("hhmmss.sss") - 1)) {
+    if ((4 == nmea_scanf(s, len, "%2d%2d%2d.%d", &t->hour, &t->min, &t->sec, &t->hsec))) {
+      t->hsec = (t->hsec + 9) / 10;
+      return true;
+    }
+    return false;
+  }
+
+  nmea_error("Parse error: invalid time format in %s", s);
+  return false;
 }
 
 /**
@@ -87,22 +84,22 @@ static bool _nmea_parse_time(const char *s, const int len, nmeaTIME *t) {
  * @return true on success, false otherwise
  */
 static bool _nmea_parse_date(const int date, nmeaTIME *t) {
-       assert(t);
-
-       if ((date < 0) || (date > 999999)) {
-               nmea_error("Parse error: invalid time format in %d", date);
-               return false;
-       }
-
-       t->day = date / 10000;
-       t->mon = (date / 100) % 100;
-       t->mon--;
-       t->year = date % 100;
-       if (t->year < 90) {
-               t->year += 100;
-       }
-
-       return true;
+  assert(t);
+
+  if ((date < 0) || (date > 999999)) {
+    nmea_error("Parse error: invalid time format in %d", date);
+    return false;
+  }
+
+  t->day = date / 10000;
+  t->mon = (date / 100) % 100;
+  t->mon--;
+  t->year = date % 100;
+  if (t->year < 90) {
+    t->year += 100;
+  }
+
+  return true;
 }
 
 /**
@@ -119,17 +116,17 @@ static bool _nmea_parse_date(const int date, nmeaTIME *t) {
  * @return true when valid, false otherwise
  */
 static bool validateTime(const nmeaTIME * t) {
-       if (!t) {
-               return false;
-       }
+  if (!t) {
+    return false;
+  }
 
-       if (!((t->hour >= 0) && (t->hour < 24) && (t->min >= 0) && (t->min < 60) && (t->sec >= 0) && (t->sec <= 60)
-                       && (t->hsec >= 0) && (t->hsec < 100))) {
-               nmea_error("Parse error: invalid time (%d:%d:%d.%d)", t->hour, t->min, t->sec, t->hsec);
-               return false;
-       }
+  if (!((t->hour >= 0) && (t->hour < 24) && (t->min >= 0) && (t->min < 60) && (t->sec >= 0) && (t->sec <= 60)
+      && (t->hsec >= 0) && (t->hsec < 100))) {
+    nmea_error("Parse error: invalid time (%d:%d:%d.%d)", t->hour, t->min, t->sec, t->hsec);
+    return false;
+  }
 
-       return true;
+  return true;
 }
 
 /**
@@ -145,16 +142,16 @@ static bool validateTime(const nmeaTIME * t) {
  * @return true when valid, false otherwise
  */
 static bool validateDate(const nmeaTIME * t) {
-       if (!t) {
-               return false;
-       }
+  if (!t) {
+    return false;
+  }
 
-       if (!((t->year >= 90) && (t->year <= 189) && (t->mon >= 0) && (t->mon <= 11) && (t->day >= 1) && (t->day <= 31))) {
-               nmea_error("Parse error: invalid date (%d-%d-%d - D-M-Y)", t->day, t->mon, t->year);
-               return false;
-       }
+  if (!((t->year >= 90) && (t->year <= 189) && (t->mon >= 0) && (t->mon <= 11) && (t->day >= 1) && (t->day <= 31))) {
+    nmea_error("Parse error: invalid date (%d-%d-%d - D-M-Y)", t->day, t->mon, t->year);
+    return false;
+  }
 
-       return true;
+  return true;
 }
 
 /**
@@ -170,25 +167,25 @@ static bool validateDate(const nmeaTIME * t) {
  * @return true when valid, false otherwise
  */
 static bool validateNSEW(char * c, const bool ns) {
-       if (!c) {
-               return false;
-       }
-
-       *c = toupper(*c);
-
-       if (ns) {
-               if (!((*c == 'N') || (*c == 'S'))) {
-                       nmea_error("Parse error: invalid north/south (%c)", *c);
-                       return false;
-               }
-       } else {
-               if (!((*c == 'E') || (*c == 'W'))) {
-                       nmea_error("Parse error: invalid east/west (%c)", *c);
-                       return false;
-               }
-       }
-
-       return true;
+  if (!c) {
+    return false;
+  }
+
+  *c = toupper(*c);
+
+  if (ns) {
+    if (!((*c == 'N') || (*c == 'S'))) {
+      nmea_error("Parse error: invalid north/south (%c)", *c);
+      return false;
+    }
+  } else {
+    if (!((*c == 'E') || (*c == 'W'))) {
+      nmea_error("Parse error: invalid east/west (%c)", *c);
+      return false;
+    }
+  }
+
+  return true;
 }
 
 /**
@@ -214,79 +211,93 @@ static bool validateNSEW(char * c, const bool ns) {
  * @return true when valid, false otherwise
  */
 static bool validateMode(char * c) {
-       if (!c) {
-               return false;
-       }
+  if (!c) {
+    return false;
+  }
 
-       *c = toupper(*c);
+  *c = toupper(*c);
 
-       if (!((*c == 'A') || (*c == 'D') || (*c == 'E') || (*c == 'F') || (*c == 'M') || (*c == 'N') || (*c == 'P')
-                       || (*c == 'R') || (*c == 'S'))) {
-               nmea_error("Parse error: invalid mode (%c)", *c);
-               return false;
-       }
+  if (!((*c == 'A') || (*c == 'D') || (*c == 'E') || (*c == 'F') || (*c == 'M') || (*c == 'N') || (*c == 'P')
+      || (*c == 'R') || (*c == 'S'))) {
+    nmea_error("Parse error: invalid mode (%c)", *c);
+    return false;
+  }
 
-       return true;
+  return true;
+}
+
+/**
+ * Determine whether the given character is not allowed in an NMEA string.
+ *
+ * @param c
+ * The character to check
+ *
+ * @return
+ * - a pointer to the invalid character name/description when the string has invalid characters
+ * - NULL otherwise
+ */
+const char * isInvalidNMEACharacter(const char * c) {
+  static const char * invalidNonAsciiCharsName = "non-ascii character";
+  static const char invalidChars[] = {
+      '$',
+      '*',
+      '!',
+      '\\',
+      '^',
+      '~'
+  };
+  static const char * invalidCharsNames[] = {
+      "sentence delimiter ($)",
+      "checksum field delimiter (*)",
+      "exclamation mark (!)",
+      "backslash (\\)",
+      "power (^)",
+      "tilde (~)"
+  };
+
+  size_t charIndex;
+
+  if (!((*c >= 32) && (*c <= 126))) {
+    return invalidNonAsciiCharsName;
+  }
+
+  for (charIndex = 0; charIndex < sizeof(invalidChars); charIndex++) {
+    if (*c == invalidChars[charIndex]) {
+      return invalidCharsNames[charIndex];
+    }
+  }
+
+  return NULL;
 }
 
 /**
  * Determine whether the given string contains characters that are not allowed
- * for fields in an NMEA string.
+ * in an NMEA string.
  *
- * @param str
+ * @param s
  * The string to check
- * @param str_len
+ * @param len
  * The length of the string to check
- * @param strName
- * The name of the string to report when invalid characters are encountered
- * @param report
- * A pointer to a buffer in which to place the report string when an invalid
- * nmea character is detected
- * @param reportSize
- * The size of the report buffer
  *
  * @return
- * - true when the string has invalid characters
- * - false otherwise
+ * - a pointer to the invalid character name/description when the string has invalid characters
+ * - NULL otherwise
  */
-bool nmea_parse_sentence_has_invalid_chars(const char * str, const size_t str_len, const char * strName, char * report,
-               const size_t reportSize) {
-       static const char invalidChars[] = { '$', '*', ',', '!', '\\', '^', '~' };
-       static const char * invalidCharsNames[] = { "sentence delimiter ($)", "checksum field delimiter (*)", "comma (,)",
-                       "exclamation mark (!)", "backslash (\\)", "power (^)", "tilde (~)" };
-
-       size_t i;
-       size_t j;
-
-       if (!str || !str_len) {
-               return false;
-       }
-
-       for (i = 0; i < str_len; i++) {
-               char c = str[i];
-
-               if (!((c >= 32) && (c <= 126))) {
-                       if (report && reportSize) {
-                               snprintf(report, reportSize, "Configured %s (%s),"
-                                               " character %lu, can not contain non-printable"
-                                               " characters (codes outside the range [32, 126])", strName, str, (unsigned long) i + 1);
-                       }
-                       return true;
-               }
-
-               for (j = 0; j < sizeof(invalidChars); j++) {
-                       if (c == invalidChars[j]) {
-                               if (report && reportSize) {
-                                       snprintf(report, reportSize, "Configured %s (%s),"
-                                                       " character %lu, can not contain %s characters", strName, str, (unsigned long) i + 1,
-                                                       invalidCharsNames[j]);
-                               }
-                               return true;
-                       }
-               }
-       }
-
-       return false;
+const char * nmea_parse_sentence_has_invalid_chars(const char * s, const size_t len) {
+  size_t i;
+
+  if (!s || !len) {
+    return NULL;
+  }
+
+  for (i = 0; i < len; i++) {
+    const char * invalidCharName = isInvalidNMEACharacter(&s[i]);
+    if (invalidCharName) {
+      return invalidCharName;
+    }
+  }
+
+  return NULL;
 }
 
 /**
@@ -297,75 +308,24 @@ bool nmea_parse_sentence_has_invalid_chars(const char * str, const size_t str_le
  * @param len the length of the string
  * @return The packet type (or GPNON when it could not be determined)
  */
-int nmea_parse_get_sentence_type(const char *s, const int len) {
-       static const char *pheads[] = { "GPGGA", "GPGSA", "GPGSV", "GPRMC", "GPVTG" };
-       static const int types[] = { GPGGA, GPGSA, GPGSV, GPRMC, GPVTG };
-       unsigned int i;
+enum nmeaPACKTYPE nmea_parse_get_sentence_type(const char *s, const int len) {
+  static const char *pheads[] = { "GPGGA", "GPGSA", "GPGSV", "GPRMC", "GPVTG" };
+  static const enum nmeaPACKTYPE types[] = { GPGGA, GPGSA, GPGSV, GPRMC, GPVTG };
+  unsigned int i;
 
-       assert(s);
+  assert(s);
 
-       if (len < 5)
-               return GPNON;
+  if (len < 5) {
+    return GPNON;
+  }
 
-       for (i = 0; i < (sizeof(types) / sizeof(int)); i++) {
-               if (!memcmp(s, pheads[i], 5)) {
-                       return types[i];
-               }
-       }
+  for (i = 0; i < (sizeof(types) / sizeof(types[0])); i++) {
+    if (!memcmp(s, pheads[i], 5)) {
+      return types[i];
+    }
+  }
 
-       return GPNON;
-}
-
-/**
- * Find the tail ("\r\n") of a sentence in a string and check the checksum of the sentence.
- *
- * @param s the string
- * @param len the length of the string
- * @param checksum a pointer to the location where the checksum (as specified
- * in the sentence) should be stored (will be -1 if the checksum did not match
- * the calculated checksum or a new sentence was found in s after the start of s)
- * @return Number of bytes from the start of the string until the tail or 0
- * when no sentence was found
- */
-int nmea_parse_get_sentence_length(const char *s, const int len, int *checksum) {
-       static const int tail_sz = 1 + 2 + 2 /* *xx\r\n */;
-
-       const char * s_end = s + len;
-       int nread = 0;
-       int cksum = 0;
-
-       assert(s);
-       assert(checksum);
-
-       *checksum = -1;
-
-       for (; s < s_end; s++, nread++) {
-               if ((*s == '$') && nread) {
-                       /* found a new sentence start marker _after_ the first character of s */
-                       s = NULL; /* do not reset nread when exiting */
-                       break;
-               }
-               if ('*' == *s) {
-                       /* found a sentence checksum marker */
-                       if (((s + tail_sz) <= s_end) && ('\r' == s[3]) && ('\n' == s[4])) {
-                               *checksum = nmea_atoi(s + 1, 2, 16);
-                               nread = len - (int) (s_end - (s + tail_sz));
-                               if (*checksum != cksum) {
-                                       *checksum = -1;
-                                       s = NULL; /* do not reset nread when exiting */
-                               }
-                       }
-                       break;
-               }
-               if (nread) {
-                       cksum ^= (int) *s;
-               }
-       }
-
-       if (s && (*checksum < 0))
-               nread = 0;
-
-       return nread;
+  return GPNON;
 }
 
 /**
@@ -373,109 +333,114 @@ int nmea_parse_get_sentence_length(const char *s, const int len, int *checksum)
  *
  * @param s the string
  * @param len the length of the string
+ * @param has_checksum true when the string contains a checksum
  * @param pack a pointer to the result structure
  * @return 1 (true) - if parsed successfully or 0 (false) otherwise.
  */
-int nmea_parse_GPGGA(const char *s, const int len, nmeaGPGGA *pack) {
-       int token_count;
-       char time_buff[NMEA_TIMEPARSE_BUF];
-       size_t time_buff_len = 0;
-
-       assert(s);
-       assert(pack);
-
-       nmea_trace_buff(s, len);
-
-       /*
-        * Clear before parsing, to be able to detect absent fields
-        */
-       time_buff[0] = '\0';
-       pack->present = 0;
-       pack->utc.hour = -1;
-       pack->utc.min = -1;
-       pack->utc.sec = -1;
-       pack->utc.hsec = -1;
-       pack->lat = NAN;
-       pack->ns = 0;
-       pack->lon = NAN;
-       pack->ew = 0;
-       pack->sig = -1;
-       pack->satinuse = -1;
-       pack->HDOP = NAN;
-       pack->elv = NAN;
-       pack->elv_units = 0;
-       pack->diff = 0;                 /* ignored */
-       pack->diff_units = 0;   /* ignored */
-       pack->dgps_age = 0;             /* ignored */
-       pack->dgps_sid = 0;             /* ignored */
-
-       /* parse */
-       token_count = nmea_scanf(s, len, "$GPGGA,%s,%f,%c,%f,%c,%d,%d,%f,%f,%c,%f,%c,%f,%d*", &time_buff[0], &pack->lat,
-                       &pack->ns, &pack->lon, &pack->ew, &pack->sig, &pack->satinuse, &pack->HDOP, &pack->elv, &pack->elv_units,
-                       &pack->diff, &pack->diff_units, &pack->dgps_age, &pack->dgps_sid);
-
-       /* see that we have enough tokens */
-       if (token_count != 14) {
-               nmea_error("GPGGA parse error: need 14 tokens, got %d in %s", token_count, s);
-               return 0;
-       }
-
-       /* determine which fields are present and validate them */
-
-       time_buff_len = strlen(&time_buff[0]);
-       if (time_buff_len > (NMEA_TIMEPARSE_BUF - 1))
-               time_buff_len = NMEA_TIMEPARSE_BUF - 1;
-       if (time_buff_len) {
-               if (!_nmea_parse_time(&time_buff[0], time_buff_len, &pack->utc)) {
-                       return 0;
-               }
-
-               if (!validateTime(&pack->utc)) {
-                       return 0;
-               }
-
-               nmea_INFO_set_present(&pack->present, UTCTIME);
-       }
-       if (!isnan(pack->lat) && (pack->ns)) {
-               if (!validateNSEW(&pack->ns, true)) {
-                       return 0;
-               }
-
-               nmea_INFO_set_present(&pack->present, LAT);
-       }
-       if (!isnan(pack->lon) && (pack->ew)) {
-               if (!validateNSEW(&pack->ew, false)) {
-                       return 0;
-               }
-
-               nmea_INFO_set_present(&pack->present, LON);
-       }
-       if (pack->sig != -1) {
-               if (!((pack->sig >= NMEA_SIG_FIRST) && (pack->sig <= NMEA_SIG_LAST))) {
-                       nmea_error("GPGGA parse error: invalid signal %d, expected [%d, %d]", pack->sig, NMEA_SIG_FIRST, NMEA_SIG_LAST);
-                       return 0;
-               }
-
-               nmea_INFO_set_present(&pack->present, SIG);
-       }
-       if (pack->satinuse != -1) {
-               nmea_INFO_set_present(&pack->present, SATINUSECOUNT);
-       }
-       if (!isnan(pack->HDOP)) {
-               nmea_INFO_set_present(&pack->present, HDOP);
-       }
-       if (!isnan(pack->elv) && (pack->elv_units)) {
-               if (pack->elv_units != 'M') {
-                       nmea_error("GPGGA parse error: invalid elevation unit (%c)", pack->elv_units);
-                       return 0;
-               }
-
-               nmea_INFO_set_present(&pack->present, ELV);
-       }
-       /* ignore diff and diff_units */
-       /* ignore dgps_age and dgps_sid */
-
-       return 1;
+int nmea_parse_GPGGA(const char *s, const int len, bool has_checksum, nmeaGPGGA *pack) {
+  int token_count;
+  char time_buff[NMEA_TIMEPARSE_BUF];
+  size_t time_buff_len = 0;
+
+  if (!has_checksum) {
+    return 0;
+  }
+
+  assert(s);
+  assert(pack);
+
+  nmea_trace_buff(s, len);
+
+  /*
+   * Clear before parsing, to be able to detect absent fields
+   */
+  time_buff[0] = '\0';
+  pack->present = 0;
+  pack->utc.hour = -1;
+  pack->utc.min = -1;
+  pack->utc.sec = -1;
+  pack->utc.hsec = -1;
+  pack->lat = NAN;
+  pack->ns = 0;
+  pack->lon = NAN;
+  pack->ew = 0;
+  pack->sig = -1;
+  pack->satinuse = -1;
+  pack->HDOP = NAN;
+  pack->elv = NAN;
+  pack->elv_units = 0;
+  pack->diff = 0;     /* ignored */
+  pack->diff_units = 0; /* ignored */
+  pack->dgps_age = 0;   /* ignored */
+  pack->dgps_sid = 0;   /* ignored */
+
+  /* parse */
+  token_count = nmea_scanf(s, len, "$GPGGA,%s,%f,%c,%f,%c,%d,%d,%f,%f,%c,%f,%c,%f,%d*", &time_buff[0], &pack->lat,
+      &pack->ns, &pack->lon, &pack->ew, &pack->sig, &pack->satinuse, &pack->HDOP, &pack->elv, &pack->elv_units,
+      &pack->diff, &pack->diff_units, &pack->dgps_age, &pack->dgps_sid);
+
+  /* see that we have enough tokens */
+  if (token_count != 14) {
+    nmea_error("GPGGA parse error: need 14 tokens, got %d in %s", token_count, s);
+    return 0;
+  }
+
+  /* determine which fields are present and validate them */
+
+  time_buff_len = strlen(&time_buff[0]);
+  if (time_buff_len > (NMEA_TIMEPARSE_BUF - 1))
+    time_buff_len = NMEA_TIMEPARSE_BUF - 1;
+  if (time_buff_len) {
+    if (!_nmea_parse_time(&time_buff[0], time_buff_len, &pack->utc)) {
+      return 0;
+    }
+
+    if (!validateTime(&pack->utc)) {
+      return 0;
+    }
+
+    nmea_INFO_set_present(&pack->present, UTCTIME);
+  }
+  if (!isnan(pack->lat) && (pack->ns)) {
+    if (!validateNSEW(&pack->ns, true)) {
+      return 0;
+    }
+
+    nmea_INFO_set_present(&pack->present, LAT);
+  }
+  if (!isnan(pack->lon) && (pack->ew)) {
+    if (!validateNSEW(&pack->ew, false)) {
+      return 0;
+    }
+
+    nmea_INFO_set_present(&pack->present, LON);
+  }
+  if (pack->sig != -1) {
+    if (!((pack->sig >= NMEA_SIG_FIRST) && (pack->sig <= NMEA_SIG_LAST))) {
+      nmea_error("GPGGA parse error: invalid signal %d, expected [%d, %d]", pack->sig, NMEA_SIG_FIRST, NMEA_SIG_LAST);
+      return 0;
+    }
+
+    nmea_INFO_set_present(&pack->present, SIG);
+  }
+  if (pack->satinuse != -1) {
+    nmea_INFO_set_present(&pack->present, SATINUSECOUNT);
+  }
+  if (!isnan(pack->HDOP)) {
+    nmea_INFO_set_present(&pack->present, HDOP);
+  }
+  if (!isnan(pack->elv) && (pack->elv_units)) {
+    if (pack->elv_units != 'M') {
+      nmea_error("GPGGA parse error: invalid elevation unit (%c)", pack->elv_units);
+      return 0;
+    }
+
+    nmea_INFO_set_present(&pack->present, ELV);
+  }
+  /* ignore diff and diff_units */
+  /* ignore dgps_age and dgps_sid */
+
+  return 1;
 }
 
 /**
@@ -483,75 +448,80 @@ int nmea_parse_GPGGA(const char *s, const int len, nmeaGPGGA *pack) {
  *
  * @param s the string
  * @param len the length of the string
+ * @param has_checksum true when the string contains a checksum
  * @param pack a pointer to the result structure
  * @return 1 (true) - if parsed successfully or 0 (false) otherwise.
  */
-int nmea_parse_GPGSA(const char *s, const int len, nmeaGPGSA *pack) {
-       int token_count;
-       int i;
-
-       assert(s);
-       assert(pack);
-
-       nmea_trace_buff(s, len);
-
-       /*
-        * Clear before parsing, to be able to detect absent fields
-        */
-       pack->present = 0;
-       pack->fix_mode = 0;
-       pack->fix_type = -1;
-       for (i = 0; i < NMEA_MAXSAT; i++) {
-               pack->sat_prn[i] = 0;
-       }
-       pack->PDOP = NAN;
-       pack->HDOP = NAN;
-       pack->VDOP = NAN;
-
-       /* parse */
-       token_count = nmea_scanf(s, len, "$GPGSA,%c,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%f,%f,%f*", &pack->fix_mode,
-                       &pack->fix_type, &pack->sat_prn[0], &pack->sat_prn[1], &pack->sat_prn[2], &pack->sat_prn[3],
-                       &pack->sat_prn[4], &pack->sat_prn[5], &pack->sat_prn[6], &pack->sat_prn[7], &pack->sat_prn[8],
-                       &pack->sat_prn[9], &pack->sat_prn[10], &pack->sat_prn[11], &pack->PDOP, &pack->HDOP, &pack->VDOP);
-
-       /* see that we have enough tokens */
-       if (token_count != 17) {
-               nmea_error("GPGSA parse error: need 17 tokens, got %d in %s", token_count, s);
-               return 0;
-       }
-
-       /* determine which fields are present and validate them */
-
-       pack->fix_mode = toupper(pack->fix_mode);
-       if (!((pack->fix_mode == 'A') || (pack->fix_mode == 'M'))) {
-               nmea_error("GPGSA parse error: invalid fix mode (%c)", pack->fix_mode);
-               return 0;
-       }
-       if (pack->fix_type != -1) {
-               if (!((pack->fix_type >= NMEA_FIX_FIRST) && (pack->fix_type <= NMEA_FIX_LAST))) {
-                       nmea_error("GPGSA parse error: invalid fix type %d, expected [%d, %d]", pack->fix_type, NMEA_FIX_FIRST, NMEA_FIX_LAST);
-                       return 0;
-               }
-
-               nmea_INFO_set_present(&pack->present, FIX);
-       }
-       for (i = 0; i < NMEA_MAXSAT; i++) {
-               if (pack->sat_prn[i] != 0) {
-                       nmea_INFO_set_present(&pack->present, SATINUSE);
-                       break;
-               }
-       }
-       if (!isnan(pack->PDOP)) {
-               nmea_INFO_set_present(&pack->present, PDOP);
-       }
-       if (!isnan(pack->HDOP)) {
-               nmea_INFO_set_present(&pack->present, HDOP);
-       }
-       if (!isnan(pack->VDOP)) {
-               nmea_INFO_set_present(&pack->present, VDOP);
-       }
-
-       return 1;
+int nmea_parse_GPGSA(const char *s, const int len, bool has_checksum, nmeaGPGSA *pack) {
+  int token_count;
+  int i;
+
+  if (!has_checksum) {
+    return 0;
+  }
+
+  assert(s);
+  assert(pack);
+
+  nmea_trace_buff(s, len);
+
+  /*
+   * Clear before parsing, to be able to detect absent fields
+   */
+  pack->present = 0;
+  pack->fix_mode = 0;
+  pack->fix_type = -1;
+  for (i = 0; i < NMEA_MAXSAT; i++) {
+    pack->sat_prn[i] = 0;
+  }
+  pack->PDOP = NAN;
+  pack->HDOP = NAN;
+  pack->VDOP = NAN;
+
+  /* parse */
+  token_count = nmea_scanf(s, len, "$GPGSA,%c,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%f,%f,%f*", &pack->fix_mode,
+      &pack->fix_type, &pack->sat_prn[0], &pack->sat_prn[1], &pack->sat_prn[2], &pack->sat_prn[3],
+      &pack->sat_prn[4], &pack->sat_prn[5], &pack->sat_prn[6], &pack->sat_prn[7], &pack->sat_prn[8],
+      &pack->sat_prn[9], &pack->sat_prn[10], &pack->sat_prn[11], &pack->PDOP, &pack->HDOP, &pack->VDOP);
+
+  /* see that we have enough tokens */
+  if (token_count != 17) {
+    nmea_error("GPGSA parse error: need 17 tokens, got %d in %s", token_count, s);
+    return 0;
+  }
+
+  /* determine which fields are present and validate them */
+
+  pack->fix_mode = toupper(pack->fix_mode);
+  if (!((pack->fix_mode == 'A') || (pack->fix_mode == 'M'))) {
+    nmea_error("GPGSA parse error: invalid fix mode (%c)", pack->fix_mode);
+    return 0;
+  }
+  if (pack->fix_type != -1) {
+    if (!((pack->fix_type >= NMEA_FIX_FIRST) && (pack->fix_type <= NMEA_FIX_LAST))) {
+      nmea_error("GPGSA parse error: invalid fix type %d, expected [%d, %d]", pack->fix_type, NMEA_FIX_FIRST, NMEA_FIX_LAST);
+      return 0;
+    }
+
+    nmea_INFO_set_present(&pack->present, FIX);
+  }
+  for (i = 0; i < NMEA_MAXSAT; i++) {
+    if (pack->sat_prn[i] != 0) {
+      nmea_INFO_set_present(&pack->present, SATINUSE);
+      break;
+    }
+  }
+  if (!isnan(pack->PDOP)) {
+    nmea_INFO_set_present(&pack->present, PDOP);
+  }
+  if (!isnan(pack->HDOP)) {
+    nmea_INFO_set_present(&pack->present, HDOP);
+  }
+  if (!isnan(pack->VDOP)) {
+    nmea_INFO_set_present(&pack->present, VDOP);
+  }
+
+  return 1;
 }
 
 /**
@@ -559,81 +529,86 @@ int nmea_parse_GPGSA(const char *s, const int len, nmeaGPGSA *pack) {
  *
  * @param s the string
  * @param len the length of the string
+ * @param has_checksum true when the string contains a checksum
  * @param pack a pointer to the result structure
  * @return 1 (true) - if parsed successfully or 0 (false) otherwise.
  */
-int nmea_parse_GPGSV(const char *s, const int len, nmeaGPGSV *pack) {
-       int token_count;
-       int token_count_expected;
-       int sat_count;
-       int sat_counted = 0;
-
-       assert(s);
-       assert(pack);
-
-       nmea_trace_buff(s, len);
-
-       /*
-        * Clear before parsing, to be able to detect absent fields
-        */
-       memset(pack, 0, sizeof(nmeaGPGSV));
-
-       /* parse */
-       token_count = nmea_scanf(s, len, "$GPGSV,%d,%d,%d,"
-                       "%d,%d,%d,%d,"
-                       "%d,%d,%d,%d,"
-                       "%d,%d,%d,%d,"
-                       "%d,%d,%d,%d*", &pack->pack_count, &pack->pack_index, &pack->sat_count, &pack->sat_data[0].id,
-                       &pack->sat_data[0].elv, &pack->sat_data[0].azimuth, &pack->sat_data[0].sig, &pack->sat_data[1].id,
-                       &pack->sat_data[1].elv, &pack->sat_data[1].azimuth, &pack->sat_data[1].sig, &pack->sat_data[2].id,
-                       &pack->sat_data[2].elv, &pack->sat_data[2].azimuth, &pack->sat_data[2].sig, &pack->sat_data[3].id,
-                       &pack->sat_data[3].elv, &pack->sat_data[3].azimuth, &pack->sat_data[3].sig);
-
-       /* return if we have no sentences or sats */
-       if ((pack->pack_count < 1) || (pack->pack_count > NMEA_NSATPACKS) || (pack->pack_index < 1)
-                       || (pack->pack_index > pack->pack_count) || (pack->sat_count < 0) || (pack->sat_count > NMEA_MAXSAT)) {
-               nmea_error("GPGSV parse error: inconsistent pack (count/index/satcount = %d/%d/%d)", pack->pack_count,
-                               pack->pack_index, pack->sat_count);
-               return 0;
-       }
-
-       /* validate all sat settings and count the number of sats in the sentence */
-       for (sat_count = 0; sat_count < NMEA_SATINPACK; sat_count++) {
-               if (pack->sat_data[sat_count].id != 0) {
-                       if ((pack->sat_data[sat_count].id < 0)) {
-                               nmea_error("GPGSV parse error: invalid sat %d id (%d)", sat_count + 1, pack->sat_data[sat_count].id);
-                               return 0;
-                       }
-                       if ((pack->sat_data[sat_count].elv < -90) || (pack->sat_data[sat_count].elv > 90)) {
-                               nmea_error("GPGSV parse error: invalid sat %d elevation (%d)", sat_count + 1, pack->sat_data[sat_count].elv);
-                               return 0;
-                       }
-                       if ((pack->sat_data[sat_count].azimuth < 0) || (pack->sat_data[sat_count].azimuth >= 360)) {
-                               nmea_error("GPGSV parse error: invalid sat %d azimuth (%d)", sat_count + 1, pack->sat_data[sat_count].azimuth);
-                               return 0;
-                       }
-                       if ((pack->sat_data[sat_count].sig < 0) || (pack->sat_data[sat_count].sig > 99)) {
-                               nmea_error("GPGSV parse error: invalid sat %d signal (%d)", sat_count + 1, pack->sat_data[sat_count].sig);
-                               return 0;
-                       }
-                       sat_counted++;
-               }
-       }
-
-       /* see that we have enough tokens */
-       token_count_expected = (sat_counted * 4) + 3;
-       if ((token_count < token_count_expected) || (token_count > (NMEA_SATINPACK * 4 + 3))) {
-               nmea_error("GPGSV parse error: need %d tokens, got %d", token_count_expected, token_count);
-               return 0;
-       }
-
-       /* determine which fields are present and validate them */
-
-       if (pack->sat_count > 0) {
-               nmea_INFO_set_present(&pack->present, SATINVIEW);
-       }
-
-       return 1;
+int nmea_parse_GPGSV(const char *s, const int len, bool has_checksum, nmeaGPGSV *pack) {
+  int token_count;
+  int token_count_expected;
+  int sat_count;
+  int sat_counted = 0;
+
+  if (!has_checksum) {
+    return 0;
+  }
+
+  assert(s);
+  assert(pack);
+
+  nmea_trace_buff(s, len);
+
+  /*
+   * Clear before parsing, to be able to detect absent fields
+   */
+  memset(pack, 0, sizeof(nmeaGPGSV));
+
+  /* parse */
+  token_count = nmea_scanf(s, len, "$GPGSV,%d,%d,%d,"
+      "%d,%d,%d,%d,"
+      "%d,%d,%d,%d,"
+      "%d,%d,%d,%d,"
+      "%d,%d,%d,%d*", &pack->pack_count, &pack->pack_index, &pack->sat_count, &pack->sat_data[0].id,
+      &pack->sat_data[0].elv, &pack->sat_data[0].azimuth, &pack->sat_data[0].sig, &pack->sat_data[1].id,
+      &pack->sat_data[1].elv, &pack->sat_data[1].azimuth, &pack->sat_data[1].sig, &pack->sat_data[2].id,
+      &pack->sat_data[2].elv, &pack->sat_data[2].azimuth, &pack->sat_data[2].sig, &pack->sat_data[3].id,
+      &pack->sat_data[3].elv, &pack->sat_data[3].azimuth, &pack->sat_data[3].sig);
+
+  /* return if we have no sentences or sats */
+  if ((pack->pack_count < 1) || (pack->pack_count > NMEA_NSATPACKS) || (pack->pack_index < 1)
+      || (pack->pack_index > pack->pack_count) || (pack->sat_count < 0) || (pack->sat_count > NMEA_MAXSAT)) {
+    nmea_error("GPGSV parse error: inconsistent pack (count/index/satcount = %d/%d/%d)", pack->pack_count,
+        pack->pack_index, pack->sat_count);
+    return 0;
+  }
+
+  /* validate all sat settings and count the number of sats in the sentence */
+  for (sat_count = 0; sat_count < NMEA_SATINPACK; sat_count++) {
+    if (pack->sat_data[sat_count].id != 0) {
+      if ((pack->sat_data[sat_count].id < 0)) {
+        nmea_error("GPGSV parse error: invalid sat %d id (%d)", sat_count + 1, pack->sat_data[sat_count].id);
+        return 0;
+      }
+      if ((pack->sat_data[sat_count].elv < -90) || (pack->sat_data[sat_count].elv > 90)) {
+        nmea_error("GPGSV parse error: invalid sat %d elevation (%d)", sat_count + 1, pack->sat_data[sat_count].elv);
+        return 0;
+      }
+      if ((pack->sat_data[sat_count].azimuth < 0) || (pack->sat_data[sat_count].azimuth >= 360)) {
+        nmea_error("GPGSV parse error: invalid sat %d azimuth (%d)", sat_count + 1, pack->sat_data[sat_count].azimuth);
+        return 0;
+      }
+      if ((pack->sat_data[sat_count].sig < 0) || (pack->sat_data[sat_count].sig > 99)) {
+        nmea_error("GPGSV parse error: invalid sat %d signal (%d)", sat_count + 1, pack->sat_data[sat_count].sig);
+        return 0;
+      }
+      sat_counted++;
+    }
+  }
+
+  /* see that we have enough tokens */
+  token_count_expected = (sat_counted * 4) + 3;
+  if ((token_count < token_count_expected) || (token_count > (NMEA_SATINPACK * 4 + 3))) {
+    nmea_error("GPGSV parse error: need %d tokens, got %d", token_count_expected, token_count);
+    return 0;
+  }
+
+  /* determine which fields are present and validate them */
+
+  if (pack->sat_count > 0) {
+    nmea_INFO_set_present(&pack->present, SATINVIEW);
+  }
+
+  return 1;
 }
 
 /**
@@ -641,132 +616,137 @@ int nmea_parse_GPGSV(const char *s, const int len, nmeaGPGSV *pack) {
  *
  * @param s the string
  * @param len the length of the string
+ * @param has_checksum true when the string contains a checksum
  * @param pack a pointer to the result structure
  * @return 1 (true) - if parsed successfully or 0 (false) otherwise.
  */
-int nmea_parse_GPRMC(const char *s, const int len, nmeaGPRMC *pack) {
-       int token_count;
-       char time_buff[NMEA_TIMEPARSE_BUF];
-       int date;
-       size_t time_buff_len = 0;
-
-       assert(s);
-       assert(pack);
-
-       nmea_trace_buff(s, len);
-
-       /*
-        * Clear before parsing, to be able to detect absent fields
-        */
-       time_buff[0] = '\0';
-       date = -1;
-       pack->present = 0;
-       pack->utc.year = -1;
-       pack->utc.mon = -1;
-       pack->utc.day = -1;
-       pack->utc.hour = -1;
-       pack->utc.min = -1;
-       pack->utc.sec = -1;
-       pack->utc.hsec = -1;
-       pack->status = 0;
-       pack->lat = NAN;
-       pack->ns = 0;
-       pack->lon = NAN;
-       pack->ew = 0;
-       pack->speed = NAN;
-       pack->track = NAN;
-       pack->magvar = NAN;
-       pack->magvar_ew = 0;
-       pack->mode = 0;
-
-       /* parse */
-       token_count = nmea_scanf(s, len, "$GPRMC,%s,%c,%f,%c,%f,%c,%f,%f,%d,%f,%c,%c*", &time_buff[0], &pack->status,
-                       &pack->lat, &pack->ns, &pack->lon, &pack->ew, &pack->speed, &pack->track, &date,
-                       &pack->magvar, &pack->magvar_ew, &pack->mode);
-
-       /* see that we have enough tokens */
-       if ((token_count != 11) && (token_count != 12)) {
-               nmea_error("GPRMC parse error: need 11 or 12 tokens, got %d in %s", token_count, s);
-               return 0;
-       }
-
-       /* determine which fields are present and validate them */
-
-       time_buff_len = strlen(&time_buff[0]);
-       if (time_buff_len) {
-               if (!_nmea_parse_time(&time_buff[0], time_buff_len, &pack->utc)) {
-                       return 0;
-               }
-
-               if (!validateTime(&pack->utc)) {
-                       return 0;
-               }
-
-               nmea_INFO_set_present(&pack->present, UTCTIME);
-       }
-
-       if (!pack->status) {
-               pack->status = 'V';
-       } else {
-               pack->status = toupper(pack->status);
-               if (!((pack->status == 'A') || (pack->status == 'V'))) {
-                       nmea_error("GPRMC parse error: invalid status (%c)", pack->status);
-                       return 0;
-               }
-       }
-       if (!isnan(pack->lat) && (pack->ns)) {
-               if (!validateNSEW(&pack->ns, true)) {
-                       return 0;
-               }
-
-               nmea_INFO_set_present(&pack->present, LAT);
-       }
-       if (!isnan(pack->lon) && (pack->ew)) {
-               if (!validateNSEW(&pack->ew, false)) {
-                       return 0;
-               }
-
-               nmea_INFO_set_present(&pack->present, LON);
-       }
-       if (!isnan(pack->speed)) {
-               nmea_INFO_set_present(&pack->present, SPEED);
-       }
-       if (!isnan(pack->track)) {
-               nmea_INFO_set_present(&pack->present, TRACK);
-       }
-
-       if (date != -1) {
-               if (!_nmea_parse_date(date, &pack->utc)) {
-                       return 0;
-               }
-
-               if (!validateDate(&pack->utc)) {
-                       return 0;
-               }
-
-               nmea_INFO_set_present(&pack->present, UTCDATE);
-       }
-
-       if (!isnan(pack->magvar) && (pack->magvar_ew)) {
-               if (!validateNSEW(&pack->magvar_ew, false)) {
-                       return 0;
-               }
-
-               nmea_INFO_set_present(&pack->present, MAGVAR);
-       }
-       if (token_count == 11) {
-               pack->mode = 'A';
-       } else {
-               if (!pack->mode) {
-                       pack->mode = 'N';
-               } else {
-                       if (!validateMode(&pack->mode)) {
-                               return 0;
-                       }
-               }
-       }
-
-       return 1;
+int nmea_parse_GPRMC(const char *s, const int len, bool has_checksum, nmeaGPRMC *pack) {
+  int token_count;
+  char time_buff[NMEA_TIMEPARSE_BUF];
+  int date;
+  size_t time_buff_len = 0;
+
+  if (!has_checksum) {
+    return 0;
+  }
+
+  assert(s);
+  assert(pack);
+
+  nmea_trace_buff(s, len);
+
+  /*
+   * Clear before parsing, to be able to detect absent fields
+   */
+  time_buff[0] = '\0';
+  date = -1;
+  pack->present = 0;
+  pack->utc.year = -1;
+  pack->utc.mon = -1;
+  pack->utc.day = -1;
+  pack->utc.hour = -1;
+  pack->utc.min = -1;
+  pack->utc.sec = -1;
+  pack->utc.hsec = -1;
+  pack->status = 0;
+  pack->lat = NAN;
+  pack->ns = 0;
+  pack->lon = NAN;
+  pack->ew = 0;
+  pack->speed = NAN;
+  pack->track = NAN;
+  pack->magvar = NAN;
+  pack->magvar_ew = 0;
+  pack->mode = 0;
+
+  /* parse */
+  token_count = nmea_scanf(s, len, "$GPRMC,%s,%c,%f,%c,%f,%c,%f,%f,%d,%f,%c,%c*", &time_buff[0], &pack->status,
+      &pack->lat, &pack->ns, &pack->lon, &pack->ew, &pack->speed, &pack->track, &date,
+      &pack->magvar, &pack->magvar_ew, &pack->mode);
+
+  /* see that we have enough tokens */
+  if ((token_count != 11) && (token_count != 12)) {
+    nmea_error("GPRMC parse error: need 11 or 12 tokens, got %d in %s", token_count, s);
+    return 0;
+  }
+
+  /* determine which fields are present and validate them */
+
+  time_buff_len = strlen(&time_buff[0]);
+  if (time_buff_len) {
+    if (!_nmea_parse_time(&time_buff[0], time_buff_len, &pack->utc)) {
+      return 0;
+    }
+
+    if (!validateTime(&pack->utc)) {
+      return 0;
+    }
+
+    nmea_INFO_set_present(&pack->present, UTCTIME);
+  }
+
+  if (!pack->status) {
+    pack->status = 'V';
+  } else {
+    pack->status = toupper(pack->status);
+    if (!((pack->status == 'A') || (pack->status == 'V'))) {
+      nmea_error("GPRMC parse error: invalid status (%c)", pack->status);
+      return 0;
+    }
+  }
+  if (!isnan(pack->lat) && (pack->ns)) {
+    if (!validateNSEW(&pack->ns, true)) {
+      return 0;
+    }
+
+    nmea_INFO_set_present(&pack->present, LAT);
+  }
+  if (!isnan(pack->lon) && (pack->ew)) {
+    if (!validateNSEW(&pack->ew, false)) {
+      return 0;
+    }
+
+    nmea_INFO_set_present(&pack->present, LON);
+  }
+  if (!isnan(pack->speed)) {
+    nmea_INFO_set_present(&pack->present, SPEED);
+  }
+  if (!isnan(pack->track)) {
+    nmea_INFO_set_present(&pack->present, TRACK);
+  }
+
+  if (date != -1) {
+    if (!_nmea_parse_date(date, &pack->utc)) {
+      return 0;
+    }
+
+    if (!validateDate(&pack->utc)) {
+      return 0;
+    }
+
+    nmea_INFO_set_present(&pack->present, UTCDATE);
+  }
+
+  if (!isnan(pack->magvar) && (pack->magvar_ew)) {
+    if (!validateNSEW(&pack->magvar_ew, false)) {
+      return 0;
+    }
+
+    nmea_INFO_set_present(&pack->present, MAGVAR);
+  }
+  if (token_count == 11) {
+    pack->mode = 'A';
+  } else {
+    if (!pack->mode) {
+      pack->mode = 'N';
+    } else {
+      if (!validateMode(&pack->mode)) {
+        return 0;
+      }
+    }
+  }
+
+  return 1;
 }
 
 /**
@@ -774,88 +754,93 @@ int nmea_parse_GPRMC(const char *s, const int len, nmeaGPRMC *pack) {
  *
  * @param s the string
  * @param len the length of the string
+ * @param has_checksum true when the string contains a checksum
  * @param pack a pointer to the result structure
  * @return 1 (true) - if parsed successfully or 0 (false) otherwise.
  */
-int nmea_parse_GPVTG(const char *s, const int len, nmeaGPVTG *pack) {
-       int token_count;
-
-       assert(s);
-       assert(pack);
-
-       nmea_trace_buff(s, len);
-
-       /*
-        * Clear before parsing, to be able to detect absent fields
-        */
-       pack->present = 0;
-       pack->track = NAN;
-       pack->track_t = 0;
-       pack->mtrack = NAN;
-       pack->mtrack_m = 0;
-       pack->spn = NAN;
-       pack->spn_n = 0;
-       pack->spk = NAN;
-       pack->spk_k = 0;
-
-       /* parse */
-       token_count = nmea_scanf(s, len, "$GPVTG,%f,%c,%f,%c,%f,%c,%f,%c*", &pack->track, &pack->track_t, &pack->mtrack,
-                       &pack->mtrack_m, &pack->spn, &pack->spn_n, &pack->spk, &pack->spk_k);
-
-       /* see that we have enough tokens */
-       if (token_count != 8) {
-               nmea_error("GPVTG parse error: need 8 tokens, got %d in %s", token_count, s);
-               return 0;
-       }
-
-       /* determine which fields are present and validate them */
-
-       if (!isnan(pack->track) && (pack->track_t)) {
-               pack->track_t = toupper(pack->track_t);
-               if (pack->track_t != 'T') {
-                       nmea_error("GPVTG parse error: invalid track unit, got %c, expected T", pack->track_t);
-                       return 0;
-               }
-
-               nmea_INFO_set_present(&pack->present, TRACK);
-       }
-       if (!isnan(pack->mtrack) && (pack->mtrack_m)) {
-               pack->mtrack_m = toupper(pack->mtrack_m);
-               if (pack->mtrack_m != 'M') {
-                       nmea_error("GPVTG parse error: invalid mtrack unit, got %c, expected M", pack->mtrack_m);
-                       return 0;
-               }
-
-               nmea_INFO_set_present(&pack->present, MTRACK);
-       }
-       if (!isnan(pack->spn) && (pack->spn_n)) {
-               pack->spn_n = toupper(pack->spn_n);
-               if (pack->spn_n != 'N') {
-                       nmea_error("GPVTG parse error: invalid knots speed unit, got %c, expected N", pack->spn_n);
-                       return 0;
-               }
-
-               nmea_INFO_set_present(&pack->present, SPEED);
-
-               if (isnan(pack->spk)) {
-                       pack->spk = pack->spn * NMEA_TUD_KNOTS;
-                       pack->spk_k = 'K';
-               }
-       }
-       if (!isnan(pack->spk) && (pack->spk_k)) {
-               pack->spk_k = toupper(pack->spk_k);
-               if (pack->spk_k != 'K') {
-                       nmea_error("GPVTG parse error: invalid kph speed unit, got %c, expected K", pack->spk_k);
-                       return 0;
-               }
-
-               nmea_INFO_set_present(&pack->present, SPEED);
-
-               if (isnan(pack->spn)) {
-                       pack->spn = pack->spk / NMEA_TUD_KNOTS;
-                       pack->spn_n = 'N';
-               }
-       }
-
-       return 1;
+int nmea_parse_GPVTG(const char *s, const int len, bool has_checksum, nmeaGPVTG *pack) {
+  int token_count;
+
+  if (!has_checksum) {
+    return 0;
+  }
+
+  assert(s);
+  assert(pack);
+
+  nmea_trace_buff(s, len);
+
+  /*
+   * Clear before parsing, to be able to detect absent fields
+   */
+  pack->present = 0;
+  pack->track = NAN;
+  pack->track_t = 0;
+  pack->mtrack = NAN;
+  pack->mtrack_m = 0;
+  pack->spn = NAN;
+  pack->spn_n = 0;
+  pack->spk = NAN;
+  pack->spk_k = 0;
+
+  /* parse */
+  token_count = nmea_scanf(s, len, "$GPVTG,%f,%c,%f,%c,%f,%c,%f,%c*", &pack->track, &pack->track_t, &pack->mtrack,
+      &pack->mtrack_m, &pack->spn, &pack->spn_n, &pack->spk, &pack->spk_k);
+
+  /* see that we have enough tokens */
+  if (token_count != 8) {
+    nmea_error("GPVTG parse error: need 8 tokens, got %d in %s", token_count, s);
+    return 0;
+  }
+
+  /* determine which fields are present and validate them */
+
+  if (!isnan(pack->track) && (pack->track_t)) {
+    pack->track_t = toupper(pack->track_t);
+    if (pack->track_t != 'T') {
+      nmea_error("GPVTG parse error: invalid track unit, got %c, expected T", pack->track_t);
+      return 0;
+    }
+
+    nmea_INFO_set_present(&pack->present, TRACK);
+  }
+  if (!isnan(pack->mtrack) && (pack->mtrack_m)) {
+    pack->mtrack_m = toupper(pack->mtrack_m);
+    if (pack->mtrack_m != 'M') {
+      nmea_error("GPVTG parse error: invalid mtrack unit, got %c, expected M", pack->mtrack_m);
+      return 0;
+    }
+
+    nmea_INFO_set_present(&pack->present, MTRACK);
+  }
+  if (!isnan(pack->spn) && (pack->spn_n)) {
+    pack->spn_n = toupper(pack->spn_n);
+    if (pack->spn_n != 'N') {
+      nmea_error("GPVTG parse error: invalid knots speed unit, got %c, expected N", pack->spn_n);
+      return 0;
+    }
+
+    nmea_INFO_set_present(&pack->present, SPEED);
+
+    if (isnan(pack->spk)) {
+      pack->spk = pack->spn * NMEA_TUD_KNOTS;
+      pack->spk_k = 'K';
+    }
+  }
+  if (!isnan(pack->spk) && (pack->spk_k)) {
+    pack->spk_k = toupper(pack->spk_k);
+    if (pack->spk_k != 'K') {
+      nmea_error("GPVTG parse error: invalid kph speed unit, got %c, expected K", pack->spk_k);
+      return 0;
+    }
+
+    nmea_INFO_set_present(&pack->present, SPEED);
+
+    if (isnan(pack->spn)) {
+      pack->spn = pack->spk / NMEA_TUD_KNOTS;
+      pack->spn_n = 'N';
+    }
+  }
+
+  return 1;
 }
index 6e82aeb..90520dd 100644 (file)
@@ -1,9 +1,6 @@
 /*
  * This file is part of nmealib.
  *
- * Copyright (c) 2008 Timur Sinitsyn
- * Copyright (c) 2011 Ferry Huberts
- *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
 
 #include <nmea/parser.h>
 
-#include <nmea/context.h>
 #include <nmea/parse.h>
 #include <nmea/sentence.h>
 #include <nmea/conversions.h>
+#include <nmea/tok.h>
 
 #include <stdlib.h>
+#include <stdbool.h>
 #include <string.h>
 #include <assert.h>
+#include <ctype.h>
+
+#define first_eol_char  ('\r')
+#define second_eol_char ('\n')
+
+static void reset_sentence_parser(nmeaPARSER * parser, sentence_parser_state new_state) {
+  assert(parser);
+  memset(&parser->sentence_parser, 0, sizeof(parser->sentence_parser));
+  parser->buffer.buffer[0] = '\0';
+  parser->buffer.length = 0;
+  parser->sentence_parser.has_checksum = false;
+  parser->sentence_parser.state = new_state;
+}
 
-/*
- * high level
- */
+static inline bool isHexChar(char c) {
+  switch (tolower(c)) {
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+    case 'a':
+    case 'b':
+    case 'c':
+    case 'd':
+    case 'e':
+    case 'f':
+      return true;
+
+    default:
+      break;
+  }
+
+  return false;
+}
 
 /**
  * Initialise the parser.
  * @return true (1) - success or false (0) - fail
  */
 int nmea_parser_init(nmeaPARSER *parser) {
-       int resv = 0;
-       int buff_size = nmea_context_get_buffer_size();
-
-       assert(parser);
-
-       memset(parser, 0, sizeof(nmeaPARSER));
-
-       if (!(parser->buffer = malloc(buff_size)))
-               nmea_error("nmea_parser_init: insufficient memory");
-       else {
-               parser->buff_size = buff_size;
-               resv = 1;
-       }
-
-       return resv;
+  assert(parser);
+  memset(&parser->sentence, 0, sizeof(parser->sentence));
+  reset_sentence_parser(parser, SKIP_UNTIL_START);
+  return 0;
 }
 
-/**
- * Destroy the parser.
- * Frees a buffer.
- *
- * @param parser a pointer to the parser
- */
-void nmea_parser_destroy(nmeaPARSER *parser) {
-       assert(parser);
-
-       if (parser->buffer) {
-               free(parser->buffer);
-               parser->buffer = NULL;
-       }
-       nmea_parser_queue_clear(parser);
-       memset(parser, 0, sizeof(nmeaPARSER));
+static bool nmea_parse_sentence_character(nmeaPARSER *parser, const char * c) {
+  assert(parser);
+
+  /* always reset when we encounter a start-of-sentence character */
+  if (*c == '$') {
+    reset_sentence_parser(parser, READ_SENTENCE);
+    parser->buffer.buffer[parser->buffer.length++] = *c;
+    return false;
+  }
+
+  /* just return when we haven't encountered a start-of-sentence character yet */
+  if (parser->sentence_parser.state == SKIP_UNTIL_START) {
+    return false;
+  }
+
+  /* this character belongs to the sentence */
+
+  /* check whether the sentence still fits in the buffer */
+  if (parser->buffer.length >= SENTENCE_SIZE) {
+    reset_sentence_parser(parser, SKIP_UNTIL_START);
+    return false;
+  }
+
+  parser->buffer.buffer[parser->buffer.length++] = *c;
+
+  switch (parser->sentence_parser.state) {
+    case READ_SENTENCE:
+      if (*c == '*') {
+        parser->sentence_parser.state = READ_CHECKSUM;
+        parser->sentence_parser.sentence_checksum_chars_count = 0;
+      } else if (*c == first_eol_char) {
+        parser->sentence_parser.state = READ_EOL;
+        parser->sentence_parser.sentence_eol_chars_count = 1;
+      } else if (isInvalidNMEACharacter(c)) {
+        reset_sentence_parser(parser, SKIP_UNTIL_START);
+      } else {
+        parser->sentence_parser.calculated_checksum ^= (int) *c;
+      }
+      break;
+
+    case READ_CHECKSUM:
+      if (!isHexChar(*c)) {
+        reset_sentence_parser(parser, SKIP_UNTIL_START);
+      } else {
+        switch (parser->sentence_parser.sentence_checksum_chars_count) {
+          case 0:
+            parser->sentence_parser.sentence_checksum_chars[0] = *c;
+            parser->sentence_parser.sentence_checksum_chars[1] = 0;
+            parser->sentence_parser.sentence_checksum_chars_count = 1;
+            break;
+
+          case 1:
+            parser->sentence_parser.sentence_checksum_chars[1] = *c;
+            parser->sentence_parser.sentence_checksum_chars_count = 2;
+            parser->sentence_parser.sentence_checksum = nmea_atoi(parser->sentence_parser.sentence_checksum_chars, 2, 16);
+            parser->sentence_parser.has_checksum = true;
+            parser->sentence_parser.state = READ_EOL;
+            break;
+
+          default:
+            reset_sentence_parser(parser, SKIP_UNTIL_START);
+            break;
+          }
+      }
+      break;
+
+
+    case READ_EOL:
+      switch (parser->sentence_parser.sentence_eol_chars_count) {
+        case 0:
+          if (*c != first_eol_char) {
+            reset_sentence_parser(parser, SKIP_UNTIL_START);
+          } else {
+            parser->sentence_parser.sentence_eol_chars_count = 1;
+          }
+          break;
+
+        case 1:
+          if (*c != second_eol_char) {
+            reset_sentence_parser(parser, SKIP_UNTIL_START);
+          } else {
+            parser->sentence_parser.state = SKIP_UNTIL_START;
+            return (!parser->sentence_parser.sentence_checksum_chars_count
+                || (parser->sentence_parser.sentence_checksum_chars_count
+                    && (parser->sentence_parser.sentence_checksum == parser->sentence_parser.calculated_checksum)));
+          }
+          break;
+
+        default:
+          reset_sentence_parser(parser, SKIP_UNTIL_START);
+          break;
+      }
+      break;
+
+      /* can't occur, but keep compiler happy */
+      case SKIP_UNTIL_START:
+      default:
+        break;
+
+  }
+
+  return false;
 }
 
 /**
@@ -84,324 +194,60 @@ void nmea_parser_destroy(nmeaPARSER *parser) {
  * @param info a pointer to the nmeaINFO structure
  * @return the number of packets that were parsed
  */
-int nmea_parse(nmeaPARSER *parser, const char *s, const int len, nmeaINFO *info) {
-       int packetType;
-       int packetsParsed = 0;
-       void *packet = 0;
-
-       assert(parser);
-
-       nmea_parser_push(parser, s, len);
-
-       while (GPNON != (packetType = nmea_parser_pop(parser, &packet))) {
-               packetsParsed++;
-
-               switch (packetType) {
-               case GPGGA:
-                       nmea_GPGGA2info((nmeaGPGGA *) packet, info);
-                       break;
-               case GPGSA:
-                       nmea_GPGSA2info((nmeaGPGSA *) packet, info);
-                       break;
-               case GPGSV:
-                       nmea_GPGSV2info((nmeaGPGSV *) packet, info);
-                       break;
-               case GPRMC:
-                       nmea_GPRMC2info((nmeaGPRMC *) packet, info);
-                       break;
-               case GPVTG:
-                       nmea_GPVTG2info((nmeaGPVTG *) packet, info);
-                       break;
-               default:
-                       break;
-               };
-
-               free(packet);
-       }
-
-       return packetsParsed;
-}
-
-/*
- * low level
- */
-
-/**
- * Do the actual parsing of a string and store the results in the parser.
- * This function is used to parse (broken up parts) of a complete string.
- *
- * @param parser a pointer to the parser
- * @param s the string
- * @param len the length of the string
- * @return the number of bytes that were parsed, -1 on error
- */
-static int nmea_parser_real_push(nmeaPARSER *parser, const char *s, int len) {
-       int charsParsed = 0;
-       int crc;
-       int sentenceLength;
-       int sentenceType;
-       nmeaParserNODE *node = NULL;
-
-       assert(parser);
-       assert(parser->buffer);
-
-       if (!s || !len)
-               return 0;
-
-       /* clear the buffer if the string is too large */
-       if ((parser->buff_use + len) >= parser->buff_size)
-               nmea_parser_buff_clear(parser);
-
-       /* check that the string will fit in the buffer */
-       if ((parser->buff_use + len) >= parser->buff_size) {
-               nmea_error("nmea_parser_real_push: string too long to fit in parser buffer");
-               return 0;
-       }
-
-       /* put the string in the buffer */
-       memcpy(parser->buffer + parser->buff_use, s, len);
-       parser->buff_use += len;
-
-       /* parse */
-       for (;; node = NULL) {
-               sentenceLength = nmea_parse_get_sentence_length(parser->buffer + charsParsed, parser->buff_use - charsParsed,
-                               &crc);
-
-               if (!sentenceLength) {
-                       if (charsParsed)
-                               memmove(parser->buffer, parser->buffer + charsParsed, parser->buff_use -= charsParsed);
-                       break;
-               } else if (crc >= 0) {
-                       sentenceType = nmea_parse_get_sentence_type(parser->buffer + charsParsed + 1,
-                                       parser->buff_use - charsParsed - 1);
-
-                       if (!(node = malloc(sizeof(nmeaParserNODE))))
-                               goto mem_fail;
-
-                       node->pack = NULL;
-
-                       switch (sentenceType) {
-                       case GPGGA:
-                               if (!(node->pack = malloc(sizeof(nmeaGPGGA))))
-                                       goto mem_fail;
-                               node->packType = GPGGA;
-                               if (!nmea_parse_GPGGA(parser->buffer + charsParsed, sentenceLength, (nmeaGPGGA *) node->pack)) {
-                                       free(node->pack);
-                                       free(node);
-                                       node = NULL;
-                               }
-                               break;
-                       case GPGSA:
-                               if (!(node->pack = malloc(sizeof(nmeaGPGSA))))
-                                       goto mem_fail;
-                               node->packType = GPGSA;
-                               if (!nmea_parse_GPGSA(parser->buffer + charsParsed, sentenceLength, (nmeaGPGSA *) node->pack)) {
-                                       free(node->pack);
-                                       free(node);
-                                       node = NULL;
-                               }
-                               break;
-                       case GPGSV:
-                               if (!(node->pack = malloc(sizeof(nmeaGPGSV))))
-                                       goto mem_fail;
-                               node->packType = GPGSV;
-                               if (!nmea_parse_GPGSV(parser->buffer + charsParsed, sentenceLength, (nmeaGPGSV *) node->pack)) {
-                                       free(node->pack);
-                                       free(node);
-                                       node = NULL;
-                               }
-                               break;
-                       case GPRMC:
-                               if (!(node->pack = malloc(sizeof(nmeaGPRMC))))
-                                       goto mem_fail;
-                               node->packType = GPRMC;
-                               if (!nmea_parse_GPRMC(parser->buffer + charsParsed, sentenceLength, (nmeaGPRMC *) node->pack)) {
-                                       free(node->pack);
-                                       free(node);
-                                       node = NULL;
-                               }
-                               break;
-                       case GPVTG:
-                               if (!(node->pack = malloc(sizeof(nmeaGPVTG))))
-                                       goto mem_fail;
-                               node->packType = GPVTG;
-                               if (!nmea_parse_GPVTG(parser->buffer + charsParsed, sentenceLength, (nmeaGPVTG *) node->pack)) {
-                                       free(node->pack);
-                                       free(node);
-                                       node = NULL;
-                               }
-                               break;
-                       default:
-                               free(node);
-                               node = NULL;
-                               break;
-                       };
-
-                       if (node) {
-                               if (parser->end_node)
-                                       parser->end_node->next_node = node;
-                               parser->end_node = node;
-                               if (!parser->top_node)
-                                       parser->top_node = node;
-                               node->next_node = NULL;
-                       }
-               }
-
-               charsParsed += sentenceLength;
-       }
-
-       return charsParsed;
-
-       mem_fail: if (node)
-               free(node);
-       nmea_error("Insufficient memory!");
-
-       return -1;
-}
-
-/**
- * Parse a string and store the results in the parser
- *
- * @param parser a pointer to the parser
- * @param s the string
- * @param len the length of the string
- * @return the number of bytes that were parsed
- */
-int nmea_parser_push(nmeaPARSER *parser, const char *s, int len) {
-       int charsParsed = 0;
-
-       assert(parser);
-
-       if (!s || !len)
-               return 0;
-
-       do {
-               int charsToParse;
-
-               if (len > parser->buff_size)
-                       charsToParse = parser->buff_size;
-               else
-                       charsToParse = len;
-
-               charsParsed += nmea_parser_real_push(parser, s, charsToParse);
-               len -= charsToParse;
-       } while (len);
-
-       return charsParsed;
-}
-
-/**
- * Get the type of top packet
- *
- * @param parser a pointer to the parser
- * @return the type of the top packet (see nmeaPACKTYPE)
- */
-int nmea_parser_top(const nmeaPARSER *parser) {
-       int retval = GPNON;
-       nmeaParserNODE *node;
-
-       assert(parser);
-
-       node = parser->top_node;
-       if (node)
-               retval = node->packType;
-
-       return retval;
-}
-
-/**
- * Remove the top packet from the parser
- *
- * @param parser a pointer to the parser
- * @param pack_ptr a pointer to the location where to store a pointer to the packet
- * @return the type of the top packet (see nmeaPACKTYPE)
- */
-int nmea_parser_pop(nmeaPARSER *parser, void **pack_ptr) {
-       int retval = GPNON;
-       nmeaParserNODE *node;
-
-       assert(parser);
-
-       node = parser->top_node;
-       if (node) {
-               retval = node->packType;
-               if (pack_ptr)
-                       *pack_ptr = node->pack;
-               parser->top_node = node->next_node;
-               if (!parser->top_node)
-                       parser->end_node = 0;
-               free(node);
-       }
-
-       return retval;
-}
-
-/**
- * Get the top packet from the parser without removing it
- *
- * @param parser a pointer to the parser
- * @param pack_ptr a pointer to the location where to store a pointer to the packet
- * @return the type of the top packet (see nmeaPACKTYPE)
- */
-int nmea_parser_peek(const nmeaPARSER *parser, void **pack_ptr) {
-       int retval = GPNON;
-       nmeaParserNODE *node;
-
-       assert(parser);
-
-       node = parser->top_node;
-       if (node) {
-               retval = node->packType;
-               if (pack_ptr)
-                       *pack_ptr = node->pack;
-       }
-
-       return retval;
-}
-
-/**
- * Remove the top packet from the parser
- *
- * @param parser a pointer to the parser
- * @return the type of the removed packet (see nmeaPACKTYPE)
- */
-int nmea_parser_drop(nmeaPARSER *parser) {
-       int retval = GPNON;
-       nmeaParserNODE *node;
-
-       assert(parser);
-
-       node = parser->top_node;
-       if (node) {
-               retval = node->packType;
-               if (node->pack)
-                       free(node->pack);
-               parser->top_node = node->next_node;
-               if (!parser->top_node)
-                       parser->end_node = NULL;
-               free(node);
-       }
-
-       return retval;
-}
-
-/**
- * Clear the cache of the parser
- *
- * @param parser a pointer to the parser
- */
-void nmea_parser_buff_clear(nmeaPARSER *parser) {
-       assert(parser);
-       parser->buff_use = 0;
-}
-
-/**
- * Clear the packets queue in the parser
- *
- * @param parser a pointer to the parser
- */
-void nmea_parser_queue_clear(nmeaPARSER *parser) {
-       assert(parser);
-       while (parser->top_node)
-               nmea_parser_drop(parser);
+int nmea_parse(nmeaPARSER * parser, const char * s, int len, nmeaINFO * info) {
+  int sentences_count = 0;
+  int charIndex = 0;
+
+  assert(parser);
+  assert(s);
+  assert(info);
+
+  for (charIndex = 0; charIndex < len; charIndex++) {
+    bool sentence_read_successfully = nmea_parse_sentence_character(parser, &s[charIndex]);
+    if (sentence_read_successfully) {
+      enum nmeaPACKTYPE sentence_type = nmea_parse_get_sentence_type(&parser->buffer.buffer[1], parser->buffer.length - 1);
+      switch (sentence_type) {
+        case GPGGA:
+          if (nmea_parse_GPGGA(parser->buffer.buffer, parser->buffer.length, parser->sentence_parser.has_checksum, &parser->sentence.gpgga)) {
+            sentences_count++;
+            nmea_GPGGA2info(&parser->sentence.gpgga, info);
+          }
+          break;
+
+        case GPGSA:
+          if (nmea_parse_GPGSA(parser->buffer.buffer, parser->buffer.length, parser->sentence_parser.has_checksum, &parser->sentence.gpgsa)) {
+            sentences_count++;
+            nmea_GPGSA2info(&parser->sentence.gpgsa, info);
+          }
+          break;
+
+        case GPGSV:
+          if (nmea_parse_GPGSV(parser->buffer.buffer, parser->buffer.length, parser->sentence_parser.has_checksum, &parser->sentence.gpgsv)) {
+            sentences_count++;
+            nmea_GPGSV2info(&parser->sentence.gpgsv, info);
+          }
+          break;
+
+        case GPRMC:
+          if (nmea_parse_GPRMC(parser->buffer.buffer, parser->buffer.length, parser->sentence_parser.has_checksum, &parser->sentence.gprmc)) {
+            sentences_count++;
+            nmea_GPRMC2info(&parser->sentence.gprmc, info);
+          }
+          break;
+
+        case GPVTG:
+          if (nmea_parse_GPVTG(parser->buffer.buffer, parser->buffer.length, parser->sentence_parser.has_checksum, &parser->sentence.gpvtg)) {
+            sentences_count++;
+            nmea_GPVTG2info(&parser->sentence.gpvtg, info);
+          }
+          break;
+
+        case GPNON:
+        default:
+          break;
+      }
+    }
+  }
+
+  return sentences_count;
 }
index cbc4d4d..8e6abc1 100644 (file)
@@ -1,9 +1,6 @@
 /*
  * This file is part of nmealib.
  *
- * Copyright (c) 2008 Timur Sinitsyn
- * Copyright (c) 2011 Ferry Huberts
- *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
index ade2ace..931c4bf 100644 (file)
@@ -1,9 +1,6 @@
 /*
  * This file is part of nmealib.
  *
- * Copyright (c) 2008 Timur Sinitsyn
- * Copyright (c) 2011 Ferry Huberts
- *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
index 8b38f41..4d07bf6 100644 (file)
@@ -335,21 +335,25 @@ static bool intSetupNodeIdBinaryDoubleLongLong(
  - false on failure
  */
 static bool intSetupNodeIdBinaryString(void) {
-       char report[256];
-       size_t nodeidlength;
-       char * nodeid = (char *)getNodeId(&nodeidlength);
-
-       if (nmea_parse_sentence_has_invalid_chars(nodeid, nodeidlength, PUD_NODE_ID_NAME, &report[0], sizeof(report))) {
-               pudError(false, "%s", &report[0]);
-               return false;
-       }
+  const char * invalidCharName;
+  size_t nodeidlength;
+  char * nodeid = (char *) getNodeId(&nodeidlength);
+
+  invalidCharName = nmea_parse_sentence_has_invalid_chars(nodeid, nodeidlength);
+  if (invalidCharName) {
+    char report[256];
+    snprintf(report, sizeof(report), "Configured %s (%s),"
+        " contains invalid NMEA characters (%s)", PUD_NODE_ID_NAME, nodeid, invalidCharName);
+    pudError(false, "%s", &report[0]);
+    return false;
+  }
 
-       if (nodeidlength > (PUD_TX_NODEID_BUFFERSIZE - 1)) {
-               pudError(false, "Length of parameter %s (%s) is too great", PUD_NODE_ID_NAME, &nodeid[0]);
-               return false;
-       }
+  if (nodeidlength > (PUD_TX_NODEID_BUFFERSIZE - 1)) {
+    pudError(false, "Length of parameter %s (%s) is too great", PUD_NODE_ID_NAME, &nodeid[0]);
+    return false;
+  }
 
-       return setupNodeIdBinaryString(&nodeIdBinary, nodeid, nodeidlength);
+  return setupNodeIdBinaryString(&nodeIdBinary, nodeid, nodeidlength);
 }
 
 /**
@@ -976,9 +980,9 @@ unsigned char * getTxNmeaMessagePrefix(void) {
 
 int setTxNmeaMessagePrefix(const char *value, void *data __attribute__ ((unused)),
                set_plugin_parameter_addon addon __attribute__ ((unused))) {
+       const char * invalidCharName;
        static const char * valueName = PUD_TX_NMEAMESSAGEPREFIX_NAME;
        size_t valueLength;
-       char report[256];
 
        assert (value != NULL);
 
@@ -989,10 +993,14 @@ int setTxNmeaMessagePrefix(const char *value, void *data __attribute__ ((unused)
                return true;
        }
 
-       if (nmea_parse_sentence_has_invalid_chars(value, valueLength, valueName, &report[0], sizeof(report))) {
-               pudError(false, "%s", &report[0]);
-               return true;
-       }
+  invalidCharName = nmea_parse_sentence_has_invalid_chars(value, valueLength);
+  if (invalidCharName) {
+    char report[256];
+    snprintf(report, sizeof(report), "Configured %s (%s),"
+        " contains invalid NMEA characters (%s)", valueName, value, invalidCharName);
+    pudError(false, "%s", report);
+    return true;
+  }
 
        if ((strchr(value, ' ') != NULL) || (strchr(value, '\t') != NULL)) {
                pudError(false, "Value of parameter %s (%s) can not contain whitespace",
index b61e973..01e7794 100644 (file)
@@ -842,6 +842,4 @@ void stopReceiver(void) {
        nmea_zero_INFO(&transmitGpsInformation.txPosition.nmeaInfo);
        transmitGpsInformation.txGateway = olsr_cnf->main_addr;
        transmitGpsInformation.positionUpdated = false;
-
-       nmea_parser_destroy(&nmeaParser);
 }
index 0b89118..ef9a8df 100644 (file)
@@ -29,7 +29,7 @@ static const char * regexCommentString = "^([[:space:]]*|[[:space:]#]+.*)$";
 
 /** regular expression describing a key/value pair */
 static const char * regexNameValueString =
-               "^[[:space:]]*([^[:space:]]+)[[:space:]]*=[[:space:]]*([[:digit:]]+)[[:space:]]*$";
+               "^[[:space:]]*([^[:space:]]+)[[:space:]]*=[[:space:]]*(.*?)[[:space:]]*$";
 
 /** the number of matches in regexNameValueString */
 static const size_t regexNameValuematchCount = 3;
@@ -87,6 +87,20 @@ static bool readUL(const char * valueName, const char * value, unsigned long * v
        return true;
 }
 
+/**
+ * Strip EOL characters from a string
+ *
+ * @param str the string to strip
+ * @param endindex the index of the \0 string terminator (end-of-string/strlen)
+ */
+static void stripEols(char * str, regoff_t endindex) {
+  regoff_t len = endindex;
+  while ((len > 0) && ((str[len - 1] == '\n') || (str[len - 1] == '\r'))) {
+    len--;
+  }
+  str[len] = '\0';
+}
+
 /**
  * Initialises the speedFile reader.
  * @return true upon success, false otherwise
@@ -154,6 +168,8 @@ static bool regexMatch(regex_t * regex, char * line, size_t nmatch, regmatch_t p
 /** the buffer in which to store a line read from the file */
 static char line[LINE_LENGTH];
 
+static bool reportedErrorsPrevious = false;
+
 /**
  * Read the speed file
  * @param fileName the filename
@@ -169,6 +185,7 @@ void readSpeedFile(char * fileName) {
        unsigned long downlink = DEF_DOWNLINK_SPEED;
        bool uplinkSet = false;
        bool downlinkSet = false;
+       bool reportedErrors = false;
 
        fd = open(fileName, O_RDONLY);
        if (fd < 0) {
@@ -203,11 +220,13 @@ void readSpeedFile(char * fileName) {
                }
 
                if (!regexMatch(&regexNameValue, line, regexNameValuematchCount, pmatch)) {
-                       sgwDynSpeedError(false, "Gateway speed file \"%s\", line %d uses invalid syntax: %s", fileName, lineNumber,
+                       sgwDynSpeedError(false, "Gateway speed file \"%s\", line %d uses invalid syntax: ignored (%s)", fileName, lineNumber,
                                        line);
-                       goto out;
+                       continue;
                }
 
+               stripEols(line, pmatch[2].rm_eo);
+
                /* determine name/value */
                name = &line[pmatch[1].rm_so];
                line[pmatch[1].rm_eo] = '\0';
@@ -216,21 +235,31 @@ void readSpeedFile(char * fileName) {
 
                if (!strncasecmp(SPEED_UPLINK_NAME, name, sizeof(line))) {
                        if (!readUL(SPEED_UPLINK_NAME, value, &uplink)) {
-                               goto out;
+                               sgwDynSpeedError(false, "Gateway speed file \"%s\", line %d: %s value \"%s\" is not a valid number: ignored",
+                                       fileName, lineNumber, SPEED_UPLINK_NAME, value);
+                               reportedErrors = true;
+                       } else {
+                               uplinkSet = true;
                        }
-                       uplinkSet = true;
                } else if (!strncasecmp(SPEED_DOWNLINK_NAME, name, sizeof(line))) {
                        if (!readUL(SPEED_DOWNLINK_NAME, value, &downlink)) {
-                               goto out;
+                               sgwDynSpeedError(false, "Gateway speed file \"%s\", line %d: %s value \"%s\" is not a valid number: ignored",
+                                       fileName, lineNumber, SPEED_DOWNLINK_NAME, value);
+                               reportedErrors = true;
+                       } else {
+                               downlinkSet = true;
                        }
-                       downlinkSet = true;
                } else {
-                       sgwDynSpeedError(false, "Gateway speed file \"%s\", line %d uses an invalid option \"%s\","
-                                       " valid options are [%s|%s]", fileName, lineNumber, name, SPEED_UPLINK_NAME, SPEED_DOWNLINK_NAME);
-                       goto out;
+                 if (!reportedErrorsPrevious) {
+                   sgwDynSpeedError(false, "Gateway speed file \"%s\", line %d specifies an unknown option \"%s\": ignored",
+                       fileName, lineNumber, name);
+                   reportedErrors = true;
+                 }
                }
        }
 
+       reportedErrorsPrevious = reportedErrors;
+
        fclose(fp);
        fp = NULL;
 
@@ -244,11 +273,7 @@ void readSpeedFile(char * fileName) {
          refresh_smartgw_netmask();
        }
 
-       out: if (fp) {
-               fclose(fp);
-       }
-       if (fd >= 0) {
+       out: if (fd >= 0) {
                close(fd);
        }
-       return;
 }
index 2cefde9..66e85cc 100644 (file)
@@ -276,7 +276,7 @@ ipc_action(int fd, void *data __attribute__ ((unused)), unsigned int flags __att
       addr[0] = '\0';
     if (!ip4equal(&pin.in4.sin_addr, &txtinfo_accept_ip.v4) && txtinfo_accept_ip.v4.s_addr != INADDR_ANY) {
 #ifdef TXTINFO_ALLOW_LOCALHOST
-      if (pin.in4.sin_addr.s_addr != INADDR_LOOPBACK) {
+      if (ntohl(pin.in4.sin_addr.s_addr) != INADDR_LOOPBACK) {
 #endif /* TXTINFO_ALLOW_LOCALHOST */
         olsr_printf(1, "(TXTINFO) From host(%s) not allowed!\n", addr);
         close(ipc_connection);
@@ -525,8 +525,6 @@ static void sgw_ipvx(struct autobuf *abuf, bool ipv6, const char * fmth, const c
   struct gw_list * list;
   struct gw_container_entry * gw;
 
-  abuf_appendf(abuf, "Table: Smart Gateway IPv%s\n", ipv6 ? "6" : "4");
-
   list = ipv6 ? &gw_list_ipv6 : &gw_list_ipv4;
   if (list->count) {
     char current[2] = { 0, 0 };
@@ -534,18 +532,21 @@ static void sgw_ipvx(struct autobuf *abuf, bool ipv6, const char * fmth, const c
     char prefix[(INET6_ADDRSTRLEN * 2) + 1];
     uint32_t uplink = 0;
     uint32_t downlink = 0;
+    olsr_linkcost pc = 0;
     char sipv4[2] = { 0, 0 };
     char sipv4nat[2] = { 0, 0 };
     char sipv6[2] = { 0, 0 };
     char if_name[IF_NAMESIZE];
     char destination[INET6_ADDRSTRLEN];
     long long unsigned int cost = 0;
+
     memset(originator, 0, sizeof(originator));
     memset(prefix, 0, sizeof(prefix));
     memset(if_name, 0, sizeof(if_name));
     memset(destination, 0, sizeof(destination));
 
-    abuf_appendf(abuf, fmth, " ", "Originator", "Prefix", "Uplink", "Downlink", "IPv4", "IPv4-NAT", "IPv6", "Tunnel-Name", "Destination", "Cost");
+    abuf_appendf(abuf, "# Table: Smart Gateway IPv%s\n", ipv6 ? "6" : "4");
+    abuf_appendf(abuf, fmth, "#", "Originator", "Prefix", "Uplink", "Downlink", "PathCost", "IPv4", "IPv4-NAT", "IPv6", "Tunnel-Name", "Destination", "Cost");
 
     current_gw = olsr_get_inet_gateway(false);
     OLSR_FOR_ALL_GWS(&list->head, gw) {
@@ -553,10 +554,13 @@ static void sgw_ipvx(struct autobuf *abuf, bool ipv6, const char * fmth, const c
         current[0] = (current_gw && (gw->gw == current_gw)) ? '*' : ' ';
 
         if (gw->gw) {
+          struct tc_entry* tc = olsr_lookup_tc_entry(&gw->gw->originator);
+
           inet_ntop(ipv6 ? AF_INET6 : AF_INET, &gw->gw->originator, originator, sizeof(originator));
           strncpy(prefix, olsr_ip_prefix_to_string(&gw->gw->external_prefix), sizeof(prefix));
           uplink = gw->gw->uplink;
           downlink = gw->gw->downlink;
+          pc = tc ?tc->path_cost : ROUTE_COST_BROKEN;
           sipv4[0] = gw->gw->ipv4 ? 'Y' : 'N';
           sipv4nat[0] = gw->gw->ipv4nat ? 'Y' : 'N';
           sipv6[0] = gw->gw->ipv6 ? 'Y' : 'N';
@@ -566,9 +570,9 @@ static void sgw_ipvx(struct autobuf *abuf, bool ipv6, const char * fmth, const c
           inet_ntop(ipv6 ? AF_INET6 : AF_INET, &gw->tunnel->target, destination, sizeof(destination));
         }
         if (gw->gw) {
-          cost = (long long unsigned int)gw->path_cost;
+          cost = (long long unsigned int)gw->gw->path_cost;
         }
-        abuf_appendf(abuf, fmtv, current, originator, prefix, uplink, downlink, sipv4, sipv4nat, sipv6, if_name, destination, cost);
+        abuf_appendf(abuf, fmtv, current, originator, prefix, uplink, downlink, pc, sipv4, sipv4nat, sipv6, if_name, destination, cost);
       }
     } OLSR_FOR_ALL_GWS_END(gw);
   }
@@ -582,10 +586,10 @@ ipc_print_sgw(struct autobuf *abuf)
   abuf_puts(abuf, "Gateway mode is only supported in linux\n");
 #else
 
-  static const char * fmth4 = "%s%-16s %-33s %-8s %-8s %-4s %-8s %-4s %-16s %-16s %s\n";
-  static const char * fmtv4 = "%s%-16s %-33s %-8u %-8u %-4s %-8s %-4s %-16s %-16s %llu\n";
-  static const char * fmth6 = "%s%-46s %-93s %-8s %-8s %-4s %-8s %-4s %-16s %-46s %s\n";
-  static const char * fmtv6 = "%s%-46s %-93s %-8u %-8u %-4s %-8s %-4s %-16s %-46s %llu\n";
+  static const char * fmth4 = "%s%-16s %-33s %-8s %-8s %-8s %-4s %-8s %-4s %-16s %-16s %s\n";
+  static const char * fmtv4 = "%s%-16s %-33s %-8u %-8u %-8u %-4s %-8s %-4s %-16s %-16s %llu\n";
+  static const char * fmth6 = "%s%-46s %-93s %-8s %-8s %-8s %-4s %-8s %-4s %-16s %-46s %s\n";
+  static const char * fmtv6 = "%s%-46s %-93s %-8u %-8u %-8u %-4s %-8s %-4s %-16s %-46s %llu\n";
 
   sgw_ipvx(abuf, false, fmth4, fmtv4);
   abuf_puts(abuf, "\n");
index dde48fd..c457bcc 100755 (executable)
@@ -23,5 +23,20 @@ if [ ${#versions[*]} -ne 3 ]; then
   versions=( 0 0 0 )
 fi
 
+# Ubuntu 13.10 and Debian Wheezy both report mingw 4.6.
+# - Debian Wheezy needs the old setup for 64 bits and the new setup for 32 bits.
+# - Ubuntu 13.10 needs the new setup for both 32 bits and 64 bits.
+# --> We decrement the version to 4.5 for Debian Wheezy 64 bits
+if [ "${versions[0]}" == "4" ] && \
+   [ "${versions[1]}" == "6" ] && \
+   [ "${versions[2]}" == "0" ]; then
+  detectDist="$(uname -a | grep -i debian)"
+  detectArch="$("$GCC" -dumpmachine | grep -i x86_64)"
+  if [ -n "$detectDist" ] && \
+     [ -n "$detectArch" ]; then
+    versions[1]=5
+  fi
+fi
+
 version=$(( versions[0]*10000 + versions[1]*100 + versions[2] ))
 echo "$version"
index f1b68ef..de07d3a 100644 (file)
@@ -569,26 +569,24 @@ void olsrd_write_cnf_autobuf(struct autobuf *out, struct olsrd_config *cnf) {
   }
   abuf_appendf(out,
     "\n"
-    "# Determines the offset of the smart gateway egress interfaces mark that are\n"
-    "# used in the policy routing rules in a multi-gateway setup. Only relevant\n"
-    "# when a multi-gateway setup is used.\n"
+    "# Determines the routing tables offset for multi-gateway policy routing tables\n"
+    "# See the policy routing script for an explanation.\n"
     "# (default is %u)\n"
-    "\n", DEF_GW_MARK_OFFSET_EGRESS);
-  abuf_appendf(out, "%sSmartGatewayMarkOffsetEgress %u\n",
-      cnf->smart_gw_mark_offset_egress == DEF_GW_MARK_OFFSET_EGRESS ? "# " : "",
-      cnf->smart_gw_mark_offset_egress);
-  abuf_appendf(out,
-    "\n"
-    "# Determines the offset of the smart gateway tunnel interfaces mark that are\n"
-    "# used in the policy routing rules in a multi-gateway setup. Only relevant\n"
-    "# when a multi-gateway setup is used.\n"
-    "# The ranges [egress offset, egress offset + egress count] and\n"
-    "# [tunnel offset, tunnel offset + use count] are not allowed to overlap.\n"
-    "# (default is %u)\n"
-    "\n", DEF_GW_MARK_OFFSET_TUNNELS);
-  abuf_appendf(out, "%sSmartGatewayMarkOffsetTunnels %u\n",
-      cnf->smart_gw_mark_offset_tunnels == DEF_GW_MARK_OFFSET_TUNNELS ? "# " : "",
-      cnf->smart_gw_mark_offset_tunnels);
+    "\n", DEF_GW_OFFSET_TABLES);
+  abuf_appendf(out, "%sSmartGatewayTablesOffset %u\n",
+      cnf->smart_gw_offset_tables == DEF_GW_OFFSET_TABLES ? "# " : "",
+      cnf->smart_gw_offset_tables);
+  abuf_appendf(out,
+    "\n"
+    "# Determines the policy routing rules offset for multi-gateway policy routing\n"
+    "# rules. See the policy routing script for an explanation.\n"
+    "# (default is %u, which indicates that the rules and tables should be aligned and\n"
+    "# puts this value at SmartGatewayTablesOffset - # egress interfaces -\n"
+    "# # olsr interfaces)\n"
+    "\n", DEF_GW_OFFSET_RULES);
+  abuf_appendf(out, "%sSmartGatewayRulesOffset %u\n",
+      cnf->smart_gw_offset_rules == DEF_GW_OFFSET_RULES ? "# " : "",
+      cnf->smart_gw_offset_rules);
   abuf_appendf(out,
     "\n"
     "# Allows the selection of a smartgateway with NAT (only for IPv4)\n"
index c1f6652..c68d244 100644 (file)
 extern FILE *yyin;
 extern int yyparse(void);
 
+#define valueInRange(value, low, high) ((low <= value) && (value <= high))
+
+#define rangesOverlap(low1, high1, low2, high2) ( \
+            valueInRange(low1 , low2, high2) || valueInRange(high1, low2, high2) || \
+            valueInRange(low2,  low1, high1) || valueInRange(high2, low1, high1))
+
 static char interface_defaults_name[] = "[InterfaceDefaults]";
 
 const char *FIB_METRIC_TXT[] = {
@@ -635,34 +641,76 @@ olsrd_sanity_check_cnf(struct olsrd_config *cnf)
     }
 
     {
-      uint8_t egressLow = cnf->smart_gw_mark_offset_egress;
-      uint8_t egressHigh = egressLow + cnf->smart_gw_egress_interfaces_count - 1;
-      uint8_t tunnelsLow = cnf->smart_gw_mark_offset_tunnels;
-      uint8_t tunnelsHigh = tunnelsLow + cnf->smart_gw_use_count - 1;
-      bool overlap = false;
-
-      /* check that the egress interface marks range does not overflow */
-      if (egressLow > (UINT8_MAX - cnf->smart_gw_egress_interfaces_count)) {
-        fprintf(stderr, "Error, egress interface mark offset %u together with egress interface count %u overflows range [0, %u]\n",
-            egressLow, cnf->smart_gw_egress_interfaces_count, UINT8_MAX);
+      uint32_t nrOfTables = 1 + cnf->smart_gw_egress_interfaces_count + cnf->smart_gw_use_count;
+
+      uint32_t nrOfBypassRules = cnf->smart_gw_egress_interfaces_count + getNrOfOlsrInterfaces(olsr_cnf);
+      uint32_t nrOfTableRules = nrOfTables;
+      uint32_t nrOfRules = nrOfBypassRules + nrOfTableRules;
+
+      uint32_t tablesLow;
+      uint32_t tablesHigh;
+      uint32_t tablesLowMax = ((1 << 31) - nrOfTables + 1);
+
+      uint32_t rulesLow;
+      uint32_t rulesHigh;
+      uint32_t rulesLowMax = UINT32_MAX - nrOfRules;
+
+      /* setup tables low/high */
+      tablesLow = cnf->smart_gw_offset_tables;
+      tablesHigh = cnf->smart_gw_offset_tables + nrOfTables;
+
+      /*
+       * tablesLow  >  0
+       * tablesLow  >  0
+       * tablesHigh <= 2^31
+       * [tablesLow, tablesHigh] no overlap with [253, 255]
+       */
+      if (!tablesLow) {
+        fprintf(stderr, "Error, smart gateway tables offset can't be zero.\n");
+        return -1;
+      }
+
+      if (tablesLow > tablesLowMax) {
+        fprintf(stderr, "Error, smart gateway tables offset too large, maximum is %ul.\n", tablesLowMax);
+        return -1;
+      }
+
+      if (rangesOverlap(tablesLow, tablesHigh, 253, 255)) {
+        fprintf(stderr, "Error, smart gateway tables range [%u, %u] overlaps with routing tables [253, 255].\n", tablesLow, tablesHigh);
+        return -1;
+      }
+
+      /* set default for rules offset if needed */
+      if (cnf->smart_gw_offset_rules == 0) {
+        if (valueInRange(tablesLow, 1, nrOfBypassRules)) {
+          fprintf(stderr, "Error, smart gateway table offset is too low: %u bypass rules won't fit between it and zero.\n", nrOfBypassRules);
+          return -1;
+        }
+
+        cnf->smart_gw_offset_rules = tablesLow - nrOfBypassRules;
+      }
+
+      /* setup rules low/high */
+      rulesLow = cnf->smart_gw_offset_rules;
+      rulesHigh = cnf->smart_gw_offset_rules + nrOfRules;
+
+      /*
+       * rulesLow  > 0
+       * rulesHigh < 2^32
+       * [rulesLow, rulesHigh] no overlap with [32766, 32767]
+       */
+      if (!rulesLow) {
+        fprintf(stderr, "Error, smart gateway rules offset can't be zero.\n");
         return -1;
       }
 
-      /* check that the tunnel interface marks range does not overflow */
-      if (tunnelsLow > (UINT8_MAX - cnf->smart_gw_use_count)) {
-        fprintf(stderr, "Error, tunnel interface mark offset %u together with use count %u overflows range [0, %u]\n",
-            tunnelsLow, cnf->smart_gw_use_count, UINT8_MAX);
+      if (rulesLow > rulesLowMax) {
+        fprintf(stderr, "Error, smart gateway rules offset too large, maximum is %ul.\n", rulesLowMax);
         return -1;
       }
 
-      /* check that the egress and tunnel marks ranges do not overlap */
-      overlap =            ((tunnelsLow <= egressLow)   && (egressLow   <= tunnelsHigh));
-      overlap = overlap || ((tunnelsLow <= egressHigh)  && (egressHigh  <= tunnelsHigh));
-      overlap = overlap || ((egressLow  <= tunnelsLow)  && (tunnelsLow  <= egressHigh));
-      overlap = overlap || ((egressLow  <= tunnelsHigh) && (tunnelsHigh <= egressHigh));
-      if (overlap) {
-        fprintf(stderr, "Error, egress interface mark range [%u, %u] overlaps with tunnel interface mark range [%u, %u]\n",
-            egressLow, egressHigh, tunnelsLow, tunnelsHigh);
+      if (rangesOverlap(rulesLow, rulesHigh, 32766, 32767)) {
+        fprintf(stderr, "Error, smart gateway rules range [%u, %u] overlaps with rules [32766, 32767].\n", rulesLow, rulesHigh);
         return -1;
       }
     }
@@ -908,8 +956,8 @@ set_default_cnf(struct olsrd_config *cnf)
   cnf->smart_gw_policyrouting_script = NULL;
   cnf->smart_gw_egress_interfaces = NULL;
   cnf->smart_gw_egress_interfaces_count = 0;
-  cnf->smart_gw_mark_offset_egress = DEF_GW_MARK_OFFSET_EGRESS;
-  cnf->smart_gw_mark_offset_tunnels = DEF_GW_MARK_OFFSET_TUNNELS;
+  cnf->smart_gw_offset_tables = DEF_GW_OFFSET_TABLES;
+  cnf->smart_gw_offset_rules = DEF_GW_OFFSET_RULES;
   cnf->smart_gw_allow_nat = DEF_GW_ALLOW_NAT;
   cnf->smart_gw_period = DEF_GW_PERIOD;
   cnf->smart_gw_stablecount = DEF_GW_STABLE_COUNT;
@@ -1056,9 +1104,9 @@ olsrd_print_cnf(struct olsrd_config *cnf)
   }
   printf("\n");
 
-  printf("SmGw. Mark Egress: %u\n", cnf->smart_gw_mark_offset_egress);
+  printf("SmGw. Offst Tabls: %u\n", cnf->smart_gw_offset_tables);
 
-  printf("SmGw. Mark Tunnel: %u\n", cnf->smart_gw_mark_offset_tunnels);
+  printf("SmGw. Offst Rules: %u\n", cnf->smart_gw_offset_rules);
 
   printf("SmGw. Allow NAT  : %s\n", cnf->smart_gw_allow_nat ? "yes" : "no");
 
index 77d222d..1ace8ca 100644 (file)
@@ -221,8 +221,8 @@ static int add_ipv6_addr(YYSTYPE ipaddr_arg, YYSTYPE prefixlen_arg)
 %token TOK_SMART_GW_TAKEDOWN_PERCENTAGE
 %token TOK_SMART_GW_POLICYROUTING_SCRIPT
 %token TOK_SMART_GW_EGRESS_IFS
-%token TOK_SMART_GW_MARK_OFFSET_EGRESS
-%token TOK_SMART_GW_MARK_OFFSET_TUNNELS
+%token TOK_SMART_GW_OFFSET_TABLES
+%token TOK_SMART_GW_OFFSET_RULES
 %token TOK_SMART_GW_ALLOW_NAT
 %token TOK_SMART_GW_PERIOD
 %token TOK_SMART_GW_STABLECOUNT
@@ -314,8 +314,8 @@ stmt:       idebug
           | ismart_gw_use_count
           | ismart_gw_takedown_percentage
    &n