• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1
2# (C) Copyright IBM Corporation 2005
3# All Rights Reserved.
4#
5# Permission is hereby granted, free of charge, to any person obtaining a
6# copy of this software and associated documentation files (the "Software"),
7# to deal in the Software without restriction, including without limitation
8# on the rights to use, copy, modify, merge, publish, distribute, sub
9# license, and/or sell copies of the Software, and to permit persons to whom
10# the Software is furnished to do so, subject to the following conditions:
11#
12# The above copyright notice and this permission notice (including the next
13# paragraph) shall be included in all copies or substantial portions of the
14# Software.
15#
16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
19# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22# IN THE SOFTWARE.
23#
24# Authors:
25#    Ian Romanick <idr@us.ibm.com>
26
27import copy
28
29class type_node(object):
30    def __init__(self):
31        self.pointer = 0  # bool
32        self.const = 0    # bool
33        self.signed = 1   # bool
34        self.integer = 1  # bool
35
36        # If elements is set to non-zero, then field is an array.
37        self.elements = 0
38
39        self.name = None
40        self.size = 0     # type's size in bytes
41        return
42
43
44    def string(self):
45        """Return string representation of this type_node."""
46        s = ""
47
48        if self.pointer:
49            s = "* "
50
51        if self.const:
52            s += "const "
53
54        if not self.pointer:
55            if self.integer:
56                if self.signed:
57                    s += "signed "
58                else:
59                    s += "unsigned "
60
61            if self.name:
62                s += "%s " % (self.name)
63
64        return s
65
66
67class type_table(object):
68    def __init__(self):
69        self.types_by_name = {}
70        return
71
72
73    def add_type(self, type_expr):
74        self.types_by_name[ type_expr.get_base_name() ] = type_expr
75        return
76
77
78    def find_type(self, name):
79        if name in self.types_by_name:
80            return self.types_by_name[ name ]
81        else:
82            return None
83
84
85def create_initial_types():
86    tt = type_table()
87
88    basic_types = [
89            ("char",   1, 1),
90            ("short",  2, 1),
91            ("int",    4, 1),
92            ("long",   4, 1),
93            ("float",  4, 0),
94            ("double", 8, 0),
95            ("enum",   4, 1)
96    ]
97
98    for (type_name, type_size, integer) in basic_types:
99        te = type_expression(None)
100        tn = type_node()
101        tn.name = type_name
102        tn.size = type_size
103        tn.integer = integer
104        te.expr.append(tn)
105        tt.add_type( te )
106
107    type_expression.built_in_types = tt
108    return
109
110
111class type_expression(object):
112    built_in_types = None
113
114    def __init__(self, type_string, extra_types = None):
115        self.expr = []
116
117        if not type_string:
118            return
119
120        self.original_string = type_string
121
122        if not type_expression.built_in_types:
123            raise RuntimeError("create_initial_types must be called before creating type_expression objects.")
124
125        # Replace '*' with ' * ' in type_string.  Then, split the string
126        # into tokens, separated by spaces.
127        tokens = type_string.replace("*", " * ").split()
128
129        const = 0
130        t = None
131        signed = 0
132        unsigned = 0
133
134        for i in tokens:
135            if i == "const":
136                if t and t.pointer:
137                    t.const = 1
138                else:
139                    const = 1
140            elif i == "signed":
141                signed = 1
142            elif i == "unsigned":
143                unsigned = 1
144            elif i == "*":
145                # This is a quirky special-case because of the
146                # way the C works for types.  If 'unsigned' is
147                # specified all by itself, it is treated the
148                # same as "unsigned int".
149
150                if unsigned:
151                    self.set_base_type( "int", signed, unsigned, const, extra_types )
152                    const = 0
153                    signed = 0
154                    unsigned = 0
155
156                if not self.expr:
157                    raise RuntimeError("Invalid type expression (dangling pointer)")
158
159                if signed:
160                    raise RuntimeError("Invalid type expression (signed / unsigned applied to pointer)")
161
162                t = type_node()
163                t.pointer = 1
164                self.expr.append( t )
165            else:
166                if self.expr:
167                    raise RuntimeError('Invalid type expression (garbage after pointer qualifier -> "%s")' % (self.original_string))
168
169                self.set_base_type( i, signed, unsigned, const, extra_types )
170                const = 0
171                signed = 0
172                unsigned = 0
173
174            if signed and unsigned:
175                raise RuntimeError("Invalid type expression (both signed and unsigned specified)")
176
177
178        if const:
179            raise RuntimeError("Invalid type expression (dangling const)")
180
181        if unsigned:
182            raise RuntimeError("Invalid type expression (dangling signed)")
183
184        if signed:
185            raise RuntimeError("Invalid type expression (dangling unsigned)")
186
187        return
188
189
190    def set_base_type(self, type_name, signed, unsigned, const, extra_types):
191        te = type_expression.built_in_types.find_type( type_name )
192        if not te:
193            te = extra_types.find_type( type_name )
194
195        if not te:
196            raise RuntimeError('Unknown base type "%s".' % (type_name))
197
198        self.expr = copy.deepcopy(te.expr)
199
200        t = self.expr[ len(self.expr) - 1 ]
201        t.const = const
202        if signed:
203            t.signed = 1
204        elif unsigned:
205            t.signed = 0
206
207
208    def set_base_type_node(self, tn):
209        self.expr = [tn]
210        return
211
212
213    def set_elements(self, count):
214        tn = self.expr[0]
215
216        tn.elements = count
217        return
218
219
220    def string(self):
221        s = ""
222        for t in self.expr:
223            s += t.string()
224
225        return s
226
227
228    def get_base_type_node(self):
229        return self.expr[0]
230
231
232    def get_base_name(self):
233        if len(self.expr):
234            return self.expr[0].name
235        else:
236            return None
237
238
239    def get_element_size(self):
240        tn = self.expr[0]
241
242        if tn.elements:
243            return tn.elements * tn.size
244        else:
245            return tn.size
246
247
248    def get_element_count(self):
249        tn = self.expr[0]
250        return tn.elements
251
252
253    def get_stack_size(self):
254        tn = self.expr[ -1 ]
255
256        if tn.elements or tn.pointer:
257            return 4
258        elif not tn.integer:
259            return tn.size
260        else:
261            return 4
262
263
264    def is_pointer(self):
265        tn = self.expr[ -1 ]
266        return tn.pointer
267
268
269    def format_string(self):
270        tn = self.expr[ -1 ]
271        if tn.pointer:
272            return "%p"
273        elif not tn.integer:
274            return "%f"
275        else:
276            return "%d"
277
278
279
280if __name__ == '__main__':
281
282    types_to_try = [ "int", "int *", "const int *", "int * const", "const int * const", \
283                     "unsigned * const *", \
284                     "float", "const double", "double * const"]
285
286    create_initial_types()
287
288    for t in types_to_try:
289        print('Trying "%s"...' % (t))
290        te = type_expression( t )
291        print('Got "%s" (%u, %u).' % (te.string(), te.get_stack_size(), te.get_element_size()))
292