Added pycrc library (MIT License) for CRC calculations to the repository.

This commit is contained in:
Christian Sltrop 2012-07-30 15:08:37 +02:00
parent c35e26f025
commit 3233dc96b1
24 changed files with 6136 additions and 0 deletions

19
pycrc/COPYING Normal file
View 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
View 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
View 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
View 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

Binary file not shown.

301
pycrc/crc_lexer.py Normal file
View 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

Binary file not shown.

370
pycrc/crc_models.py Normal file
View 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

Binary file not shown.

398
pycrc/crc_opt.py Normal file
View 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

Binary file not shown.

418
pycrc/crc_parser.py Normal file
View 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

Binary file not shown.

1354
pycrc/crc_symtable.py Normal file

File diff suppressed because it is too large Load diff

BIN
pycrc/crc_symtable.pyc Normal file

Binary file not shown.

26
pycrc/doc/Makefile Normal file
View 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
View 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
View 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 &lt;stdlib.h&gt;
/* 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 &lt;stdio.h&gt;
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 &lt;&lt; (cfg-&gt;width - 1)
crc_t crc_mask; // initialise as (cfg-&gt;msb_mask - 1) | cfg-&gt;msb_mask
unsigned int crc_shift; // initialise as cfg-&gt;width &lt; 8 ? 8 - cfg-&gt;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
View 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>&check;</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 &lt;stdlib.h&gt;
/* &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 &lt;stdio.h&gt;
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 &lt;&lt; (cfg-&gt;width - 1)
crc_t crc_mask; // initialise as (cfg-&gt;msb_mask - 1) | cfg-&gt;msb_mask
unsigned int crc_shift; // initialise as cfg-&gt;width &lt; 8 ? 8 - cfg-&gt;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
View 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

Binary file not shown.

283
pycrc/test/main.c Normal file
View 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
View 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
View 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