Ejemplo n.º 1
0
def _model_cb(option, opt_str, value, parser):
    """
    This function sets up the single parameters if the 'model' option has been selected
    by the user.
    """
    model_name = value.lower()
    models = CrcModels()
    model = models.get_params(model_name)
    if model != None:
        setattr(parser.values, 'width', model['width'])
        setattr(parser.values, 'poly', model['poly'])
        setattr(parser.values, 'reflect_in', model['reflect_in'])
        setattr(parser.values, 'xor_in', model['xor_in'])
        setattr(parser.values, 'reflect_out', model['reflect_out'])
        setattr(parser.values, 'xor_out', model['xor_out'])
    else:
        models = CrcModels()
        model_list = ", ".join(models.names())
        raise OptionValueError(
            "unsupported model {0:s}. Supported models are: {1:s}."
            .format(value, model_list))
Ejemplo n.º 2
0
    def parse(self, argv=None):
        """
        Parses and validates the options given as arguments
        """
        # pylint: disable=too-many-branches, too-many-statements

        usage = """python %prog [OPTIONS]

To calculate the checksum of a string or hexadecimal data:
    python %prog [model] --check-string "123456789"
    python %prog [model] --check-hexstring "313233343536373839"

To calculate the checksum of a file:
    python %prog [model] --check-file filename

To generate the C source code and write it to filename:
    python %prog [model] --generate c -o filename

The model can be defined either with the --model switch or by specifying each
of the following parameters:
    --width --poly --reflect-in --xor-in --reflect-out --xor-out"""

        models = CrcModels()
        model_list = ", ".join(models.names())
        parser = OptionParser(option_class=MyOption, usage=usage, version=self.version_str)
        parser.add_option(
            "-v", "--verbose",
            action="store_true", dest="verbose", default=False,
            help="be more verbose; print the value of the parameters "
            "and the chosen model to stdout")
        parser.add_option(
            "--check-string",
            action="store", type="string", dest="check_string",
            help="calculate the checksum of a string (default: '123456789')",
            metavar="STRING")
        parser.add_option(
            "--check-hexstring",
            action="store", type="string", dest="check_hexstring",
            help="calculate the checksum of a hexadecimal number string",
            metavar="STRING")
        parser.add_option(
            "--check-file",
            action="store", type="string", dest="check_file",
            help="calculate the checksum of a file",
            metavar="FILE")
        parser.add_option(
            "--generate",
            action="store", type="string", dest="generate", default=None,
            help="generate C source code; choose the type from {h, c, c-main, table}",
            metavar="CODE")
        parser.add_option(
            "--std",
            action="store", type="string", dest="c_std", default="C99",
            help="choose the C dialect of the generated code from {C89, ANSI, C99}",
            metavar="STD")
        parser.add_option(
            "--algorithm",
            action="store", type="string", dest="algorithm", default="all",
            help="choose an algorithm from "
            "{bit-by-bit, bbb, bit-by-bit-fast, bbf, table-driven, tbl, all}",
            metavar="ALGO")
        parser.add_option(
            "--model",
            action="callback", callback=_model_cb, type="string", dest="model", default=None,
            help="choose a parameter set from {{{0:s}}}".format(model_list),
            metavar="MODEL")
        parser.add_option(
            "--width",
            action="store", type="hex", dest="width",
            help="use NUM bits in the polynomial",
            metavar="NUM")
        parser.add_option(
            "--poly",
            action="store", type="hex", dest="poly",
            help="use HEX as polynomial",
            metavar="HEX")
        parser.add_option(
            "--reflect-in",
            action="store", type="bool", dest="reflect_in",
            help="reflect the octets in the input message",
            metavar="BOOL")
        parser.add_option(
            "--xor-in",
            action="store", type="hex", dest="xor_in",
            help="use HEX as initial value",
            metavar="HEX")
        parser.add_option(
            "--reflect-out",
            action="store", type="bool", dest="reflect_out",
            help="reflect the resulting checksum before applying the --xor-out value",
            metavar="BOOL")
        parser.add_option(
            "--xor-out",
            action="store", type="hex", dest="xor_out",
            help="xor the final CRC value with HEX",
            metavar="HEX")
        parser.add_option(
            "--slice-by",
            action="store", type="int", dest="slice_by",
            help="read NUM bytes at a time from the input. NUM must be one of the values {4, 8, 16}",
            metavar="NUM")
        parser.add_option(
            "--table-idx-width",
            action="store", type="int", dest="table_idx_width",
            help="use NUM bits to index the CRC table; NUM must be one of the values {1, 2, 4, 8}",
            metavar="NUM")
        parser.add_option(
            "--symbol-prefix",
            action="store", type="string", dest="symbol_prefix",
            help="when generating source code, use STRING as prefix to the exported C symbols",
            metavar="STRING")
        parser.add_option(
            "--crc-type",
            action="store", type="string", dest="crc_type",
            help="when generating source code, use STRING as crc_t type",
            metavar="STRING")
        parser.add_option(
            "--include-file",
            action="append", type="string", dest="include_files",
            help="when generating source code, include also FILE as header file; "
            "can be specified multiple times",
            metavar="FILE")
        parser.add_option(
            "-o", "--output",
            action="store", type="string", dest="output_file",
            help="write the generated code to file instead to stdout",
            metavar="FILE")

        (options, args) = parser.parse_args(argv)

        if options.c_std != None:
            std = options.c_std.upper()
            if std == "ANSI" or std == "C89":
                self.c_std = "C89"
            elif std == "C99":
                self.c_std = std
            else:
                self.__error("unknown C standard {0:s}".format(options.c_std))

        undefined_params = []
        if options.width != None:
            self.width = options.width
        else:
            undefined_params.append("--width")
        if options.poly != None:
            self.poly = options.poly
        else:
            undefined_params.append("--poly")
        if options.reflect_in != None:
            self.reflect_in = options.reflect_in
        else:
            undefined_params.append("--reflect-in")
        if options.xor_in != None:
            self.xor_in = options.xor_in
        else:
            undefined_params.append("--xor-in")
        if options.reflect_out != None:
            self.reflect_out = options.reflect_out
        else:
            undefined_params.append("--reflect-out")
        if options.xor_out != None:
            self.xor_out = options.xor_out
        else:
            undefined_params.append("--xor-out")

        if options.table_idx_width != None:
            if options.table_idx_width in set((1, 2, 4, 8)):
                self.tbl_idx_width = options.table_idx_width
                self.tbl_width = 1 << options.table_idx_width
            else:
                self.__error("unsupported table-idx-width {0:d}".format(options.table_idx_width))

        if self.width != None:
            if self.width <= 0:
                self.__error("Width must be strictly positive")
            self.msb_mask = 0x1 << (self.width - 1)
            self.mask = ((self.msb_mask - 1) << 1) | 1
            if self.poly != None:
                self.poly = self.poly & self.mask
            if self.xor_in != None:
                self.xor_in = self.xor_in & self.mask
            if self.xor_out != None:
                self.xor_out = self.xor_out & self.mask
        else:
            self.msb_mask = None
            self.mask = None

        if self.width == None or \
                self.poly == None or \
                self.reflect_in == None or \
                self.xor_in == None or \
                self.reflect_out == None or \
                self.xor_out == None:
            self.undefined_crc_parameters = True
        else:
            self.undefined_crc_parameters = False

        if options.slice_by != None:
            if options.slice_by in set((4, 8, 16)):
                self.slice_by = options.slice_by
            else:
                self.__error("unsupported slice-by {0:d}".format(options.slice_by))
            if self.undefined_crc_parameters:
                self.__error("slice-by is only implemented for fully defined models")
            if self.tbl_idx_width != 8:
                self.__error("slice-by is only implemented for table-idx-width=8")
            # FIXME tp: Fix corner cases and disable the following tests
            if self.width < 8:
                self.__warning("disabling slice-by for width {0}".format(self.width))
                self.slice_by = 1
            if self.width < 16:
                self.__warning("disabling slice-by for width {0}".format(self.width))
                self.slice_by = 1
            if self.width > 32:
                self.__warning("disabling slice-by for width {0}".format(self.width))
                self.slice_by = 1
            if not self.reflect_in:
                self.__warning("disabling slice-by for non-reflected algorithm")
                self.slice_by = 1
# FIXME tp: reintroduce this?
#            if self.width % 8 != 0:
#                self.__error("slice-by is only implemented for width multiples of 8")
#            if options.slice_by < self.width / 8:
#                self.__error("slice-by must be greater or equal width / 8")
            if self.c_std == "C89":
                self.__error("--slice-by not supported for C89")

        if options.algorithm != None:
            alg = options.algorithm.lower()
            if alg in set(["bit-by-bit", "bbb", "all"]):
                self.algorithm |= self.algo_bit_by_bit
            if alg in set(["bit-by-bit-fast", "bbf", "all"]):
                self.algorithm |= self.algo_bit_by_bit_fast
            if alg in set(["table-driven", "tbl", "all"]):
                self.algorithm |= self.algo_table_driven
            if self.algorithm == 0:
                self.__error("unknown algorithm {0:s}".format(options.algorithm))

        if options.symbol_prefix != None:
            self.symbol_prefix = options.symbol_prefix
        if options.include_files != None:
            self.include_files = options.include_files
        if options.crc_type != None:
            self.crc_type = options.crc_type
        if options.output_file != None:
            self.output_file = options.output_file
        op_count = 0
        if options.check_string != None:
            self.action = self.action_check_str
            self.check_string = options.check_string
            op_count += 1
        if options.check_hexstring != None:
            self.action = self.action_check_hex_str
            self.check_string = options.check_hexstring
            op_count += 1
        if options.check_file != None:
            self.action = self.action_check_file
            self.check_file = options.check_file
            op_count += 1
        if options.generate != None:
            arg = options.generate.lower()
            if arg == 'h':
                self.action = self.action_generate_h
            elif arg == 'c':
                self.action = self.action_generate_c
            elif arg == 'c-main':
                self.action = self.action_generate_c_main
            elif arg == 'table':
                self.action = self.action_generate_table
            else:
                self.__error("don't know how to generate {0:s}".format(options.generate))
            op_count += 1

            if self.action == self.action_generate_table:
                if self.algorithm & self.algo_table_driven == 0:
                    self.__error("the --generate table option is incompatible "
                        "with the --algorithm option")
                self.algorithm = self.algo_table_driven
            elif self.algorithm not in set(
                    [self.algo_bit_by_bit, self.algo_bit_by_bit_fast, self.algo_table_driven]):
                self.__error("select an algorithm to be used in the generated file")
        else:
            if self.tbl_idx_width != 8:
                self.__warning("reverting to Table Index Width = 8 "
                    "for internal CRC calculation")
                self.tbl_idx_width = 8
                self.tbl_width = 1 << options.table_idx_width
        if op_count == 0:
            self.action = self.action_check_str
        if op_count > 1:
            self.__error("too many actions specified")

        if len(args) != 0:
            self.__error("unrecognized argument(s): {0:s}".format(" ".join(args)))

        def_params_acts = (self.action_check_str, self.action_check_hex_str,
                           self.action_check_file, self.action_generate_table)
        if self.undefined_crc_parameters and self.action in set(def_params_acts):
            self.__error("undefined parameters: Add {0:s} or use --model"
                .format(", ".join(undefined_params)))
        self.verbose = options.verbose