Added pycrc library (MIT License) for CRC calculations to the repository.
This commit is contained in:
parent
c35e26f025
commit
3233dc96b1
24 changed files with 6136 additions and 0 deletions
19
pycrc/COPYING
Normal file
19
pycrc/COPYING
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
Copyright (c) 2006-2012, Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
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.
|
||||||
432
pycrc/ChangeLog
Normal file
432
pycrc/ChangeLog
Normal file
|
|
@ -0,0 +1,432 @@
|
||||||
|
#
|
||||||
|
# Version 0.7.10, 2012-02-13
|
||||||
|
#
|
||||||
|
|
||||||
|
2012-02-08 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* crc_symtable.py:
|
||||||
|
When generating C code for the C89 or ANSI standard, don't include <stdint.h>.
|
||||||
|
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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* all files:
|
||||||
|
Updated the copyright year.
|
||||||
|
Fixed some coding style issues found by pylint and pychecker.
|
||||||
|
|
||||||
|
2010-12-13 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* crc_symtable.py:
|
||||||
|
Fixed a minor bug in the command line parsing of the generated main function.
|
||||||
|
|
||||||
|
2010-08-07 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* crc_symtable.py, crc_parser.py, crc_lexer.py:
|
||||||
|
Rewritten macro parser from scratch. Simplified the macro language.
|
||||||
|
|
||||||
|
2010-08-03 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* pycrc.py, crc_opt.py, crc_algorithms.py, crc_symtable.py:
|
||||||
|
Removed half-baken and confusing --direct option.
|
||||||
|
|
||||||
|
2010-02-10 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* pycrc.py, crc_opt.py: minor code cleanup.
|
||||||
|
|
||||||
|
#
|
||||||
|
# Version 0.7.4, 2010-01-24
|
||||||
|
#
|
||||||
|
|
||||||
|
2010-01-24 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* pycrc.py, crc_opt.py, crc_parser: uniform error messages.
|
||||||
|
* crc_opt.py: added a warning for even polynoms.
|
||||||
|
|
||||||
|
2009-11-12 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* crc_models.py: added crc-16-modbus. Closes issue 2896611.
|
||||||
|
|
||||||
|
2009-11-07 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* crc_models.py: renamed crc-32mpeg to crc-32-mpeg.
|
||||||
|
|
||||||
|
2009-10-19 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* crc_models.py: added crc-64-jones CRC model. Thanks to Waterspirit.
|
||||||
|
|
||||||
|
#
|
||||||
|
# Version 0.7.2, 2009-09-30
|
||||||
|
#
|
||||||
|
|
||||||
|
2009-09-30 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* crc_models.py: added crc-32mpeg. Thanks to Thomas Edwards.
|
||||||
|
|
||||||
|
#
|
||||||
|
# Version 0.7, 2009-02-27
|
||||||
|
#
|
||||||
|
|
||||||
|
2009-02-15 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* crc_opt.py: added --check-hexstring option. Closes issue 2545183.
|
||||||
|
Thanks to Arnim Littek.
|
||||||
|
|
||||||
|
2009-01-31 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* doc/pycrc.xml: Added one more example.
|
||||||
|
|
||||||
|
#
|
||||||
|
# Version 0.6.7, 2008-12-11
|
||||||
|
#
|
||||||
|
|
||||||
|
2008-12-11 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* crc_symtable.py: fixed a bug in the print_params function. Closes issue
|
||||||
|
1985197. Thanks to Artur Lipowski.
|
||||||
|
|
||||||
|
2008-03-03 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* crc_models.py: added dallas-1-wire 8 bit CRC.
|
||||||
|
|
||||||
|
2008-02-07 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* crc_symtable.py: added extern "C" declaration to the generated C header
|
||||||
|
file. Thanks to Nathan Royer.
|
||||||
|
|
||||||
|
2007-12-10 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* crc_symtable.py: fixed some portability problems in the generated code.
|
||||||
|
Thanks to Helmut Bauer. Closes issue 1812894
|
||||||
|
|
||||||
|
2007-09-10 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* crc_symtable.py: simplified the table-driven code. Closes issue 1727128
|
||||||
|
|
||||||
|
2007-08-18 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* crc_symtable.py: Fixed a typo in the C89 source code generator.
|
||||||
|
Thanks to Helmut Bauer
|
||||||
|
|
||||||
|
2007-06-10 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* all files: Tidied up the documentation
|
||||||
|
* all files: Code cleanup
|
||||||
|
|
||||||
|
2007-05-15 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* crc_opt.py: Deleted obsolete options
|
||||||
|
|
||||||
|
#
|
||||||
|
# Version 0.6, 2007-05-21
|
||||||
|
#
|
||||||
|
|
||||||
|
2007-05-15 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* pycrc.py: Added obsolete options again tor legacy reasons.
|
||||||
|
Added a better handling of the --model parameter.
|
||||||
|
|
||||||
|
2007-04-07 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* pycrc.py: Eliminated needless documentation of not generated functions
|
||||||
|
|
||||||
|
2007-01-23 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* 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 <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* test/test.sh: Added a non-regression test on the generated C source
|
||||||
|
|
||||||
|
#
|
||||||
|
# Version 0.3, 2007-01-14
|
||||||
|
#
|
||||||
|
|
||||||
|
2007-01-14 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
|
||||||
|
* pycrc.py: first public release pycrc v0.3
|
||||||
66
pycrc/README
Normal file
66
pycrc/README
Normal file
|
|
@ -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
|
||||||
|
<pycrc-users@lists.sourceforge.net>. 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.
|
||||||
231
pycrc/crc_algorithms.py
Normal file
231
pycrc/crc_algorithms.py
Normal file
|
|
@ -0,0 +1,231 @@
|
||||||
|
# -*- coding: Latin-1 -*-
|
||||||
|
|
||||||
|
# pycrc -- parametrisable CRC calculation utility and C source code generator
|
||||||
|
#
|
||||||
|
# Copyright (c) 2006-2012 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
|
||||||
BIN
pycrc/crc_algorithms.pyc
Normal file
BIN
pycrc/crc_algorithms.pyc
Normal file
Binary file not shown.
301
pycrc/crc_lexer.py
Normal file
301
pycrc/crc_lexer.py
Normal file
|
|
@ -0,0 +1,301 @@
|
||||||
|
# -*- coding: Latin-1 -*-
|
||||||
|
|
||||||
|
# pycrc -- parametrisable CRC calculation utility and C source code generator
|
||||||
|
#
|
||||||
|
# Copyright (c) 2006-2012 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
#
|
||||||
|
# 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
|
||||||
BIN
pycrc/crc_lexer.pyc
Normal file
BIN
pycrc/crc_lexer.pyc
Normal file
Binary file not shown.
370
pycrc/crc_models.py
Normal file
370
pycrc/crc_models.py
Normal file
|
|
@ -0,0 +1,370 @@
|
||||||
|
# -*- coding: Latin-1 -*-
|
||||||
|
|
||||||
|
# pycrc -- parametrisable CRC calculation utility and C source code generator
|
||||||
|
#
|
||||||
|
# Copyright (c) 2006-2012 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
#
|
||||||
|
# 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
|
||||||
BIN
pycrc/crc_models.pyc
Normal file
BIN
pycrc/crc_models.pyc
Normal file
Binary file not shown.
398
pycrc/crc_opt.py
Normal file
398
pycrc/crc_opt.py
Normal file
|
|
@ -0,0 +1,398 @@
|
||||||
|
# -*- coding: Latin-1 -*-
|
||||||
|
|
||||||
|
# pycrc -- parametrisable CRC calculation utility and C source code generator
|
||||||
|
#
|
||||||
|
# Copyright (c) 2006-2012 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
|
||||||
BIN
pycrc/crc_opt.pyc
Normal file
BIN
pycrc/crc_opt.pyc
Normal file
Binary file not shown.
418
pycrc/crc_parser.py
Normal file
418
pycrc/crc_parser.py
Normal file
|
|
@ -0,0 +1,418 @@
|
||||||
|
# -*- coding: Latin-1 -*-
|
||||||
|
|
||||||
|
# pycrc -- parametrisable CRC calculation utility and C source code generator
|
||||||
|
#
|
||||||
|
# Copyright (c) 2006-2012 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
#
|
||||||
|
# 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
|
||||||
BIN
pycrc/crc_parser.pyc
Normal file
BIN
pycrc/crc_parser.pyc
Normal file
Binary file not shown.
1354
pycrc/crc_symtable.py
Normal file
1354
pycrc/crc_symtable.py
Normal file
File diff suppressed because it is too large
Load diff
BIN
pycrc/crc_symtable.pyc
Normal file
BIN
pycrc/crc_symtable.pyc
Normal file
Binary file not shown.
26
pycrc/doc/Makefile
Normal file
26
pycrc/doc/Makefile
Normal file
|
|
@ -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 $< > $@
|
||||||
531
pycrc/doc/pycrc.1
Normal file
531
pycrc/doc/pycrc.1
Normal file
|
|
@ -0,0 +1,531 @@
|
||||||
|
'\" t
|
||||||
|
.\" Title: pycrc
|
||||||
|
.\" Author: Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
.\" Generator: DocBook XSL Stylesheets v1.76.1 <http://docbook.sf.net/>
|
||||||
|
.\" 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 <stdlib\&.h>
|
||||||
|
/* 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 <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\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
|
||||||
247
pycrc/doc/pycrc.html
Normal file
247
pycrc/doc/pycrc.html
Normal file
|
|
@ -0,0 +1,247 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>pycrc</title><meta name="generator" content="DocBook XSL Stylesheets V1.76.1" /></head><body><div class="refentry" title="pycrc"><a id="pycrc"></a><div class="titlepage"></div><div class="refnamediv"><h2>Name</h2><p>pycrc — a free, easy to use Cyclic Redundancy Check (CRC) calculator and source code generator.</p></div><div class="refsynopsisdiv" title="Synopsis"><h2>Synopsis</h2><div class="cmdsynopsis"><p><code class="command">pycrc</code> [OPTIONS]</p></div></div><div class="refsect1" title="Description"><a id="idp66576"></a><h2>Description</h2><p>
|
||||||
|
<a class="ulink" href="http://www.tty1.net/pycrc/" target="_top">pycrc</a>
|
||||||
|
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:
|
||||||
|
</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>
|
||||||
|
generate the checksum of a string (ASCII or hex)
|
||||||
|
</p></li><li class="listitem"><p>
|
||||||
|
generate the checksum of a file
|
||||||
|
</p></li><li class="listitem"><p>
|
||||||
|
generate the C header and source files for a client implementation.
|
||||||
|
</p></li></ul></div><p>
|
||||||
|
</p><p>
|
||||||
|
The following variants of the CRC algorithm are supported:
|
||||||
|
</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>
|
||||||
|
<em class="replaceable"><code>bit-by-bit</code></em>: the basic algorithm which operates individually on every bit of the augmented message
|
||||||
|
(i.e. the input data with <em class="replaceable"><code>Width</code></em> 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.
|
||||||
|
</p></li><li class="listitem"><p>
|
||||||
|
<em class="replaceable"><code>bit-by-bit-fast</code></em>: a variation of the simple <em class="replaceable"><code>bit-by-bit</code></em> algorithm,
|
||||||
|
with the difference that it does not need to augment the data, i.e. it does not add <em class="replaceable"><code>Width</code></em> 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.
|
||||||
|
</p></li><li class="listitem"><p>
|
||||||
|
<em class="replaceable"><code>table-driven</code></em>: 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 <code class="option">--table-idx-width</code> 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.
|
||||||
|
</p></li></ul></div><p>
|
||||||
|
</p></div><div class="refsect1" title="Options"><a id="idp80400"></a><h2>Options</h2><div class="variablelist"><dl><dt><span class="term">
|
||||||
|
<code class="option">--version</code>
|
||||||
|
</span></dt><dd><p>show program's version number and exit</p></dd><dt><span class="term">
|
||||||
|
<code class="option">-h</code>
|
||||||
|
, </span><span class="term">
|
||||||
|
<code class="option">--help</code>
|
||||||
|
</span></dt><dd><p>show this help message and exit</p></dd><dt><span class="term">
|
||||||
|
<code class="option">--verbose</code>
|
||||||
|
</span></dt><dd><p>be more verbose; in particular, print the value of the parameters and the chosen model</p></dd><dt><span class="term">
|
||||||
|
<code class="option">--check-string=</code><em class="replaceable"><code>STRING</code></em>
|
||||||
|
</span></dt><dd><p>calculate the checksum of the given string ('<em class="replaceable"><code>123456789</code></em>' default)</p></dd><dt><span class="term">
|
||||||
|
<code class="option">--check-hexstring=</code><em class="replaceable"><code>STRING</code></em>
|
||||||
|
</span></dt><dd><p>calculate the checksum of the given hexadecimal string</p></dd><dt><span class="term">
|
||||||
|
<code class="option">--check-file=</code><em class="replaceable"><code>FILE</code></em>
|
||||||
|
</span></dt><dd><p>calculate the checksum of the given file</p></dd><dt><span class="term">
|
||||||
|
<code class="option">--generate=</code><em class="replaceable"><code>CODE</code></em>
|
||||||
|
</span></dt><dd><p>generate the source code type as a choice from {c, h, c-main, table}</p></dd><dt><span class="term">
|
||||||
|
<code class="option">--std=</code><em class="replaceable"><code>STD</code></em>
|
||||||
|
</span></dt><dd><p>C standard style of the generated code from {C89, ANSI, C99}</p></dd><dt><span class="term">
|
||||||
|
<code class="option">--algorithm=</code><em class="replaceable"><code>ALGO</code></em>
|
||||||
|
</span></dt><dd><p>choose an algorithm from {<em class="replaceable"><code>bit-by-bit</code></em>, <em class="replaceable"><code>bit-by-bit-fast</code></em>,
|
||||||
|
<em class="replaceable"><code>table-driven</code></em>, <em class="replaceable"><code>all</code></em>}</p></dd><dt><span class="term">
|
||||||
|
<code class="option">--model=</code><em class="replaceable"><code>MODEL</code></em>
|
||||||
|
</span></dt><dd><p>choose a parameter set from
|
||||||
|
{<em class="replaceable"><code>crc-5</code></em>,
|
||||||
|
<em class="replaceable"><code>crc-8</code></em>,
|
||||||
|
<em class="replaceable"><code>dallas-1-wire</code></em>,
|
||||||
|
<em class="replaceable"><code>crc-12-3gpp</code></em>,
|
||||||
|
<em class="replaceable"><code>crc-15</code></em>,
|
||||||
|
<em class="replaceable"><code>crc-16</code></em>,
|
||||||
|
<em class="replaceable"><code>crc-16-usb</code></em>,
|
||||||
|
<em class="replaceable"><code>crc-16-modbus</code></em>,
|
||||||
|
<em class="replaceable"><code>crc-16-genibus</code></em>,
|
||||||
|
<em class="replaceable"><code>ccitt</code></em>,
|
||||||
|
<em class="replaceable"><code>r-crc-16</code></em>,
|
||||||
|
<em class="replaceable"><code>kermit</code></em>,
|
||||||
|
<em class="replaceable"><code>x-25</code></em>,
|
||||||
|
<em class="replaceable"><code>xmodem</code></em>,
|
||||||
|
<em class="replaceable"><code>zmodem</code></em>,
|
||||||
|
<em class="replaceable"><code>crc-24</code></em>,
|
||||||
|
<em class="replaceable"><code>crc-32</code></em>,
|
||||||
|
<em class="replaceable"><code>crc-32c</code></em>,
|
||||||
|
<em class="replaceable"><code>crc-32-mpeg</code></em>,
|
||||||
|
<em class="replaceable"><code>crc-32-bzip2</code></em>,
|
||||||
|
<em class="replaceable"><code>posix</code></em>,
|
||||||
|
<em class="replaceable"><code>jam</code></em>,
|
||||||
|
<em class="replaceable"><code>xfer</code></em>,
|
||||||
|
<em class="replaceable"><code>crc-64</code></em>,
|
||||||
|
<em class="replaceable"><code>crc-64-jones</code></em>,
|
||||||
|
<em class="replaceable"><code>crc-64-xz</code></em>}</p></dd><dt><span class="term">
|
||||||
|
<code class="option">--width=</code><em class="replaceable"><code>NUM</code></em>
|
||||||
|
</span></dt><dd><p>use <em class="replaceable"><code>NUM</code></em> bits in the <em class="replaceable"><code>Polynomial</code></em></p></dd><dt><span class="term">
|
||||||
|
<code class="option">--poly=</code><em class="replaceable"><code>HEX</code></em>
|
||||||
|
</span></dt><dd><p>use <em class="replaceable"><code>HEX</code></em> as <em class="replaceable"><code>Polynomial</code></em></p></dd><dt><span class="term">
|
||||||
|
<code class="option">--reflect-in=</code><em class="replaceable"><code>BOOL</code></em>
|
||||||
|
</span></dt><dd><p>reflect input bytes</p></dd><dt><span class="term">
|
||||||
|
<code class="option">--xor-in=</code><em class="replaceable"><code>HEX</code></em>
|
||||||
|
</span></dt><dd><p>use <em class="replaceable"><code>HEX</code></em> as initial value</p></dd><dt><span class="term">
|
||||||
|
<code class="option">--reflect-out=</code><em class="replaceable"><code>BOOL</code></em>
|
||||||
|
</span></dt><dd><p>reflect output bytes</p></dd><dt><span class="term">
|
||||||
|
<code class="option">--xor-out=</code><em class="replaceable"><code>HEX</code></em>
|
||||||
|
</span></dt><dd><p>xor the final CRC value with <em class="replaceable"><code>HEX</code></em></p></dd><dt><span class="term">
|
||||||
|
<code class="option">--table-idx-width=</code><em class="replaceable"><code>NUM</code></em>
|
||||||
|
</span></dt><dd><p>use <em class="replaceable"><code>NUM</code></em> bits to index the CRC table; <em class="replaceable"><code>NUM</code></em> must be one of the values
|
||||||
|
{<em class="replaceable"><code>1</code></em>, <em class="replaceable"><code>2</code></em>, <em class="replaceable"><code>4</code></em>, <em class="replaceable"><code>8</code></em>}</p></dd><dt><span class="term">
|
||||||
|
<code class="option">--symbol-prefix=</code><em class="replaceable"><code>STRING</code></em>
|
||||||
|
</span></dt><dd><p>when generating source code, use <em class="replaceable"><code>STRING</code></em> as prefix to the generated symbols</p></dd><dt><span class="term">
|
||||||
|
<code class="option">--crc-type=</code><em class="replaceable"><code>STRING</code></em>
|
||||||
|
</span></dt><dd><p>when generating source code, use <em class="replaceable"><code>STRING</code></em> as crc_t type</p></dd><dt><span class="term">
|
||||||
|
<code class="option">--include-file=</code><em class="replaceable"><code>FILE</code></em>
|
||||||
|
</span></dt><dd><p>when generating source code, include also <em class="replaceable"><code>FILE</code></em> as header file</p></dd><dt><span class="term">
|
||||||
|
<code class="option">-o</code><em class="replaceable"><code>FILE</code></em>
|
||||||
|
, </span><span class="term">
|
||||||
|
<code class="option">--output=</code><em class="replaceable"><code>FILE</code></em>
|
||||||
|
</span></dt><dd><p>write the generated code to <em class="replaceable"><code>FILE</code></em> instead to stdout</p></dd></dl></div></div><div class="refsect1" title="The CRC Parametric Model"><a id="idp170688"></a><h2>The CRC Parametric Model</h2><p>
|
||||||
|
The parametric model follows Ross N. Williams' convention described in
|
||||||
|
<a class="ulink" href="http://www.ross.net/crc/crcpaper.html" target="_top">A Painless Guide to CRC Error Detection Algorithms</a>,
|
||||||
|
commonly called the Rocksoft Model.
|
||||||
|
Since most people are familiar with this kind of parameters, pycrc follows this convention, described as follows:
|
||||||
|
</p><div class="glosslist"><dl><dt><em class="replaceable"><code>Width</code></em></dt><dd><p>
|
||||||
|
The width of the CRC <em class="replaceable"><code>Polynomial</code></em>, 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 <em class="replaceable"><code>Width</code></em> for the
|
||||||
|
<em class="replaceable"><code>table-driven</code></em> algorithm. As of version 0.7.5, any <em class="replaceable"><code>Width</code></em> is accepted
|
||||||
|
on all algorithms.
|
||||||
|
</p></dd><dt><em class="replaceable"><code>Polynomial</code></em></dt><dd><p>
|
||||||
|
The unreflected polynomial of the CRC algorithm.
|
||||||
|
</p><p>
|
||||||
|
The <em class="replaceable"><code>Polynomial</code></em> may be specified in its standard form, i.e. with bit <em class="replaceable"><code>Width</code></em>+1
|
||||||
|
set to 1, but the most significant bit may also be omitted. For example, for a <em class="replaceable"><code>Width</code></em> of 16,
|
||||||
|
both forms 0x18005 and 0x8005 are accepted.
|
||||||
|
</p></dd><dt><em class="replaceable"><code>ReflectIn</code></em></dt><dd><p>
|
||||||
|
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.
|
||||||
|
</p><p>
|
||||||
|
Reflected algorithms are more efficient than straight-forward implementations, thus many of the standard algorithmic
|
||||||
|
variants use reflected input bytes.
|
||||||
|
</p></dd><dt><em class="replaceable"><code>XorIn</code></em></dt><dd><p>
|
||||||
|
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 <em class="replaceable"><code>Width</code></em>
|
||||||
|
iterations of the <em class="replaceable"><code>bit-by-bit</code></em> algorithm.
|
||||||
|
This means the simple <em class="replaceable"><code>bit-by-bit</code></em> algorithm must calculate the initial value using some sort of
|
||||||
|
reverse CRC algorithm on the <em class="replaceable"><code>XorIn</code></em> value.
|
||||||
|
</p></dd><dt><em class="replaceable"><code>ReflectOut</code></em></dt><dd><p>
|
||||||
|
Reflect the final CRC result. This operation takes place before XOR-ing the final CRC
|
||||||
|
value with the <em class="replaceable"><code>XorOut</code></em> parameter.
|
||||||
|
</p></dd><dt><em class="replaceable"><code>XorOut</code></em></dt><dd><p>
|
||||||
|
A value (usually all bits 0 or all 1) which will be XOR-ed to the final CRC value.
|
||||||
|
</p></dd><dt><em class="replaceable"><code>Check</code></em></dt><dd><p>
|
||||||
|
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 "<em class="replaceable"><code>123456789</code></em>" and
|
||||||
|
may be used to validate an implementation.
|
||||||
|
</p></dd></dl></div><p>
|
||||||
|
</p></div><div class="refsect1" title="Code generation"><a id="idp203248"></a><h2>Code generation</h2><p>
|
||||||
|
In the default configuration, the generated code is strict ISO C99 code.
|
||||||
|
A minimal set of three functions are defined for each algorithm:
|
||||||
|
<code class="function">crc_init()</code>, <code class="function">crc_update()</code> and <code class="function">crc_finalize()</code>.
|
||||||
|
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.
|
||||||
|
</p><p>
|
||||||
|
The generated source code uses the type <span class="type">crc_t</span>, which is used throughout the code. It may be redefined in the generated header file.
|
||||||
|
</p><div class="refsect2" title="Fully parametrised models"><a id="idp206896"></a><h3>Fully parametrised models</h3><p>
|
||||||
|
The prototypes of these functions are normally generated by pycrc using the <em class="replaceable"><code>--generate h</code></em> option.
|
||||||
|
The prototypes of the
|
||||||
|
</p><div class="funcsynopsis"><pre class="funcsynopsisinfo">
|
||||||
|
#include <stdlib.h>
|
||||||
|
/* pycrc will define the appropriate type
|
||||||
|
* when generating the header file. */
|
||||||
|
typedef XXXX crc_t;
|
||||||
|
</pre><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">crc_t <strong>fsfunccrc_init</strong>(</code></td><td><code>void)</code>;</td><td> </td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">crc_t <strong>fsfunccrc_update</strong>(</code></td><td>crc_t <var class="pdparam">crc</var>, </td></tr><tr><td> </td><td>const unsigned char *<var class="pdparam">data</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">data_len</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">crc_t <strong>fsfunccrc_finalize</strong>(</code></td><td>crc_t <var class="pdparam">crc</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div></div><p>
|
||||||
|
The following code snippet shows how to use the generated functions.
|
||||||
|
</p><pre class="programlisting">
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
</pre><p>
|
||||||
|
</p></div><div class="refsect2" title="Models with runtime-configurable parameters"><a id="idp218176"></a><h3>Models with runtime-configurable parameters</h3><p>
|
||||||
|
When the model is not fully defined then the missing parameters are contained in a structure of
|
||||||
|
type <span class="type">crc_cfg_t</span>.
|
||||||
|
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, <em class="parameter"><code>msb_mask</code></em>, <em class="parameter"><code>crc_mask</code></em>
|
||||||
|
and <em class="parameter"><code>crc_shift</code></em>, if the <em class="replaceable"><code>Width</code></em> was undefined when the code was generated.
|
||||||
|
</p><pre class="programlisting">
|
||||||
|
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;
|
||||||
|
</pre><p>
|
||||||
|
</p><p>
|
||||||
|
<em class="parameter"><code>msb_mask</code></em> is a bitmask with the most significant bit of a <em class="replaceable"><code>Width</code></em> bits
|
||||||
|
wide data type set to 1.
|
||||||
|
<em class="parameter"><code>crc_mask</code></em> is a bitmask with all bits of a <em class="replaceable"><code>Width</code></em> bits
|
||||||
|
wide data type set to 1.
|
||||||
|
<em class="parameter"><code>crc_shift</code></em> is a shift counter that is used when <em class="replaceable"><code>Width</code></em> is less than 8.
|
||||||
|
It is the number of bits to shift the CRC register to align its top bit at a byte boundary.
|
||||||
|
</p><p>
|
||||||
|
The file <code class="filename">test/main.c</code> in the source package of pycrc contains a fully featured example
|
||||||
|
of how to use the generated source code.
|
||||||
|
A shorter, more compact <code class="code">main()</code> function can be generated with the <em class="replaceable"><code>--generate c-main</code></em>
|
||||||
|
option.
|
||||||
|
This second variant is the better option when some of the CRC parameters are known and some are unknown during code generation.
|
||||||
|
</p></div></div><div class="refsect1" title="Examples"><a id="idp228256"></a><h2>Examples</h2><p>
|
||||||
|
</p><div class="glosslist"><dl><dt>Calculate the CRC-32 checksum of the string 123456789:</dt><dd><p>
|
||||||
|
<strong class="userinput"><code>python pycrc.py --model crc-32 --check-string 123456789</code></strong>
|
||||||
|
</p></dd><dt>Generate the source code of the table-driven algorithm for an embedded application.</dt><dd><p>
|
||||||
|
<strong class="userinput"><code>python pycrc.py --model crc-16 --algorithm table-driven --table-idx-width 4 --generate h -o crc.h</code></strong>
|
||||||
|
</p><p>
|
||||||
|
<strong class="userinput"><code>python pycrc.py --model crc-16 --algorithm table-driven --table-idx-width 4 --generate c -o crc.c</code></strong>
|
||||||
|
</p><p>
|
||||||
|
The table index width of 4 bits ensures a moderate memory consumption.
|
||||||
|
In fact, the size of the resulting table is <code class="code">16 * sizeof(crc_t)</code> bytes.
|
||||||
|
A variant of the last generated output is the <em class="replaceable"><code>c-main</code></em> target:
|
||||||
|
a simple <em class="replaceable"><code>main()</code></em> function is generated in addition to the CRC routines:
|
||||||
|
</p><p>
|
||||||
|
<strong class="userinput"><code>python pycrc.py --model crc-16 --algorithm table-driven --table-idx-width 4 --generate c-main -o crc.c</code></strong>
|
||||||
|
</p></dd><dt>Generate the CRC table only:</dt><dd><p>
|
||||||
|
<strong class="userinput"><code>python pycrc.py --model kermit --generate table -o crc-table.txt</code></strong>
|
||||||
|
</p></dd></dl></div><p>
|
||||||
|
</p></div><div class="refsect1" title="See Also"><a id="idp239696"></a><h2>See Also</h2><p>
|
||||||
|
The homepage of pycrc is <a class="ulink" href="http://www.tty1.net/pycrc/" target="_top">http://www.tty1.net/pycrc/</a>.
|
||||||
|
</p><p>
|
||||||
|
For a long list of known CRC models, see Greg Cook's <a class="ulink" href="http://regregex.bbcmicro.net/crc-catalogue.htm" target="_top">Catalogue of Parameterised CRC Algorithms</a>.
|
||||||
|
</p></div><div class="refsect1" title="Copyright"><a id="idp242800"></a><h2>Copyright</h2><p>
|
||||||
|
This work is licensed under a
|
||||||
|
<a class="ulink" href="http://creativecommons.org/licenses/by-sa/3.0/" target="_top">Creative Commons Attribution-Share Alike 3.0 Unported License</a>.
|
||||||
|
</p></div></div></body></html>
|
||||||
582
pycrc/doc/pycrc.xml
Normal file
582
pycrc/doc/pycrc.xml
Normal file
|
|
@ -0,0 +1,582 @@
|
||||||
|
<?xml version='1.0'?>
|
||||||
|
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
|
||||||
|
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||||
|
<!ENTITY program_name "pycrc">
|
||||||
|
<!ENTITY program_version "0.7.9">
|
||||||
|
<!ENTITY date "2011-11-19">
|
||||||
|
<!ENTITY author_firstname "Thomas">
|
||||||
|
<!ENTITY author_surname "Pircher">
|
||||||
|
<!ENTITY author_email "tehpeh@gmx.net">
|
||||||
|
<!ENTITY author "&author_firstname; &author_surname;">
|
||||||
|
<!ENTITY bit-by-bit "bit-by-bit">
|
||||||
|
<!ENTITY bit-by-bit-fast "bit-by-bit-fast">
|
||||||
|
<!ENTITY table-driven "table-driven">
|
||||||
|
<!ENTITY width "Width">
|
||||||
|
<!ENTITY poly "Polynomial">
|
||||||
|
<!ENTITY reflect_in "ReflectIn">
|
||||||
|
<!ENTITY xor_in "XorIn">
|
||||||
|
<!ENTITY reflect_out "ReflectOut">
|
||||||
|
<!ENTITY xor_out "XorOut">
|
||||||
|
<!ENTITY check "Check">
|
||||||
|
]>
|
||||||
|
|
||||||
|
<refentry id="&program_name;">
|
||||||
|
|
||||||
|
<refentryinfo>
|
||||||
|
<title>&program_name;</title>
|
||||||
|
<productname>&program_name;</productname>
|
||||||
|
<productnumber>&program_version;</productnumber>
|
||||||
|
<author>
|
||||||
|
<firstname>&author_firstname;</firstname>
|
||||||
|
<surname>&author_surname;</surname>
|
||||||
|
<contrib>Author of &program_name; and this manual page.</contrib>
|
||||||
|
<email>&author_email;</email>
|
||||||
|
</author>
|
||||||
|
<date>&date;</date>
|
||||||
|
</refentryinfo>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>&program_name;</refentrytitle>
|
||||||
|
<manvolnum>1</manvolnum>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>&program_name;</refname>
|
||||||
|
<refpurpose>a free, easy to use Cyclic Redundancy Check (CRC) calculator and source code generator.</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsynopsisdiv>
|
||||||
|
<cmdsynopsis>
|
||||||
|
<command>&program_name;</command>
|
||||||
|
<arg>OPTIONS</arg>
|
||||||
|
</cmdsynopsis>
|
||||||
|
</refsynopsisdiv>
|
||||||
|
|
||||||
|
<refsect1><title>Description</title>
|
||||||
|
<para>
|
||||||
|
<ulink url="http://www.tty1.net/pycrc/">&program_name;</ulink>
|
||||||
|
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:
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
generate the checksum of a string (ASCII or hex)
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
generate the checksum of a file
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
generate the C header and source files for a client implementation.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The following variants of the CRC algorithm are supported:
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<replaceable>&bit-by-bit;</replaceable>: the basic algorithm which operates individually on every bit of the augmented message
|
||||||
|
(i.e. the input data with <replaceable>&width;</replaceable> 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.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<replaceable>&bit-by-bit-fast;</replaceable>: a variation of the simple <replaceable>&bit-by-bit;</replaceable> algorithm,
|
||||||
|
with the difference that it does not need to augment the data, i.e. it does not add <replaceable>&width;</replaceable> 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.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<replaceable>&table-driven;</replaceable>: 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 <option>--table-idx-width</option> 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.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1><title>Options</title>
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>--version</option>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>show program's version number and exit</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>-h</option>
|
||||||
|
</term>
|
||||||
|
<term>
|
||||||
|
<option>--help</option>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>show this help message and exit</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>--verbose</option>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>be more verbose; in particular, print the value of the parameters and the chosen model</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>--check-string=</option><replaceable>STRING</replaceable>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>calculate the checksum of the given string ('<replaceable>123456789</replaceable>' default)</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>--check-hexstring=</option><replaceable>STRING</replaceable>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>calculate the checksum of the given hexadecimal string</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>--check-file=</option><replaceable>FILE</replaceable>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>calculate the checksum of the given file</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>--generate=</option><replaceable>CODE</replaceable>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>generate the source code type as a choice from {c, h, c-main, table}</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>--std=</option><replaceable>STD</replaceable>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>C standard style of the generated code from {C89, ANSI, C99}</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>--algorithm=</option><replaceable>ALGO</replaceable>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>choose an algorithm from {<replaceable>bit-by-bit</replaceable>, <replaceable>bit-by-bit-fast</replaceable>,
|
||||||
|
<replaceable>table-driven</replaceable>, <replaceable>all</replaceable>}</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>--model=</option><replaceable>MODEL</replaceable>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>choose a parameter set from
|
||||||
|
{<replaceable>crc-5</replaceable>,
|
||||||
|
<replaceable>crc-8</replaceable>,
|
||||||
|
<replaceable>dallas-1-wire</replaceable>,
|
||||||
|
<replaceable>crc-12-3gpp</replaceable>,
|
||||||
|
<replaceable>crc-15</replaceable>,
|
||||||
|
<replaceable>crc-16</replaceable>,
|
||||||
|
<replaceable>crc-16-usb</replaceable>,
|
||||||
|
<replaceable>crc-16-modbus</replaceable>,
|
||||||
|
<replaceable>crc-16-genibus</replaceable>,
|
||||||
|
<replaceable>ccitt</replaceable>,
|
||||||
|
<replaceable>r-crc-16</replaceable>,
|
||||||
|
<replaceable>kermit</replaceable>,
|
||||||
|
<replaceable>x-25</replaceable>,
|
||||||
|
<replaceable>xmodem</replaceable>,
|
||||||
|
<replaceable>zmodem</replaceable>,
|
||||||
|
<replaceable>crc-24</replaceable>,
|
||||||
|
<replaceable>crc-32</replaceable>,
|
||||||
|
<replaceable>crc-32c</replaceable>,
|
||||||
|
<replaceable>crc-32-mpeg</replaceable>,
|
||||||
|
<replaceable>crc-32-bzip2</replaceable>,
|
||||||
|
<replaceable>posix</replaceable>,
|
||||||
|
<replaceable>jam</replaceable>,
|
||||||
|
<replaceable>xfer</replaceable>,
|
||||||
|
<replaceable>crc-64</replaceable>,
|
||||||
|
<replaceable>crc-64-jones</replaceable>,
|
||||||
|
<replaceable>crc-64-xz</replaceable>}</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>--width=</option><replaceable>NUM</replaceable>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>use <replaceable>NUM</replaceable> bits in the <replaceable>&poly;</replaceable></para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>--poly=</option><replaceable>HEX</replaceable>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>use <replaceable>HEX</replaceable> as <replaceable>&poly;</replaceable></para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>--reflect-in=</option><replaceable>BOOL</replaceable>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>reflect input bytes</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>--xor-in=</option><replaceable>HEX</replaceable>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>use <replaceable>HEX</replaceable> as initial value</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>--reflect-out=</option><replaceable>BOOL</replaceable>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>reflect output bytes</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>--xor-out=</option><replaceable>HEX</replaceable>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>xor the final CRC value with <replaceable>HEX</replaceable></para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>--table-idx-width=</option><replaceable>NUM</replaceable>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>use <replaceable>NUM</replaceable> bits to index the CRC table; <replaceable>NUM</replaceable> must be one of the values
|
||||||
|
{<replaceable>1</replaceable>, <replaceable>2</replaceable>, <replaceable>4</replaceable>, <replaceable>8</replaceable>}</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>--symbol-prefix=</option><replaceable>STRING</replaceable>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>when generating source code, use <replaceable>STRING</replaceable> as prefix to the generated symbols</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>--crc-type=</option><replaceable>STRING</replaceable>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>when generating source code, use <replaceable>STRING</replaceable> as crc_t type</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>--include-file=</option><replaceable>FILE</replaceable>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>when generating source code, include also <replaceable>FILE</replaceable> as header file</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>-o</option><replaceable>FILE</replaceable>
|
||||||
|
</term>
|
||||||
|
<term>
|
||||||
|
<option>--output=</option><replaceable>FILE</replaceable>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>write the generated code to <replaceable>FILE</replaceable> instead to stdout</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1><title>The CRC Parametric Model</title>
|
||||||
|
<para>
|
||||||
|
The parametric model follows Ross N. Williams' convention described in
|
||||||
|
<ulink url="http://www.ross.net/crc/crcpaper.html">A Painless Guide to CRC Error Detection Algorithms</ulink>,
|
||||||
|
commonly called the Rocksoft Model.
|
||||||
|
Since most people are familiar with this kind of parameters, &program_name; follows this convention, described as follows:
|
||||||
|
<glosslist>
|
||||||
|
<glossentry>
|
||||||
|
<glossterm><replaceable>&width;</replaceable></glossterm>
|
||||||
|
<glossdef>
|
||||||
|
<para>
|
||||||
|
The width of the CRC <replaceable>&poly;</replaceable>, 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 <replaceable>&width;</replaceable> for the
|
||||||
|
<replaceable>&table-driven;</replaceable> algorithm. As of version 0.7.5, any <replaceable>&width;</replaceable> is accepted
|
||||||
|
on all algorithms.
|
||||||
|
</para>
|
||||||
|
</glossdef>
|
||||||
|
</glossentry>
|
||||||
|
<glossentry>
|
||||||
|
<glossterm><replaceable>&poly;</replaceable></glossterm>
|
||||||
|
<glossdef>
|
||||||
|
<para>
|
||||||
|
The unreflected polynomial of the CRC algorithm.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The <replaceable>&poly;</replaceable> may be specified in its standard form, i.e. with bit <replaceable>&width;</replaceable>+1
|
||||||
|
set to 1, but the most significant bit may also be omitted. For example, for a <replaceable>&width;</replaceable> of 16,
|
||||||
|
both forms 0x18005 and 0x8005 are accepted.
|
||||||
|
</para>
|
||||||
|
</glossdef>
|
||||||
|
</glossentry>
|
||||||
|
<glossentry>
|
||||||
|
<glossterm><replaceable>&reflect_in;</replaceable></glossterm>
|
||||||
|
<glossdef>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Reflected algorithms are more efficient than straight-forward implementations, thus many of the standard algorithmic
|
||||||
|
variants use reflected input bytes.
|
||||||
|
</para>
|
||||||
|
</glossdef>
|
||||||
|
</glossentry>
|
||||||
|
<glossentry>
|
||||||
|
<glossterm><replaceable>&xor_in;</replaceable></glossterm>
|
||||||
|
<glossdef>
|
||||||
|
<para>
|
||||||
|
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 <replaceable>&width;</replaceable>
|
||||||
|
iterations of the <replaceable>&bit-by-bit;</replaceable> algorithm.
|
||||||
|
This means the simple <replaceable>&bit-by-bit;</replaceable> algorithm must calculate the initial value using some sort of
|
||||||
|
reverse CRC algorithm on the <replaceable>&xor_in;</replaceable> value.
|
||||||
|
</para>
|
||||||
|
</glossdef>
|
||||||
|
</glossentry>
|
||||||
|
<glossentry>
|
||||||
|
<glossterm><replaceable>&reflect_out;</replaceable></glossterm>
|
||||||
|
<glossdef>
|
||||||
|
<para>
|
||||||
|
Reflect the final CRC result. This operation takes place before XOR-ing the final CRC
|
||||||
|
value with the <replaceable>&xor_out;</replaceable> parameter.
|
||||||
|
</para>
|
||||||
|
</glossdef>
|
||||||
|
</glossentry>
|
||||||
|
<glossentry>
|
||||||
|
<glossterm><replaceable>&xor_out;</replaceable></glossterm>
|
||||||
|
<glossdef>
|
||||||
|
<para>
|
||||||
|
A value (usually all bits 0 or all 1) which will be XOR-ed to the final CRC value.
|
||||||
|
</para>
|
||||||
|
</glossdef>
|
||||||
|
</glossentry>
|
||||||
|
<glossentry>
|
||||||
|
<glossterm><replaceable>✓</replaceable></glossterm>
|
||||||
|
<glossdef>
|
||||||
|
<para>
|
||||||
|
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 "<replaceable>123456789</replaceable>" and
|
||||||
|
may be used to validate an implementation.
|
||||||
|
</para>
|
||||||
|
</glossdef>
|
||||||
|
</glossentry>
|
||||||
|
</glosslist>
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1><title>Code generation</title>
|
||||||
|
<para>
|
||||||
|
In the default configuration, the generated code is strict ISO C99 code.
|
||||||
|
A minimal set of three functions are defined for each algorithm:
|
||||||
|
<function>crc_init()</function>, <function>crc_update()</function> and <function>crc_finalize()</function>.
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The generated source code uses the type <type>crc_t</type>, which is used throughout the code. It may be redefined in the generated header file.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<refsect2><title>Fully parametrised models</title>
|
||||||
|
<para>
|
||||||
|
The prototypes of these functions are normally generated by &program_name; using the <replaceable>--generate h</replaceable> option.
|
||||||
|
The prototypes of the
|
||||||
|
</para>
|
||||||
|
<funcsynopsis>
|
||||||
|
<funcsynopsisinfo>
|
||||||
|
#include <stdlib.h>
|
||||||
|
/* &program_name; will define the appropriate type
|
||||||
|
* when generating the header file. */
|
||||||
|
typedef XXXX crc_t;
|
||||||
|
</funcsynopsisinfo>
|
||||||
|
<funcprototype>
|
||||||
|
<?dbhtml funcsynopsis-style='ansi'?>
|
||||||
|
<funcdef>crc_t <function>crc_init</function></funcdef>
|
||||||
|
<void/>
|
||||||
|
</funcprototype>
|
||||||
|
|
||||||
|
<funcprototype>
|
||||||
|
<?dbhtml funcsynopsis-style='ansi'?>
|
||||||
|
<funcdef>crc_t <function>crc_update</function></funcdef>
|
||||||
|
<paramdef>crc_t <parameter>crc</parameter></paramdef>
|
||||||
|
<paramdef>const unsigned char *<parameter>data</parameter></paramdef>
|
||||||
|
<paramdef>size_t <parameter>data_len</parameter></paramdef>
|
||||||
|
</funcprototype>
|
||||||
|
|
||||||
|
<funcprototype>
|
||||||
|
<?dbhtml funcsynopsis-style='ansi'?>
|
||||||
|
<funcdef>crc_t <function>crc_finalize</function></funcdef>
|
||||||
|
<paramdef>crc_t <parameter>crc</parameter></paramdef>
|
||||||
|
</funcprototype>
|
||||||
|
</funcsynopsis>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The following code snippet shows how to use the generated functions.
|
||||||
|
<programlisting>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
</refsect2>
|
||||||
|
|
||||||
|
<refsect2><title>Models with runtime-configurable parameters</title>
|
||||||
|
<para>
|
||||||
|
When the model is not fully defined then the missing parameters are contained in a structure of
|
||||||
|
type <type>crc_cfg_t</type>.
|
||||||
|
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, <parameter>msb_mask</parameter>, <parameter>crc_mask</parameter>
|
||||||
|
and <parameter>crc_shift</parameter>, if the <replaceable>&width;</replaceable> was undefined when the code was generated.
|
||||||
|
<programlisting>
|
||||||
|
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;
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<parameter>msb_mask</parameter> is a bitmask with the most significant bit of a <replaceable>&width;</replaceable> bits
|
||||||
|
wide data type set to 1.
|
||||||
|
<parameter>crc_mask</parameter> is a bitmask with all bits of a <replaceable>&width;</replaceable> bits
|
||||||
|
wide data type set to 1.
|
||||||
|
<parameter>crc_shift</parameter> is a shift counter that is used when <replaceable>&width;</replaceable> is less than 8.
|
||||||
|
It is the number of bits to shift the CRC register to align its top bit at a byte boundary.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The file <filename>test/main.c</filename> in the source package of &program_name; contains a fully featured example
|
||||||
|
of how to use the generated source code.
|
||||||
|
A shorter, more compact <code>main()</code> function can be generated with the <replaceable>--generate c-main</replaceable>
|
||||||
|
option.
|
||||||
|
This second variant is the better option when some of the CRC parameters are known and some are unknown during code generation.
|
||||||
|
</para>
|
||||||
|
</refsect2>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1><title>Examples</title>
|
||||||
|
<para>
|
||||||
|
<glosslist>
|
||||||
|
<glossentry>
|
||||||
|
<glossterm>Calculate the CRC-32 checksum of the string 123456789:</glossterm>
|
||||||
|
<glossdef>
|
||||||
|
<para>
|
||||||
|
<userinput>python pycrc.py --model crc-32 --check-string 123456789</userinput>
|
||||||
|
</para>
|
||||||
|
</glossdef>
|
||||||
|
</glossentry>
|
||||||
|
<glossentry>
|
||||||
|
<glossterm>Generate the source code of the table-driven algorithm for an embedded application.</glossterm>
|
||||||
|
<glossdef>
|
||||||
|
<para>
|
||||||
|
<userinput>python pycrc.py --model crc-16 --algorithm table-driven --table-idx-width 4 --generate h -o crc.h</userinput>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<userinput>python pycrc.py --model crc-16 --algorithm table-driven --table-idx-width 4 --generate c -o crc.c</userinput>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The table index width of 4 bits ensures a moderate memory consumption.
|
||||||
|
In fact, the size of the resulting table is <code>16 * sizeof(crc_t)</code> bytes.
|
||||||
|
A variant of the last generated output is the <replaceable>c-main</replaceable> target:
|
||||||
|
a simple <replaceable>main()</replaceable> function is generated in addition to the CRC routines:
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<userinput>python pycrc.py --model crc-16 --algorithm table-driven --table-idx-width 4 --generate c-main -o crc.c</userinput>
|
||||||
|
</para>
|
||||||
|
</glossdef>
|
||||||
|
</glossentry>
|
||||||
|
<glossentry>
|
||||||
|
<glossterm>Generate the CRC table only:</glossterm>
|
||||||
|
<glossdef>
|
||||||
|
<para>
|
||||||
|
<userinput>python pycrc.py --model kermit --generate table -o crc-table.txt</userinput>
|
||||||
|
</para>
|
||||||
|
</glossdef>
|
||||||
|
</glossentry>
|
||||||
|
</glosslist>
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1><title>See Also</title>
|
||||||
|
<para>
|
||||||
|
The homepage of &program_name; is <ulink url="http://www.tty1.net/pycrc/">http://www.tty1.net/pycrc/</ulink>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For a long list of known CRC models, see Greg Cook's <ulink url="http://regregex.bbcmicro.net/crc-catalogue.htm">Catalogue of Parameterised CRC Algorithms</ulink>.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1><title>Copyright</title>
|
||||||
|
<para>
|
||||||
|
This work is licensed under a
|
||||||
|
<ulink url="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-Share Alike 3.0 Unported License</ulink>.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
</refentry>
|
||||||
|
|
||||||
253
pycrc/pycrc.py
Normal file
253
pycrc/pycrc.py
Normal file
|
|
@ -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 <tehpeh@gmx.net>
|
||||||
|
#
|
||||||
|
# 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())
|
||||||
BIN
pycrc/pycrc.pyc
Normal file
BIN
pycrc/pycrc.pyc
Normal file
Binary file not shown.
283
pycrc/test/main.c
Normal file
283
pycrc/test/main.c
Normal file
|
|
@ -0,0 +1,283 @@
|
||||||
|
// Copyright (c) 2006-2010 Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
//
|
||||||
|
// 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 <getopt.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
152
pycrc/test/performance.sh
Normal file
152
pycrc/test/performance.sh
Normal file
|
|
@ -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 <<EOF
|
||||||
|
#include "crc_bbb.h"
|
||||||
|
#include "crc_bbf.h"
|
||||||
|
#include "crc_tbl.h"
|
||||||
|
#include "crc_tb4.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/times.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#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 <<EOF
|
||||||
|
/**
|
||||||
|
* Test $algo Algorithm.
|
||||||
|
*
|
||||||
|
* \return void
|
||||||
|
*****************************************************************************/
|
||||||
|
void test_${prefix}(unsigned char *buf, size_t buf_len, size_t num_runs, clock_t clock_per_sec)
|
||||||
|
{
|
||||||
|
crc_${prefix}_t crc;
|
||||||
|
unsigned int i, j;
|
||||||
|
struct tms tm1, tm2;
|
||||||
|
|
||||||
|
times(&tm1);
|
||||||
|
crc = crc_${prefix}_init();
|
||||||
|
for (i = 0; i < num_runs; i++) {
|
||||||
|
crc = crc_${prefix}_update(crc, buf, buf_len);
|
||||||
|
}
|
||||||
|
crc = crc_${prefix}_finalize(crc);
|
||||||
|
times(&tm2);
|
||||||
|
show_times("CRC32, $algo, block-wise", crc, buf_len, num_runs,
|
||||||
|
((double)(tm2.tms_utime - tm1.tms_utime) / (double)clock_per_sec),
|
||||||
|
((double)(tm2.tms_stime - tm1.tms_stime) / (double)clock_per_sec));
|
||||||
|
|
||||||
|
times(&tm1);
|
||||||
|
crc = crc_${prefix}_init();
|
||||||
|
for (i = 0; i < num_runs; i++) {
|
||||||
|
for (j = 0; j < buf_len; j++) {
|
||||||
|
crc = crc_${prefix}_update(crc, &buf[j], 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
crc = crc_${prefix}_finalize(crc);
|
||||||
|
times(&tm2);
|
||||||
|
show_times("CRC32, $algo, byte-wise", crc, buf_len, num_runs,
|
||||||
|
((double)(tm2.tms_utime - tm1.tms_utime) / (double)clock_per_sec),
|
||||||
|
((double)(tm2.tms_stime - tm1.tms_stime) / (double)clock_per_sec));
|
||||||
|
}
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
print_main > 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
|
||||||
473
pycrc/test/test.sh
Normal file
473
pycrc/test/test.sh
Normal file
|
|
@ -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
|
||||||
Loading…
Add table
Add a link
Reference in a new issue