source: mainline/tools/xstruct.py@ 81475250

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 81475250 was 6582b36, checked in by Sean Bartell <wingedtachikoma@…>, 13 years ago

Make some scripts work with Python 3.

Arch Linux has already switched so "python" means version 3, so these
scripts don't run otherwise. Only the simplest fixes are made. Note that
automatic int-to-long conversion has existed since at least Python 2.4.

  • Property mode set to 100644
File size: 4.5 KB
Line 
1#
2# Copyright (c) 2008 Martin Decky
3# Copyright (c) 2011 Martin Sucha
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9#
10# - Redistributions of source code must retain the above copyright
11# notice, this list of conditions and the following disclaimer.
12# - Redistributions in binary form must reproduce the above copyright
13# notice, this list of conditions and the following disclaimer in the
14# documentation and/or other materials provided with the distribution.
15# - The name of the author may not be used to endorse or promote products
16# derived from this software without specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28#
29"""
30Convert descriptive structure definitions to structure object
31"""
32
33import struct
34import sys
35import types
36
37integer_types = (int, long) if sys.version < '3' else (int,)
38
39ranges = {
40 'B': (integer_types, 0x00, 0xff),
41 'H': (integer_types, 0x0000, 0xffff),
42 'L': (integer_types, 0x00000000, 0xffffffff),
43 'Q': (integer_types, 0x0000000000000000, 0xffffffffffffffff),
44 'b': (integer_types, -0x80, 0x7f),
45 'h': (integer_types, -0x8000, 0x7fff),
46 'l': (integer_types, -0x80000000, 0x7fffffff) ,
47 'q': (integer_types, -0x8000000000000000, 0x7fffffffffffffff),
48}
49
50def check_range(varname, fmt, value):
51 if value == None:
52 raise ValueError('Variable "%s" not set' % varname)
53 if not fmt in ranges:
54 return
55 vartype, varmin, varmax = ranges[fmt]
56 if not isinstance(value, vartype):
57 raise ValueError('Variable "%s" is %s but should be %s' %
58 (varname, str(type(value)), str(vartype)))
59 if value < varmin or value > varmax:
60 raise ValueError('Variable "%s" value %s out of range %s..%s' %
61 (varname, repr(value), repr(varmin), repr(varmax)))
62
63class Struct:
64 def size(self):
65 return struct.calcsize(self._format_)
66
67 def pack(self):
68 args = []
69 for variable, fmt, length in self._args_:
70 value = self.__dict__[variable]
71 if isinstance(value, list):
72 if length != None and length != len(value):
73 raise ValueError('Variable "%s" length %u does not match %u' %
74 (variable, len(value), length))
75 for index, item in enumerate(value):
76 check_range(variable + '[' + repr(index) + ']', fmt, item)
77 args.append(item)
78 else:
79 check_range(variable, fmt, value)
80 args.append(value)
81 return struct.pack(self._format_, *args)
82
83 def unpack(self, data):
84 values = struct.unpack(self._format_, data)
85 i = 0
86 for variable, fmt, length in self._args_:
87 self.__dict__[variable] = values[i]
88 i += 1
89
90def create(definition):
91 "Create structure object"
92
93 tokens = definition.split(None)
94
95 # Initial byte order tag
96 format = {
97 "little:": lambda: "<",
98 "big:": lambda: ">",
99 "network:": lambda: "!"
100 }[tokens[0]]()
101 inst = Struct()
102 args = []
103
104 # Member tags
105 comment = False
106 variable = None
107 for token in tokens[1:]:
108 if (comment):
109 if (token == "*/"):
110 comment = False
111 continue
112
113 if (token == "/*"):
114 comment = True
115 continue
116
117 if (variable != None):
118 subtokens = token.split("[")
119
120 length = None
121 if (len(subtokens) > 1):
122 length = int(subtokens[1].split("]")[0])
123 format += "%d" % length
124
125 format += variable
126
127 inst.__dict__[subtokens[0]] = None
128 args.append((subtokens[0], variable, length))
129
130 variable = None
131 continue
132
133 if (token[0:8] == "padding["):
134 size = token[8:].split("]")[0]
135 format += "%dx" % int(size)
136 continue
137
138 variable = {
139 "char": lambda: "s",
140 "uint8_t": lambda: "B",
141 "uint16_t": lambda: "H",
142 "uint32_t": lambda: "L",
143 "uint64_t": lambda: "Q",
144
145 "int8_t": lambda: "b",
146 "int16_t": lambda: "h",
147 "int32_t": lambda: "l",
148 "int64_t": lambda: "q"
149 }[token]()
150
151 inst.__dict__['_format_'] = format
152 inst.__dict__['_args_'] = args
153 return inst
Note: See TracBrowser for help on using the repository browser.