From 3233dc96b1fa2f736f9e8db5990861f24c2d5d40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20S=FCltrop?= Date: Mon, 30 Jul 2012 15:08:37 +0200 Subject: [PATCH] Added pycrc library (MIT License) for CRC calculations to the repository. --- pycrc/COPYING | 19 + pycrc/ChangeLog | 432 ++++++++++++ pycrc/README | 66 ++ pycrc/crc_algorithms.py | 231 +++++++ pycrc/crc_algorithms.pyc | Bin 0 -> 5880 bytes pycrc/crc_lexer.py | 301 +++++++++ pycrc/crc_lexer.pyc | Bin 0 -> 6945 bytes pycrc/crc_models.py | 370 ++++++++++ pycrc/crc_models.pyc | Bin 0 -> 5051 bytes pycrc/crc_opt.py | 398 +++++++++++ pycrc/crc_opt.pyc | Bin 0 -> 11745 bytes pycrc/crc_parser.py | 418 ++++++++++++ pycrc/crc_parser.pyc | Bin 0 -> 8714 bytes pycrc/crc_symtable.py | 1354 +++++++++++++++++++++++++++++++++++++ pycrc/crc_symtable.pyc | Bin 0 -> 37808 bytes pycrc/doc/Makefile | 26 + pycrc/doc/pycrc.1 | 531 +++++++++++++++ pycrc/doc/pycrc.html | 247 +++++++ pycrc/doc/pycrc.xml | 582 ++++++++++++++++ pycrc/pycrc.py | 253 +++++++ pycrc/pycrc.pyc | Bin 0 -> 6939 bytes pycrc/test/main.c | 283 ++++++++ pycrc/test/performance.sh | 152 +++++ pycrc/test/test.sh | 473 +++++++++++++ 24 files changed, 6136 insertions(+) create mode 100644 pycrc/COPYING create mode 100644 pycrc/ChangeLog create mode 100644 pycrc/README create mode 100644 pycrc/crc_algorithms.py create mode 100644 pycrc/crc_algorithms.pyc create mode 100644 pycrc/crc_lexer.py create mode 100644 pycrc/crc_lexer.pyc create mode 100644 pycrc/crc_models.py create mode 100644 pycrc/crc_models.pyc create mode 100644 pycrc/crc_opt.py create mode 100644 pycrc/crc_opt.pyc create mode 100644 pycrc/crc_parser.py create mode 100644 pycrc/crc_parser.pyc create mode 100644 pycrc/crc_symtable.py create mode 100644 pycrc/crc_symtable.pyc create mode 100644 pycrc/doc/Makefile create mode 100644 pycrc/doc/pycrc.1 create mode 100644 pycrc/doc/pycrc.html create mode 100644 pycrc/doc/pycrc.xml create mode 100644 pycrc/pycrc.py create mode 100644 pycrc/pycrc.pyc create mode 100644 pycrc/test/main.c create mode 100644 pycrc/test/performance.sh create mode 100644 pycrc/test/test.sh diff --git a/pycrc/COPYING b/pycrc/COPYING new file mode 100644 index 0000000..c7eb2e8 --- /dev/null +++ b/pycrc/COPYING @@ -0,0 +1,19 @@ +Copyright (c) 2006-2012, Thomas Pircher + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/pycrc/ChangeLog b/pycrc/ChangeLog new file mode 100644 index 0000000..7ca2502 --- /dev/null +++ b/pycrc/ChangeLog @@ -0,0 +1,432 @@ +# +# Version 0.7.10, 2012-02-13 +# + +2012-02-08 Thomas Pircher + + * crc_symtable.py: + Bad-looking C code generated; make sure the bit-by-bit(fast) code does not + contain two instructions on one line. Thanks to "intgr" for the fix. + + * crc_symtable.py: + Some small code clean-up: use set() when appropriate. + +2011-12-19 Thomas Pircher + + * crc_models.py: + * doc/pycrc.xml: + Added the models crc-12-3gpp, crc-16-genibus, crc-32-bzip2 and crc-64-xz. + Taken from Greg Cook's Catalogue of parametrised CRC algorithms: + http://regregex.bbcmicro.net/crc-catalogue.htm + +2011-12-14 Thomas Pircher + + * doc/pycrc.xml: + Fixed a mistake in the man page that still used the old model name + crc-32mpeg instead of crc-32-mpeg. Thanks to Marek Erban. + +# +# Version 0.7.9, 2011-12-08 +# + +2011-12-08 Thomas Pircher + + * crc_symtable.py: + Fixed a bug in the generated C89 code that included stdint.h. + Thanks to Frank (ftheile). + Closes issue 3454356. + +2011-11-08 Thomas Pircher + + * crc_symtable.py: + Fixed a bug in the generated C89 code when using a 64 bit CRC. + + * pycrc.py: + Using the --verbose option made pycrc quit without error message. + +# +# Version 0.7.8, 2011-07-10 +# + +2011-07-10 Thomas Pircher + + * crc_symtable.py: + When generating C code for the C89 or ANSI standard, don't include . + This closes issue 3338930 + + * crc_symtable.py: + If no output file name is given while generating a C file, then pycrc will + #include a hypothetical pycrc.h file instead of a stdout.h file. + Also, added a comment on that line to make debugging easier. + Closes issue 3325109. + + * crc_symtable.py: + Removed unused variable "this_option_optind" in the generated option parser. + +# +# Version 0.7.7, 2011-02-11 +# + +2011-02-11 Thomas Pircher + + * all files: + Updated the copyright year. + Fixed some coding style issues found by pylint and pychecker. + +2010-12-13 Thomas Pircher + + * crc_opt.py: + Substituted the deprecated function atoi() with int(). Closes issue 3136566. + Thanks to Tony Smith. + + * doc/pycrc.xml: + Updated the documentation using Windows-style calls to the Python interpreter. + +# +# Version 0.7.6, 2010-10-21 +# + +2010-10-21 Thomas Pircher + + * crc_symtable.py: + Fixed a minor bug in the command line parsing of the generated main function. + +2010-08-07 Thomas Pircher + + * crc_symtable.py, crc_parser.py, crc_lexer.py: + Rewritten macro parser from scratch. Simplified the macro language. + +2010-08-03 Thomas Pircher + + * crc_symtable.py: changed a simple division (/) to a integer division (//) + for Python3 compatibility. + +# +# Version 0.7.5, 2010-03-28 +# + +2010-03-27 Thomas Pircher + + * crc_symtable.py: + C/C++ code can now be generated for the table-driven algorithm with widths + that are not byte-ligned or less than 8. + + W A R N I N G: introduced new variable crc_shift, member of the crc_cfg_t + structure, that must be initialised manually when the width + was undefined during C/C++ code generation. + +2010-03-27 Thomas Pircher + + * crc_opt.py, crc_algorithms.py: + Python implementation of the table-driven algorithm can handle widths less + than 8. + * crc_symtable.py: + Suppressed warnings of unused cfg structure on partially defined models. + +2010-03-26 Thomas Pircher + + * pycrc.py, crc_opt.py, crc_algorithms.py, crc_symtable.py: + Removed half-baken and confusing --direct option. + +2010-02-10 Thomas Pircher + + * pycrc.py, crc_opt.py: minor code cleanup. + +# +# Version 0.7.4, 2010-01-24 +# + +2010-01-24 Thomas Pircher + + * crc_models.py: changed the xor-in value of the crc-64-jones model. + * crc_models.py: Set xmodem parameters equal to the zmodem params. + +2009-12-29 Thomas Pircher + + * pycrc.py, crc_opt.py, crc_parser: uniform error messages. + * crc_opt.py: added a warning for even polynoms. + +2009-11-12 Thomas Pircher + + * crc_models.py: added crc-16-modbus. Closes issue 2896611. + +2009-11-07 Thomas Pircher + + * crc_opt.py: Fix for unused variable argv. + Closes issue 2893224. Thanks to Marko von Oppen. + +# +# Version 0.7.3, 2009-10-25 +# + +2009-10-25 Thomas Pircher + + * crc_models.py: renamed crc-32mpeg to crc-32-mpeg. + +2009-10-19 Thomas Pircher + + * crc_models.py: added crc-64-jones CRC model. Thanks to Waterspirit. + +# +# Version 0.7.2, 2009-09-30 +# + +2009-09-30 Thomas Pircher + + * pycrc.py: fixed a bug that caused the result of the Python table-driven + code not being evaluated at all. + Closes issue 2870630. Thanks to Ildar Muslukhov. + +# +# Version 0.7.1, 2009-04-05 +# + +2009-03-26 Thomas Pircher + + * crc_models.py: added crc-32mpeg. Thanks to Thomas Edwards. + +# +# Version 0.7, 2009-02-27 +# + +2009-02-15 Thomas Pircher + + * crc_algorithms.py: code tidy-up. + * crc_algorithms.py, crc_opt.py: added --direct option. + * crc_symtable.py: added --direct option for the generated code. + +2009-02-03 Thomas Pircher + + * crc_opt.py: added --check-hexstring option. Closes issue 2545183. + Thanks to Arnim Littek. + +2009-01-31 Thomas Pircher + + * crc_opt.py: added a check for extra arguments on the command line. + Closes issue 2545185. Thanks to Arnim Littek. + +2008-12-24 Thomas Pircher + + * doc/pycrc.xml: Added one more example. + +# +# Version 0.6.7, 2008-12-11 +# + +2008-12-11 Thomas Pircher + + * all files: run Python's 2to3 script on the files. + * all files: check the code on a x64 platform. + * crc_opt.py: fixed a bug that raised an exception when an unknown model + was selected. + +# +# Version 0.6.6, 2008-06-05 +# + +2008-06-05 Thomas Pircher + + * crc_symtable.py: fixed a bug in the print_params function. Closes issue + 1985197. Thanks to Artur Lipowski. + +2008-03-03 Thomas Pircher + + * pycrc.xml: new license: Creative Commons Attribution-Share Alike 3.0 + Unported License. + +# +# Version 0.6.5, 2008-03-03 +# + +2008-03-02 Thomas Pircher + + * crc_models.py: added dallas-1-wire 8 bit CRC. + +2008-02-07 Thomas Pircher + + * crc_symtable.py: fixed a problem with the generated code for + bit-by-bit-fast algorithms. Thanks to Hans Bacher. + +2007-12-19 Thomas Pircher + + * crc_models.py: added r-crc-16 model (DECT (cordless digital standard) + packets A-field according to ETSI EN 300 175-3 v2.1.1). + Thanks to "raimondo". + +2007-12-10 Thomas Pircher + + * crc_symtable.py: added extern "C" declaration to the generated C header + file. Thanks to Nathan Royer. + +2007-12-10 Thomas Pircher + + * crc_algorithms.py: changed the API to take the CRC model direct as + parameter. Deleted the need for an obscure "opt" object. + +2007-12-09 Thomas Pircher + + * crc_opt.py: added --crc-type and --include-file options. + * crc_models.py: added new file to handle CRC models + +# +# Version 0.6.4, 2007-12-05 +# + +2007-12-05 Thomas Pircher + + * crc_symtable.py: fixed a bug in the code generator for the table-driven + algorithm. Thanks to Tom McDermott. Closes issue 1843774 + +# +# Version 0.6.3, 2007-10-13 +# + +2007-10-13 Thomas Pircher + + * crc_symtable.py: fixed some portability problems in the generated code. + Thanks to Helmut Bauer. Closes issue 1812894 + +2007-09-10 Thomas Pircher + + * crc_opt.py: added new models: crc-5, crc-15, crc-16-usb, crc-24, crc-64. + The new models are taken from Ray Burr's CrcMoose. + * pycrc.py: --check-file works now with --width < 8. Closes issue 1794343 + * pycrc.py: Removed unnecessary restriction on the width when using the + bit-by-bit-fast algorithm. Closes issue 1794344 + +# +# Version 0.6.2, 2007-08-25 +# + +2007-08-25 Thomas Pircher + + * crc_opt.py: the parameter to --check-string was ignored. Closes issue + 1781637 + * pycrc.py: the parameter to --check-string was ignored. Closes issue + 1781637 + +2007-08-18 Thomas Pircher + + * crc_symtable.py: simplified the table-driven code. Closes issue 1727128 + +2007-08-18 Thomas Pircher + + * crc_parser.py: changed the macro language syntax to a better format + * crc_lexer.py: changed the macro language syntax to a better format + * crc_symtable.py: changed the macro language syntax to a better format + * crc_parser.py: Renamed crc_code_gen.py to crc_parser.py + * all files: Documented thge usage of the crc_* modules + +# +# Version 0.6.1, 2007-08-12 +# + +2007-08-12 Thomas Pircher + + * test/test.sh: Added test for C89 compilation + * test/main.c: Added a test case to loop over the input bytes one by one + * crc_symtable.py: Bugfix in the source code generator for C89: + Compilation error due to mismatch of parameters in the crc_finalize + funtion + * crc_symtable.py: Changes related to 919107: Code generator includes + reflect() function even if not needed + +2007-07-22 Thomas Pircher + + * crc_symtable.py: Fixed a typo in the C89 source code generator. + Thanks to Helmut Bauer + +2007-06-10 Thomas Pircher + + * all files: Tidied up the documentation + * all files: Code cleanup + +2007-05-15 Thomas Pircher + + * crc_opt.py: Deleted obsolete options + +# +# Version 0.6, 2007-05-21 +# + +2007-05-15 Thomas Pircher + + * crc_opt.py: Added the --std option to generate C89 (ANSI) compliant code + * crc_symtable.py: Reduced the size of the symbol table by re-arranging + items + +2007-05-13 Thomas Pircher + + * test/test.sh: Added a new check to the test script which validate all + possible combination of undefined parameters + * crc_code_gen.py: Made the generated main function cope with command line + arguments + +2007-05-12 Thomas Pircher + + * pycrc.py: Added the --generate table option + * pycrc.py: Added a template engine for the code generation. Split up + pycrc.py into smaller modules + +2007-04-11 Thomas Pircher + + * pycrc.py: Added obsolete options again tor legacy reasons. + Added a better handling of the --model parameter. + +2007-04-07 Thomas Pircher + + * pycrc.py: Changed licence to the MIT licence. This makes the additional + clause for generated source code obsolete. + Changed all command line options with underscores to hyphen (e.g. + table_driven becomes table-driven). + Added the option --generate which obsoletes the old options --generate_c + --generate_h etc. + +# +# Version 0.5, 2007-03-25 +# + +2007-03-25 Thomas Pircher + + * pycrc.py: Fixed bug 1686404: unhandled exception when called with + both options --table_idx_width and --check_file + * pycrc.py: Eliminated useless declaration of crc_reflect, when not used + * pycrc.py: Corrected typos in the documentation + +# +# Version 0.4, 2007-01-26 +# + +2007-01-27 Thomas Pircher + + * pycrc.py: Eliminated needless documentation of not generated functions + +2007-01-23 Thomas Pircher + + * pycrc.py: Added more parameter sets (now supported: crc-8, crc-16, citt, + kermit, x-25, xmodem, zmodem, crc-32, crc-32c, posix, jam, xfer) from + http://homepages.tesco.net/~rainstorm/crc-catalogue.htm + * doc/pycrc.xml: Many corrections to the manual (thanks Francesca) + Documented the new parameter sets + * test/test.sh: added some new tests, disabled the random loop + +2007-01-21 Thomas Pircher + + * pycrc.py: Added Doxygen documentation strings to the functions. + Added the --symbol_prefix option + Added the --check_file option + + * doc/pycrc.xml: Corrected many typos and bad phrasing (still a lot to do) + Documented the --symbol_prefix option + +2007-01-17 Thomas Pircher + + * test/test.sh: Added a non-regression test on the generated C source + +# +# Version 0.3, 2007-01-14 +# + +2007-01-14 Thomas Pircher + + * pycrc.py: first public release pycrc v0.3 diff --git a/pycrc/README b/pycrc/README new file mode 100644 index 0000000..d5bdfd2 --- /dev/null +++ b/pycrc/README @@ -0,0 +1,66 @@ + + + _ __ _ _ ___ _ __ ___ + | '_ \| | | |/ __| '__/ __| + | |_) | |_| | (__| | | (__ + | .__/ \__, |\___|_| \___| + |_| |___/ + + + http://www.tty1.net/pycrc/ + + +pycrc is a free, easy to use Cyclic Redundancy Check (CRC) calculator and +source code generator. + + + +Installation +============ + +pycrc requires Python 2.4 or later. Python 3.x is supported. + +This program doesn't need any particular installation. The script can be +called from any directory. +Simply call the python interpreter with the script as parameter: + +python pycrc.py [options] + +On UNIX-like systems, you might want to make the script executable: + +chmod +x pycrc.py + +Then the script can be called like an application. +./pycrc.py [options] + + +Getting help +============ + +If you are new to pycrc and want to generate C code, start with the tutorial +http://www.tty1.net/pycrc/tutorial_en.html + +The manual page (http://www.tty1.net/pycrc/pycrc.html) explains the command +line options and gives some examples how to use pycrc. + +If you have questions about using pycrc which is not answered in a satisfactory +way by the documentation, please send a mail to the pycrc user mailing list +. The list info page is available at +https://lists.sourceforge.net/lists/listinfo/pycrc-users +Due to excessive spamming a subscription is required to post on the list. + +If you have found a bug in pycrc, please take the time and file it to the issue +tracker at https://sourceforge.net/tracker/?group_id=186891 +Thanks for your collaboration. + +Also see http://www.tty1.net/pycrc/faq.html for frequently asked questions. + + +Copyright of the generated source code +====================================== + +Prior to v0.6, pycrc was released under the GPL and an additional addition to +the licence was required to permit to use the generated source code in products +with a OSI unapproved licence. As of version 0.6, pycrc is released under the +terms of the MIT licence and such an additional clause to the licence is no +more required. diff --git a/pycrc/crc_algorithms.py b/pycrc/crc_algorithms.py new file mode 100644 index 0000000..90af6cd --- /dev/null +++ b/pycrc/crc_algorithms.py @@ -0,0 +1,231 @@ +# -*- coding: Latin-1 -*- + +# pycrc -- parametrisable CRC calculation utility and C source code generator +# +# Copyright (c) 2006-2012 Thomas Pircher +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + + +""" +CRC algorithms implemented in Python. +If you want to study the Python implementation of the CRC routines, then this +is a good place to start from. + +The algorithms Bit by Bit, Bit by Bit Fast and Table-Driven are implemented. + +This module can also be used as a library from within Python. + +Examples +======== + +This is an example use of the different algorithms: + +>>> from crc_algorithms import Crc +>>> +>>> crc = Crc(width = 16, poly = 0x8005, +... reflect_in = True, xor_in = 0x0000, +... reflect_out = True, xor_out = 0x0000) +>>> print("0x%x" % crc.bit_by_bit("123456789")) +>>> print("0x%x" % crc.bit_by_bit_fast("123456789")) +>>> print("0x%x" % crc.table_driven("123456789")) +""" + +# Class Crc +############################################################################### +class Crc(object): + """ + A base class for CRC routines. + """ + + # Class constructor + ############################################################################### + def __init__(self, width, poly, reflect_in, xor_in, reflect_out, xor_out, table_idx_width = None): + """The Crc constructor. + + The parameters are as follows: + width + poly + reflect_in + xor_in + reflect_out + xor_out + """ + self.Width = width + self.Poly = poly + self.ReflectIn = reflect_in + self.XorIn = xor_in + self.ReflectOut = reflect_out + self.XorOut = xor_out + self.TableIdxWidth = table_idx_width + + self.MSB_Mask = 0x1 << (self.Width - 1) + self.Mask = ((self.MSB_Mask - 1) << 1) | 1 + if self.TableIdxWidth != None: + self.TableWidth = 1 << self.TableIdxWidth + else: + self.TableIdxWidth = 8 + self.TableWidth = 1 << self.TableIdxWidth + + self.DirectInit = self.XorIn + self.NonDirectInit = self.__get_nondirect_init(self.XorIn) + if self.Width < 8: + self.CrcShift = 8 - self.Width + else: + self.CrcShift = 0 + + + # function __get_nondirect_init + ############################################################################### + def __get_nondirect_init(self, init): + """ + return the non-direct init if the direct algorithm has been selected. + """ + crc = init + for i in range(self.Width): + bit = crc & 0x01 + if bit: + crc^= self.Poly + crc >>= 1 + if bit: + crc |= self.MSB_Mask + return crc & self.Mask + + + # function reflect + ############################################################################### + def reflect(self, data, width): + """ + reflect a data word, i.e. reverts the bit order. + """ + x = data & 0x01 + for i in range(width - 1): + data >>= 1 + x = (x << 1) | (data & 0x01) + return x + + + # function bit_by_bit + ############################################################################### + def bit_by_bit(self, in_str): + """ + Classic simple and slow CRC implementation. This function iterates bit + by bit over the augmented input message and returns the calculated CRC + value at the end. + """ + register = self.NonDirectInit + for c in in_str: + octet = ord(c) + if self.ReflectIn: + octet = self.reflect(octet, 8) + for i in range(8): + topbit = register & self.MSB_Mask + register = ((register << 1) & self.Mask) | ((octet >> (7 - i)) & 0x01) + if topbit: + register ^= self.Poly + + for i in range(self.Width): + topbit = register & self.MSB_Mask + register = ((register << 1) & self.Mask) + if topbit: + register ^= self.Poly + + if self.ReflectOut: + register = self.reflect(register, self.Width) + return register ^ self.XorOut + + + # function bit_by_bit_fast + ############################################################################### + def bit_by_bit_fast(self, in_str): + """ + This is a slightly modified version of the bit-by-bit algorithm: it + does not need to loop over the augmented bits, i.e. the Width 0-bits + wich are appended to the input message in the bit-by-bit algorithm. + """ + register = self.DirectInit + for c in in_str: + octet = ord(c) + if self.ReflectIn: + octet = self.reflect(octet, 8) + for i in range(8): + topbit = register & self.MSB_Mask + if octet & (0x80 >> i): + topbit ^= self.MSB_Mask + register <<= 1 + if topbit: + register ^= self.Poly + register &= self.Mask + if self.ReflectOut: + register = self.reflect(register, self.Width) + return register ^ self.XorOut + + + # function gen_table + ############################################################################### + def gen_table(self): + """ + This function generates the CRC table used for the table_driven CRC + algorithm. The Python version cannot handle tables of an index width + other than 8. See the generated C code for tables with different sizes + instead. + """ + table_length = 1 << self.TableIdxWidth + tbl = [0] * table_length + for i in range(table_length): + register = i + if self.ReflectIn: + register = self.reflect(register, self.TableIdxWidth) + register = register << (self.Width - self.TableIdxWidth + self.CrcShift) + for j in range(self.TableIdxWidth): + if register & (self.MSB_Mask << self.CrcShift) != 0: + register = (register << 1) ^ (self.Poly << self.CrcShift) + else: + register = (register << 1) + if self.ReflectIn: + register = self.reflect(register >> self.CrcShift, self.Width) << self.CrcShift + tbl[i] = register & (self.Mask << self.CrcShift) + return tbl + + + # function table_driven + ############################################################################### + def table_driven(self, in_str): + """ + The Standard table_driven CRC algorithm. + """ + tbl = self.gen_table() + + register = self.DirectInit << self.CrcShift + if not self.ReflectIn: + for c in in_str: + tblidx = ((register >> (self.Width - self.TableIdxWidth + self.CrcShift)) ^ ord(c)) & 0xff + register = ((register << (self.TableIdxWidth - self.CrcShift)) ^ tbl[tblidx]) & (self.Mask << self.CrcShift) + register = register >> self.CrcShift + else: + register = self.reflect(register, self.Width + self.CrcShift) << self.CrcShift + for c in in_str: + tblidx = ((register >> self.CrcShift) ^ ord(c)) & 0xff + register = ((register >> self.TableIdxWidth) ^ tbl[tblidx]) & (self.Mask << self.CrcShift) + register = self.reflect(register, self.Width + self.CrcShift) & self.Mask + + if self.ReflectOut: + register = self.reflect(register, self.Width) + return register ^ self.XorOut + diff --git a/pycrc/crc_algorithms.pyc b/pycrc/crc_algorithms.pyc new file mode 100644 index 0000000000000000000000000000000000000000..124b92f31f657469c9e77115192c761438f8667e GIT binary patch literal 5880 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 literal 0 HcmV?d00001 diff --git a/pycrc/crc_lexer.py b/pycrc/crc_lexer.py new file mode 100644 index 0000000..ea2051b --- /dev/null +++ b/pycrc/crc_lexer.py @@ -0,0 +1,301 @@ +# -*- coding: Latin-1 -*- + +# pycrc -- parametrisable CRC calculation utility and C source code generator +# +# Copyright (c) 2006-2012 Thomas Pircher +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + + +""" +Lexical analyzer for pycrc. This module is used internally by pycrc for the +macro processing and code generation. + +A basic example of how the lexer is used: + + from crc_lexer import Lexer + + input_str = "the input string to parse" + lex = Lexer() + lex.set_str(input_str) + while True: + tok = lex.peek() + if tok == lex.tok_EOF: + break + else: + print("%4d: %s\n" % (tok, lex.text)) + lex.advance() +""" + +import re + + +# Class Lexer +############################################################################### +class Lexer(object): + """ + A lexical analyser base class. + """ + + tok_unknown = 0 + tok_EOF = 1 + tok_gibberish = 10 + tok_identifier = 11 + tok_block_open = 12 + tok_block_close = 13 + tok_num = 20 + tok_str = 21 + tok_par_open = 22 + tok_par_close = 23 + tok_op = 24 + tok_and = 25 + tok_or = 26 + + state_gibberish = 0 + state_expr = 1 + + + # Class constructor + ############################################################################### + def __init__(self, input_str = ""): + """ + The class constructor. + """ + self.re_id = re.compile("^\\$[a-zA-Z][a-zA-Z0-9_-]*") + self.re_num = re.compile("^(0[xX][0-9a-fA-F]+|[0-9]+)") + self.re_op = re.compile("<=|<|==|!=|>=|>") + self.re_str = re.compile("\"?([a-zA-Z0-9_-]+)\"?") + self.set_str(input_str) + self.state = self.state_gibberish + + + # function set_str + ############################################################################### + def set_str(self, input_str): + """ + Set the parse input string. + """ + self.input_str = input_str + self.text = "" + self.next_token = None + + + # function peek + ############################################################################### + def peek(self): + """ + Return the next token, without taking it away from the input_str. + """ + if self.next_token == None: + self.next_token = self._parse_next() + return self.next_token + + + # function advance + ############################################################################### + def advance(self, skip_nl = False): + """ + Discard the current symbol from the input stream and advance to the + following characters. If skip_nl is True, then skip also a following + newline character. + """ + self.next_token = None + if skip_nl and len(self.input_str) > 1 and self.input_str[0] == "\n": + self.input_str = self.input_str[1:] + + + # function delete_spaces + ############################################################################### + def delete_spaces(self, skip_unconditional = True): + """ + Delete spaces in the input string. + If skip_unconditional is False, then skip the spaces only if followed + by $if() $else() or $elif(). + """ + new_input = self.input_str.lstrip(" \t") + + # check for an identifier + m = self.re_id.match(new_input) + if m != None: + text = m.group(0)[1:] + # if the identifier is a reserved keyword, skip the spaces. + if (text == "if" or text == "elif" or text == "else"): + skip_unconditional = True + if skip_unconditional: + self.next_token = None + self.input_str = new_input + + + # function prepend + ############################################################################### + def prepend(self, in_str): + """ + Prepend the parameter to to the input string. + """ + self.input_str = in_str + self.input_str + + + # function set_state + ############################################################################### + def set_state(self, new_state): + """ + Set the new state for the lexer. + This changes the behaviour of the lexical scanner from normal operation + to expression scanning (within $if () expressions) and back. + """ + self.state = new_state + self.next_token = None + + + # function _parse_next + ############################################################################### + def _parse_next(self): + """ + Parse the next token, update the state variables and take the consumed + text from the imput stream. + """ + if len(self.input_str) == 0: + return self.tok_EOF + + if self.state == self.state_gibberish: + return self._parse_gibberish() + if self.state == self.state_expr: + return self._parse_expr() + return self.tok_unknown + + + # function _parse_gibberish + ############################################################################### + def _parse_gibberish(self): + """ + Parse the next token, update the state variables and take the consumed + text from the imput stream. + """ + # check for an identifier + m = self.re_id.match(self.input_str) + if m != None: + self.text = m.group(0)[1:] + self.input_str = self.input_str[m.end():] + return self.tok_identifier + + if len(self.input_str) > 1: + # check for "{:" + if self.input_str[0:2] == "{:": + self.text = self.input_str[0:2] + self.input_str = self.input_str[2:] + return self.tok_block_open + # check for ":}" + if self.input_str[0:2] == ":}": + self.text = self.input_str[0:2] + self.input_str = self.input_str[2:] + return self.tok_block_close + # check for "$$" + if self.input_str[0:2] == "$$": + self.text = self.input_str[0:1] + self.input_str = self.input_str[2:] + return self.tok_gibberish + # check for malformed "$" + if self.input_str[0] == "$": + self.text = self.input_str[0:1] + # self.input_str = self.input_str[1:] + return self.tok_unknown + + # the character is gibberish. + # find the position of the next special character. + pos = self.input_str.find("$") + tmp = self.input_str.find("{:") + if pos < 0 or (tmp >= 0 and tmp < pos): + pos = tmp + tmp = self.input_str.find(":}") + if pos < 0 or (tmp >= 0 and tmp < pos): + pos = tmp + + if pos < 0 or len(self.input_str) == 1: + # neither id nor block start nor block end found: + # the whole text is just gibberish. + self.text = self.input_str + self.input_str = "" + else: + self.text = self.input_str[:pos] + self.input_str = self.input_str[pos:] + return self.tok_gibberish + + + # function _parse_expr + ############################################################################### + def _parse_expr(self): + """ + Parse the next token, update the state variables and take the consumed + text from the imput stream. + """ + # skip whitespaces + pos = 0 + while pos < len(self.input_str) and self.input_str[pos] == ' ': + pos = pos + 1 + if pos > 0: + self.input_str = self.input_str[pos:] + + if len(self.input_str) == 0: + return self.tok_EOF + + m = self.re_id.match(self.input_str) + if m != None: + self.text = m.group(0)[1:] + self.input_str = self.input_str[m.end():] + return self.tok_identifier + + m = self.re_num.match(self.input_str) + if m != None: + self.text = m.group(0) + self.input_str = self.input_str[m.end():] + return self.tok_num + + m = self.re_op.match(self.input_str) + if m != None: + self.text = m.string[:m.end()] + self.input_str = self.input_str[m.end():] + return self.tok_op + + if self.input_str[:4] == "and ": + self.text = "and" + self.input_str = self.input_str[len(self.text) + 1:] + return self.tok_and + + if self.input_str[:3] == "or ": + self.text = "or" + self.input_str = self.input_str[len(self.text) + 1:] + return self.tok_or + + m = self.re_str.match(self.input_str) + if m != None: + self.text = m.group(1) + self.input_str = self.input_str[m.end():] + return self.tok_str + + if self.input_str[0] == "(": + self.text = self.input_str[0] + self.input_str = self.input_str[len(self.text):] + return self.tok_par_open + + if self.input_str[0] == ")": + self.text = self.input_str[0] + self.input_str = self.input_str[len(self.text):] + return self.tok_par_close + + return self.tok_unknown diff --git a/pycrc/crc_lexer.pyc b/pycrc/crc_lexer.pyc new file mode 100644 index 0000000000000000000000000000000000000000..88e73b9f6cf5f196300de42936bcf418b19ef09c GIT binary patch literal 6945 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 myc||Z~rd@kJN?lM``H$vQcY{Z-Q%ezQWcj z$y+4XNp6s^i1XG+zDshAgej=^brNb(KDv1<8Ku^hdfekjY403~OR`9^M8b4Yf`doR zjC3olukiKLgB0~GT;@%X>O{3tMX~zAKlV&Dj@D*sGmY8CsambpsGX=?wPElUW_yg? e;zsG_BOT@<`|wK?!(6kbxIqt>qg1Ulrv3#H_nK7z literal 0 HcmV?d00001 diff --git a/pycrc/crc_models.py b/pycrc/crc_models.py new file mode 100644 index 0000000..00f2805 --- /dev/null +++ b/pycrc/crc_models.py @@ -0,0 +1,370 @@ +# -*- coding: Latin-1 -*- + +# pycrc -- parametrisable CRC calculation utility and C source code generator +# +# Copyright (c) 2006-2012 Thomas Pircher +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + + +""" +Collection of CRC models. This module contains the CRC models known to pycrc. + +To print the parameters of a particular model: + + from crc_models import CrcModels + + models = CrcModels() + print(models.getList()) + m = models.getParams("crc-32") + if m != None: + print("Width: %(width)s" % m) + print("Poly: %(poly)s" % m) + print("ReflectIn: %(reflect_in)s" % m) + print("XorIn: %(xor_in)s" % m) + print("ReflectOut: %(reflect_out)s" % m) + print("XorOut: %(xor_out)s" % m) + print("Check: %(check)s" % m) + else: + print("model not found.") +""" + + + +# Class CrcModels +############################################################################### +class CrcModels(object): + """ + CRC Models. + All models are generated in the constructor. + """ + + models = [] + + models.append({ + 'name': 'crc-5', + 'width': 5, + 'poly': 0x05, + 'reflect_in': True, + 'xor_in': 0x1f, + 'reflect_out': True, + 'xor_out': 0x1f, + 'direct': True, + 'check': 0x19, + }) + models.append({ + 'name': 'crc-8', + 'width': 8, + 'poly': 0x07, + 'reflect_in': False, + 'xor_in': 0x0, + 'reflect_out': False, + 'xor_out': 0x0, + 'direct': True, + 'check': 0xf4, + }) + models.append({ + 'name': 'dallas-1-wire', + 'width': 8, + 'poly': 0x31, + 'reflect_in': True, + 'xor_in': 0x0, + 'reflect_out': True, + 'xor_out': 0x0, + 'direct': True, + 'check': 0xa1, + }) + models.append({ + 'name': 'crc-12-3gpp', + 'width': 12, + 'poly': 0x80f, + 'reflect_in': False, + 'xor_in': 0x0, + 'reflect_out': True, + 'xor_out': 0x0, + 'direct': True, + 'check': 0xdaf, + }) + models.append({ + 'name': 'crc-15', + 'width': 15, + 'poly': 0x4599, + 'reflect_in': False, + 'xor_in': 0x0, + 'reflect_out': False, + 'xor_out': 0x0, + 'direct': True, + 'check': 0x59e, + }) + models.append({ + 'name': 'crc-16', + 'width': 16, + 'poly': 0x8005, + 'reflect_in': True, + 'xor_in': 0x0, + 'reflect_out': True, + 'xor_out': 0x0, + 'direct': True, + 'check': 0xbb3d, + }) + models.append({ + 'name': 'crc-16-usb', + 'width': 16, + 'poly': 0x8005, + 'reflect_in': True, + 'xor_in': 0xffff, + 'reflect_out': True, + 'xor_out': 0xffff, + 'direct': True, + 'check': 0xb4c8, + }) + models.append({ + 'name': 'crc-16-modbus', + 'width': 16, + 'poly': 0x8005, + 'reflect_in': True, + 'xor_in': 0xffff, + 'reflect_out': True, + 'xor_out': 0x0, + 'direct': True, + 'check': 0x4b37, + }) + models.append({ + 'name': 'crc-16-genibus', + 'width': 16, + 'poly': 0x1021, + 'reflect_in': False, + 'xor_in': 0xffff, + 'reflect_out': False, + 'xor_out': 0xffff, + 'direct': True, + 'check': 0xd64e, + }) + models.append({ + 'name': 'ccitt', + 'width': 16, + 'poly': 0x1021, + 'reflect_in': False, + 'xor_in': 0xffff, + 'reflect_out': False, + 'xor_out': 0x0, + 'direct': True, + 'check': 0x29b1, + }) + models.append({ + 'name': 'r-crc-16', + 'width': 16, + 'poly': 0x0589, + 'reflect_in': False, + 'xor_in': 0x0, + 'reflect_out': False, + 'xor_out': 0x0001, + 'direct': True, + 'check': 0x007e, + }) + models.append({ + 'name': 'kermit', + 'width': 16, + 'poly': 0x1021, + 'reflect_in': True, + 'xor_in': 0x0, + 'reflect_out': True, + 'xor_out': 0x0, + 'direct': True, + 'check': 0x2189, + }) + models.append({ + 'name': 'x-25', + 'width': 16, + 'poly': 0x1021, + 'reflect_in': True, + 'xor_in': 0xffff, + 'reflect_out': True, + 'xor_out': 0xffff, + 'direct': True, + 'check': 0x906e, + }) + models.append({ + 'name': 'xmodem', + 'width': 16, + 'poly': 0x1021, + 'reflect_in': False, + 'xor_in': 0x0, + 'reflect_out': False, + 'xor_out': 0x0, + 'direct': True, + 'check': 0x31c3, + }) + models.append({ + 'name': 'zmodem', + 'width': 16, + 'poly': 0x1021, + 'reflect_in': False, + 'xor_in': 0x0, + 'reflect_out': False, + 'xor_out': 0x0, + 'direct': True, + 'check': 0x31c3, + }) + models.append({ + 'name': 'crc-24', + 'width': 24, + 'poly': 0x864cfb, + 'reflect_in': False, + 'xor_in': 0xb704ce, + 'reflect_out': False, + 'xor_out': 0x0, + 'direct': True, + 'check': 0x21cf02, + }) + models.append({ + 'name': 'crc-32', + 'width': 32, + 'poly': 0x4c11db7, + 'reflect_in': True, + 'xor_in': 0xffffffff, + 'reflect_out': True, + 'xor_out': 0xffffffff, + 'direct': True, + 'check': 0xcbf43926, + }) + models.append({ + 'name': 'crc-32c', + 'width': 32, + 'poly': 0x1edc6f41, + 'reflect_in': True, + 'xor_in': 0xffffffff, + 'reflect_out': True, + 'xor_out': 0xffffffff, + 'direct': True, + 'check': 0xe3069283, + }) + models.append({ + 'name': 'crc-32-mpeg', + 'width': 32, + 'poly': 0x4c11db7, + 'reflect_in': False, + 'xor_in': 0xffffffff, + 'reflect_out': False, + 'xor_out': 0x0, + 'direct': False, + 'check': 0x0376e6e7, + }) + models.append({ + 'name': 'crc-32-bzip2', + 'width': 32, + 'poly': 0x04c11db7, + 'reflect_in': False, + 'xor_in': 0xffffffff, + 'reflect_out': False, + 'xor_out': 0xffffffff, + 'direct': True, + 'check': 0xfc891918, + }) + models.append({ + 'name': 'posix', + 'width': 32, + 'poly': 0x4c11db7, + 'reflect_in': False, + 'xor_in': 0x0, + 'reflect_out': False, + 'xor_out': 0xffffffff, + 'direct': True, + 'check': 0x765e7680, + }) + models.append({ + 'name': 'jam', + 'width': 32, + 'poly': 0x4c11db7, + 'reflect_in': True, + 'xor_in': 0xffffffff, + 'reflect_out': True, + 'xor_out': 0x0, + 'direct': True, + 'check': 0x340bc6d9, + }) + models.append({ + 'name': 'xfer', + 'width': 32, + 'poly': 0x000000af, + 'reflect_in': False, + 'xor_in': 0x0, + 'reflect_out': False, + 'xor_out': 0x0, + 'direct': True, + 'check': 0xbd0be338, + }) + models.append({ + 'name': 'crc-64', + 'width': 64, + 'poly': 0x000000000000001b, + 'reflect_in': True, + 'xor_in': 0x0, + 'reflect_out': True, + 'xor_out': 0x0, + 'direct': True, + 'check': 0x46a5a9388a5beffe, + }) + models.append({ + 'name': 'crc-64-jones', + 'width': 64, + 'poly': 0xad93d23594c935a9, + 'reflect_in': True, + 'xor_in': 0xffffffffffffffff, + 'reflect_out': True, + 'xor_out': 0x0, + 'direct': True, + 'check': 0xe9c6d914c4b8d9ca, + }) + models.append({ + 'name': 'crc-64-xz', + 'width': 64, + 'poly': 0x42f0e1eba9ea3693, + 'reflect_in': True, + 'xor_in': 0xffffffffffffffff, + 'reflect_out': True, + 'xor_out': 0xffffffffffffffff, + 'direct': True, + 'check': 0x995dc9bbdf1939fa, + }) + + + # function getList + ############################################################################### + def getList(self): + """ + This function returns the list of supported CRC models. + """ + l = [] + for i in self.models: + l.append(i['name']) + return l + + + # function getParams + ############################################################################### + def getParams(self, model): + """ + This function returns the paremeters of a given model. + """ + model = model.lower(); + for i in self.models: + if i['name'] == model: + return i + return None diff --git a/pycrc/crc_models.pyc b/pycrc/crc_models.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c7495a89aff2d94b56f8ac6b2fda5e1e4b8c3af3 GIT binary patch literal 5051 zcmeI0O>7%Q6o6-K$4Q)|Nz*oITG~!RQyjo<<0Nhpn$k9HNdMAc2hxU6%h_EgldN~$ z-F5!d(n_sBy;X4HQi&rMDkP*HI3Xm2IKTx}LP8uk04F%W2_(XMGaK7OH&Fz=K_X9P z=Dqpm&6~ID_Y(ZIA#!hg;F3zbpCJ4_0Uw7#qY*L%twMB#$Q?p%6LMuLK(ru9 zM?lCdEz`|1)1mI1UZF%6Ol!%c zu0;zgs;$N&kqPM9%yhY8A!}#zx~tm`va=M%E>nv}))t!#Mk18boNeVPtj>syDa#iu z+oi*{dXZbgl|0!{c{4Hl!j8S2wi9cWER>W(Su|@ zL|82bHiUE%B3TQGKUE~DR}n1?qiUknh*7N=MZ~BMM)gE%Aj#VbQOc}sg4HNkO+-Uh zSg^JW7L1SuqY75D4{L|S+9_C`T^)9={WV@d8VLdOgVv=26e0g@oC4U|EVI7fJ-Wj(LtKB}V#3roG?y<**)$7NCQ{l5M zpHcQ#pARef1X)J~t6#+ZfaLqZP2LkP_}Fz!u!aQdxbzIYD8)UDD&qcx59_4FI<;li zun+6B#PaO&eDB%i#h2%M7~y;Mj1OyM%PjefFZr-WH(|*!A+yfu1z*gs@lFj%rK8jMJwE~s&$}@16xm*!k53wgm%Gudt^Eqf257XbVPu_HcWem& ztQ%$Tp$zv!%exb?p4mcy)uW^lDC_|&b8t&8?qiK8dG`!7_u*J&Ns=|8r0NzlLmz_# zPsrCKV?}3%t*wFJ^N&D)c6b6v%VvrWJ9-|bx0R>C)ePs`0m;T5t)Ee4uFF2`0$n_w z9TO0C7wljP%&<40;qF<`?L2eY-FDE$t5}XD`j~ld-N%>>=Gmuke6GF9$EBkrdf9HI z{c+(q)5Wr1kB7 zF1y{_Faol5PxmBZ`GP*ne*9rE=%BmBg4oO|D}4lF#P*^b!|+e*;m+?5#`;2}v}v+8HV?&z z!{zVyz1{U_^u7@h>UcK%Z4|>Vu3W24Yss-~#KG(tO@`IWt9r-pv*Yx~WCcX6|E0H*zj&8@y#v=n~%Wql^wtpHU4~aP;XV%U*B_Syi9r)oAQU z{Aj%U$TWD$D=p)N75+4Pb>dZ^@^B`hu+pULQdB%AZj2x9tbXXATX^-1F6-njQ@~|= zxXXmIKxH97>=txh`dSN_gz_ZKkKl{~p>%3qQu}%hN@KmURGwvvx+z|P;suB08F$*4 za192OVJ+!)YCH6}r?8CW!qg6&LJjWM)Gp}#OSfUjm8xin67h~9p?Yv!lTxEZQNgW& zCX>OJZzjWEvl;X}`~v}o_+Vx-nx$qk+~iaQA^s8y=}_FMP=obsRZLAbVFJW8p35Fh;2W6jLNH#?7+ClGu5 RX*ee0|9Bi@5MM9h@Ly(9s#gF2 literal 0 HcmV?d00001 diff --git a/pycrc/crc_opt.py b/pycrc/crc_opt.py new file mode 100644 index 0000000..419bca7 --- /dev/null +++ b/pycrc/crc_opt.py @@ -0,0 +1,398 @@ +# -*- coding: Latin-1 -*- + +# pycrc -- parametrisable CRC calculation utility and C source code generator +# +# Copyright (c) 2006-2012 Thomas Pircher +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + + +""" +Option parsing library for pycrc. +use as follows: + + from crc_opt import Options + + opt = Options() + opt.parse(sys.argv[1:]) +""" + +from optparse import OptionParser, Option, OptionValueError +from copy import copy +import sys +from crc_models import CrcModels + + +# Class Options +############################################################################### +class Options(object): + """ + The options parsing and validationg class + """ + + # Program details + ProgramName = "pycrc" + Version = "0.7.10" + VersionStr = "%s v%s" % (ProgramName, Version) + WebAddress = "http://www.tty1.net/pycrc/" + + # Bitmap of the algorithms + Algo_None = 0x00 + Algo_Bit_by_Bit = 0x01 + Algo_Bit_by_Bit_Fast = 0x02 + Algo_Table_Driven = 0x04 + + Action_Check_String = 0x01 + Action_Check_Hex_String = 0x02 + Action_Check_File = 0x03 + Action_Generate_H = 0x04 + Action_Generate_C = 0x05 + Action_Generate_C_Main = 0x06 + Action_Generate_Table = 0x07 + + + # Class constructor + ############################################################################### + def __init__(self): + self.Width = None + self.Poly = None + self.ReflectIn = None + self.XorIn = None + self.ReflectOut = None + self.XorOut = None + self.TableIdxWidth = 8 + self.TableWidth = 1 << self.TableIdxWidth + self.Verbose = False + self.CheckString = "123456789" + self.MSB_Mask = None + self.Mask = None + + self.Algorithm = self.Algo_None + self.SymbolPrefix = "crc_" + self.CrcType = None + self.IncludeFile = None + self.OutputFile = None + self.Action = self.Action_Check_String + self.CheckFile = None + self.CStd = None + self.UndefinedCrcParameters = False + + + # function parse + ############################################################################### + def parse(self, argv = None): + """ + Parses and validates the options given as arguments + """ + usage = """\ +%prog [OPTIONS] + +To generate the checksum of a string or hexadecimal data: + %prog [model] --check-string "123456789" + %prog [model] --check-hexstring "313233343536373839" + +To generate the checksum of a file: + %prog [model] --check-file filename + +To generate the c-source and write it to filename: + %prog [model] --generate c -o filename + +The model can be defined by 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.getList()) + parser = OptionParser(option_class=MyOption, usage=usage, version=self.VersionStr) + parser.add_option("-v", "--verbose", + action="store_true", dest="verbose", default=False, + help="print information about the model") + parser.add_option("--check-string", + action="store", type="string", dest="check_string", + help="calculate the checksum of the given string (default: '123456789')", metavar="STRING") + parser.add_option("--check-hexstring", + action="store", type="string", dest="check_hexstring", + help="calculate the checksum of the given hexadecimal number string", metavar="STRING") + parser.add_option("--check-file", + action="store", type="string", dest="check_file", + help="calculate the checksum of the given file", metavar="FILE") + parser.add_option("--generate", + action="store", type="string", dest="generate", default=None, + help="choose which type of code to generate from {c, h, c-main, table}", metavar="CODE") + parser.add_option("--std", + action="store", type="string", dest="c_std", default="C99", + help="C standard style 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, bit-by-bit-fast, table-driven, all}", metavar="ALGO") + parser.add_option("--model", + action="callback", callback=self.model_cb, type="string", dest="model", default=None, + help="choose a parameter set from {%s}" % 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 Polynom", metavar="HEX") + parser.add_option("--reflect-in", + action="store", type="bool", dest="reflect_in", + help="reflect input bytes", 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 output bytes", 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("--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 generated 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="store", type="string", dest="include_file", + help="when generating source code, use FILE as additional include file", 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) + + 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.ReflectIn = options.reflect_in + else: + undefined_params.append("--reflect-in") + if options.xor_in != None: + self.XorIn = options.xor_in + else: + undefined_params.append("--xor-in") + if options.reflect_out != None: + self.ReflectOut = options.reflect_out + else: + undefined_params.append("--reflect-out") + if options.xor_out != None: + self.XorOut = options.xor_out + else: + undefined_params.append("--xor-out") + if options.table_idx_width != None: + if options.table_idx_width == 1 or \ + options.table_idx_width == 2 or \ + options.table_idx_width == 4 or \ + options.table_idx_width == 8: + self.TableIdxWidth = options.table_idx_width + self.TableWidth = 1 << options.table_idx_width + else: + sys.stderr.write("%s: error: unsupported table-idx-width %d\n" % (sys.argv[0], options.table_idx_width)) + sys.exit(1) + + if self.Poly != None and self.Poly % 2 == 0: + sys.stderr.write("%s: warning: the polynomial 0x%x is even. A valid CRC polynomial must be odd.\n" % (sys.argv[0], self.Poly)) + + if self.Width != None: + if self.Width <= 0: + sys.stderr.write("%s: error: Width must be strictly positive\n" % sys.argv[0]) + sys.exit(1) + 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.XorIn != None: + self.XorIn = self.XorIn & self.Mask + if self.XorOut != None: + self.XorOut = self.XorOut & self.Mask + else: + self.MSB_Mask = None + self.Mask = None + + if self.Width == None or \ + self.Poly == None or \ + self.ReflectIn == None or \ + self.XorIn == None or \ + self.ReflectOut == None or \ + self.XorOut == None: + self.UndefinedCrcParameters = True + else: + self.UndefinedCrcParameters = False + + if options.algorithm != None: + alg = options.algorithm.lower() + if alg == "bit-by-bit" or alg == "all": + self.Algorithm |= self.Algo_Bit_by_Bit + if alg == "bit-by-bit-fast" or alg == "all": + self.Algorithm |= self.Algo_Bit_by_Bit_Fast + if alg == "table-driven" or alg == "all": + self.Algorithm |= self.Algo_Table_Driven + if self.Algorithm == 0: + sys.stderr.write("%s: error: unknown algorithm %s\n" % (sys.argv[0], options.algorithm)) + sys.exit(1) + + if options.c_std != None: + std = options.c_std.upper() + if std == "ANSI" or std == "C89": + self.CStd = "C89" + elif std == "C99": + self.CStd = std + else: + sys.stderr.write("%s: error: unknown C standard %s\n" % (sys.argv[0], options.c_std)) + sys.exit(1) + if options.symbol_prefix != None: + self.SymbolPrefix = options.symbol_prefix + if options.include_file != None: + self.IncludeFile = options.include_file + if options.crc_type != None: + self.CrcType = options.crc_type + if options.output_file != None: + self.OutputFile = options.output_file + op_count = 0 + if options.check_string != None: + self.Action = self.Action_Check_String + self.CheckString = options.check_string + op_count += 1 + if options.check_hexstring != None: + self.Action = self.Action_Check_Hex_String + self.CheckString = options.check_hexstring + op_count += 1 + if options.check_file != None: + self.Action = self.Action_Check_File + self.CheckFile = 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: + sys.stderr.write("%s: error: don't know how to generate %s\n" % (sys.argv[0], options.generate)) + sys.exit(1) + op_count += 1 + + if self.Action == self.Action_Generate_Table: + if self.Algorithm & self.Algo_Table_Driven == 0: + sys.stderr.write("%s: error: the --generate table option is incompatible with the --algorithm option\n" % sys.argv[0]) + sys.exit(1) + self.Algorithm = self.Algo_Table_Driven + elif self.Algorithm != self.Algo_Bit_by_Bit and self.Algorithm != self.Algo_Bit_by_Bit_Fast and self.Algorithm != self.Algo_Table_Driven: + sys.stderr.write("%s: error: select an algorithm to be used in the generated file\n" % sys.argv[0]) + sys.exit(1) + else: + if self.TableIdxWidth != 8: + sys.stderr.write("%s: warning: reverting to Table Index Width = 8 for internal CRC calculation\n" % sys.argv[0]) + self.TableIdxWidth = 8 + self.TableWidth = 1 << options.table_idx_width + if op_count == 0: + self.Action = self.Action_Check_String + if op_count > 1: + sys.stderr.write("%s: error: too many actions scecified\n" % sys.argv[0]) + sys.exit(1) + + if len(args) != 0: + sys.stderr.write("%s: error: unrecognized argument(s): %s\n" % (sys.argv[0], " ".join(args))) + sys.exit(1) + + if self.UndefinedCrcParameters and self.Action in set((self.Action_Check_String, self.Action_Check_Hex_String, self.Action_Check_File, self.Action_Generate_Table)): + sys.stderr.write("%s: error: undefined parameters: Add %s or use --model\n" % (sys.argv[0], ", ".join(undefined_params))) + sys.exit(1) + self.Verbose = options.verbose + + + # function model_cb + ############################################################################## + def model_cb(self, 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.getParams(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: + raise OptionValueError("Error: unsupported model %s" % (value)) + + +# function check_hex +############################################################################### +def check_hex(option, opt, value): + """ + Checks if a value is given in a decimal integer of hexadecimal reppresentation. + Returns the converted value or rises an exception on error. + """ + try: + if value.lower().startswith("0x"): + return int(value, 16) + else: + return int(value) + except ValueError: + raise OptionValueError("option %s: invalid integer or hexadecimal value: %r" % (opt, value)) + + +# function check_bool +############################################################################### +def check_bool(option, opt, value): + """ + Checks if a value is given as a boolean value (either 0 or 1 or "true" or "false") + Returns the converted value or rises an exception on error. + """ + if value.isdigit(): + return int(value, 10) != 0 + elif value.lower() == "false": + return False + elif value.lower() == "true": + return True + else: + raise OptionValueError("option %s: invalid boolean value: %r" % (opt, value)) + + +# Class MyOption +############################################################################### +class MyOption(Option): + """ + New option parsing class extends the Option class + """ + TYPES = Option.TYPES + ("hex", "bool") + TYPE_CHECKER = copy(Option.TYPE_CHECKER) + TYPE_CHECKER["hex"] = check_hex + TYPE_CHECKER["bool"] = check_bool + diff --git a/pycrc/crc_opt.pyc b/pycrc/crc_opt.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0b4ca6d12eb5478b702716c748536ff65651315c GIT binary patch literal 11745 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 literal 0 HcmV?d00001 diff --git a/pycrc/crc_parser.py b/pycrc/crc_parser.py new file mode 100644 index 0000000..78d22de --- /dev/null +++ b/pycrc/crc_parser.py @@ -0,0 +1,418 @@ +# -*- coding: Latin-1 -*- + +# pycrc -- parametrisable CRC calculation utility and C source code generator +# +# Copyright (c) 2006-2012 Thomas Pircher +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + + +""" +Macro Language parser for pycrc. +use as follows: + + import sys + from crc_opt import Options + from crc_parser import MacroParser + + opt = Options() + opt.parse(sys.argv[1:]) + mp = MacroParser(opt) + if mp.parse("Test 1 2 3"): + print(mp.out_str) +""" + +from crc_symtable import SymbolTable +from crc_lexer import Lexer +import re +import sys + + +# Class ParseError +############################################################################### +class ParseError(Exception): + """ + The exception class for the parser. + """ + + # Class constructor + ############################################################################### + def __init__(self, reason): + self.reason = reason + + # function __str__ + ############################################################################### + def __str__(self): + return self.reason + + +# Class MacroParser +############################################################################### +class MacroParser(object): + """ + The macro language parser and code generator class. + """ + re_is_int = re.compile("^[-+]?[0-9]+$") + #re_is_hex = re.compile("^(0[xX])?[0-9a-fA-F]+$") + re_is_hex = re.compile("^0[xX][0-9a-fA-F]+$") + + opt = None + sym = None + lex = Lexer() + + + # Class constructor + ############################################################################### + def __init__(self, opt): + self.opt = opt + self.sym = SymbolTable(opt) + self.out_str = None + + # function parse + # + # The used grammar is: + # term: LITERAL + # | IDENTIFIER + # | '(' or_exp ')' + # ; + # + # comp_exp: term OP_COMPARISON term + # ; + # + # and_exp: term + # | and_exp OP_AND comp_exp + # ; + # + # or_exp: and_exp + # | or_exp OP_OR and_exp + # ; + # + # else_block: /* empty */ + # | ELSE '{:' data ':}' + # ; + # + # elif_blocks: /* empty */ + # | elif_blocks ELIF '(' or_exp ')' '{:' data ':}' + # ; + # + # if_block: IF '(' or_exp ')' '{:' data ':}' elif_blocks else_block + # ; + # + # data: /* empty */ + # | data GIBBERISH + # | data IDENTIFIER + # | data '{:' data ':}' + # | data if_block + # ; + ############################################################################### + def parse(self, in_str): + """ + Parse a macro string. + """ + self.lex.set_str(in_str) + self.out_str = "" + self._parse_data(do_print = True) + + tok = self.lex.peek() + if tok != self.lex.tok_EOF: + raise ParseError("%s: error: misaligned closing block '%s'" % (sys.argv[0], self.lex.text)) + + + # function _parse_data + ############################################################################### + def _parse_data(self, do_print): + """ + Private top-level parsing function. + """ + tok = self.lex.peek() + while tok != self.lex.tok_EOF: + if tok == self.lex.tok_gibberish: + self._parse_gibberish(do_print) + elif tok == self.lex.tok_block_open: + self._parse_data_block(do_print) + elif tok == self.lex.tok_identifier and self.lex.text == "if": + self._parse_if_block(do_print) + elif tok == self.lex.tok_identifier: + self._parse_identifier(do_print) + elif tok == self.lex.tok_block_close: + return + else: + raise ParseError("%s: error: wrong token '%s'" % (sys.argv[0], self.lex.text)) + tok = self.lex.peek() + + + # function _parse_gibberish + ############################################################################### + def _parse_gibberish(self, do_print): + """ + Parse gibberish. + Actually, just print the characters in 'text' if do_print is True. + """ + if do_print: + self.out_str = self.out_str + self.lex.text + self.lex.advance() + + + # function _parse_identifier + ############################################################################### + def _parse_identifier(self, do_print): + """ + Parse an identifier. + """ + try: + sym_value = self.sym.getTerminal(self.lex.text) + except LookupError: + raise ParseError("%s: error: unknown terminal '%s'" % (sys.argv[0], self.lex.text)) + self.lex.advance() + if do_print: + self.lex.prepend(sym_value) + + + # function _parse_if_block + ############################################################################### + def _parse_if_block(self, do_print): + """ + Parse an if block. + """ + # parse the expression following the 'if' and the associated block. + exp_res = self._parse_conditional_block(do_print) + do_print = do_print and not exp_res + + # try $elif + tok = self.lex.peek() + while tok == self.lex.tok_identifier and self.lex.text == "elif": + exp_res = self._parse_conditional_block(do_print) + do_print = do_print and not exp_res + tok = self.lex.peek() + + # try $else + if tok == self.lex.tok_identifier and self.lex.text == "else": + # get rid of the tok_identifier, 'else' and following spaces + self.lex.advance() + self.lex.delete_spaces() + + # expect a data block + self._parse_data_block(do_print) + + + + # function _parse_conditional_block + ############################################################################### + def _parse_conditional_block(self, do_print): + """ + Parse a conditional block (such as $if or $elif). + Return the truth value of the expression. + """ + # get rid of the tok_identifier, 'if' or 'elif' + self.lex.advance() + self.lex.set_state(self.lex.state_expr) + + # expect an open parenthesis + tok = self.lex.peek() + if tok != self.lex.tok_par_open: + raise ParseError("%s: error: open parenthesis expected: '%s'" % (sys.argv[0], self.lex.text)) + self.lex.advance() + + # parse the boolean expression + exp_res = self._parse_exp_or() + + # expect a closed parenthesis + tok = self.lex.peek() + if tok != self.lex.tok_par_close: + raise ParseError("%s: error: closed parenthesis expected: '%s'" % (sys.argv[0], self.lex.text)) + self.lex.advance() + + # get rid of eventual spaces, and switch back to gibberish. + self.lex.delete_spaces() + self.lex.set_state(self.lex.state_gibberish) + + # expect a data block + self._parse_data_block(do_print and exp_res) + + # get rid of eventual spaces + # but only if followed by $if, $else or $elif + self.lex.delete_spaces(skip_unconditional = False) + + return exp_res + + + # function _parse_data_block + ############################################################################### + def _parse_data_block(self, do_print): + """ + Parse a data block. + """ + # expect an open block + tok = self.lex.peek() + if tok != self.lex.tok_block_open: + raise ParseError("%s: error: open block expected: '%s'" % (sys.argv[0], self.lex.text)) + self.lex.advance(skip_nl = True) + + # more data follows... + self._parse_data(do_print) + + # expect a closed block + tok = self.lex.peek() + if tok != self.lex.tok_block_close: + raise ParseError("%s: error: closed block expected: '%s'" % (sys.argv[0], self.lex.text)) + self.lex.advance(skip_nl = True) + + + # function _parse_exp_or + ############################################################################### + def _parse_exp_or(self): + """ + Parse a boolean 'or' expression. + """ + ret = False + while True: + ret = self._parse_exp_and() or ret + + # is the expression terminated? + tok = self.lex.peek() + if tok == self.lex.tok_par_close: + return ret + # expect an 'or' token. + elif tok == self.lex.tok_or: + self.lex.advance() + # everything else is the end of the expression. + # Let the caling function worry about error reporting. + else: + return ret + return False + + + # function _parse_exp_and + ############################################################################### + def _parse_exp_and(self): + """ + Parse a boolean 'and' expression. + """ + ret = True + while True: + ret = self._parse_exp_comparison() and ret + + # is the expression terminated? + tok = self.lex.peek() + if tok == self.lex.tok_par_close: + return ret + # expect an 'and' token. + elif tok == self.lex.tok_and: + self.lex.advance() + # everything else is a parse error. + else: + return ret + return False + + + # function _parse_exp_comparison + ############################################################################### + def _parse_exp_comparison(self): + """ + Parse a boolean comparison. + """ + # left hand side of the comparison + lhs = self._parse_exp_term() + + # expect a comparison + tok = self.lex.peek() + if tok != self.lex.tok_op: + raise ParseError("%s: error: operator expected: '%s'" % (sys.argv[0], self.lex.text)) + operator = self.lex.text + self.lex.advance() + + # right hand side of the comparison + rhs = self._parse_exp_term() + + # if both operands ar numbers, convert them + num_l = self._get_num(lhs) + num_r = self._get_num(rhs) + if num_l != None and num_r != None: + lhs = num_l + rhs = num_r + + # now calculate the result of the comparison, whatever that means + if operator == "<=": + ret = lhs <= rhs + elif operator == "<": + ret = lhs < rhs + elif operator == "==": + ret = lhs == rhs + elif operator == "!=": + ret = lhs != rhs + elif operator == ">=": + ret = lhs >= rhs + elif operator == ">": + ret = lhs > rhs + else: + raise ParseError("%s: error: unknow operator: '%s'" % (sys.argv[0], self.lex.text)) + return ret + + + # function _parse_exp_term + ############################################################################### + def _parse_exp_term(self): + """ + Parse a terminal. + """ + tok = self.lex.peek() + + # identifier + if tok == self.lex.tok_identifier: + try: + ret = self.sym.getTerminal(self.lex.text) + except LookupError: + raise ParseError("%s: error: unknown terminal '%s'" % (sys.argv[0], self.lex.text)) + if ret == None: + ret = "Undefined" + # string + elif tok == self.lex.tok_str: + ret = self.lex.text + # number + elif tok == self.lex.tok_num: + ret = self.lex.text + # parenthesised expression + elif tok == self.lex.tok_par_open: + self.lex.advance() + ret = self._parse_exp_or() + tok = self.lex.peek() + if tok != self.lex.tok_par_close: + raise ParseError("%s: error: closed parenthesis expected: '%s'" % (sys.argv[0], self.lex.text)) + self.lex.advance() + return ret + + + # function _get_num + ############################################################################### + def _get_num(self, in_str): + """ + Check if in_str is a number and return the numeric value. + """ + ret = None + + if in_str != None: + m = self.re_is_int.match(in_str) + if m != None: + ret = int(in_str) + + m = self.re_is_hex.match(in_str) + if m != None: + ret = int(in_str, 16) + + return ret diff --git a/pycrc/crc_parser.pyc b/pycrc/crc_parser.pyc new file mode 100644 index 0000000000000000000000000000000000000000..164a26e433c6069cdf85e55e2c800bfa89d6fc1d GIT binary patch literal 8714 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 BzA69! literal 0 HcmV?d00001 diff --git a/pycrc/crc_symtable.py b/pycrc/crc_symtable.py new file mode 100644 index 0000000..651250d --- /dev/null +++ b/pycrc/crc_symtable.py @@ -0,0 +1,1354 @@ +# -*- coding: Latin-1 -*- + +# pycrc -- parametrisable CRC calculation utility and C source code generator +# +# Copyright (c) 2006-2012 Thomas Pircher +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + + +""" +Symbol table for the macro processor used by pycrc. +use as follows: + + from crc_opt import Options + from crc_symtable import SymbolTable + + opt = Options("0.6") + sym = SymbolTable(opt) + + str = " .... " + terminal = sym.getTerminal(str) +""" + +from crc_algorithms import Crc +import time +import os + + +# Class SymbolTable +############################################################################### +class SymbolTable: + """ + The symbol table class. + """ + opt = None + table = {} + + + # Class constructor + ############################################################################### + def __init__(self, opt): + """ + The class constructor. + """ + self.opt = opt + self.table["nop"] = "" + self.table["datetime"] = time.asctime() + self.table["program_version"] = self.opt.VersionStr + self.table["program_url"] = self.opt.WebAddress + if self.opt.OutputFile == None: + self.table["filename"] = "pycrc_stdout" + else: + self.table["filename"] = self.opt.OutputFile + + if self.opt.OutputFile == None: + self.table["header_filename"] = "pycrc_stdout.h" + elif self.opt.OutputFile[-2:] == ".c": + self.table["header_filename"] = self.opt.OutputFile[0:-1] + "h" + else: + self.table["header_filename"] = self.opt.OutputFile + ".h" + + self.table["crc_width"] = self.__pretty_str(self.opt.Width) + self.table["crc_poly"] = self.__pretty_hex(self.opt.Poly, self.opt.Width) + self.table["crc_reflect_in"] = self.__pretty_bool(self.opt.ReflectIn) + self.table["crc_xor_in"] = self.__pretty_hex(self.opt.XorIn, self.opt.Width) + self.table["crc_reflect_out"] = self.__pretty_bool(self.opt.ReflectOut) + self.table["crc_xor_out"] = self.__pretty_hex(self.opt.XorOut, self.opt.Width) + self.table["crc_table_idx_width"] = str(self.opt.TableIdxWidth) + self.table["crc_table_width"] = str(1 << self.opt.TableIdxWidth) + self.table["crc_table_mask"] = self.__pretty_hex(self.opt.TableWidth - 1, 8) + self.table["crc_mask"] = self.__pretty_hex(self.opt.Mask, self.opt.Width) + self.table["crc_msb_mask"] = self.__pretty_hex(self.opt.MSB_Mask, self.opt.Width) + if self.opt.Algorithm == self.opt.Algo_Table_Driven and (self.opt.Width == None or self.opt.Width < 8): + self.table["crc_do_shift"] = self.__pretty_bool(True) + if self.opt.Width == None: + self.table["crc_shift"] = self.__pretty_str(None) + else: + self.table["crc_shift"] = self.__pretty_str(8 - self.opt.Width) + else: + self.table["crc_do_shift"] = self.__pretty_bool(False) + self.table["crc_shift"] = self.__pretty_str(0) + + self.table["cfg_width"] = "$if ($crc_width != Undefined) {:$crc_width:} $else {:cfg->width:}" + self.table["cfg_poly"] = "$if ($crc_poly != Undefined) {:$crc_poly:} $else {:cfg->poly:}" + self.table["cfg_poly_shifted"] = "$if ($crc_do_shift == True) {:($cfg_poly << $cfg_shift):} $else {:$cfg_poly:}" + self.table["cfg_reflect_in"] = "$if ($crc_reflect_in != Undefined) {:$crc_reflect_in:} $else {:cfg->reflect_in:}" + self.table["cfg_xor_in"] = "$if ($crc_xor_in != Undefined) {:$crc_xor_in:} $else {:cfg->xor_in:}" + self.table["cfg_reflect_out"] = "$if ($crc_reflect_out != Undefined) {:$crc_reflect_out:} $else {:cfg->reflect_out:}" + self.table["cfg_xor_out"] = "$if ($crc_xor_out != Undefined) {:$crc_xor_out:} $else {:cfg->xor_out:}" + self.table["cfg_table_idx_width"] = "$if ($crc_table_idx_width != Undefined) {:$crc_table_idx_width:} $else {:cfg->table_idx_width:}" + self.table["cfg_table_width"] = "$if ($crc_table_width != Undefined) {:$crc_table_width:} $else {:cfg->table_width:}" + self.table["cfg_mask"] = "$if ($crc_mask != Undefined) {:$crc_mask:} $else {:cfg->crc_mask:}" + self.table["cfg_mask_shifted"] = "$if ($crc_do_shift == True) {:($cfg_mask << $cfg_shift):} $else {:$cfg_mask:}" + self.table["cfg_msb_mask"] = "$if ($crc_msb_mask != Undefined) {:$crc_msb_mask:} $else {:cfg->msb_mask:}" + self.table["cfg_msb_mask_shifted"] = "$if ($crc_do_shift == True) {:($cfg_msb_mask << $cfg_shift):} $else {:$cfg_msb_mask:}" + self.table["cfg_shift"] = "$if ($crc_shift != Undefined) {:$crc_shift:} $else {:cfg->crc_shift:}" + + self.table["undefined_parameters"] = self.__pretty_bool(self.opt.UndefinedCrcParameters) + self.table["use_cfg_t"] = self.__pretty_bool(self.opt.UndefinedCrcParameters) + self.table["c_std"] = self.opt.CStd + self.table["c_bool"] = "$if ($c_std == C89) {:int:} $else {:bool:}" + self.table["c_true"] = "$if ($c_std == C89) {:1:} $else {:true:}" + self.table["c_false"] = "$if ($c_std == C89) {:0:} $else {:false:}" + + self.table["underlying_crc_t"] = self.__get_underlying_crc_t() + self.table["include_file"] = self.__get_include_file() + + self.table["crc_prefix"] = self.opt.SymbolPrefix + self.table["crc_t"] = self.opt.SymbolPrefix + "t" + self.table["cfg_t"] = self.opt.SymbolPrefix + "cfg_t" + self.table["crc_reflect_function"] = self.opt.SymbolPrefix + "reflect" + self.table["crc_table_gen_function"] = self.opt.SymbolPrefix + "table_gen" + self.table["crc_init_function"] = self.opt.SymbolPrefix + "init" + self.table["crc_update_function"] = self.opt.SymbolPrefix + "update" + self.table["crc_finalize_function"] = self.opt.SymbolPrefix + "finalize" + + + # function getTerminal + ############################################################################### + def getTerminal(self, id): + """ + Return the expanded terminal, if it exists or None otherwise. + """ + + if id != None: + if id == "": + return "" + if id in self.table: + return self.table[id] + key = self.__getTerminal(id) + if key != None: + self.table[id] = key + return key + raise LookupError + + + # function __getTerminal + ############################################################################### + def __getTerminal(self, id): + """ + Return the expanded terminal, if it exists or None otherwise. + """ + if id == "constant_crc_init": + if self.__get_init_value() == None: + return self.__pretty_bool(False) + else: + return self.__pretty_bool(True) + + if id == "constant_crc_table": + if self.opt.Width != None and self.opt.Poly != None and self.opt.ReflectIn != None: + return self.__pretty_bool(True) + else: + return self.__pretty_bool(False) + + elif id == "simple_crc_update_def": + if self.opt.Algorithm in set([self.opt.Algo_Bit_by_Bit, self.opt.Algo_Bit_by_Bit_Fast]): + if self.opt.Width != None and self.opt.Poly != None and self.opt.ReflectIn != None: + return self.__pretty_bool(True) + elif self.opt.Algorithm == self.opt.Algo_Table_Driven: + if self.opt.Width != None and self.opt.ReflectIn != None: + return self.__pretty_bool(True) + return self.__pretty_bool(False) + + elif id == "inline_crc_finalize": + if self.opt.Algorithm in set([self.opt.Algo_Bit_by_Bit_Fast, self.opt.Algo_Table_Driven]) and \ + (self.opt.Width != None and self.opt.ReflectIn != None and self.opt.ReflectOut != None and self.opt.XorOut != None): + return self.__pretty_bool(True) + else: + return self.__pretty_bool(False) + + elif id == "simple_crc_finalize_def": + if self.opt.Algorithm == self.opt.Algo_Bit_by_Bit: + if self.opt.Width != None and self.opt.Poly != None and self.opt.ReflectOut != None and self.opt.XorOut != None: + return self.__pretty_bool(True) + elif self.opt.Algorithm == self.opt.Algo_Bit_by_Bit_Fast: + if self.opt.Width != None and self.opt.ReflectOut != None and self.opt.XorOut != None: + return self.__pretty_bool(True) + elif self.opt.Algorithm == self.opt.Algo_Table_Driven: + if self.opt.Width != None and self.opt.ReflectIn != None and self.opt.ReflectOut != None and self.opt.XorOut != None: + return self.__pretty_bool(True) + return self.__pretty_bool(False) + + elif id == "use_reflect_func": + if self.opt.ReflectOut == False and self.opt.ReflectIn == False: + return self.__pretty_bool(False) + else: + return self.__pretty_bool(True) + + elif id == "static_reflect_func": + if self.opt.Algorithm == self.opt.Algo_Table_Driven: + return self.__pretty_bool(False) + elif self.opt.ReflectOut != None and self.opt.Algorithm == self.opt.Algo_Bit_by_Bit_Fast: + return self.__pretty_bool(False) + else: + return self.__pretty_bool(True) + + elif id == "crc_algorithm": + if self.opt.Algorithm == self.opt.Algo_Bit_by_Bit: + return "bit-by-bit" + elif self.opt.Algorithm == self.opt.Algo_Bit_by_Bit_Fast: + return "bit-by-bit-fast" + elif self.opt.Algorithm == self.opt.Algo_Table_Driven: + return "table-driven" + else: + return "UNDEFINED" + + elif id == "crc_table_init": + return self.__get_table_init() + elif id == "crc_table_core_algorithm_ni": + return self.__get_table_core_algorithm_ni() + elif id == "crc_table_core_algorithm_ri": + return self.__get_table_core_algorithm_ri() + + elif id == "header_protection": + return self.__pretty_hdrprotection() + + elif id == "crc_init_value": + ret = self.__get_init_value() + if ret == None: + return "" + else: + return ret + + elif id == "crc_final_value": + return """\ +$if ($crc_algorithm == "table-driven") {: +$if ($crc_reflect_in == $crc_reflect_out) {: +$if ($crc_do_shift == True) {:(crc >> $cfg_shift):} $else {:crc:} ^ $crc_xor_out\ +:} $else {: +$crc_reflect_function($if ($crc_do_shift == True) {:(crc >> $cfg_shift):} $else {:crc:}, $crc_width) ^ $crc_xor_out\ +:}:} $elif ($crc_reflect_out == True) {: +$crc_reflect_function(crc, $crc_width) ^ $crc_xor_out\ +:} $else {: +crc ^ $crc_xor_out\ +:}\ +""" + elif id == "h_template": + return """\ +$source_header +#ifndef $header_protection +#define $header_protection + +$if ($include_file != Undefined) {: +#include $include_file +:} +#include +$if ($c_std != C89) {: +#include +:} +$if ($undefined_parameters == True and $c_std != C89) {: +#include +:} + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * The definition of the used algorithm. + *****************************************************************************/ +$if ($crc_algorithm == "bit-by-bit") {: +#define CRC_ALGO_BIT_BY_BIT 1 +:} $elif ($crc_algorithm == "bit-by-bit-fast") {: +#define CRC_ALGO_BIT_BY_BIT_FAST 1 +:} $elif ($crc_algorithm == "table-driven") {: +#define CRC_ALGO_TABLE_DRIVEN 1 +:} + + +/** + * The type of the CRC values. + * + * This type must be big enough to contain at least $cfg_width bits. + *****************************************************************************/ +typedef $underlying_crc_t $crc_t; + + +$if ($undefined_parameters == True) {: +/** + * The configuration type of the CRC algorithm. + *****************************************************************************/ +typedef struct { +$if ($crc_width == Undefined) {: + unsigned int width; /*!< The width of the polynomial */ +:} +$if ($crc_poly == Undefined) {: + $crc_t poly; /*!< The CRC polynomial */ +:} +$if ($crc_reflect_in == Undefined) {: + $c_bool reflect_in; /*!< Whether the input shall be reflected or not */ +:} +$if ($crc_xor_in == Undefined) {: + $crc_t xor_in; /*!< The initial value of the algorithm */ +:} +$if ($crc_reflect_out == Undefined) {: + $c_bool reflect_out; /*!< Wether the output shall be reflected or not */ +:} +$if ($crc_xor_out == Undefined) {: + $crc_t xor_out; /*!< The value which shall be XOR-ed to the final CRC value */ +:} +$if ($crc_width == Undefined) {: + + /* internal parameters */ + $crc_t msb_mask; /*!< a bitmask with the Most Significant Bit set to 1 + initialise as 1UL << (width - 1) */ + $crc_t crc_mask; /*!< a bitmask with all width bits set to 1 + initialise as (cfg->msb_mask - 1) | cfg->msb_mask */ + unsigned int crc_shift; /*!< a shift count that is used when width < 8 + initialise as cfg->width < 8 ? 8 - cfg->width : 0 */ +:} +} $cfg_t; + + +:} +$if ($use_reflect_func == True and $static_reflect_func != True) {: +$crc_reflect_doc +$crc_reflect_function_def; + + +:} +$if ($crc_algorithm == "table-driven" and $constant_crc_table != True) {: +$crc_table_gen_doc +$crc_table_gen_function_def; + + +:} +$crc_init_doc +$if ($constant_crc_init == False) {: +$crc_init_function_def; +:} $elif ($c_std == C89) {: +#define $crc_init_function() ($crc_init_value$if ($crc_do_shift == True) {: << $cfg_shift:}) +:} $else {: +static inline $crc_init_function_def$nop +{ + return $crc_init_value$if ($crc_do_shift == True) {: << $cfg_shift:}; +} +:} + + +$crc_update_doc +$crc_update_function_def; + + +$crc_finalize_doc +$if ($inline_crc_finalize == True) {: +$if ($c_std == C89) {: +#define $crc_finalize_function(crc) ($crc_final_value) +:} $else {: +static inline $crc_finalize_function_def$nop +{ + return $crc_final_value; +} +:} +:} $else {: +$crc_finalize_function_def; +:} + + +#ifdef __cplusplus +} /* closing brace for extern "C" */ +#endif + +#endif /* $header_protection */ +""" + + elif id == "source_header": + return """\ +/** + * \\file $filename + * Functions and types for CRC checks. + * + * Generated on $datetime, + * by $program_version, $program_url + * using the configuration: + * Width = $crc_width + * Poly = $crc_poly + * XorIn = $crc_xor_in + * ReflectIn = $crc_reflect_in + * XorOut = $crc_xor_out + * ReflectOut = $crc_reflect_out + * Algorithm = $crc_algorithm + *****************************************************************************/\ +""" + + elif id == "crc_reflect_doc": + return """\ +/** + * Reflect all bits of a \\a data word of \\a data_len bytes. + * + * \\param data The data word to be reflected. + * \\param data_len The width of \\a data expressed in number of bits. + * \\return The reflected data. + *****************************************************************************/\ +""" + + elif id == "crc_reflect_function_def": + return """\ +$crc_t $crc_reflect_function($crc_t data, size_t data_len)\ +""" + + elif id == "crc_reflect_function_body": + return """\ +$if ($crc_reflect_in == Undefined or $crc_reflect_in == True or $crc_reflect_out == Undefined or $crc_reflect_out == True) {: +$crc_reflect_doc +$crc_reflect_function_def$nop +{ + unsigned int i; + $crc_t ret; + + ret = data & 0x01; + for (i = 1; i < data_len; i++) { + data >>= 1; + ret = (ret << 1) | (data & 0x01); + } + return ret; +} +:}\ +""" + + elif id == "crc_table_gen_doc": + return """\ +/** + * Populate the private static crc table. + * + * \\param cfg A pointer to a initialised $cfg_t structure. + * \\return void + *****************************************************************************/\ +""" + + elif id == "crc_table_gen_function_def": + return """\ +void $crc_table_gen_function(const $cfg_t *cfg)\ +""" + + elif id == "crc_init_doc": + return """\ +/** + * Calculate the initial crc value. + * +$if ($use_cfg_t == True) {: + * \\param cfg A pointer to a initialised $cfg_t structure. +:} + * \\return The initial crc value. + *****************************************************************************/\ +""" + + elif id == "crc_init_function_def": + return """\ +$if ($constant_crc_init == False) {: +$crc_t $crc_init_function(const $cfg_t *cfg)\ +:} $else {: +$crc_t $crc_init_function(void)\ +:}\ +""" + + elif id == "crc_update_doc": + return """\ +/** + * Update the crc value with new data. + * + * \\param crc The current crc value. +$if ($simple_crc_update_def != True) {: + * \\param cfg A pointer to a initialised $cfg_t structure. +:} + * \\param data Pointer to a buffer of \\a data_len bytes. + * \\param data_len Number of bytes in the \\a data buffer. + * \\return The updated crc value. + *****************************************************************************/\ +""" + + elif id == "crc_update_function_def": + return """\ +$if ($simple_crc_update_def != True) {: +$crc_t $crc_update_function(const $cfg_t *cfg, $crc_t crc, const unsigned char *data, size_t data_len)\ +:} $else {: +$crc_t $crc_update_function($crc_t crc, const unsigned char *data, size_t data_len)\ +:}\ +""" + + elif id == "crc_finalize_doc": + return """\ +/** + * Calculate the final crc value. + * +$if ($simple_crc_finalize_def != True) {: + * \\param cfg A pointer to a initialised $cfg_t structure. +:} + * \\param crc The current crc value. + * \\return The final crc value. + *****************************************************************************/\ +""" + + elif id == "crc_finalize_function_def": + return """\ +$if ($simple_crc_finalize_def != True) {: +$crc_t $crc_finalize_function(const $cfg_t *cfg, $crc_t crc)\ +:} $else {: +$crc_t $crc_finalize_function($crc_t crc)\ +:}\ +""" + + elif id == "c_template": + return """\ +$source_header +$if ($include_file != Undefined) {: +#include $include_file +:} +#include "$header_filename" /* include the header file generated with pycrc */ +#include +$if ($c_std != C89) {: +#include +$if ($undefined_parameters == True or $crc_algorithm == "bit-by-bit" or $crc_algorithm == "bit-by-bit-fast") {: +#include +:} +:} + +$if ($use_reflect_func == True and $static_reflect_func == True) {: +static $crc_reflect_function_def; + +:} +$if ($crc_algorithm == "bit-by-bit") {: +$c_bit_by_bit +:} $elif ($crc_algorithm == "bit-by-bit-fast") {: +$c_bit_by_bit_fast +:} $elif ($crc_algorithm == "table-driven") {: +$c_table_driven +:} +""" + + elif id == "c_table": + return """\ +/** + * Static table used for the table_driven implementation. +$if ($undefined_parameters == True) {: + * Must be initialised with the $crc_init_function function. +:} + *****************************************************************************/ +$if ($constant_crc_table != True) {: +static $crc_t crc_table[$crc_table_width]; +:} $else {: +static const $crc_t crc_table[$crc_table_width] = { +$crc_table_init +}; +:} +""" + + elif id == "c_bit_by_bit": + return """\ +$if ($use_reflect_func == True) {: +$crc_reflect_function_body + +:} +$if ($constant_crc_init == False) {: +$crc_init_doc +$crc_init_function_def$nop +{ + unsigned int i; + $c_bool bit; + $crc_t crc = $cfg_xor_in; + for (i = 0; i < $cfg_width; i++) { + bit = crc & 0x01; + if (bit) { + crc = ((crc ^ $cfg_poly) >> 1) | $cfg_msb_mask; + } else { + crc >>= 1; + } + } + return crc & $cfg_mask; +} +:} + +$crc_update_doc +$crc_update_function_def$nop +{ + unsigned int i; + $c_bool bit; + unsigned char c; + + while (data_len--) { +$if ($crc_reflect_in == Undefined) {: + if ($cfg_reflect_in) { + c = $crc_reflect_function(*data++, 8); + } else { + c = *data++; + } +:} $elif ($crc_reflect_in == True) {: + c = $crc_reflect_function(*data++, 8); +:} $else {: + c = *data++; +:} + for (i = 0; i < 8; i++) { + bit = $if ($c_std == C89) {:!!(crc & $cfg_msb_mask):} $else {:crc & $cfg_msb_mask:}; + crc = (crc << 1) | ((c >> (7 - i)) & 0x01); + if (bit) { + crc ^= $cfg_poly; + } + } + crc &= $cfg_mask; + } + return crc & $cfg_mask; +} + + +$crc_finalize_doc +$crc_finalize_function_def$nop +{ + unsigned int i; + $c_bool bit; + + for (i = 0; i < $cfg_width; i++) { + bit = $if ($c_std == C89) {:!!(crc & $cfg_msb_mask):} $else {:crc & $cfg_msb_mask:}; + crc = (crc << 1) | 0x00; + if (bit) { + crc ^= $cfg_poly; + } + } +$if ($crc_reflect_out == Undefined) {: + if ($cfg_reflect_out) { + crc = $crc_reflect_function(crc, $cfg_width); + } +:} $elif ($crc_reflect_out == True) {: + crc = $crc_reflect_function(crc, $cfg_width); +:} + return (crc ^ $cfg_xor_out) & $cfg_mask; +} +""" + + elif id == "c_bit_by_bit_fast": + return """\ +$if ($use_reflect_func == True) {: +$crc_reflect_function_body + +:} +$if ($constant_crc_init == False) {: +$crc_init_doc +$crc_init_function_def$nop +{ + return $cfg_xor_in & $cfg_mask; +} +:} + +$crc_update_doc +$crc_update_function_def$nop +{ + unsigned int i; + $c_bool bit; + unsigned char c; + + while (data_len--) { +$if ($crc_reflect_in == Undefined) {: + if ($cfg_reflect_in) { + c = $crc_reflect_function(*data++, 8); + } else { + c = *data++; + } +:} $else {: + c = *data++; +:} +$if ($crc_reflect_in == True) {: + for (i = 0x01; i & 0xff; i <<= 1) { +:} $else {: + for (i = 0x80; i > 0; i >>= 1) { +:} + bit = $if ($c_std == C89) {:!!(crc & $cfg_msb_mask):} $else {:crc & $cfg_msb_mask:}; + if (c & i) { + bit = !bit; + } + crc <<= 1; + if (bit) { + crc ^= $cfg_poly; + } + } + crc &= $cfg_mask; + } + return crc & $cfg_mask; +} + +$if ($inline_crc_finalize != True) {: +$crc_finalize_doc +$crc_finalize_function_def$nop +{ +$if ($crc_reflect_out == Undefined) {: + if (cfg->reflect_out) { + crc = $crc_reflect_function(crc, $cfg_width); + } +:} $elif ($crc_reflect_out == True) {: + crc = $crc_reflect_function(crc, $cfg_width); +:} + return (crc ^ $cfg_xor_out) & $cfg_mask; +} + +:} +""" + + elif id == "c_table_driven": + return """\ +$c_table +$if ($use_reflect_func == True) {: +$crc_reflect_function_body +:} + +$if ($constant_crc_init == False) {: +$crc_init_doc +$crc_init_function_def$nop +{ +$if ($crc_reflect_in == Undefined) {: + if ($cfg_reflect_in) { + return $crc_reflect_function($cfg_xor_in & $cfg_mask, $cfg_width)$if ($crc_do_shift == True) {: << $cfg_shift:}; + } else { + return $cfg_xor_in & $cfg_mask$if ($crc_do_shift == True) {: << $cfg_shift:}; + } +:} $elif ($crc_reflect_in == True) {: + return $crc_reflect_function($cfg_xor_in & $cfg_mask, $cfg_width)$if ($crc_do_shift == True) {: << $cfg_shift:}; +:} $else {: + return $cfg_xor_in & $cfg_mask$if ($crc_do_shift == True) {: << $cfg_shift:}; +:} +} +:} + +$if ($constant_crc_table != True) {: +$crc_table_gen_doc +$crc_table_gen_function_def +{ + $crc_t crc; + unsigned int i, j; + + for (i = 0; i < $cfg_table_width; i++) { +$if ($crc_reflect_in == Undefined) {: + if (cfg->reflect_in) { + crc = $crc_reflect_function(i, $cfg_table_idx_width); + } else { + crc = i; + } +:} $elif ($crc_reflect_in == True) {: + crc = $crc_reflect_function(i, $cfg_table_idx_width); +:} $else {: + crc = i; +:} +$if ($crc_do_shift == True) {: + crc <<= ($cfg_width - $cfg_table_idx_width + $cfg_shift); +:} $else {: + crc <<= ($cfg_width - $cfg_table_idx_width); +:} + for (j = 0; j < $cfg_table_idx_width; j++) { + if (crc & $cfg_msb_mask_shifted) { + crc = (crc << 1) ^ $cfg_poly_shifted; + } else { + crc = crc << 1; + } + } +$if ($crc_reflect_in == Undefined) {: + if (cfg->reflect_in) { +$if ($crc_do_shift == True) {: + crc = $crc_reflect_function(crc >> $cfg_shift, $cfg_width) << $cfg_shift; +:} $else {: + crc = $crc_reflect_function(crc, $cfg_width); +:} + } +:} $elif ($crc_reflect_in == True) {: +$if ($crc_do_shift == True) {: + crc = $crc_reflect_function(crc >> $cfg_shift, $cfg_width) << $cfg_shift; +:} $else {: + crc = $crc_reflect_function(crc, $cfg_width); +:} +:} + crc_table[i] = crc & $cfg_mask_shifted; + } +} + +:} +$crc_update_doc +$crc_update_function_def$nop +{ + unsigned int tbl_idx; + +$if ($crc_reflect_in == Undefined) {: + if (cfg->reflect_in) { + while (data_len--) { +$crc_table_core_algorithm_ri + data++; + } + } else { + while (data_len--) { +$crc_table_core_algorithm_ni + data++; + } + } +:} $else {: + while (data_len--) { +$if ($crc_reflect_in == True) {: +$crc_table_core_algorithm_ri +:} $elif ($crc_reflect_in == False) {: +$crc_table_core_algorithm_ni +:} + data++; + } +:} + return crc & $cfg_mask_shifted; +} + +$if ($inline_crc_finalize == False) {: +$crc_finalize_doc +$crc_finalize_function_def$nop +{ +$if ($crc_do_shift == True) {: + crc >>= $cfg_shift; +:} +$if ($crc_reflect_in == Undefined or $crc_reflect_out == Undefined) {: +$if ($crc_reflect_in == Undefined and $crc_reflect_out == Undefined) {: + if (cfg->reflect_in == !cfg->reflect_out):} + $elif ($crc_reflect_out == Undefined) {: + if ($if ($crc_reflect_in == True) {:!:}cfg->reflect_out):} + $elif ($crc_reflect_in == Undefined) {: + if ($if ($crc_reflect_out == True) {:!:}cfg->reflect_in):} { + crc = $crc_reflect_function(crc, $cfg_width); + } +:} $elif ($crc_reflect_in != $crc_reflect_out) {: + crc = $crc_reflect_function(crc, $cfg_width); +:} + return (crc ^ $cfg_xor_out) & $cfg_mask; +} +:} +""" + + elif id == "main_template": + return """\ +$if ($include_file != Undefined) {: +#include $include_file +:} +#include +#include +$if ($undefined_parameters == True) {: +#include +#include +#include +:} +$if ($c_std != C89) {: +#include +:} +#include + +static char str[256] = "123456789"; +static $c_bool verbose = $c_false; + +void print_params($if ($undefined_parameters == True) {:const $cfg_t *cfg:} $else {:void:}); +$getopt_template + +void print_params($if ($undefined_parameters == True) {:const $cfg_t *cfg:} $else {:void:}) +{ + char format[20]; + + snprintf(format, sizeof(format), "%%-16s = 0x%%0%dx\\n", (unsigned int)($cfg_width + 3) / 4); + printf("%-16s = %d\\n", "width", (unsigned int)$cfg_width); + printf(format, "poly", (unsigned int)$cfg_poly); + printf("%-16s = %s\\n", "reflect_in", $if ($crc_reflect_in == Undefined) {:$cfg_reflect_in ? "true": "false":} $else {:$if ($crc_reflect_in == True) {:"true":} $else {:"false":}:}); + printf(format, "xor_in", $cfg_xor_in); + printf("%-16s = %s\\n", "reflect_out", $if ($crc_reflect_out == Undefined) {:$cfg_reflect_out ? "true": "false":} $else {:$if ($crc_reflect_out == True) {:"true":} $else {:"false":}:}); + printf(format, "xor_out", (unsigned int)$cfg_xor_out); + printf(format, "crc_mask", (unsigned int)$cfg_mask); + printf(format, "msb_mask", (unsigned int)$cfg_msb_mask); +} + +/** + * C main function. + * + * \\return 0 on success, != 0 on error. + *****************************************************************************/ +int main(int argc, char *argv[]) +{ +$if ($undefined_parameters == True) {: + $cfg_t cfg = { +$if ($crc_width == Undefined) {: + 0, /* width */ +:} +$if ($crc_poly == Undefined) {: + 0, /* poly */ +:} +$if ($crc_xor_in == Undefined) {: + 0, /* xor_in */ +:} +$if ($crc_reflect_in == Undefined) {: + 0, /* reflect_in */ +:} +$if ($crc_xor_out == Undefined) {: + 0, /* xor_out */ +:} +$if ($crc_reflect_out == Undefined) {: + 0, /* reflect_out */ +:} +$if ($crc_width == Undefined) {: + + 0, /* crc_mask */ + 0, /* msb_mask */ + 0, /* crc_shift */ +:} + }; +:} + $crc_t crc; + +$if ($undefined_parameters == True) {: + get_config(argc, argv, &cfg); +:} $else {: + get_config(argc, argv); +:} +$if ($crc_algorithm == "table-driven" and $constant_crc_table != True) {: + $crc_table_gen_function(&cfg); +:} + crc = $crc_init_function($if ($constant_crc_init != True) {:&cfg:}); + crc = $crc_update_function($if ($simple_crc_update_def != True) {:&cfg, :}crc, (unsigned char *)str, strlen(str)); + crc = $crc_finalize_function($if ($simple_crc_finalize_def != True) {:&cfg, :}crc); + + if (verbose) { + print_params($if ($undefined_parameters == True) {:&cfg:}); + } + printf("0x%lx\\n", (unsigned long)crc); + return 0; +} +""" + + elif id == "getopt_template": + return """\ +$if ($crc_reflect_in == Undefined or $crc_reflect_out == Undefined) {: +static $c_bool atob(const char *str); +:} +$if ($crc_poly == Undefined or $crc_xor_in == Undefined or $crc_xor_out == Undefined) {: +static crc_t xtoi(const char *str); +:} +static int get_config(int argc, char *argv[]$if ($undefined_parameters == True) {:, $cfg_t *cfg:}); + + +$if ($crc_reflect_in == Undefined or $crc_reflect_out == Undefined) {: +$c_bool atob(const char *str) +{ + if (!str) { + return 0; + } + if (isdigit(str[0])) { + return ($c_bool)atoi(str); + } + if (tolower(str[0]) == 't') { + return $c_true; + } + return $c_false; +} + +:} +$if ($crc_poly == Undefined or $crc_xor_in == Undefined or $crc_xor_out == Undefined) {: +crc_t xtoi(const char *str) +{ + crc_t ret = 0; + + if (!str) { + return 0; + } + if (str[0] == '0' && tolower(str[1]) == 'x') { + str += 2; + while (*str) { + if (isdigit(*str)) + ret = 16 * ret + *str - '0'; + else if (isxdigit(*str)) + ret = 16 * ret + tolower(*str) - 'a' + 10; + else + return ret; + str++; + } + } else if (isdigit(*str)) { + while (*str) { + if (isdigit(*str)) + ret = 10 * ret + *str - '0'; + else + return ret; + str++; + } + } + return ret; +} + + +:} +static int get_config(int argc, char *argv[]$if ($undefined_parameters == True) {:, $cfg_t *cfg:}) +{ + int c; + int option_index; + static struct option long_options[] = { +$if ($crc_width == Undefined) {: + {"width", 1, 0, 'w'}, +:} +$if ($crc_poly == Undefined) {: + {"poly", 1, 0, 'p'}, +:} +$if ($crc_reflect_in == Undefined) {: + {"reflect-in", 1, 0, 'n'}, +:} +$if ($crc_xor_in == Undefined) {: + {"xor-in", 1, 0, 'i'}, +:} +$if ($crc_reflect_out == Undefined) {: + {"reflect-out", 1, 0, 'u'}, +:} +$if ($crc_xor_out == Undefined) {: + {"xor-out", 1, 0, 'o'}, +:} + {"verbose", 0, 0, 'v'}, + {"check-string", 1, 0, 's'}, +$if ($crc_width == Undefined) {: + {"table-idx-with", 1, 0, 't'}, +:} + {0, 0, 0, 0} + }; + + while (1) { + option_index = 0; + + c = getopt_long (argc, argv, "w:p:n:i:u:o:s:vt", long_options, &option_index); + if (c == -1) + break; + + switch (c) { + case 0: + printf ("option %s", long_options[option_index].name); + if (optarg) + printf (" with arg %s", optarg); + printf ("\\n"); +$if ($crc_width == Undefined) {: + case 'w': + cfg->width = atoi(optarg); + break; +:} +$if ($crc_poly == Undefined) {: + case 'p': + cfg->poly = xtoi(optarg); + break; +:} +$if ($crc_reflect_in == Undefined) {: + case 'n': + cfg->reflect_in = atob(optarg); + break; +:} +$if ($crc_xor_in == Undefined) {: + case 'i': + cfg->xor_in = xtoi(optarg); + break; +:} +$if ($crc_reflect_out == Undefined) {: + case 'u': + cfg->reflect_out = atob(optarg); + break; +:} +$if ($crc_xor_out == Undefined) {: + case 'o': + cfg->xor_out = xtoi(optarg); + break; +:} + case 's': + memcpy(str, optarg, strlen(optarg) < sizeof(str) ? strlen(optarg) + 1 : sizeof(str)); + str[sizeof(str) - 1] = '\\0'; + break; + case 'v': + verbose = $c_true; + break; +$if ($crc_width == Undefined) {: + case 't': + /* ignore --table_idx_width option */ + break; +:} + case '?': + return -1; + case ':': + fprintf(stderr, "missing argument to option %c\\n", c); + return -1; + default: + fprintf(stderr, "unhandled option %c\\n", c); + return -1; + } + } +$if ($crc_width == Undefined) {: + cfg->msb_mask = 1UL << (cfg->width - 1); + cfg->crc_mask = (cfg->msb_mask - 1) | cfg->msb_mask; + cfg->crc_shift = cfg->width < 8 ? 8 - cfg->width : 0; +:} + +$if ($crc_poly == Undefined) {: + cfg->poly &= $cfg_mask; +:} +$if ($crc_xor_in == Undefined) {: + cfg->xor_in &= $cfg_mask; +:} +$if ($crc_xor_out == Undefined) {: + cfg->xor_out &= $cfg_mask; +:} + return 0; +}\ +""" + + + # function __pretty_str + ############################################################################### + def __pretty_str(self, value): + """ + Return a value of width bits as a pretty string. + """ + if value == None: + return "Undefined" + return str(value) + + + # function __pretty_hex + ############################################################################### + def __pretty_hex(self, value, width = None): + """ + Return a value of width bits as a pretty hexadecimal formatted string. + """ + if value == None: + return "Undefined" + if width == None: + return "0x%x" % value + width = (width + 3) // 4 + hex_str = "0x%%0%dx" % width + return hex_str % value + + + # function __pretty_bool + ############################################################################### + def __pretty_bool(self, value): + """ + Return a boolen value of width bits as a pretty formatted string. + """ + if value == None: + return "Undefined" + if value: + return "True" + else: + return "False" + + + # function __pretty_hdrprotection + ############################################################################### + def __pretty_hdrprotection(self): + """ + Return the name of a C header protection (e.g. __CRC_IMPLEMENTATION_H__). + """ + tr_str = "" + for i in range(256): + if chr(i).isalpha(): + tr_str += chr(i).upper() + else: + tr_str += '_' + if self.opt.OutputFile == None: + out_str = "pycrc_stdout" + else: + out_str = self.opt.OutputFile + out_str = os.path.basename(out_str) + out_str = out_str.upper() + out_str = out_str.translate(tr_str) + return "__" + out_str + "__" + + + # function __get_underlying_crc_t + ############################################################################### + def __get_underlying_crc_t(self): + """ + Return the C type of the crc_t typedef. + """ + if self.opt.CrcType != None: + return self.opt.CrcType + if self.opt.Width == None: + return "unsigned long" + if self.opt.CStd == "C89": + if self.opt.Width <= 8: + return "unsigned char" + elif self.opt.Width <= 16: + return "unsigned int" + else: + return "unsigned long" + else: # C99 + if self.opt.Width <= 8: + return "uint8_t" + elif self.opt.Width <= 16: + return "uint16_t" + elif self.opt.Width <= 32: + return "uint32_t" + else: + return "unsigned long" + return "unsigned long" + + + # function __get_include_file + ############################################################################### + def __get_include_file(self): + """ + Return an addittional include instruction if specified. + """ + if self.opt.IncludeFile == None: + return None + if self.opt.IncludeFile[0] == '"' or self.opt.IncludeFile[0] == '<': + return self.opt.IncludeFile + return '"%s"' % self.opt.IncludeFile + + + # function __get_init_value + ############################################################################### + def __get_init_value(self): + """ + Return the init value of a C implementation, according to the selected algorithm and + to the given options. + If no default option is given for a given parameter, value in the cfg_t structure must be used. + """ + if self.opt.Algorithm == self.opt.Algo_Bit_by_Bit: + if self.opt.XorIn == None or self.opt.Width == None or self.opt.Poly == None: + return None + crc = Crc(width = self.opt.Width, poly = self.opt.Poly, + reflect_in = self.opt.ReflectIn, xor_in = self.opt.XorIn, + reflect_out = self.opt.ReflectOut, xor_out = self.opt.XorOut, + table_idx_width = self.opt.TableIdxWidth) + init = crc.NonDirectInit + elif self.opt.Algorithm == self.opt.Algo_Bit_by_Bit_Fast: + if self.opt.XorIn == None: + return None + init = self.opt.XorIn + elif self.opt.Algorithm == self.opt.Algo_Table_Driven: + if self.opt.ReflectIn == None or self.opt.XorIn == None or self.opt.Width == None: + return None + if self.opt.Poly == None: + poly = 0 + else: + poly = self.opt.Poly + crc = Crc(width = self.opt.Width, poly = poly, + reflect_in = self.opt.ReflectIn, xor_in = self.opt.XorIn, + reflect_out = self.opt.ReflectOut, xor_out = self.opt.XorOut, + table_idx_width = self.opt.TableIdxWidth) + if self.opt.ReflectIn: + init = crc.reflect(crc.DirectInit, self.opt.Width) + else: + init = crc.DirectInit + else: + init = 0 + return self.__pretty_hex(init, self.opt.Width) + + + # function __get_table_init + ############################################################################### + def __get_table_init(self): + """ + Return the precalculated CRC table for the table_driven implementation. + """ + if self.opt.Algorithm != self.opt.Algo_Table_Driven: + return "0" + if self.opt.Width == None or self.opt.Poly == None or self.opt.ReflectIn == None: + return "0" + crc = Crc(width = self.opt.Width, poly = self.opt.Poly, + reflect_in = self.opt.ReflectIn, + xor_in = 0, reflect_out = False, xor_out = 0, # set unimportant variables to known values + table_idx_width = self.opt.TableIdxWidth) + tbl = crc.gen_table() + if self.opt.Width >= 32: + values_per_line = 4 + elif self.opt.Width >= 16: + values_per_line = 8 + else: + values_per_line = 16 + format_width = max(self.opt.Width, 8) + out = "" + for i in range(self.opt.TableWidth): + if i % values_per_line == 0: + out += " " + if i == (self.opt.TableWidth - 1): + out += "%s" % self.__pretty_hex(tbl[i], format_width) + elif i % values_per_line == (values_per_line - 1): + out += "%s,\n" % self.__pretty_hex(tbl[i], format_width) + else: + out += "%s, " % self.__pretty_hex(tbl[i], format_width) + return out + + + # function __get_table_core_algorithm_ni + ############################################################################### + def __get_table_core_algorithm_ni(self): + """ + Return the core loop of the table-driven algorithm. + """ + if self.opt.Algorithm != self.opt.Algo_Table_Driven: + return "" + + loop_core_ni = "" + loop_indent = "" + if self.opt.UndefinedCrcParameters: + loop_indent = " " + else: + loop_indent = " " + + if self.opt.Width == None: + shr = "($cfg_width - $cfg_table_idx_width + $cfg_shift)" + elif self.opt.Width < 8: + shr = "%d" % (self.opt.Width - self.opt.TableIdxWidth + 8 - self.opt.Width) + else: + shr = "%d" % (self.opt.Width - self.opt.TableIdxWidth) + + reg_shift = "$if ($crc_do_shift == True) {:($cfg_table_idx_width - $cfg_shift):} $else {:$cfg_table_idx_width:}" + + if self.opt.TableIdxWidth == 8: + loop_core_ni += loop_indent + "tbl_idx = ((crc >> " + shr + ") ^ *data) & $crc_table_mask;" + '\n' + \ + loop_indent + "crc = (crc_table[tbl_idx] ^ (crc << " + reg_shift + ")) & $cfg_mask_shifted;" + '\n' + else: + for i in range (8 / self.opt.TableIdxWidth): + str_idx = "%s" % (8 - (i + 1) * self.opt.TableIdxWidth) + loop_core_ni += loop_indent + "tbl_idx = (crc >> " + shr + ") ^ (*data >> " + str_idx + ");" + '\n' + \ + loop_indent + "crc = crc_table[tbl_idx & $crc_table_mask] ^ (crc << " + reg_shift + ");" + '\n' + return loop_core_ni + + + # function __get_table_core_algorithm_ri + ############################################################################### + def __get_table_core_algorithm_ri(self): + """ + Return the core loop of the table-driven algorithm. + """ + if self.opt.Algorithm != self.opt.Algo_Table_Driven: + return "" + + loop_core_ri = "" + loop_indent = "" + if self.opt.UndefinedCrcParameters: + loop_indent = " " + else: + loop_indent = " " + crc_shifted = "$if ($crc_do_shift == True) {:(crc >> $cfg_shift):} $else {:crc:}" + + if self.opt.TableIdxWidth == 8: + loop_core_ri += loop_indent + "tbl_idx = (" + crc_shifted + " ^ *data) & $crc_table_mask;" + '\n' + \ + loop_indent + "crc = (crc_table[tbl_idx] ^ (crc >> $cfg_table_idx_width)) & $cfg_mask_shifted;" + '\n' + else: + for i in range (8 / self.opt.TableIdxWidth): + str_idx = "%d" % i + loop_core_ri += loop_indent + "tbl_idx = " + crc_shifted + " ^ (*data >> (" + str_idx + " * $cfg_table_idx_width));" + '\n' + \ + loop_indent + "crc = crc_table[tbl_idx & $crc_table_mask] ^ (crc >> $cfg_table_idx_width);" + '\n' + + return loop_core_ri diff --git a/pycrc/crc_symtable.pyc b/pycrc/crc_symtable.pyc new file mode 100644 index 0000000000000000000000000000000000000000..361108b0bf15b1bb898529038ebcad37662fd3e4 GIT binary patch literal 37808 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 JbA597{{f9gZZH4< literal 0 HcmV?d00001 diff --git a/pycrc/doc/Makefile b/pycrc/doc/Makefile new file mode 100644 index 0000000..b4f843d --- /dev/null +++ b/pycrc/doc/Makefile @@ -0,0 +1,26 @@ +XSLTPROC = xsltproc +XSLTPARAM = --nonet --novalid +HTML_STYLESHEET = /usr/share/xml/docbook/stylesheet/nwalsh/xhtml/docbook.xsl +MAN_STYLESHEET = /usr/share/xml/docbook/stylesheet/nwalsh/manpages/docbook.xsl + +source = pycrc.xml +targets = $(source:.xml=.html) $(source:.xml=.1) + +all: $(targets) + +.PHONY: clean +clean: + $(RM) $(targets) + +.PHONY: check +check: + xmllint --valid --noout $(source) + +%.html: %.xml + $(XSLTPROC) $(XSLTPARAM) -o $@ $(HTML_STYLESHEET) $< + +%.1: %.xml + $(XSLTPROC) $(XSLTPARAM) -o $@ $(MAN_STYLESHEET) $< + +%.txt: %.html + links -dump -no-numbering -no-references $< > $@ diff --git a/pycrc/doc/pycrc.1 b/pycrc/doc/pycrc.1 new file mode 100644 index 0000000..99fcfec --- /dev/null +++ b/pycrc/doc/pycrc.1 @@ -0,0 +1,531 @@ +'\" t +.\" Title: pycrc +.\" Author: Thomas Pircher +.\" Generator: DocBook XSL Stylesheets v1.76.1 +.\" Date: 2011-11-19 +.\" Manual: pycrc +.\" Source: pycrc 0.7.9 +.\" Language: English +.\" +.TH "PYCRC" "1" "2011\-11\-19" "pycrc 0.7.9" "pycrc" +.\" ----------------------------------------------------------------- +.\" * Define some portability stuff +.\" ----------------------------------------------------------------- +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.\" http://bugs.debian.org/507673 +.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" ----------------------------------------------------------------- +.\" * set default formatting +.\" ----------------------------------------------------------------- +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.\" ----------------------------------------------------------------- +.\" * MAIN CONTENT STARTS HERE * +.\" ----------------------------------------------------------------- +.SH "NAME" +pycrc \- a free, easy to use Cyclic Redundancy Check (CRC) calculator and source code generator\&. +.SH "SYNOPSIS" +.HP \w'\fBpycrc\fR\ 'u +\fBpycrc\fR [OPTIONS] +.SH "DESCRIPTION" +.PP + +\m[blue]\fBpycrc\fR\m[]\&\s-2\u[1]\d\s+2 +provides a parametrised CRC reference implementation written in Python and a source code generator for C\&. The generated C source code can be optimised for simplicity, speed or tight memory constraints for embedded platforms\&. The following operations are implemented: +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +generate the checksum of a string (ASCII or hex) +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +generate the checksum of a file +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +generate the C header and source files for a client implementation\&. +.RE +.PP +The following variants of the CRC algorithm are supported: +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} + +\fIbit\-by\-bit\fR: the basic algorithm which operates individually on every bit of the augmented message (i\&.e\&. the input data with +\fIWidth\fR +0\-bits attached to the end)\&. This algorithm is the easiest to understand because it is a straightforward implementation of the basic polynomial division, but it is also the slowest among all possible variants\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} + +\fIbit\-by\-bit\-fast\fR: a variation of the simple +\fIbit\-by\-bit\fR +algorithm, with the difference that it does not need to augment the data, i\&.e\&. it does not add +\fIWidth\fR +zero bits at the end of the message\&. This algorithm might be a good choice for embedded platforms, where code space is a major concern\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} + +\fItable\-driven\fR: the standard table driven algorithm\&. This is the fastest variant because it operates on one byte at a time, as opposed to bits, and uses a look\-up table of 256 elements, which might not be feasible for small embedded systems, though\&. Anyway, the number of elements in the look\-up table can be reduced by means of the +\fB\-\-table\-idx\-width\fR +command line switch\&. By using 4 bits (16 elements in the look\-up table) a significant speed\-up can be measured with respect to the bit\-by\-bit algorithms\&. +.RE +.sp +.SH "OPTIONS" +.PP +\fB\-\-version\fR +.RS 4 +show program\*(Aqs version number and exit +.RE +.PP +\fB\-h\fR, \fB\-\-help\fR +.RS 4 +show this help message and exit +.RE +.PP +\fB\-\-verbose\fR +.RS 4 +be more verbose; in particular, print the value of the parameters and the chosen model +.RE +.PP +\fB\-\-check\-string=\fR\fISTRING\fR +.RS 4 +calculate the checksum of the given string (\*(Aq\fI123456789\fR\*(Aq default) +.RE +.PP +\fB\-\-check\-hexstring=\fR\fISTRING\fR +.RS 4 +calculate the checksum of the given hexadecimal string +.RE +.PP +\fB\-\-check\-file=\fR\fIFILE\fR +.RS 4 +calculate the checksum of the given file +.RE +.PP +\fB\-\-generate=\fR\fICODE\fR +.RS 4 +generate the source code type as a choice from {c, h, c\-main, table} +.RE +.PP +\fB\-\-std=\fR\fISTD\fR +.RS 4 +C standard style of the generated code from {C89, ANSI, C99} +.RE +.PP +\fB\-\-algorithm=\fR\fIALGO\fR +.RS 4 +choose an algorithm from {\fIbit\-by\-bit\fR, +\fIbit\-by\-bit\-fast\fR, +\fItable\-driven\fR, +\fIall\fR} +.RE +.PP +\fB\-\-model=\fR\fIMODEL\fR +.RS 4 +choose a parameter set from {\fIcrc\-5\fR, +\fIcrc\-8\fR, +\fIdallas\-1\-wire\fR, +\fIcrc\-12\-3gpp\fR, +\fIcrc\-15\fR, +\fIcrc\-16\fR, +\fIcrc\-16\-usb\fR, +\fIcrc\-16\-modbus\fR, +\fIcrc\-16\-genibus\fR, +\fIccitt\fR, +\fIr\-crc\-16\fR, +\fIkermit\fR, +\fIx\-25\fR, +\fIxmodem\fR, +\fIzmodem\fR, +\fIcrc\-24\fR, +\fIcrc\-32\fR, +\fIcrc\-32c\fR, +\fIcrc\-32\-mpeg\fR, +\fIcrc\-32\-bzip2\fR, +\fIposix\fR, +\fIjam\fR, +\fIxfer\fR, +\fIcrc\-64\fR, +\fIcrc\-64\-jones\fR, +\fIcrc\-64\-xz\fR} +.RE +.PP +\fB\-\-width=\fR\fINUM\fR +.RS 4 +use +\fINUM\fR +bits in the +\fIPolynomial\fR +.RE +.PP +\fB\-\-poly=\fR\fIHEX\fR +.RS 4 +use +\fIHEX\fR +as +\fIPolynomial\fR +.RE +.PP +\fB\-\-reflect\-in=\fR\fIBOOL\fR +.RS 4 +reflect input bytes +.RE +.PP +\fB\-\-xor\-in=\fR\fIHEX\fR +.RS 4 +use +\fIHEX\fR +as initial value +.RE +.PP +\fB\-\-reflect\-out=\fR\fIBOOL\fR +.RS 4 +reflect output bytes +.RE +.PP +\fB\-\-xor\-out=\fR\fIHEX\fR +.RS 4 +xor the final CRC value with +\fIHEX\fR +.RE +.PP +\fB\-\-table\-idx\-width=\fR\fINUM\fR +.RS 4 +use +\fINUM\fR +bits to index the CRC table; +\fINUM\fR +must be one of the values {\fI1\fR, +\fI2\fR, +\fI4\fR, +\fI8\fR} +.RE +.PP +\fB\-\-symbol\-prefix=\fR\fISTRING\fR +.RS 4 +when generating source code, use +\fISTRING\fR +as prefix to the generated symbols +.RE +.PP +\fB\-\-crc\-type=\fR\fISTRING\fR +.RS 4 +when generating source code, use +\fISTRING\fR +as crc_t type +.RE +.PP +\fB\-\-include\-file=\fR\fIFILE\fR +.RS 4 +when generating source code, include also +\fIFILE\fR +as header file +.RE +.PP +\fB\-o\fR\fIFILE\fR, \fB\-\-output=\fR\fIFILE\fR +.RS 4 +write the generated code to +\fIFILE\fR +instead to stdout +.RE +.SH "THE CRC PARAMETRIC MODEL" +.PP +The parametric model follows Ross N\&. Williams\*(Aq convention described in +\m[blue]\fBA Painless Guide to CRC Error Detection Algorithms\fR\m[]\&\s-2\u[2]\d\s+2, commonly called the Rocksoft Model\&. Since most people are familiar with this kind of parameters, pycrc follows this convention, described as follows: +.PP +\fIWidth\fR +.RS 4 +The width of the CRC +\fIPolynomial\fR, in number of bits\&. This is also the width of the final CRC result\&. Previous versions of pycrc only multiples of 8 could be be used as +\fIWidth\fR +for the +\fItable\-driven\fR +algorithm\&. As of version 0\&.7\&.5, any +\fIWidth\fR +is accepted on all algorithms\&. +.RE +.PP +\fIPolynomial\fR +.RS 4 +The unreflected polynomial of the CRC algorithm\&. +.sp +The +\fIPolynomial\fR +may be specified in its standard form, i\&.e\&. with bit +\fIWidth\fR+1 set to 1, but the most significant bit may also be omitted\&. For example, for a +\fIWidth\fR +of 16, both forms 0x18005 and 0x8005 are accepted\&. +.RE +.PP +\fIReflectIn\fR +.RS 4 +Reflect the bytes of the message before processing them\&. A word is reflected by inverting the position of its bits with respect to the middle axis of the word\&. The reversed value of 0xa3 (10100010b) is 0x45 (01000101b), for example\&. Some CRC algorithms can be implemented more efficiently in a bit reversed version\&. +.sp +Reflected algorithms are more efficient than straight\-forward implementations, thus many of the standard algorithmic variants use reflected input bytes\&. +.RE +.PP +\fIXorIn\fR +.RS 4 +The initial value (usually all 0 or all 1) in the algorithms which operate on the non\-augmented message\&. This value can be seen as a value which will be XOR\-ed into the CRC register after +\fIWidth\fR +iterations of the +\fIbit\-by\-bit\fR +algorithm\&. This means the simple +\fIbit\-by\-bit\fR +algorithm must calculate the initial value using some sort of reverse CRC algorithm on the +\fIXorIn\fR +value\&. +.RE +.PP +\fIReflectOut\fR +.RS 4 +Reflect the final CRC result\&. This operation takes place before XOR\-ing the final CRC value with the +\fIXorOut\fR +parameter\&. +.RE +.PP +\fIXorOut\fR +.RS 4 +A value (usually all bits 0 or all 1) which will be XOR\-ed to the final CRC value\&. +.RE +.PP +\fICheck\fR +.RS 4 +This value is not exactly a parameter of a model but it is sometimes given together with the Rocksoft Model parameters\&. It is the CRC value of the parametrised model over the string "\fI123456789\fR" and may be used to validate an implementation\&. +.RE +.SH "CODE GENERATION" +.PP +In the default configuration, the generated code is strict ISO C99 code\&. A minimal set of three functions are defined for each algorithm: +\fBcrc_init()\fR, +\fBcrc_update()\fR +and +\fBcrc_finalize()\fR\&. According to the number of parameters given to pycrc, a different interface definition is generated\&. Fully parametrised models have a simpler API, while the generated code for runtime\-specified implementations adds a pointer to a configuration structure as first parameter to all functions\&. +.PP +The generated source code uses the type +\fBcrc_t\fR, which is used throughout the code\&. It may be redefined in the generated header file\&. +.SS "Fully parametrised models" +.PP +The prototypes of these functions are normally generated by pycrc using the +\fI\-\-generate h\fR +option\&. The prototypes of the +.sp +.ft B +.nf +#include +/* pycrc will define the appropriate type + * when generating the header file\&. */ +typedef XXXX crc_t; + +.fi +.ft +.HP \w'crc_t\ crc_init('u +.BI "crc_t crc_init(void);" +.HP \w'crc_t\ crc_update('u +.BI "crc_t crc_update(crc_t\ " "crc" ", const\ unsigned\ char\ *" "data" ", size_t\ " "data_len" ");" +.HP \w'crc_t\ crc_finalize('u +.BI "crc_t crc_finalize(crc_t\ " "crc" ");" +.PP +The following code snippet shows how to use the generated functions\&. +.sp +.if n \{\ +.RS 4 +.\} +.nf +#include "pycrc_generated_crc\&.h" +#include + +int main(void) +{ + static const unsigned char str1[] = "1234"; + static const unsigned char str2[] = "56789"; + crc_t crc; + + crc = crc_init(); + crc = crc_update(crc, str1, sizeof(str1) \- 1); + crc = crc_update(crc, str2, sizeof(str2) \- 1); + // more calls to crc_update\&.\&.\&. + crc = crc_finalize(crc); + + printf("0x%lx\en", (long)crc); + return 0; +} + +.fi +.if n \{\ +.RE +.\} +.sp +.SS "Models with runtime\-configurable parameters" +.PP +When the model is not fully defined then the missing parameters are contained in a structure of type +\fBcrc_cfg_t\fR\&. The first argument of the CRC functions is a pointer to that structure, and its fields must be initialised properly by the user before the first call to the CRC functions\&. This structure contains three additional parameters, +\fImsb_mask\fR, +\fIcrc_mask\fR +and +\fIcrc_shift\fR, if the +\fIWidth\fR +was undefined when the code was generated\&. +.sp +.if n \{\ +.RS 4 +.\} +.nf +typedef struct { + unsigned int width; + crc_t poly; + bool reflect_in; + crc_t xor_in; + bool reflect_out; + crc_t xor_out; + + // internal parameters + crc_t msb_mask; // initialise as 1UL << (cfg\->width \- 1) + crc_t crc_mask; // initialise as (cfg\->msb_mask \- 1) | cfg\->msb_mask + unsigned int crc_shift; // initialise as cfg\->width < 8 ? 8 \- cfg\->width : 0 +} crc_cfg_t; + +.fi +.if n \{\ +.RE +.\} +.PP + +\fImsb_mask\fR +is a bitmask with the most significant bit of a +\fIWidth\fR +bits wide data type set to 1\&. +\fIcrc_mask\fR +is a bitmask with all bits of a +\fIWidth\fR +bits wide data type set to 1\&. +\fIcrc_shift\fR +is a shift counter that is used when +\fIWidth\fR +is less than 8\&. It is the number of bits to shift the CRC register to align its top bit at a byte boundary\&. +.PP +The file +test/main\&.c +in the source package of pycrc contains a fully featured example of how to use the generated source code\&. A shorter, more compact +main() +function can be generated with the +\fI\-\-generate c\-main\fR +option\&. This second variant is the better option when some of the CRC parameters are known and some are unknown during code generation\&. +.SH "EXAMPLES" +.PP +.PP +Calculate the CRC\-32 checksum of the string 123456789: +.RS 4 + +\fBpython pycrc\&.py \-\-model crc\-32 \-\-check\-string 123456789\fR +.RE +.PP +Generate the source code of the table\-driven algorithm for an embedded application\&. +.RS 4 + +\fBpython pycrc\&.py \-\-model crc\-16 \-\-algorithm table\-driven \-\-table\-idx\-width 4 \-\-generate h \-o crc\&.h\fR +.sp + +\fBpython pycrc\&.py \-\-model crc\-16 \-\-algorithm table\-driven \-\-table\-idx\-width 4 \-\-generate c \-o crc\&.c\fR +.sp +The table index width of 4 bits ensures a moderate memory consumption\&. In fact, the size of the resulting table is +16 * sizeof(crc_t) +bytes\&. A variant of the last generated output is the +\fIc\-main\fR +target: a simple +\fImain()\fR +function is generated in addition to the CRC routines: +.sp + +\fBpython pycrc\&.py \-\-model crc\-16 \-\-algorithm table\-driven \-\-table\-idx\-width 4 \-\-generate c\-main \-o crc\&.c\fR +.RE +.PP +Generate the CRC table only: +.RS 4 + +\fBpython pycrc\&.py \-\-model kermit \-\-generate table \-o crc\-table\&.txt\fR +.RE +.SH "SEE ALSO" +.PP +The homepage of pycrc is +\m[blue]\fBhttp://www\&.tty1\&.net/pycrc/\fR\m[]\&. +.PP +For a long list of known CRC models, see Greg Cook\*(Aqs +\m[blue]\fBCatalogue of Parameterised CRC Algorithms\fR\m[]\&\s-2\u[3]\d\s+2\&. +.SH "COPYRIGHT" +.PP +This work is licensed under a +\m[blue]\fBCreative Commons Attribution\-Share Alike 3\&.0 Unported License\fR\m[]\&\s-2\u[4]\d\s+2\&. +.SH "AUTHOR" +.PP +\fBThomas Pircher\fR <\&tehpeh@gmx\&.net\&> +.RS 4 +Author of pycrc and this manual page\&. +.RE +.SH "NOTES" +.IP " 1." 4 +pycrc +.RS 4 +\%http://www.tty1.net/pycrc/ +.RE +.IP " 2." 4 +A Painless Guide to CRC Error Detection Algorithms +.RS 4 +\%http://www.ross.net/crc/crcpaper.html +.RE +.IP " 3." 4 +Catalogue of Parameterised CRC Algorithms +.RS 4 +\%http://regregex.bbcmicro.net/crc-catalogue.htm +.RE +.IP " 4." 4 +Creative Commons Attribution-Share Alike 3.0 Unported License +.RS 4 +\%http://creativecommons.org/licenses/by-sa/3.0/ +.RE diff --git a/pycrc/doc/pycrc.html b/pycrc/doc/pycrc.html new file mode 100644 index 0000000..17d4df7 --- /dev/null +++ b/pycrc/doc/pycrc.html @@ -0,0 +1,247 @@ + + +pycrc

Name

pycrc — a free, easy to use Cyclic Redundancy Check (CRC) calculator and source code generator.

Synopsis

pycrc [OPTIONS]

Description

+ pycrc + provides a parametrised CRC reference implementation written in Python and a source code generator for C. + The generated C source code can be optimised for simplicity, speed or tight memory constraints for embedded platforms. + + The following operations are implemented: +

  • + generate the checksum of a string (ASCII or hex) +

  • + generate the checksum of a file +

  • + generate the C header and source files for a client implementation. +

+

+ The following variants of the CRC algorithm are supported: +

  • + bit-by-bit: the basic algorithm which operates individually on every bit of the augmented message + (i.e. the input data with Width 0-bits attached to the end). + This algorithm is the easiest to understand because it is a straightforward implementation of the basic polynomial division, + but it is also the slowest among all possible variants. +

  • + bit-by-bit-fast: a variation of the simple bit-by-bit algorithm, + with the difference that it does not need to augment the data, i.e. it does not add Width zero + bits at the end of the message. + This algorithm might be a good choice for embedded platforms, where code space is a major concern. +

  • + table-driven: the standard table driven algorithm. + This is the fastest variant because it operates on one byte at a time, as opposed to bits, and uses a look-up table of 256 elements, + which might not be feasible for small embedded systems, though. Anyway, the number of elements in the look-up table can be reduced by + means of the --table-idx-width command line switch. By using 4 bits (16 elements in the look-up table) a significant + speed-up can be measured with respect to the bit-by-bit algorithms. +

+

Options

+ --version +

show program's version number and exit

+ -h + , + --help +

show this help message and exit

+ --verbose +

be more verbose; in particular, print the value of the parameters and the chosen model

+ --check-string=STRING +

calculate the checksum of the given string ('123456789' default)

+ --check-hexstring=STRING +

calculate the checksum of the given hexadecimal string

+ --check-file=FILE +

calculate the checksum of the given file

+ --generate=CODE +

generate the source code type as a choice from {c, h, c-main, table}

+ --std=STD +

C standard style of the generated code from {C89, ANSI, C99}

+ --algorithm=ALGO +

choose an algorithm from {bit-by-bit, bit-by-bit-fast, + table-driven, all}

+ --model=MODEL +

choose a parameter set from + {crc-5, + crc-8, + dallas-1-wire, + crc-12-3gpp, + crc-15, + crc-16, + crc-16-usb, + crc-16-modbus, + crc-16-genibus, + ccitt, + r-crc-16, + kermit, + x-25, + xmodem, + zmodem, + crc-24, + crc-32, + crc-32c, + crc-32-mpeg, + crc-32-bzip2, + posix, + jam, + xfer, + crc-64, + crc-64-jones, + crc-64-xz}

+ --width=NUM +

use NUM bits in the Polynomial

+ --poly=HEX +

use HEX as Polynomial

+ --reflect-in=BOOL +

reflect input bytes

+ --xor-in=HEX +

use HEX as initial value

+ --reflect-out=BOOL +

reflect output bytes

+ --xor-out=HEX +

xor the final CRC value with HEX

+ --table-idx-width=NUM +

use NUM bits to index the CRC table; NUM must be one of the values + {1, 2, 4, 8}

+ --symbol-prefix=STRING +

when generating source code, use STRING as prefix to the generated symbols

+ --crc-type=STRING +

when generating source code, use STRING as crc_t type

+ --include-file=FILE +

when generating source code, include also FILE as header file

+ -oFILE + , + --output=FILE +

write the generated code to FILE instead to stdout

The CRC Parametric Model

+ The parametric model follows Ross N. Williams' convention described in + A Painless Guide to CRC Error Detection Algorithms, + commonly called the Rocksoft Model. + Since most people are familiar with this kind of parameters, pycrc follows this convention, described as follows: +

Width

+ The width of the CRC Polynomial, in number of bits. This is also the width of the final CRC result. + Previous versions of pycrc only multiples of 8 could be be used as Width for the + table-driven algorithm. As of version 0.7.5, any Width is accepted + on all algorithms. +

Polynomial

+ The unreflected polynomial of the CRC algorithm. +

+ The Polynomial may be specified in its standard form, i.e. with bit Width+1 + set to 1, but the most significant bit may also be omitted. For example, for a Width of 16, + both forms 0x18005 and 0x8005 are accepted. +

ReflectIn

+ Reflect the bytes of the message before processing them. A word is reflected by inverting the position of its bits with + respect to the middle axis of the word. + The reversed value of 0xa3 (10100010b) is 0x45 (01000101b), for example. + Some CRC algorithms can be implemented more efficiently in a bit reversed version. +

+ Reflected algorithms are more efficient than straight-forward implementations, thus many of the standard algorithmic + variants use reflected input bytes. +

XorIn

+ The initial value (usually all 0 or all 1) in the algorithms which operate on the non-augmented message. + This value can be seen as a value which will be XOR-ed into the CRC register after Width + iterations of the bit-by-bit algorithm. + This means the simple bit-by-bit algorithm must calculate the initial value using some sort of + reverse CRC algorithm on the XorIn value. +

ReflectOut

+ Reflect the final CRC result. This operation takes place before XOR-ing the final CRC + value with the XorOut parameter. +

XorOut

+ A value (usually all bits 0 or all 1) which will be XOR-ed to the final CRC value. +

Check

+ This value is not exactly a parameter of a model but it is sometimes given together with the Rocksoft Model parameters. + It is the CRC value of the parametrised model over the string "123456789" and + may be used to validate an implementation. +

+

Code generation

+ In the default configuration, the generated code is strict ISO C99 code. + A minimal set of three functions are defined for each algorithm: + crc_init(), crc_update() and crc_finalize(). + According to the number of parameters given to pycrc, a different interface definition is generated. + Fully parametrised models have a simpler API, while the generated code for runtime-specified implementations adds a + pointer to a configuration structure as first parameter to all functions. +

+ The generated source code uses the type crc_t, which is used throughout the code. It may be redefined in the generated header file. +

Fully parametrised models

+ The prototypes of these functions are normally generated by pycrc using the --generate h option. + The prototypes of the +

+#include <stdlib.h>
+/* pycrc will define the appropriate type
+ * when generating the header file. */
+typedef XXXX crc_t;
+                
crc_t fsfunccrc_init(void); 
 
crc_t fsfunccrc_update(crc_t crc,
 const unsigned char *data,
 size_t data_len);
 
crc_t fsfunccrc_finalize(crc_t crc);
 

+ The following code snippet shows how to use the generated functions. +

+#include "pycrc_generated_crc.h"
+#include <stdio.h>
+
+int main(void)
+{
+    static const unsigned char str1[] = "1234";
+    static const unsigned char str2[] = "56789";
+    crc_t crc;
+
+    crc = crc_init();
+    crc = crc_update(crc, str1, sizeof(str1) - 1);
+    crc = crc_update(crc, str2, sizeof(str2) - 1);
+    // more calls to crc_update...
+    crc = crc_finalize(crc);
+
+    printf("0x%lx\n", (long)crc);
+    return 0;
+}
+            

+

Models with runtime-configurable parameters

+ When the model is not fully defined then the missing parameters are contained in a structure of + type crc_cfg_t. + The first argument of the CRC functions is a pointer to that structure, and its fields must be initialised + properly by the user before the first call to the CRC functions. + This structure contains three additional parameters, msb_mask, crc_mask + and crc_shift, if the Width was undefined when the code was generated. +

+typedef struct {
+    unsigned int width;
+    crc_t poly;
+    bool reflect_in;
+    crc_t xor_in;
+    bool reflect_out;
+    crc_t xor_out;
+
+    // internal parameters
+    crc_t msb_mask;             // initialise as 1UL << (cfg->width - 1)
+    crc_t crc_mask;             // initialise as (cfg->msb_mask - 1) | cfg->msb_mask
+    unsigned int crc_shift;     // initialise as cfg->width < 8 ? 8 - cfg->width : 0
+} crc_cfg_t;
+            

+

+ msb_mask is a bitmask with the most significant bit of a Width bits + wide data type set to 1. + crc_mask is a bitmask with all bits of a Width bits + wide data type set to 1. + crc_shift is a shift counter that is used when Width is less than 8. + It is the number of bits to shift the CRC register to align its top bit at a byte boundary. +

+ The file test/main.c in the source package of pycrc contains a fully featured example + of how to use the generated source code. + A shorter, more compact main() function can be generated with the --generate c-main + option. + This second variant is the better option when some of the CRC parameters are known and some are unknown during code generation. +

Examples

+

Calculate the CRC-32 checksum of the string 123456789:

+ python pycrc.py --model crc-32 --check-string 123456789 +

Generate the source code of the table-driven algorithm for an embedded application.

+ python pycrc.py --model crc-16 --algorithm table-driven --table-idx-width 4 --generate h -o crc.h +

+ python pycrc.py --model crc-16 --algorithm table-driven --table-idx-width 4 --generate c -o crc.c +

+ The table index width of 4 bits ensures a moderate memory consumption. + In fact, the size of the resulting table is 16 * sizeof(crc_t) bytes. + A variant of the last generated output is the c-main target: + a simple main() function is generated in addition to the CRC routines: +

+ python pycrc.py --model crc-16 --algorithm table-driven --table-idx-width 4 --generate c-main -o crc.c +

Generate the CRC table only:

+ python pycrc.py --model kermit --generate table -o crc-table.txt +

+

See Also

+ The homepage of pycrc is http://www.tty1.net/pycrc/. +

+ For a long list of known CRC models, see Greg Cook's Catalogue of Parameterised CRC Algorithms. +

Copyright

+ This work is licensed under a + Creative Commons Attribution-Share Alike 3.0 Unported License. +

diff --git a/pycrc/doc/pycrc.xml b/pycrc/doc/pycrc.xml new file mode 100644 index 0000000..eeffea2 --- /dev/null +++ b/pycrc/doc/pycrc.xml @@ -0,0 +1,582 @@ + + + + + + + + + + + + + + + + + + +]> + + + + + &program_name; + &program_name; + &program_version; + + &author_firstname; + &author_surname; + Author of &program_name; and this manual page. + &author_email; + + &date; + + + + &program_name; + 1 + + + + &program_name; + a free, easy to use Cyclic Redundancy Check (CRC) calculator and source code generator. + + + + + &program_name; + OPTIONS + + + + Description + + &program_name; + provides a parametrised CRC reference implementation written in Python and a source code generator for C. + The generated C source code can be optimised for simplicity, speed or tight memory constraints for embedded platforms. + + The following operations are implemented: + + + + generate the checksum of a string (ASCII or hex) + + + + + generate the checksum of a file + + + + + generate the C header and source files for a client implementation. + + + + + + The following variants of the CRC algorithm are supported: + + + + &bit-by-bit;: the basic algorithm which operates individually on every bit of the augmented message + (i.e. the input data with &width; 0-bits attached to the end). + This algorithm is the easiest to understand because it is a straightforward implementation of the basic polynomial division, + but it is also the slowest among all possible variants. + + + + + &bit-by-bit-fast;: a variation of the simple &bit-by-bit; algorithm, + with the difference that it does not need to augment the data, i.e. it does not add &width; zero + bits at the end of the message. + This algorithm might be a good choice for embedded platforms, where code space is a major concern. + + + + + &table-driven;: the standard table driven algorithm. + This is the fastest variant because it operates on one byte at a time, as opposed to bits, and uses a look-up table of 256 elements, + which might not be feasible for small embedded systems, though. Anyway, the number of elements in the look-up table can be reduced by + means of the command line switch. By using 4 bits (16 elements in the look-up table) a significant + speed-up can be measured with respect to the bit-by-bit algorithms. + + + + + + + Options + + + + + + + show program's version number and exit + + + + + + + + + + + show this help message and exit + + + + + + + + be more verbose; in particular, print the value of the parameters and the chosen model + + + + + STRING + + + calculate the checksum of the given string ('123456789' default) + + + + + STRING + + + calculate the checksum of the given hexadecimal string + + + + + FILE + + + calculate the checksum of the given file + + + + + CODE + + + generate the source code type as a choice from {c, h, c-main, table} + + + + + STD + + + C standard style of the generated code from {C89, ANSI, C99} + + + + + ALGO + + + choose an algorithm from {bit-by-bit, bit-by-bit-fast, + table-driven, all} + + + + + MODEL + + + choose a parameter set from + {crc-5, + crc-8, + dallas-1-wire, + crc-12-3gpp, + crc-15, + crc-16, + crc-16-usb, + crc-16-modbus, + crc-16-genibus, + ccitt, + r-crc-16, + kermit, + x-25, + xmodem, + zmodem, + crc-24, + crc-32, + crc-32c, + crc-32-mpeg, + crc-32-bzip2, + posix, + jam, + xfer, + crc-64, + crc-64-jones, + crc-64-xz} + + + + + NUM + + + use NUM bits in the &poly; + + + + + HEX + + + use HEX as &poly; + + + + + BOOL + + + reflect input bytes + + + + + HEX + + + use HEX as initial value + + + + + BOOL + + + reflect output bytes + + + + + HEX + + + xor the final CRC value with HEX + + + + + NUM + + + use NUM bits to index the CRC table; NUM must be one of the values + {1, 2, 4, 8} + + + + + STRING + + + when generating source code, use STRING as prefix to the generated symbols + + + + + STRING + + + when generating source code, use STRING as crc_t type + + + + + FILE + + + when generating source code, include also FILE as header file + + + + + FILE + + + FILE + + + write the generated code to FILE instead to stdout + + + + + + The CRC Parametric Model + + The parametric model follows Ross N. Williams' convention described in + A Painless Guide to CRC Error Detection Algorithms, + commonly called the Rocksoft Model. + Since most people are familiar with this kind of parameters, &program_name; follows this convention, described as follows: + + + &width; + + + The width of the CRC &poly;, in number of bits. This is also the width of the final CRC result. + Previous versions of &program_name; only multiples of 8 could be be used as &width; for the + &table-driven; algorithm. As of version 0.7.5, any &width; is accepted + on all algorithms. + + + + + &poly; + + + The unreflected polynomial of the CRC algorithm. + + + The &poly; may be specified in its standard form, i.e. with bit &width;+1 + set to 1, but the most significant bit may also be omitted. For example, for a &width; of 16, + both forms 0x18005 and 0x8005 are accepted. + + + + + &reflect_in; + + + Reflect the bytes of the message before processing them. A word is reflected by inverting the position of its bits with + respect to the middle axis of the word. + The reversed value of 0xa3 (10100010b) is 0x45 (01000101b), for example. + Some CRC algorithms can be implemented more efficiently in a bit reversed version. + + + Reflected algorithms are more efficient than straight-forward implementations, thus many of the standard algorithmic + variants use reflected input bytes. + + + + + &xor_in; + + + The initial value (usually all 0 or all 1) in the algorithms which operate on the non-augmented message. + This value can be seen as a value which will be XOR-ed into the CRC register after &width; + iterations of the &bit-by-bit; algorithm. + This means the simple &bit-by-bit; algorithm must calculate the initial value using some sort of + reverse CRC algorithm on the &xor_in; value. + + + + + &reflect_out; + + + Reflect the final CRC result. This operation takes place before XOR-ing the final CRC + value with the &xor_out; parameter. + + + + + &xor_out; + + + A value (usually all bits 0 or all 1) which will be XOR-ed to the final CRC value. + + + + + + + + This value is not exactly a parameter of a model but it is sometimes given together with the Rocksoft Model parameters. + It is the CRC value of the parametrised model over the string "123456789" and + may be used to validate an implementation. + + + + + + + + Code generation + + In the default configuration, the generated code is strict ISO C99 code. + A minimal set of three functions are defined for each algorithm: + crc_init(), crc_update() and crc_finalize(). + According to the number of parameters given to &program_name;, a different interface definition is generated. + Fully parametrised models have a simpler API, while the generated code for runtime-specified implementations adds a + pointer to a configuration structure as first parameter to all functions. + + + The generated source code uses the type crc_t, which is used throughout the code. It may be redefined in the generated header file. + + + Fully parametrised models + + The prototypes of these functions are normally generated by &program_name; using the --generate h option. + The prototypes of the + + + +#include <stdlib.h> +/* &program_name; will define the appropriate type + * when generating the header file. */ +typedef XXXX crc_t; + + + + crc_t crc_init + + + + + + crc_t crc_update + crc_t crc + const unsigned char *data + size_t data_len + + + + + crc_t crc_finalize + crc_t crc + + + + + The following code snippet shows how to use the generated functions. + +#include "&program_name;_generated_crc.h" +#include <stdio.h> + +int main(void) +{ + static const unsigned char str1[] = "1234"; + static const unsigned char str2[] = "56789"; + crc_t crc; + + crc = crc_init(); + crc = crc_update(crc, str1, sizeof(str1) - 1); + crc = crc_update(crc, str2, sizeof(str2) - 1); + // more calls to crc_update... + crc = crc_finalize(crc); + + printf("0x%lx\n", (long)crc); + return 0; +} + + + + + Models with runtime-configurable parameters + + When the model is not fully defined then the missing parameters are contained in a structure of + type crc_cfg_t. + The first argument of the CRC functions is a pointer to that structure, and its fields must be initialised + properly by the user before the first call to the CRC functions. + This structure contains three additional parameters, msb_mask, crc_mask + and crc_shift, if the &width; was undefined when the code was generated. + +typedef struct { + unsigned int width; + crc_t poly; + bool reflect_in; + crc_t xor_in; + bool reflect_out; + crc_t xor_out; + + // internal parameters + crc_t msb_mask; // initialise as 1UL << (cfg->width - 1) + crc_t crc_mask; // initialise as (cfg->msb_mask - 1) | cfg->msb_mask + unsigned int crc_shift; // initialise as cfg->width < 8 ? 8 - cfg->width : 0 +} crc_cfg_t; + + + + msb_mask is a bitmask with the most significant bit of a &width; bits + wide data type set to 1. + crc_mask is a bitmask with all bits of a &width; bits + wide data type set to 1. + crc_shift is a shift counter that is used when &width; is less than 8. + It is the number of bits to shift the CRC register to align its top bit at a byte boundary. + + + + The file test/main.c in the source package of &program_name; contains a fully featured example + of how to use the generated source code. + A shorter, more compact main() function can be generated with the --generate c-main + option. + This second variant is the better option when some of the CRC parameters are known and some are unknown during code generation. + + + + + Examples + + + + Calculate the CRC-32 checksum of the string 123456789: + + + python pycrc.py --model crc-32 --check-string 123456789 + + + + + Generate the source code of the table-driven algorithm for an embedded application. + + + python pycrc.py --model crc-16 --algorithm table-driven --table-idx-width 4 --generate h -o crc.h + + + python pycrc.py --model crc-16 --algorithm table-driven --table-idx-width 4 --generate c -o crc.c + + + The table index width of 4 bits ensures a moderate memory consumption. + In fact, the size of the resulting table is 16 * sizeof(crc_t) bytes. + A variant of the last generated output is the c-main target: + a simple main() function is generated in addition to the CRC routines: + + + python pycrc.py --model crc-16 --algorithm table-driven --table-idx-width 4 --generate c-main -o crc.c + + + + + Generate the CRC table only: + + + python pycrc.py --model kermit --generate table -o crc-table.txt + + + + + + + + See Also + + The homepage of &program_name; is http://www.tty1.net/pycrc/. + + + For a long list of known CRC models, see Greg Cook's Catalogue of Parameterised CRC Algorithms. + + + + Copyright + + This work is licensed under a + Creative Commons Attribution-Share Alike 3.0 Unported License. + + + + + diff --git a/pycrc/pycrc.py b/pycrc/pycrc.py new file mode 100644 index 0000000..b5354da --- /dev/null +++ b/pycrc/pycrc.py @@ -0,0 +1,253 @@ +#!/usr/bin/env python +# -*- coding: Latin-1 -*- + +# pycrc -- parametrisable CRC calculation utility and C source code generator +# +# Copyright (c) 2006-2012 Thomas Pircher +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + + +""" +pycrc is a fully parametrisable Cyclic Redundancy Check (CRC) calculation +utility and C source code generator written in Python. + +It can: + - generate the checksum of a string + - generate the checksum of a file + - generate the C header file and source of any of the algorithms below + +It supports the following CRC algorithms: + - bit-by-bit the basic algorithm which operates bit by bit on the + augmented message + - bit-by-bit-fast a variation of the simple bit-by-bit algorithm + - table-driven the standard table driven algorithm +""" + +from crc_opt import Options +from crc_algorithms import Crc +from crc_parser import MacroParser +import binascii +import sys + + +# function print_parameters +############################################################################### +def print_parameters(opt): + """ + Generate a string with the options pretty-printed (used in the --verbose mode). + """ + in_str = "" + in_str += "Width = $crc_width\n" + in_str += "Poly = $crc_poly\n" + in_str += "ReflectIn = $crc_reflect_in\n" + in_str += "XorIn = $crc_xor_in\n" + in_str += "ReflectOut = $crc_reflect_out\n" + in_str += "XorOut = $crc_xor_out\n" + in_str += "Algorithm = $crc_algorithm\n" + + mp = MacroParser(opt) + mp.parse(in_str) + return mp.out_str + + +# function check_string +############################################################################### +def check_string(opt): + """ + Return the calculated CRC sum of a string. + """ + error = False + if opt.UndefinedCrcParameters: + sys.stderr.write("%s: error: undefined parameters\n" % sys.argv[0]) + sys.exit(1) + if opt.Algorithm == 0: + opt.Algorithm = opt.Algo_Bit_by_Bit | opt.Algo_Bit_by_Bit_Fast | opt.Algo_Table_Driven + + alg = Crc(width = opt.Width, poly = opt.Poly, + reflect_in = opt.ReflectIn, xor_in = opt.XorIn, + reflect_out = opt.ReflectOut, xor_out = opt.XorOut, + table_idx_width = opt.TableIdxWidth) + crc = None + if opt.Algorithm & opt.Algo_Bit_by_Bit: + bbb_crc = alg.bit_by_bit(opt.CheckString) + if crc != None and bbb_crc != crc: + error = True + crc = bbb_crc + if opt.Algorithm & opt.Algo_Bit_by_Bit_Fast: + bbf_crc = alg.bit_by_bit_fast(opt.CheckString) + if crc != None and bbf_crc != crc: + error = True + crc = bbf_crc + if opt.Algorithm & opt.Algo_Table_Driven: + opt.TableIdxWidth = 8 # no point making the python implementation slower by using less than 8 bits as index. + tbl_crc = alg.table_driven(opt.CheckString) + if crc != None and tbl_crc != crc: + error = True + crc = tbl_crc + + if error: + sys.stderr.write("%s: error: different checksums!\n" % sys.argv[0]) + if opt.Algorithm & opt.Algo_Bit_by_Bit: + sys.stderr.write(" bit-by-bit: 0x%x\n" % bbb_crc) + if opt.Algorithm & opt.Algo_Bit_by_Bit_Fast: + sys.stderr.write(" bit-by-bit-fast: 0x%x\n" % bbf_crc) + if opt.Algorithm & opt.Algo_Table_Driven: + sys.stderr.write(" table_driven: 0x%x\n" % tbl_crc) + sys.exit(1) + return crc + + +# function check_hexstring +############################################################################### +def check_hexstring(opt): + """ + Return the calculated CRC sum of a hex string. + """ + if opt.UndefinedCrcParameters: + sys.stderr.write("%s: error: undefined parameters\n" % sys.argv[0]) + sys.exit(1) + if len(opt.CheckString) % 2 != 0: + opt.CheckString = "0" + opt.CheckString + try: + check_str = binascii.unhexlify(opt.CheckString) + except TypeError: + sys.stderr.write("%s: error: invalid hex string %s\n" % (sys.argv[0], opt.CheckString)) + sys.exit(1) + + opt.CheckString = check_str + return check_string(opt) + + +# function crc_file_update +############################################################################### +def crc_file_update(alg, register, check_str): + """ + Update the CRC using the bit-by-bit-fast CRC algorithm. + """ + for i in range(len(check_str)): + octet = ord(check_str[i]) + if alg.ReflectIn: + octet = alg.reflect(octet, 8) + for j in range(8): + bit = register & alg.MSB_Mask + register <<= 1 + if octet & (0x80 >> j): + bit ^= alg.MSB_Mask + if bit: + register ^= alg.Poly + register &= alg.Mask + return register + + +# function check_file +############################################################################### +def check_file(opt): + """ + Calculate the CRC of a file. + This algorithm uses the table_driven CRC algorithm. + """ + if opt.UndefinedCrcParameters: + sys.stderr.write("%s: error: undefined parameters\n" % sys.argv[0]) + sys.exit(1) + alg = Crc(width = opt.Width, poly = opt.Poly, + reflect_in = opt.ReflectIn, xor_in = opt.XorIn, + reflect_out = opt.ReflectOut, xor_out = opt.XorOut, + table_idx_width = opt.TableIdxWidth) + + try: + in_file = open(opt.CheckFile, 'rb') + except IOError: + sys.stderr.write("%s: error: can't open file %s\n" % (sys.argv[0], opt.CheckFile)) + sys.exit(1) + + if not opt.ReflectIn: + register = opt.XorIn + else: + register = alg.reflect(opt.XorIn, opt.Width) + try: + check_str = in_file.read() + except IOError: + sys.stderr.write("%s: error: can't open read %s\n" % (sys.argv[0], opt.CheckFile)) + sys.exit(1) + while len(check_str): + register = crc_file_update(alg, register, check_str) + try: + check_str = in_file.read() + except IOError: + sys.stderr.write("%s: error: can't open read %s\n" % (sys.argv[0], opt.CheckFile)) + sys.exit(1) + in_file.close() + + if opt.ReflectOut: + register = alg.reflect(register, opt.Width) + register = register ^ opt.XorOut + return register + + +# main function +############################################################################### +def main(): + """ + Main function. + """ + opt = Options() + opt.parse(sys.argv[1:]) + if opt.Verbose: + print(print_parameters(opt)) + if opt.Action == opt.Action_Check_String: + crc = check_string(opt) + print("0x%x" % crc) + if opt.Action == opt.Action_Check_Hex_String: + crc = check_hexstring(opt) + print("0x%x" % crc) + if opt.Action == opt.Action_Check_File: + crc = check_file(opt) + print("0x%x" % crc) + if opt.Action == opt.Action_Generate_H or opt.Action == opt.Action_Generate_C or opt.Action == opt.Action_Generate_C_Main or opt.Action == opt.Action_Generate_Table: + mp = MacroParser(opt) + if opt.Action == opt.Action_Generate_H: + in_str = "$h_template" + elif opt.Action == opt.Action_Generate_C: + in_str = "$c_template" + elif opt.Action == opt.Action_Generate_C_Main: + in_str = "$c_template\n\n$main_template" + elif opt.Action == opt.Action_Generate_Table: + in_str = "$crc_table_init" + else: + sys.stderr.write("%s: error: unknown action. Please file a bug report!\n" % sys.argv[0]) + sys.exit(1) + mp.parse(in_str) + if opt.OutputFile == None: + print(mp.out_str) + else: + try: + out_file = open(opt.OutputFile, "w") + out_file.write(mp.out_str) + out_file.close() + except IOError: + sys.stderr.write("%s: error: cannot write to file %s\n" % (sys.argv[0], opt.OutputFile)) + sys.exit(1) + return 0 + + +# program entry point +############################################################################### +if __name__ == "__main__": + sys.exit(main()) diff --git a/pycrc/pycrc.pyc b/pycrc/pycrc.pyc new file mode 100644 index 0000000000000000000000000000000000000000..744f9d928bc99ee007dec0047ed2855c8becd431 GIT binary patch literal 6939 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 WzJ%?WuQykkFE>~5x86KA@B9x?u;cFl literal 0 HcmV?d00001 diff --git a/pycrc/test/main.c b/pycrc/test/main.c new file mode 100644 index 0000000..a752dba --- /dev/null +++ b/pycrc/test/main.c @@ -0,0 +1,283 @@ +// Copyright (c) 2006-2010 Thomas Pircher +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include "crc.h" +#include +#include +#include +#include +#include +#include + +static bool atob(const char *str); +static crc_t xtoi(const char *str); +static int get_config(int argc, char *argv[], crc_cfg_t *cfg); +#if CRC_ALGO_BIT_BY_BIT +static crc_t crc_verify(const crc_cfg_t *cfg, crc_t crc_pre_final, crc_t crc); +static crc_t crc_reflect(crc_t data, size_t data_len); +#endif + + + +static bool verbose = false; +static unsigned char str[256] = "123456789"; + +bool atob(const char *str) +{ + if (!str) { + return 0; + } + if (isdigit(str[0])) { + return (bool)atoi(str); + } + if (tolower(str[0]) == 't') { + return true; + } + return false; +} + +crc_t xtoi(const char *str) +{ + crc_t ret = 0; + + if (!str) { + return 0; + } + if (str[0] == '0' && tolower(str[1]) == 'x') { + str += 2; + while (*str) { + if (isdigit(*str)) + ret = 16 * ret + *str - '0'; + else if (isxdigit(*str)) + ret = 16 * ret + tolower(*str) - 'a' + 10; + else + return ret; + str++; + } + } else if (isdigit(*str)) { + while (*str) { + if (isdigit(*str)) + ret = 10 * ret + *str - '0'; + else + return ret; + str++; + } + } + return ret; +} + + +int get_config(int argc, char *argv[], crc_cfg_t *cfg) +{ + int c; + int option_index; + static struct option long_options[] = { + {"width", 1, 0, 'w'}, + {"poly", 1, 0, 'p'}, + {"reflect-in", 1, 0, 'n'}, + {"xor-in", 1, 0, 'i'}, + {"reflect-out", 1, 0, 'u'}, + {"xor-out", 1, 0, 'o'}, + {"verbose", 0, 0, 'v'}, + {"check-string", 1, 0, 's'}, + {"table-idx-with", 1, 0, 't'}, + {0, 0, 0, 0} + }; + + while (1) { + option_index = 0; + + c = getopt_long (argc, argv, "w:p:ni:uo:v", long_options, &option_index); + if (c == -1) + break; + + switch (c) { + case 0: + printf ("option %s", long_options[option_index].name); + if (optarg) + printf (" with arg %s", optarg); + printf ("\n"); + case 'w': + cfg->width = atoi(optarg); + break; + case 'p': + cfg->poly = xtoi(optarg); + break; + case 'n': + cfg->reflect_in = atob(optarg); + break; + case 'i': + cfg->xor_in = xtoi(optarg); + break; + case 'u': + cfg->reflect_out = atob(optarg); + break; + case 'o': + cfg->xor_out = xtoi(optarg); + break; + case 's': + memcpy(str, optarg, strlen(optarg) < sizeof(str) ? strlen(optarg) + 1 : sizeof(str)); + str[sizeof(str) - 1] = '\0'; + break; + case 'v': + verbose = true; + break; + case 't': + // ignore --table_idx_width option + break; + case '?': + return -1; + case ':': + fprintf(stderr, "missing argument to option %c\n", c); + return -1; + default: + fprintf(stderr, "unhandled option %c\n", c); + return -1; + } + } + cfg->msb_mask = 1UL << (cfg->width - 1); + cfg->crc_mask = (cfg->msb_mask - 1) | cfg->msb_mask; + cfg->crc_shift = cfg->width < 8 ? 8 - cfg->width : 0; + + cfg->poly &= cfg->crc_mask; + cfg->xor_in &= cfg->crc_mask; + cfg->xor_out &= cfg->crc_mask; + return 0; +} + + +#if CRC_ALGO_BIT_BY_BIT +crc_t crc_verify(const crc_cfg_t *cfg, crc_t crc_pre_final, crc_t crc) +{ + crc_t result; + unsigned char data; + unsigned int i; + + // don't verify if the width is not a multiple of 8 + if (cfg->width % 8) { + return 0; + } + if (cfg->xor_out) { + crc ^= cfg->xor_out; + } + if (cfg->reflect_out) { + crc = crc_reflect(crc, cfg->width); + } + result = crc_pre_final; + for (i = 0; i < cfg->width / 8; i++) { + data = (crc >> (cfg->width - 8 * i - 8)) & 0xff; + if (cfg->reflect_in) { + data = crc_reflect(data, 8); + } + result = crc_update(cfg, result, &data, 1); + } + // no crc_finalize, because if the CRC calculation is correct, result == 0. + // A crc_finalize would XOR-in again some ones into the solution. + // In theory the finalize function of the bit-by-bit algorithm + // would also loop over cfg->width zero bits, but since + // a) result == 0, and + // b) input data == 0 + // the output would always be zero + return result; +} + +crc_t crc_reflect(crc_t data, size_t data_len) +{ + unsigned int i; + crc_t ret; + + ret = 0; + for (i = 0; i < data_len; i++) + { + if (data & 0x01) { + ret = (ret << 1) | 1; + } else { + ret = ret << 1; + } + data >>= 1; + } + return ret; +} +#endif // CRC_ALGO_BIT_BY_BIT + + +int main(int argc, char *argv[]) +{ + crc_cfg_t cfg = { + 0, // width + 0, // poly + 0, // xor_in + 0, // reflect_in + 0, // xor_out + 0, // reflect_out + + 0, // crc_mask + 0, // msb_mask + 0, // crc_shift + }; + crc_t crc; + crc_t crc_test, crc_pre_final; + char format[20]; + int ret, i; + + ret = get_config(argc, argv, &cfg); + if (ret == 0) { +# if CRC_ALGO_TABLE_DRIVEN + crc_table_gen(&cfg); +# endif // CRC_ALGO_TABLE_DRIVEN + crc = crc_init(&cfg); + crc = crc_pre_final = crc_update(&cfg, crc, str, strlen((char *)str)); + crc = crc_finalize(&cfg, crc); + +# if CRC_ALGO_BIT_BY_BIT + if (crc_verify(&cfg, crc_pre_final, crc) != 0) { + fprintf(stderr, "error: crc verification failed\n"); + return 1; + } +# endif + + // calculate the checksum again, but this time loop over the input + // bytes one-by-one. + crc_test = crc_init(&cfg); + for (i = 0; str[i]; i++) + { + crc_test = crc_update(&cfg, crc_test, str + i, 1); + } + crc_test = crc_finalize(&cfg, crc_test); + if (crc_test != crc) { + fprintf(stderr, "error: crc loop verification failed\n"); + return 1; + } + + if (verbose) { + snprintf(format, sizeof(format), "%%-16s = 0x%%0%dx\n", (unsigned int)(cfg.width + 3) / 4); + printf("%-16s = %d\n", "width", (unsigned int)cfg.width); + printf(format, "poly", (unsigned int)cfg.poly); + printf("%-16s = %s\n", "reflect_in", cfg.reflect_in ? "true": "false"); + printf(format, "xor_in", cfg.xor_in); + printf("%-16s = %s\n", "reflect_out", cfg.reflect_out ? "true": "false"); + printf(format, "xor_out", (unsigned int)cfg.xor_out); + printf(format, "crc_mask", (unsigned int)cfg.crc_mask); + printf(format, "msb_mask", (unsigned int)cfg.msb_mask); + } + printf("0x%lx\n", (unsigned long)crc); + } + return !ret; +} diff --git a/pycrc/test/performance.sh b/pycrc/test/performance.sh new file mode 100644 index 0000000..25c70a4 --- /dev/null +++ b/pycrc/test/performance.sh @@ -0,0 +1,152 @@ +#!/bin/bash +set -e + +PYCRC=`dirname $0`/../pycrc.py + +function cleanup { + rm -f a.out performance.c crc_bbb.[ch] crc_bbf.[ch] crc_tbl.[ch] crc_tb4.[ch] +} + +trap cleanup 0 1 2 3 15 + + +prefix=bbb +$PYCRC --model crc-32 --symbol-prefix crc_${prefix}_ --generate c -o crc_$prefix.c --algo bit-by-bit +$PYCRC --model crc-32 --symbol-prefix crc_${prefix}_ --generate h -o crc_$prefix.h --algo bit-by-bit +prefix=bbf +$PYCRC --model crc-32 --symbol-prefix crc_${prefix}_ --generate h -o crc_$prefix.h --algo bit-by-bit-fast +$PYCRC --model crc-32 --symbol-prefix crc_${prefix}_ --generate c -o crc_$prefix.c --algo bit-by-bit-fast +prefix=tbl +$PYCRC --model crc-32 --symbol-prefix crc_${prefix}_ --generate h -o crc_$prefix.h --algo table-driven +$PYCRC --model crc-32 --symbol-prefix crc_${prefix}_ --generate c -o crc_$prefix.c --algo table-driven +prefix=tb4 +$PYCRC --model crc-32 --symbol-prefix crc_${prefix}_ --generate h -o crc_$prefix.h --algo table-driven --table-idx-width 4 +$PYCRC --model crc-32 --symbol-prefix crc_${prefix}_ --generate c -o crc_$prefix.c --algo table-driven --table-idx-width 4 + + +function print_main { +cat < +#include +#include +#include +#include +#include + +#define NUM_RUNS (256*256) + +unsigned char buf[1024]; + +void test_bbb(unsigned char *buf, size_t buf_len, size_t num_runs, clock_t clock_per_sec); +void test_bbf(unsigned char *buf, size_t buf_len, size_t num_runs, clock_t clock_per_sec); +void test_tbl(unsigned char *buf, size_t buf_len, size_t num_runs, clock_t clock_per_sec); +void test_tb4(unsigned char *buf, size_t buf_len, size_t num_runs, clock_t clock_per_sec); + +/** + * Print results. + * + * \param dsc Description of the test + * \param crc Resulting CRC + * \param buflen Length of one buffer + * \param num_runs Number of runs over that buffer + * \param t_user user time + * \param t_sys system time + * \return void + *****************************************************************************/ +void show_times(const char *dsc, unsigned int crc, size_t buflen, size_t num_runs, double t_user, double t_sys) +{ + printf("%s of %ld bytes (%ld * %ld): 0x%08x\n", dsc, (long)buflen*num_runs, (long)buflen, (long)num_runs, crc); + printf("%13s: %7.3f s\n", "user time", t_user); + printf("%13s: %7.3f s\n", "system time", t_sys); + printf("\n"); +} + + +/** + * C main function. + * + * \retval 0 on success + * \retval 1 on failure + *****************************************************************************/ +int main(void) +{ + unsigned int i; + long int clock_per_sec; + + for (i = 0; i < sizeof(buf); i++) { + buf[i] = (unsigned char)rand(); + } + clock_per_sec = sysconf(_SC_CLK_TCK); + + // bit-by-bit + test_bbb(buf, sizeof(buf), NUM_RUNS, clock_per_sec); + + // bit-by-bit-fast + test_bbf(buf, sizeof(buf), NUM_RUNS, clock_per_sec); + + // table-driven + test_tbl(buf, sizeof(buf), NUM_RUNS, clock_per_sec); + + // table-driven idx4 + test_tb4(buf, sizeof(buf), NUM_RUNS, clock_per_sec); + + return 0; +} +EOF +} + +function print_routine { + algo=$1 + prefix=$2 + cat < performance.c +print_routine "bit-by-bit" bbb >> performance.c +print_routine "bit-by-bit-fast" bbf >> performance.c +print_routine "table-driven" tbl >> performance.c +print_routine "table-driven idx4" tb4 >> performance.c + +gcc -W -Wall -O3 crc_bbb.c crc_bbf.c crc_tbl.c crc_tb4.c performance.c +./a.out diff --git a/pycrc/test/test.sh b/pycrc/test/test.sh new file mode 100644 index 0000000..def5442 --- /dev/null +++ b/pycrc/test/test.sh @@ -0,0 +1,473 @@ +#!/bin/bash +set -e + +PYCRC=`dirname $0`/../pycrc.py + +usage() { + echo >&2 "usage: $0 [OPTIONS]" + echo >&2 "" + echo >&2 "with OPTIONS in" + echo >&2 " -c test compiled version" + echo >&2 " -n test compiled version with fixed parameters" + echo >&2 " -f test file" + echo >&2 " -r test random parameters" + echo >&2 " -p test compiled C program with random arguments" + echo >&2 " -w test variable width from 1 to 64" + echo >&2 " -a do all tests" +} + + +crc_std_test=on +crc_compiled_test=off +crc_compile_noparam_test=off +crc_file_test=off +crc_random_loop_test=off +crc_args_compile_test=off +crc_variable_width_test=off +crc_all_tests=off + +while getopts cnfrpwah opt; do + case "$opt" in + c) crc_compiled_test=on;; + n) crc_compile_noparam_test=on;; + f) crc_file_test=on;; + r) crc_random_loop_test=on;; + p) crc_args_compile_test=on;; + w) crc_variable_width_test=on;; + a) crc_all_tests=on;; + h) usage + exit 0 + ;; + \?) usage # unknown flag + exit 1 + ;; + esac +done +shift `expr $OPTIND - 1` + + +cleanup() { + rm -f crc.c crc.h a.out crc-bb crc-bf crc-td2 crc-td4 crc-td8 file.txt +} + +trap cleanup 0 1 2 3 15 + + +testres() { + testres_lcmd="$1" + testres_lres="$2" + testres_lres=`echo $testres_lres | sed -e 's/.*0x0*\([0-9a-fA-F][0-9a-fA-F]*\).*/\1/'` + testres_lclc=`$testres_lcmd | sed -e '$!d; s/.*0x0*\([0-9a-fA-F][0-9a-fA-F]*\).*/\1/'` + if [ "$testres_lclc" != "$testres_lres" ]; then + echo >&2 test failed: $testres_lcmd + echo >&2 got $testres_lclc instead of expected $testres_lres + return 1 + fi +} + + +teststr() { + teststr_lopt="$1 --check-string 123456789" + teststr_lres="$2" + testres "$teststr_lopt" "$teststr_lres" +} + + +compile() { + compile_lalg="$1" + compile_lopt="$2" + compile_lout="$3" + + $PYCRC --algorithm "$compile_lalg" $compile_lopt --generate h -o crc.h + ldef=`echo "$compile_lopt" | egrep -c 'width|poly|reflect|xor'` || true + if [ "$ldef" -eq 0 ]; then + $PYCRC --algorithm "$compile_lalg" $compile_lopt --generate c -o crc.c + gcc -W -Wall -pedantic -std=c99 main.c crc.c -o "$compile_lout" + else + $PYCRC --algorithm "$compile_lalg" $compile_lopt --generate c-main -o crc.c + gcc -W -Wall -pedantic -std=c99 crc.c -o "$compile_lout" + fi +} + + +testcmp() { + testcmp_lalg="$1" + testcmp_lopt="$2" + testcmp_larg="$3" + testcmp_lres="$4" + + compile "$testcmp_lalg" "$testcmp_lopt --std C89" "a.out" + testres "./a.out $testcmp_larg" "$testcmp_lres" + + compile "$testcmp_lalg" "$testcmp_lopt --std C99" "a.out" + testres "./a.out $testcmp_larg" "$testcmp_lres" +} + + +testbin() { + testbin_lopt="$1" + testbin_lres="$2" + + if [ "$crc_compiled_test" == on -o "$crc_all_tests" == on ]; then + testres "./crc-bb $testbin_lopt" "$testbin_lres" + testres "./crc-bf $testbin_lopt" "$testbin_lres" + testres "./crc-td2 $testbin_lopt" "$testbin_lres" + testres "./crc-td4 $testbin_lopt" "$testbin_lres" + testres "./crc-td8 $testbin_lopt" "$testbin_lres" + + if [ "$crc_compile_noparam_test" == on -o "$crc_all_tests" == on ]; then + testcmp bit-by-bit "$testbin_lopt" "" "$testbin_lres" + testcmp bit-by-bit-fast "$testbin_lopt" "" "$testbin_lres" + testcmp table-driven "$testbin_lopt --table-idx-width 2" "" "$testbin_lres" + testcmp table-driven "$testbin_lopt --table-idx-width 4" "" "$testbin_lres" + testcmp table-driven "$testbin_lopt --table-idx-width 8" "" "$testbin_lres" + fi + fi +} + + +testfil() { + testfil_lopt="$1 --check-file file.txt" + testfil_lres="$2" + + if [ "$crc_file_test" == on -o "$crc_all_tests" == on ]; then + testres "$testfil_lopt" "$testfil_lres" + fi +} + + +if [ "$crc_compiled_test" == on -o "$crc_all_tests" == on ]; then + compile "bit-by-bit" "" "crc-bb" + compile "bit-by-bit-fast" "" "crc-bf" + compile "table-driven" "--table-idx-width 2" "crc-td2" + compile "table-driven" "--table-idx-width 4" "crc-td4" + compile "table-driven" "--table-idx-width 8" "crc-td8" +fi +if [ ! -f file.txt ]; then + echo -n "123456789" > file.txt +fi + + +if [ "$crc_std_test" == on -o "$crc_all_tests" == on ]; then +#CRC-5 +res="0x19" +cmd="$PYCRC --model crc-5" +opt="--width 5 --poly 0x05 --reflect-in 1 --xor-in 0x1f --reflect-out 1 --xor-out 0x1f" +teststr "$cmd" "$res" +teststr "$PYCRC $opt" "$res" +testfil "$cmd" "$res" +testbin "$opt" "$res" + +#CRC-8 +res="0xf4" +cmd="$PYCRC --model crc-8" +opt="--width 8 --poly 0x07 --reflect-in 0 --xor-in 0x0 --reflect-out 0 --xor-out 0x0" +teststr "$cmd" "$res" +teststr "$PYCRC $opt" "$res" +testfil "$cmd" "$res" +testbin "$opt" "$res" + +#DALLAS-1-WIRE +res="0xa1" +cmd="$PYCRC --model dallas-1-wire" +opt="--width 8 --poly 0x31 --reflect-in 1 --xor-in 0 --reflect-out 1 --xor-out 0" +teststr "$cmd" "$res" +teststr "$PYCRC $opt" "$res" +testfil "$cmd" "$res" +testbin "$opt" "$res" + +#3gpp +res="0xdaf" +cmd="$PYCRC --model crc-12-3gpp" +opt="--width 12 --poly 0x80f --reflect-in 0 --xor-in 0x0 --reflect-out 1 --xor-out 0x0" +teststr "$cmd" "$res" +teststr "$PYCRC $opt" "$res" +testfil "$cmd" "$res" +testbin "$opt" "$res" + +#CRC-15 +res="0x59e" +cmd="$PYCRC --model crc-15" +opt="--width 15 --poly 0x4599 --reflect-in 0 --xor-in 0x0 --reflect-out 0 --xor-out 0x0" +teststr "$cmd" "$res" +teststr "$PYCRC $opt" "$res" +testfil "$cmd" "$res" +testbin "$opt" "$res" + +#CRC-16/ARC +res="0xbb3d" +cmd="$PYCRC --model crc-16" +opt="--width 16 --poly 0x8005 --reflect-in 1 --xor-in 0x0 --reflect-out 1 --xor-out 0x0" +teststr "$cmd" "$res" +teststr "$PYCRC $opt" "$res" +testfil "$cmd" "$res" +testbin "$opt" "$res" + +#CRC-16-USB +res="0xb4c8" +cmd="$PYCRC --model crc-16-usb" +opt="--width 16 --poly 0x8005 --reflect-in 1 --xor-in 0xffff --reflect-out 1 --xor-out 0xffff" +teststr "$cmd" "$res" +teststr "$PYCRC $opt" "$res" +testfil "$cmd" "$res" +testbin "$opt" "$res" + +#CRC-16-MODBUS +res="0x4b37" +cmd="$PYCRC --model crc-16-modbus" +opt="--width 16 --poly 0x8005 --reflect-in 1 --xor-in 0xffff --reflect-out 1 --xor-out 0x0" +teststr "$cmd" "$res" +teststr "$PYCRC $opt" "$res" +testfil "$cmd" "$res" +testbin "$opt" "$res" + +#CRC-16-GENIBUS +res="0xd64e" +cmd="$PYCRC --model crc-16-genibus" +opt="--width 16 --poly 0x1021 --reflect-in 0 --xor-in 0xffff --reflect-out 0 --xor-out 0xffff" +teststr "$cmd" "$res" +teststr "$PYCRC $opt" "$res" +testfil "$cmd" "$res" +testbin "$opt" "$res" + +#CRC-16/CITT +res="0x29b1" +cmd="$PYCRC --model ccitt" +opt="--width 16 --poly 0x1021 --reflect-in 0 --xor-in 0xffff --reflect-out 0 --xor-out 0x0" +teststr "$cmd" "$res" +teststr "$PYCRC $opt" "$res" +testfil "$cmd" "$res" +testbin "$opt" "$res" + +#R-CRC-16/DECT packets A-field according to ETSI EN 300 175-3 v2.1.1 +res="0x007e" +cmd="$PYCRC --model r-crc-16" +opt="--width 16 --poly 0x0589 --reflect-in 0 --xor-in 0x0 --reflect-out 0 --xor-out 0x0001" +teststr "$cmd" "$res" +teststr "$PYCRC $opt" "$res" +testfil "$cmd" "$res" +testbin "$opt" "$res" + +#kermit +res="0x2189" +cmd="$PYCRC --model kermit" +opt="--width 16 --poly 0x1021 --reflect-in 1 --xor-in 0x0 --reflect-out 1 --xor-out 0x0" +teststr "$cmd" "$res" +teststr "$PYCRC $opt" "$res" +testfil "$cmd" "$res" +testbin "$opt" "$res" + +#X-25 +res="0x906e" +cmd="$PYCRC --model x-25" +opt="--width 16 --poly 0x1021 --reflect-in 1 --xor-in 0xffff --reflect-out 1 --xor-out 0xffff" +teststr "$cmd" "$res" +teststr "$PYCRC $opt" "$res" +testfil "$cmd" "$res" +testbin "$opt" "$res" + +#xmodem +res="0x31c3" +cmd="$PYCRC --model xmodem" +opt="--width 16 --poly 0x1021 --reflect-in 0 --xor-in 0x0 --reflect-out 0 --xor-out 0x0" +teststr "$cmd" "$res" +teststr "$PYCRC $opt" "$res" +testfil "$cmd" "$res" +testbin "$opt" "$res" + +#zmodem +res="0x31c3" +cmd="$PYCRC --model zmodem" +opt="--width 16 --poly 0x1021 --reflect-in 0 --xor-in 0x0 --reflect-out 0 --xor-out 0x0" +teststr "$cmd" "$res" +teststr "$PYCRC $opt" "$res" +testfil "$cmd" "$res" +testbin "$opt" "$res" + +#crc-24 +res="0x21cf02" +cmd="$PYCRC --model crc-24" +opt="--width 24 --poly 0x1864cfb --reflect-in 0 --xor-in 0xb704ce --reflect-out 0 --xor-out 0x0" +teststr "$cmd" "$res" +teststr "$PYCRC $opt" "$res" +testfil "$cmd" "$res" +testbin "$opt" "$res" + +#CRC-32 +res="0xcbf43926" +cmd="$PYCRC --model crc-32" +opt="--width 32 --poly 0x4c11db7 --reflect-in 1 --xor-in 0xffffffff --reflect-out 1 --xor-out 0xffffffff" +teststr "$cmd" "$res" +teststr "$PYCRC $opt" "$res" +testfil "$cmd" "$res" +testbin "$opt" "$res" + +#CRC-32C +res="0xe3069283" +cmd="$PYCRC --model crc-32c" +opt="--width 32 --poly 0x1edc6f41 --reflect-in 1 --xor-in 0xffffffff --reflect-out 1 --xor-out 0xffffffff" +teststr "$cmd" "$res" +teststr "$PYCRC $opt" "$res" +testfil "$cmd" "$res" +testbin "$opt" "$res" + +#CRC-32/POSIX +res="0x765e7680" +cmd="$PYCRC --model posix" +opt="--width 32 --poly 0x4c11db7 --reflect-in 0 --xor-in 0x0 --reflect-out 0 --xor-out 0xffffffff" +teststr "$cmd" "$res" +teststr "$PYCRC $opt" "$res" +testfil "$cmd" "$res" +testbin "$opt" "$res" + +#JAMCRC +res="0x340bc6d9" +cmd="$PYCRC --model jam" +opt="--width 32 --poly 0x4c11db7 --reflect-in 1 --xor-in 0xffffffff --reflect-out 1 --xor-out 0x0" +teststr "$cmd" "$res" +teststr "$PYCRC $opt" "$res" +testfil "$cmd" "$res" +testbin "$opt" "$res" + +#CRC-32MPEG +res="0x376e6e7" +cmd="$PYCRC --model crc-32-mpeg" +opt="--width 32 --poly 0x4c11db7 --reflect-in 0 --xor-in 0xffffffff --reflect-out 0 --xor-out 0x0" +teststr "$cmd" "$res" +teststr "$PYCRC $opt" "$res" +testfil "$cmd" "$res" +testbin "$opt" "$res" + +#CRC-32-BZIP2 +res="0xfc891918" +cmd="$PYCRC --model crc-32-bzip2" +opt="--width 32 --poly 0x04c11db7 --reflect-in 0 --xor-in 0xffffffff --reflect-out 0 --xor-out 0xffffffff" +teststr "$cmd" "$res" +teststr "$PYCRC $opt" "$res" +testfil "$cmd" "$res" +testbin "$opt" "$res" + +#XFER +res="0xbd0be338" +cmd="$PYCRC --model xfer" +opt="--width 32 --poly 0x000000af --reflect-in 0 --xor-in 0x0 --reflect-out 0 --xor-out 0x0" +teststr "$cmd" "$res" +teststr "$PYCRC $opt" "$res" +testfil "$cmd" "$res" +testbin "$opt" "$res" + +#CRC-64 +res="0x46a5a9388a5beffe" +cmd="$PYCRC --model crc-64" +opt="--width 64 --poly 0x000000000000001b --reflect-in 1 --xor-in 0x0 --reflect-out 1 --xor-out 0x0" +teststr "$cmd" "$res" +teststr "$PYCRC $opt" "$res" +testfil "$cmd" "$res" +testbin "$opt" "$res" + +#CRC-64-jones +res="0xcaa717168609f281" +cmd="$PYCRC --model crc-64-jones" +opt="--width 64 --poly 0xad93d23594c935a9 --reflect-in 1 --xor-in 0xffffffffffffffff --reflect-out 1 --xor-out 0x0" +teststr "$cmd" "$res" +teststr "$PYCRC $opt" "$res" +testfil "$cmd" "$res" +testbin "$opt" "$res" + +#CRC-64-zx +res="0x995dc9bbdf1939fa" +cmd="$PYCRC --model crc-64-xz" +opt="--width 64 --poly 0x42f0e1eba9ea3693 --reflect-in 1 --xor-in 0xffffffffffffffff --reflect-out 1 --xor-out 0xffffffffffffffff" +teststr "$cmd" "$res" +teststr "$PYCRC $opt" "$res" +testfil "$cmd" "$res" +testbin "$opt" "$res" +fi + + +if [ "$crc_random_loop_test" == on -o "$crc_all_tests" == on ]; then + for width in 8 16 32; do + for poly in 0x8005 0x4c11db7 0xa5a5a5a5; do + for refxx in "--reflect-in 0 --reflect-out 0" "--reflect-in 0 --reflect-out 1" "--reflect-in 1 --reflect-out 0" "--reflect-in 1 --reflect-out 1"; do + for init in 0x0 0x1 0xa5a5a5a5; do + opt="--width $width --poly $poly $refxx --xor-in $init --xor-out 0x0" + cmd="$PYCRC $opt" + res=`$cmd` || $cmd + testbin "$opt" "$res" + done + done + done + done +fi + + +if [ "$crc_args_compile_test" == on -o "$crc_all_tests" == on ]; then + #zmodem + res="0x31c3" + opt_width="--width 16" + opt_poly="--poly 0x1021" + opt_refin="--reflect-in 0" + opt_xorin="--xor-in 0x0" + opt_refout="--reflect-out 0" + opt_xorout="--xor-out 0x0" + for b_width in 0 1; do + if [ "$b_width" -eq 1 ]; then cmp_width="$opt_width"; arg_width=""; else cmp_width=""; arg_width="$opt_width"; fi + for b_poly in 0 1; do + if [ "$b_poly" -eq 1 ]; then cmp_poly="$opt_poly"; arg_poly=""; else cmp_poly=""; arg_poly="$opt_poly"; fi + for b_ref_in in 0 1; do + if [ "$b_ref_in" -eq 1 ]; then cmp_refin="$opt_refin"; arg_refin=""; else cmp_refin=""; arg_refin="$opt_refin"; fi + for b_ref_out in 0 1; do + if [ "$b_ref_out" -eq 1 ]; then cmp_refout="$opt_refout"; arg_refout=""; else cmp_refout=""; arg_refout="$opt_refout"; fi + for b_xor_in in 0 1; do + if [ "$b_xor_in" -eq 1 ]; then cmp_xorin="$opt_xorin"; arg_xorin=""; else cmp_xorin=""; arg_xorin="$opt_xorin"; fi + for b_xor_out in 0 1; do + if [ "$b_xor_out" -eq 1 ]; then cmp_xorout="$opt_xorout"; arg_xorout=""; else cmp_xorout=""; arg_xorout="$opt_xorout"; fi + + cmp_opt="$cmp_width $cmp_poly $cmp_refin $cmp_refout $cmp_xorin $cmp_xorout" + arg_opt="$arg_width $arg_poly $arg_refin $arg_refout $arg_xorin $arg_xorout" + testcmp bit-by-bit "$cmp_opt" "$arg_opt" "$res" + testcmp bit-by-bit-fast "$cmp_opt" "$arg_opt" "$res" + testcmp table-driven "$cmp_opt" "$arg_opt" "$res" + done + done + done + done + done + done +fi + + +if [ "$crc_variable_width_test" == on -o "$crc_all_tests" == on ]; then + opt_poly="--poly 0xad93d23594c935a9" + opt_refin="--reflect-in 1" + opt_xorin="--xor-in 0xffffffffffffffff" + opt_refout="--reflect-out 1" + opt_xorout="--xor-out 0x0000000000000000" + for width in 1 2 3 4 5 6 7 8 9 11 12 15 16 17 24 31 32 33 63 64; do + for b_width in 0 1; do + if [ "$b_width" -eq 1 ]; then cmp_width="--width $width"; arg_width=""; else cmp_width=""; arg_width="--width $width"; fi + for b_poly in 0 1; do + if [ "$b_poly" -eq 1 ]; then cmp_poly="$opt_poly"; arg_poly=""; else cmp_poly=""; arg_poly="$opt_poly"; fi + for b_ref_in in 0 1; do + if [ "$b_ref_in" -eq 1 ]; then cmp_refin="$opt_refin"; arg_refin=""; else cmp_refin=""; arg_refin="$opt_refin"; fi + for b_ref_out in 0 1; do + if [ "$b_ref_out" -eq 1 ]; then cmp_refout="$opt_refout"; arg_refout=""; else cmp_refout=""; arg_refout="$opt_refout"; fi + for b_xor_in in 0 1; do + if [ "$b_xor_in" -eq 1 ]; then cmp_xorin="$opt_xorin"; arg_xorin=""; else cmp_xorin=""; arg_xorin="$opt_xorin"; fi + for b_xor_out in 0 1; do + if [ "$b_xor_out" -eq 1 ]; then cmp_xorout="$opt_xorout"; arg_xorout=""; else cmp_xorout=""; arg_xorout="$opt_xorout"; fi + + cmp_opt="$cmp_width $cmp_poly $cmp_refin $cmp_refout $cmp_xorin $cmp_xorout" + arg_opt="$arg_width $arg_poly $arg_refin $arg_refout $arg_xorin $arg_xorout" + res=`$PYCRC --algorithm bit-by-bit $cmp_opt $arg_opt` + testcmp table-driven "$cmp_opt" "$arg_opt" "$res" + done + done + done + done + done + done + done +fi + +echo Test OK