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