#! /usr/bin/python3
# -*- coding: UTF-8
# This code is generated by scons.  Do not hand-hack it!
# This program conforms to the JAVAD document:
#    GNSS Receiver External Interface Specification
#    Revised: October 11, 2017
#
# Hereafter referred to as "the specification"
#
# This file is Copyright 2018 by the GPSD project
# SPDX-License-Identifier: BSD-2-clause
#
# This code runs compatibly under Python 2 and 3.x for x >= 2.
# Preserve this property!
#
# ENVIRONMENT:
#    Options in the ZERKOPTS environment variable will be parsed before
#    the CLI options.  A handy place to put your '-f /dev/ttyXX -s SPEED'
#
# example usages:
#    Coldboot the GPS:          zerk -p COLDBOOT
#    Print current serial port: zerk -c "print,/cur/term"
#    Decode raw log file:       zerk -r -f greis-binary.log -v 2
#    Change GPS port speed:     zerk -S 230400
#    Watch entire reset cycle:  zerk -p RESET -v 2 -w 20 -W
#    poll SVs Status:     zerk -W -w 2 -v 2 -c "out,,jps/{CS,ES,GS,Is,WS,QS}"
#    dump local gpsd data       zerk -v 2 -w 5 localhost
#
# TODO: no CRC16 packets handled yet
# TODO: more packet decodes
# Codacy D203 and D211 conflict, I choose D203
# Codacy D212 and D213 conflict, I choose D212
"""zerk -- GREIS configurator and packet decoder.

usage: zerk [OPTIONS] [server[:port[:device]]]
"""


from __future__ import absolute_import, print_function, division

import binascii      # for binascii.hexlify()
import getopt        # for getopt.getopt(), to parse CLI options
import hashlib       # for hashlib.sha1
import os            # for os.environ
import socket        # for socket.error
import stat          # for stat.S_ISBLK()
import struct        # for pack()
import sys
import time
import xml.etree.ElementTree  # to parse .jpo files

PROG_NAME = 'zerk'

try:
    import serial
except ImportError:
    serial = None  # Defer complaining until we know we need it.

try:
    import gps
    import gps.misc      # for polybyte() polystr()
except ImportError:
    # PEP8 says local imports last
    sys.stderr.write("%s: failed to import gps, check PYTHON_PATH\n" %
                     PROG_NAME)
    sys.exit(2)

gps_version = '3.22'
if gps.__version__ != gps_version:
    sys.stderr.write("%s: ERROR: need gps module version %s, got %s\n" %
                     (PROG_NAME, gps_version, gps.__version__))
    sys.exit(1)

# Some old versions of Python fail to accept a bytearray as an input to
# struct.unpack_from, though it can be worked around by wrapping it with
# buffer().  Since the fix is only needed in rare cases, this monkey-patches
# struct.unpack_from() when needed, and otherwise changes nothing.  If
# struct.unpack() were used, it would need similar treatment, as would
# methods from struct.Struct if that were used.
try:
    struct.unpack_from('B', bytearray(1))
except TypeError:
    unpack_from_orig = struct.unpack_from

    def unpack_from_fixed(fmt, buf, offset=0):
        """Unpack_from_fixed."""
        return unpack_from_orig(fmt, buffer(buf), offset=offset)

    struct.unpack_from = unpack_from_fixed

VERB_QUIET = 0   # quiet
VERB_NONE = 1    # just output requested data and some info
VERB_DECODE = 2  # decode all messages
VERB_INFO = 3    # more info
VERB_RAW = 4     # raw info
VERB_PROG = 5    # program trace

# dictionary to hold all user options
opts = {
    # command to send to GPS, -c
    'command': None,
    # command for -d disable
    'disable': None,
    # command for -e enable
    'enable': None,
    # default input -f file
    'input_file_name': None,
    # default forced wait? -W
    'input_forced_wait': False,
    # default port speed -s
    'input_speed': 115200,
    # default input wait time -w in seconds
    'input_wait': 2.0,
    # the name of an OAF file, extension .jpo
    'oaf_name': None,
    # poll command -p
    'poll': None,
    # raw log file name
    'raw_file': None,
    # open port read only -r
    'read_only': False,
    # speed to set GPS -S
    'set_speed': None,
    # target gpsd (server:port:device) to connect to
    'target': {"server": None, "port": gps.GPSD_PORT, "device": None},
    # verbosity level, -v
    'verbosity': VERB_NONE,
    # contents of environment variable ZERKOPTS
    'progopts': '',
}


class greis(object):

    """A class for working with the GREIS GPS message formats.

This class contains functions to decode messages in the Javad GREIS
"Receiver Input Language" and "Receiver Messages" formats.
"""

    # when a statement identifier is received, it is stored here
    last_statement_identifier = None
    # expected statement identifier.
    expect_statement_identifier = False
    # ID of current message as a string
    s_id = ''

    def __init__(self):
        """Initialize class."""
        self.last_statement_identifier = None
        self.expect_statement_identifier = False
        # last epoch received in [~~]
        # epoch == None means never got epoch, epoch == -1 means missing.
        self.epoch = None

    def f4_s(self, f):
        """Convert an '! f4' to a string."""
        if gps.isfinite(f):
            # yeah, the precision is a guess
            return "%.6f" % f
        return 'X'

    def f8_s(self, f):
        """Convert an '! f8' to a string."""
        if gps.isfinite(f):
            # yeah, the precision is a guess
            return "%.4f" % f
        return 'X'

    def i1_s(self, i):
        """Convert an '! i1' to a string."""
        return 'X' if i == 127 else str(i)

    def i2_s(self, i):
        """Convert an '! i2' to a string."""
        return 'X' if i == 32767 else str(i)

    def i4_s(self, i):
        """Convert an '! i4' to a string."""
        return 'X' if i == 2147483647 else str(i)

    def u1_s(self, u):
        """Convert an '! u1' to a string."""
        return 'X' if u == 255 else str(u)

    def u2_s(self, u):
        """Convert an '! u2' to a string."""
        return 'X' if u == 65535 else str(u)

    def u4_s(self, u):
        """Convert an '! u4' to a string."""
        return 'X' if u == 4294967295 else str(u)

    def isuchex(self, c):
        """Is byte an upper case hex char?"""
        if 48 <= c <= 57:
            # 0 to 9
            return int(c) - 48
        if 65 <= c <= 70:
            # A to F
            return int(c) - 55
        return -1

    soltypes = {0: "None",
                1: "3D",
                2: "DGPS",
                3: "RTK float",
                4: "RTK fixed",
                5: "fixed"
                }

    # allowable speeds
    speeds = (460800, 230400, 153600, 115200, 57600, 38400, 19200, 9600,
              4800, 2400, 1200, 600, 300)

    def msg_c_(self, payload):
        """[c?] decode, Smoothing Corrections."""
        s = ' smooth'
        for i in range(0, len(payload) - 1, 2):
            u = struct.unpack_from('<h', payload, i)
            s += " " + self.i2_s(u[0])

        return s + '\n'

    def msg__p(self, payload):
        """[?p] decode, Integer Relative Carrier Phases."""
        s = ' rcp'
        for i in range(0, len(payload) - 1, 4):
            u = struct.unpack_from('<l', payload, i)
            s += " " + self.i4_s(u[0])

        return s + '\n'

    def msg__d(self, payload):
        """[?d] decode, Relative Doppler."""
        s = ' srdp'
        for i in range(0, len(payload) - 1, 2):
            u = struct.unpack_from('<h', payload, i)
            s += " " + self.i2_s(u[0])

        return s + '\n'

    def msg__r(self, payload):
        """[?r] decode, Integer Relative Pseudo-ranges."""
        s = ' srdp'
        for i in range(0, len(payload) - 1, 2):
            u = struct.unpack_from('<h', payload, i)
            s += " " + self.i2_s(u[0])

        return s + '\n'

    def msg__A(self, payload):
        """[?A] decode, GPS, GALILEO Almanac."""
        m_len = len(payload)

        if ('[EA]' == self.s_id) and (49 > m_len):
            return " Bad Length %s" % m_len

        u = struct.unpack_from('<BhlBBBfffffffff', payload, 0)

        s = (" sv %u wna %d toa %d healthA %u healthS %u config %u\n"
             "     af1 %f af0 %f rootA %f ecc %f m0 %f\n"
             "     omega0 %f argPer %f delf %f omegaDot %f\n" % u)

        if '[EA]' == self.s_id:
            u = struct.unpack_from('<H', payload, 46)
            s += ("     iod %d" % (u[0]))
        return s

    def msg__E(self, payload):
        """[?E] decode, SNR x 4."""
        s = ' cnrX4'
        for i in range(0, len(payload) - 1, 1):
            u = struct.unpack_from('<B', payload, i)
            s += " " + self.u1_s(u[0])

        return s + '\n'

    def msg_WE(self, payload):
        """[WE] decode, SBAS Ephemeris."""
        u = struct.unpack_from('<BBBBLdddffffffffLHB', payload, 0)
        s = (" waasPrn %u gpsPrn %u iod %u acc %u tod %u\n"
             "     xg %f yg %f zg %f\n"
             "     vxg %f vyg %f vzg %f\n"
             "     vvxg %f vvyg %f vvzg %f\n"
             "     agf0 %f agf1 %f tow %u wn %u flags %u\n" % u)

        return s

    def msg_r(self, payload):
        """[r?] decode, Integer Psudeo Ranges."""
        s = ' spr'
        for i in range(0, len(payload) - 1, 4):
            u = struct.unpack_from('<l', payload, i)
            s += " " + self.i4_s(u[0])

        return s + '\n'

    def msg_AZ(self, payload):
        """[AZ] decode, Satellite Azimuths."""
        s = " azim"
        for i in range(0, len(payload) - 1):
            # azimuth/2, 0 to 180 degrees
            s += " " + self.u1_s(payload[i])

        return s + '\n'

    def msg_BP(self, payload):
        """[BP] decode."""
        u = struct.unpack_from('<f', payload, 0)
        return " acc %.3e\n" % u[0]

    def msg_D_(self, payload):
        """[D?] decode, Doppler."""
        s = " dp"
        for i in range(0, len(payload) - 1, 4):
            # This is dopple in Hz * 1e4
            u = struct.unpack_from('<l', payload, i)
            s += " " + self.i4_s(u[0])

        return s + '\n'

    def msg_DO(self, payload):
        """[DO] decode."""
        u = struct.unpack_from('<ff', payload, 0)
        return " val %.3f sval %.3f\n" % u

    def msg_DP(self, payload):
        """[DP] decode."""
        u = struct.unpack_from('<fffBfB', payload, 0)
        return (" hdop %f vdop %f tdop %f edop %f\n"
                "     solType %s\n" %
                (u[0], u[1], u[2], u[4], self.soltypes[u[3]]))

    def msg_E_(self, payload):
        """[E?] decode, SNR."""
        s = ' cnr'
        for i in range(0, len(payload) - 1):
            s += " " + self.u1_s(payload[i])

        return s + '\n'

    def msg_ET(self, payload):
        """[::](ET) decode, Epoch time, end of epoch."""
        u = struct.unpack_from('<L', payload, 0)
        if ((self.epoch is not None and self.epoch != u[0])):
            if -1 == self.epoch:
                print("Error: [::](ET) missing [~~](RT)\n")
            else:
                print("Error: [::](ET) Wrong Epoch %u, should be %u\n" %
                      (u[0], self.epoch))
        # reset epoch
        self.epoch = -1
        return "(ET) tod %u\n" % u[0]

    def msg_EL(self, payload):
        """[EL] decode, Satellite Elevations."""
        s = " elev"
        for i in range(0, len(payload) - 1):
            # looking for integer (-90 to 90), not byte
            u = struct.unpack_from('<b', payload, i)
            s += " " + self.i1_s(u[0])

        return s + '\n'

    def msg_ER(self, payload):
        """[ER] decode, Error messages."""
        parts = payload.split(b'%')
        if 1 < len(parts):
            self.last_statement_identifier = parts[1]

        s_payload = "".join(map(chr, payload))
        print("[ER] %s\n" % s_payload)
        return " %s\n" % s_payload

    def msg_EU(self, payload):
        """[EU] decode, GALILEO UTC and GPS Time Parameters."""
        u = struct.unpack_from('<dfLHbBHbffLHH', payload, 0)
        return (" ao %f a1 %f tot %u wnt %u dtls %d dn %u wnlsf %u\n"
                "     dtlsf %d a0g %f a1g %f t0g %u wn0g %u flags %#x\n" % u)

    def msg_FC(self, payload):
        """[FC] [F1] [F2] [F3] [f5] [Fl] decode, Signal Lock Loop Flags."""
        s = " flags 0x"
        for i in range(0, len(payload) - 1):
            u = struct.unpack_from('<H', payload, i)
            s += " %2x" % (u[0])

        return s + '\n'

    def msg__E1(self, payload):
        """[?E] decode, BeiDos, GPS, GALILEO, IRNSS Ephemeris."""
        m_len = len(payload)
        # [GE]
        if ('[IE]' == self.s_id) and (124 > m_len):
            return " Bad Length %s" % m_len
        if ('[CN]' == self.s_id) and (132 > m_len):
            return " Bad Length %s" % m_len
        if ('[EN]' == self.s_id) and (145 > m_len):
            return " Bad Length %s" % m_len

        u = struct.unpack_from('<BLBhlbBhfffflhddddddfffffffff', payload, 0)
        s = (" sv %u tow %u flags %u iodc %d toc %d ura %d healthS %u\n"
             "     wn %d tgd %f af2 %f af1 %f af0 %f toe %d\n"
             "     iode %d rootA %f ecc %f m0 %f omega0 %f\n"
             "     inc0 %f argPer %f deln %f omegaDot %f\n"
             "     incDot %f crc %f crs %f cuc %f\n"
             "     cus %f cic %f cis %f\n" % u)

        if '[EN]' == self.s_id:
            u = struct.unpack_from('<fffffBB', payload, 122)
            s += ("     bgdE1E5a %f bgdE1E5b %f aio %f ai1 %f ai2 %f\n"
                  "     sfi %u navType %u" % u)
            if 149 <= m_len:
                # DAf0 added in 3.7.0
                u = struct.unpack_from('<f', payload, 144)
                s += (" DAf0 %f" % u)
            s += '\n'

        if ('[IE]' == self.s_id) and (124 > m_len):
            u = struct.unpack_from('<B', payload, 122)
            s += ("     navType %u\n" % u[0])

        if ('[CN]' == self.s_id) and (132 > m_len):
            u = struct.unpack_from('<fBf', payload, 122)
            s += ("     tgd2 %f navType %u DAf0 %f\n" % u)

        # TODO: decode length 160 168

        return s

    def msg_GT(self, payload):
        """[GT] decode, GPS Time."""
        u = struct.unpack_from('<LH', payload, 0)
        return " tow %u wn %d\n" % u

    def msg_ID(self, payload):
        """[ID] Ionosphere Delays."""
        s = ' delay'
        for i in range(0, len(payload) - 1, 4):
            u = struct.unpack_from('<f', payload, i)
            s += " %s" % self.f4_s(u[0])

        return s + '\n'

    def msg_IO(self, payload):
        """[IO] decode, GPS Ionospheric Parameters."""
        u = struct.unpack_from('<LHffffffff', payload, 0)

        return (" tot %d wn %u alpha0 %f alpha1 %f alpha2 %f\n"
                "     alpha3 %f beta0 %u beta1 %d beta2 %f\n"
                "     beta3 %f\n" % u)

    def msg_LO(self, payload):
        """[LO] decode, undocumented message."""
        return " Undocumented message\n"

    def msg_MF(self, payload):
        """[MF] Messages Format."""
        u = struct.unpack_from('<BBBBBBB', payload, 0)
        return (" id %c%c majorVer %c%c minorVer %c%c order %c\n" %
                (chr(u[0]), chr(u[1]), chr(u[2]), chr(u[3]),
                 chr(u[4]), chr(u[5]), chr(u[6])))

    def msg_P_(self, payload):
        """[P?] decode, Carrier Phases."""
        s = " cp"
        for i in range(0, len(payload) - 1, 8):
            # carrier phases in cycles
            u = struct.unpack_from('<d', payload, i)
            s += " " + self.f8_s(u[0])

        return s + '\n'

    def msg_PM(self, payload):
        """[PM] parameters."""
        # PM only seems to work after a coldboot, once
        # zerk -v 2 -w 20 -c 'out,,jps/{PM}' -W
        return " %s\n" % payload

    def msg_PV(self, payload):
        """[PV] decode, Cartesian Position and Velocity."""
        u = struct.unpack_from('<dddfffffBB', payload, 0)
        return (" x %s y %s z %s sigma %s\n"
                "     vx %s vy %s vz %s\n"
                "     vsigma %s soltype %s\n" %
                (self.f8_s(u[0]), self.f8_s(u[1]), self.f8_s(u[2]),
                 self.f4_s(u[3]), self.f4_s(u[4]), self.f4_s(u[5]),
                 self.f4_s(u[6]), self.f4_s(u[7]), self.soltypes[u[8]]))

    def msg_R_(self, payload):
        """[R?] decode, Pseudo-ranges."""
        s = " pr"
        for i in range(0, len(payload) - 1, 8):
            # pseudo in seconds
            u = struct.unpack_from('<d', payload, i)
            s += " %s" % self.f8_s(u[0])

        return s + '\n'

    def msg_RD(self, payload):
        """[RD] decode, Receiver Date."""
        u = struct.unpack_from('<HBBB', payload, 0)
        return " year %d month %d day %d base %d\n" % u

    def msg_RE(self, payload):
        """[RE] decode."""
        parts = payload.split(b'%')
        if 1 < len(parts):
            # Got a statement identifier (ID), save it?
            # Multiline statement if payload ends with comma or left brace
            if payload[-1] not in (ord(','), ord('{')):
                # yes, this is the end
                self.last_statement_identifier = parts[1]

            # Get the message body
            part1 = parts[1].split(b',')

            if 'em' == parts[1]:
                # Probably no parts[2]
                print("Enable Messages %s" % parts[2])
                return " Enable Messages %s\n" % parts[2]

            if 'id' == parts[1]:
                print("ID: %s" % parts[2])
                return " ID %s\n" % parts[2]

            if 'opts' == part1[0]:
                if 1 < len(part1):
                    s = "OAF %s: %s" % (part1[1], parts[2])
                else:
                    s = " OAF: %s" % (parts[2])
                print(s)
                return " %s\n" % s

            if 'serial' == parts[1]:
                print("SERIAL: %s" % parts[2])
                return " SERIAL %s\n" % parts[2]

            if 'vendor' == parts[1]:
                print("VENDOR: %s" % parts[2])
                return " Vendor %s\n" % parts[2]

            if 'ver' == parts[1]:
                print("VER: %s" % parts[2])
                return " Version %s\n" % parts[2]

            # unknown statement identifier
            s_payload = "".join(map(chr, payload))
            print("RE: %s\n" % s_payload)

        return " %s\n" % s_payload

    def msg_RT(self, payload):
        """[~~](RT) decode, Receiver Time, start of epoch."""
        if self.epoch is not None and -1 != self.epoch:
            print("Error: [~~](RT) missing [::](ET)\n")

        u = struct.unpack_from('<L', payload, 0)
        # save start of epoch
        self.epoch = u[0]
        return "(RT) tod %u\n" % self.epoch

    def msg_S_(self, payload):
        """[CS], [ES], [GS], [Is], [WS], [NS], [QS], decode, SVs Status."""
        # to poll them all: zerk -W -w 2 -v 2 -c "out,,jps/{CS,ES,GS,Is,WS,QS}"
        # TODO, check @checksum

        return "%s" % payload

    def msg_SE(self, payload):
        """[SE] decode."""
        u = struct.unpack_from('<BBBBB', payload, 0)
        return " data 0x %x %x %x %x %x\n" % u

    def msg_SG(self, payload):
        """[SG] decode."""
        u = struct.unpack_from('<ffffBB', payload, 0)
        return (" hpos %s vpos %s hvel %s vvel %s\n"
                "     soltype %s\n" %
                (self.f4_s(u[0]), self.f4_s(u[1]), self.f4_s(u[2]),
                 self.f4_s(u[3]), self.soltypes[u[4]]))

    def msg_SI(self, payload):
        """[SI] decode, Satellite Index, deprecated by Javad, use [SX]."""
        # [SX] require 3.7 firmware, we use [SI] to support 3.6
        s = " usi"
        for i in range(0, len(payload) - 1):
            s += " %d" % payload[i]

        return s + '\n'

    def msg_SP(self, payload):
        """[SP] decode, Position Covariance Matrix."""
        u = struct.unpack_from('<ffffffffffB', payload, 0)
        return (" xx % f yy % f zz % f tt % f xy % f\n"
                "     xz % f xt % f yz % f yt % f zt % f\n"
                "     solType %s\n" %
                (u[0], u[1], u[2], u[3], u[4],
                 u[5], u[6], u[7], u[8], u[9],
                 self.soltypes[u[10]]))

    def msg_SS(self, payload):
        """[SS] decode, Satellite Navigation Status."""
        s = " ns"
        for i in range(0, len(payload) - 2):
            s += " %d" % payload[i]

        return (s + '\n     solType %s\n' %
                self.soltypes[payload[len(payload) - 2]])

    def msg_ST(self, payload):
        """[ST] decode, Solution Time Tag."""
        u = struct.unpack_from('<LBB', payload, 0)
        return (" time %u ms, soltype %s\n" %
                (u[0], self.soltypes[u[1]]))

    def msg_SX(self, payload):
        """[SX] decode, Extended Satellite Indices."""
        # [SX] require 3.7 firmware
        s = " ESI"
        for i in range(0, len(payload) - 2, 2):
            u = struct.unpack_from('<BB', payload, i)
            s += " (%u, %u)" % u

        return s + '\n'

    def msg_TC(self, payload):
        """[TC] decode, CA/L1 Continuous Tracking Time."""
        s = " tt"
        for i in range(0, len(payload) - 1, 2):
            u = struct.unpack_from('<H', payload, i)
            s += " %.2f" % u[0]

        return s + '\n'

    def msg_TO(self, payload):
        """[TO] decode, Reference Time to Receiver Time Offset."""
        u = struct.unpack_from('<dd', payload, 0)
        return " val %.3f sval %.3f\n" % u

    def msg_UO(self, payload):
        """[UO] decode, GPS UTC Time Parameters."""
        u = struct.unpack_from('<dfLHbBHb', payload, 0)
        return (" a0 %f a1 %f tot %d wnt %d dtls %d\n"
                "     dn %d wnlsf %d dtlsf %d\n" % u)

    def msg_WA(self, payload):
        """[WA] decode."""
        u = struct.unpack_from('<BBBBLdddfffLH', payload, 0)
        return (" waasPrn %d gpsPrn %d if %d healthS %d tod %d\n"
                "     ECEF %.3f %.3f %.3f, %.3f %.3f %.3f\n"
                "     tow %d wn %d\n" % u)

    def msg_WU(self, payload):
        """[WU] decode, SBAS UTC Time Parameters."""
        u = struct.unpack_from('<dfLHbBHbfbLHB', payload, 0)
        return (" ao %f a1 %f tot %u wnt %u dtls %d dn %u\n"
                "wnlsf %u dtlsf %d utcsi %d tow %u wn %u flags %#x\n" % u)

    # table from message id to respective message decoder.
    # Note: id (%id%) is different than ID (statement identifier)
    # the id is the first two characters of a GREIS receiver Message
    # see section 3.3 of the specification
    messages = {
        '[0d]': (msg__d, 1),
        '[1d]': (msg__d, 1),
        '[1E]': (msg__E, 1),
        '[1p]': (msg__p, 1),
        '[1r]': (msg__r, 1),
        '[2d]': (msg__d, 1),
        '[2E]': (msg__E, 1),
        '[2p]': (msg__p, 1),
        '[2r]': (msg__r, 1),
        '[3d]': (msg__d, 1),
        '[3E]': (msg__E, 1),
        '[3p]': (msg__p, 1),
        '[3r]': (msg__r, 1),
        '[5d]': (msg__d, 1),
        '[5E]': (msg__E, 1),
        '[5p]': (msg__p, 1),
        '[5r]': (msg__r, 1),
        '[AZ]': (msg_AZ, 1),
        '[BP]': (msg_BP, 5),
        '[c1]': (msg_c_, 1),
        '[c2]': (msg_c_, 1),
        '[c3]': (msg_c_, 1),
        '[c5]': (msg_c_, 1),
        '[CA]': (msg__A, 47),
        '[cc]': (msg_c_, 1),
        '[CE]': (msg__E, 1),
        '[cl]': (msg_c_, 1),
        '[CN]': (msg__E1, 123),
        '[cp]': (msg__p, 1),
        '[cr]': (msg__r, 1),
        '[CS]': (msg_S_, 8),
        '[D1]': (msg_D_, 1),
        '[D2]': (msg_D_, 1),
        '[D3]': (msg_D_, 1),
        '[D5]': (msg_D_, 1),
        '[DC]': (msg_D_, 1),
        '[Dl]': (msg_D_, 1),
        '[DO]': (msg_DO, 6),
        '[DP]': (msg_DP, 18),
        '[DX]': (msg_D_, 1),
        '[E1]': (msg_E_, 1),
        '[E2]': (msg_E_, 1),
        '[E3]': (msg_E_, 1),
        '[E5]': (msg_E_, 1),
        '[EA]': (msg__A, 47),
        '[EC]': (msg_E_, 1),
        '[El]': (msg_E_, 1),
        '[EL]': (msg_EL, 1),
        '[EN]': (msg__E1, 123),
        '[ER]': (msg_ER, 1),
        '[ES]': (msg_S_, 8),
        '[EU]': (msg_EU, 40),
        '[F1]': (msg_FC, 1),
        '[F2]': (msg_FC, 1),
        '[F3]': (msg_FC, 1),
        '[F5]': (msg_FC, 1),
        '[FA]': (msg_FC, 1),
        '[FC]': (msg_FC, 1),
        '[Fl]': (msg_FC, 1),
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 