2017-07-04 21:12:41 +00:00
|
|
|
# -*- coding: UTF-8 -*-
|
|
|
|
#/**
|
|
|
|
# * Software Name : pycrate
|
2019-02-25 10:26:10 +00:00
|
|
|
# * Version : 0.4
|
2017-07-04 21:12:41 +00:00
|
|
|
# *
|
2017-11-12 13:43:59 +00:00
|
|
|
# * Copyright 2017. Benoit Michau. ANSSI.
|
2017-07-04 21:12:41 +00:00
|
|
|
# *
|
2018-04-15 19:47:21 +00:00
|
|
|
# * This library is free software; you can redistribute it and/or
|
|
|
|
# * modify it under the terms of the GNU Lesser General Public
|
|
|
|
# * License as published by the Free Software Foundation; either
|
|
|
|
# * version 2.1 of the License, or (at your option) any later version.
|
|
|
|
# *
|
|
|
|
# * This library is distributed in the hope that it will be useful,
|
2017-07-04 21:12:41 +00:00
|
|
|
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2018-04-15 19:47:21 +00:00
|
|
|
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
# * Lesser General Public License for more details.
|
|
|
|
# *
|
|
|
|
# * You should have received a copy of the GNU Lesser General Public
|
|
|
|
# * License along with this library; if not, write to the Free Software
|
|
|
|
# * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
|
|
# * MA 02110-1301 USA
|
2017-07-04 21:12:41 +00:00
|
|
|
# *
|
|
|
|
# *--------------------------------------------------------
|
|
|
|
# * 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
|
|
|
|
|
|
|
|
|
2017-12-15 20:19:59 +00:00
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
# CSN.1 errors
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
2018-07-31 21:01:45 +00:00
|
|
|
def csnlog(msg):
|
|
|
|
'''
|
|
|
|
customizable logging function for the whole csn1 part
|
|
|
|
'''
|
|
|
|
log(msg)
|
|
|
|
|
|
|
|
|
2017-12-15 20:19:59 +00:00
|
|
|
# generic CSN.1 error
|
|
|
|
class CSN1Err(PycrateErr):
|
|
|
|
pass
|
|
|
|
|
|
|
|
class CSN1InvalidValueErr(CSN1Err):
|
|
|
|
pass
|
|
|
|
|
2018-07-31 21:01:45 +00:00
|
|
|
class CSN1NoCharErr(CSN1Err):
|
|
|
|
pass
|
|
|
|
|
2017-12-15 20:19:59 +00:00
|
|
|
|
2017-07-04 21:12:41 +00:00
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
# text processing
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
2018-07-31 21:01:45 +00:00
|
|
|
def scan_for_comments(text=''):
|
|
|
|
"""
|
|
|
|
returns a list of 2-tuple (start offset, end offset) for each CSN.1 comment
|
|
|
|
found in text
|
|
|
|
"""
|
|
|
|
ret = []
|
|
|
|
cur = 0
|
|
|
|
next = text.find('--')
|
|
|
|
while next >= 0:
|
|
|
|
cur += next
|
|
|
|
# start of comment
|
|
|
|
start = cur
|
|
|
|
# move cursor forward to reach the end of comment
|
|
|
|
cur += 2
|
|
|
|
# exception for line full of ------------------ sh*t
|
|
|
|
#while text[cur:1+cur] == '-':
|
|
|
|
# cur += 1
|
|
|
|
while True:
|
|
|
|
# move 1 by 1 and find an end-of-comment or end-of-file
|
|
|
|
if text[cur:1+cur] == '\n' or cur >= len(text):
|
|
|
|
comment = False
|
|
|
|
ret.append((start, cur))
|
|
|
|
cur += 1
|
|
|
|
break
|
|
|
|
#elif text[cur:2+cur] == '--':
|
|
|
|
# comment = False
|
|
|
|
# cur += 2
|
|
|
|
# ret.append((start, cur))
|
|
|
|
# break
|
|
|
|
else:
|
|
|
|
cur += 1
|
|
|
|
# find the next comment
|
|
|
|
next = text[cur:].find('--')
|
|
|
|
return ret
|
|
|
|
|
|
|
|
|
2017-07-04 21:12:41 +00:00
|
|
|
def clean_text(text=''):
|
|
|
|
"""
|
|
|
|
processes text to:
|
2018-07-31 21:01:45 +00:00
|
|
|
remove CSN.1 comments
|
2017-07-04 21:12:41 +00:00
|
|
|
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
|
2018-07-31 21:01:45 +00:00
|
|
|
return name.lower()
|
2017-07-04 21:12:41 +00:00
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
# CSN.1 tokens
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
|
2018-07-31 21:01:45 +00:00
|
|
|
_RE_NAME = '[0-9a-zA-Z_ \-/\.]{1,}'
|
|
|
|
_RE_VAL = 'val\s{0,}\(\s{0,}(%s)\s{0,}\)' % _RE_NAME
|
|
|
|
|
|
|
|
SYNT_RE_NAME = re.compile('<\s{0,}(%s)\s{0,}>' % _RE_NAME)
|
|
|
|
SYNT_RE_VALUE = re.compile('([01\s]{1,})|([LH\s]{1,})|(null)')
|
|
|
|
SYNT_RE_NOSTR = re.compile('=\s{0,}<\s{0,}no\s{1,}string\s{0,}>')
|
|
|
|
|
|
|
|
# {iteration / length} arithmetic expression
|
|
|
|
TOK_UINT = 1
|
|
|
|
TOK_REF = 2
|
|
|
|
TOK_ADD = 3
|
|
|
|
TOK_SUB = 4
|
|
|
|
TOK_MUL = 5
|
|
|
|
TOK_OPEN = 6
|
|
|
|
TOK_CLOS = 7
|
2017-07-04 21:12:41 +00:00
|
|
|
|
2018-07-31 21:01:45 +00:00
|
|
|
def arithm_get_expr(m):
|
|
|
|
return m.group()
|
2017-07-04 21:12:41 +00:00
|
|
|
|
|
|
|
#------------------------------------------------------------------------------#
|
|
|
|
# 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
|
|
|
|
|