128 lines
3.9 KiB
Python
128 lines
3.9 KiB
Python
# -*- coding: UTF-8 -*-
|
|
#/**
|
|
# * Software Name : pycrate
|
|
# * Version : 0.2
|
|
# *
|
|
# * Copyright 2017. Benoit Michau. ANSSI.
|
|
# *
|
|
# * This program is free software; you can redistribute it and/or
|
|
# * modify it under the terms of the GNU General Public License
|
|
# * as published by the Free Software Foundation; either version 2
|
|
# * of the License, or (at your option) any later version.
|
|
# *
|
|
# * This program is distributed in the hope that it will be useful,
|
|
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# * GNU General Public License for more details.
|
|
# *
|
|
# * You should have received a copy of the GNU General Public License
|
|
# * along with this program; if not, write to the Free Software
|
|
# * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
# * 02110-1301, USA.
|
|
# *
|
|
# *--------------------------------------------------------
|
|
# * File Name : pycrate_csn1/utils.py
|
|
# * Created : 2017-06-12
|
|
# * Authors : Benoit Michau
|
|
# *--------------------------------------------------------
|
|
#*/
|
|
|
|
import re
|
|
|
|
from pycrate_core.elt import Element
|
|
from pycrate_core.utils import *
|
|
from pycrate_core.utils import TYPE_UINT as _TYPE_UINT
|
|
from pycrate_asn1c.utils import scan_for_comments
|
|
from pycrate_asn1c.dictobj import ASN1Dict as CSN1Dict
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
# CSN.1 errors
|
|
#------------------------------------------------------------------------------#
|
|
|
|
# generic CSN.1 error
|
|
class CSN1Err(PycrateErr):
|
|
pass
|
|
|
|
class CSN1InvalidValueErr(CSN1Err):
|
|
pass
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
# text processing
|
|
#------------------------------------------------------------------------------#
|
|
|
|
def clean_text(text=''):
|
|
"""
|
|
processes text to:
|
|
remove ASN.1 comments
|
|
replace tab with space
|
|
remove duplicated spaces
|
|
"""
|
|
# remove comments
|
|
comments = scan_for_comments(text)
|
|
if comments:
|
|
# get the complementary text to comments, to get the text containing
|
|
# the actual definitions
|
|
start, defins = 0, []
|
|
for (so, eo) in comments:
|
|
defins.append( text[start:so] )
|
|
start = eo
|
|
defins.append( text[start:len(text)] )
|
|
text = ''.join(defins)
|
|
#
|
|
# replace tab and \xa0 with space
|
|
text = text.replace('\t', ' ').replace('\xa0', ' ')
|
|
# remove duplicated CR
|
|
text = re.sub('\n{2,}', '\n', text)
|
|
# remove duplicated spaces
|
|
text = re.sub(' {2,}', ' ', text)
|
|
#
|
|
return text
|
|
|
|
def pythonize_name(name=''):
|
|
"""
|
|
pythonize CSN.1 object name
|
|
"""
|
|
# remove any trailing special chars
|
|
name = re.sub('[-/\.\s]{1,}$', '', name)
|
|
# change space(s) and special character(s) to a single underscore
|
|
name = re.sub('[-/\.\s]{1,}', '_', name)
|
|
# do not let name starts with a numeric char
|
|
if name and name[0] in '0123456789':
|
|
name = '_' + name
|
|
return name
|
|
|
|
#------------------------------------------------------------------------------#
|
|
# CSN.1 tokens
|
|
#------------------------------------------------------------------------------#
|
|
|
|
_RE_NAME = '[a-zA-Z0-9_\-/ \.]{1,}'
|
|
|
|
SYNT_RE_NAME = re.compile(
|
|
'<\s{0,}(%s)\s{0,}>\s{0,}' % _RE_NAME)
|
|
SYNT_RE_REPET = re.compile(
|
|
'(?:\(\s{0,}(?:([0-9]{1,})|(\*))\s{0,}\))|(?:\*\s{0,}(?:([0-9]{1,})|(\*)))')
|
|
SYNT_RE_VALUE = re.compile(
|
|
'([01\s]{1,})|([LH\s]{1,})|(null)')
|
|
SYNT_RE_LENREF = re.compile(
|
|
'\(\s{0,}val\s{0,}\(\s{0,}(%s)\)\s{0,}\)\s{0,}\&' % _RE_NAME)
|
|
|
|
#------------------------------------------------------------------------------#
|
|
# value conversion
|
|
#------------------------------------------------------------------------------#
|
|
|
|
CSN1T_UINT = _TYPE_UINT
|
|
CSN1T_BSTR = 20
|
|
|
|
def bitstr_to_uint(bitstr):
|
|
return int(bitstr, 2)
|
|
|
|
def uint_to_bitstr(uint, bl):
|
|
bs = bin(uint)[2:]
|
|
if len(bs) < bl:
|
|
return (bl-len(bs)) * '0' + bs
|
|
else:
|
|
return bs
|
|
|