Skip to content

Commit

Permalink
Added support for Asm labels
Browse files Browse the repository at this point in the history
- Fixed superclass for ArrayDeclExt
- Added some spaces for readability to _generate_type
- Moved templated rules into _AsmAndAttributesMixin
  • Loading branch information
t11230 committed Aug 15, 2020
1 parent 9365b81 commit 36f1c04
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 74 deletions.
16 changes: 13 additions & 3 deletions pycparserext/ext_c_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,17 @@ def _generate_type(self, n, modifiers=[]):
#
for i, modifier in enumerate(modifiers):
if isinstance(modifier, c_ast.ArrayDecl):
if (i != 0 and isinstance(modifiers[i - 1], c_ast.PtrDecl)):
if i != 0 and isinstance(modifiers[i - 1], c_ast.PtrDecl):
nstr = '(' + nstr + ')'
nstr += '[' + self.visit(modifier.dim) + ']'

elif isinstance(modifier, c_ast.FuncDecl):
if (i != 0 and isinstance(modifiers[i - 1], c_ast.PtrDecl)):
if i != 0 and isinstance(modifiers[i - 1], c_ast.PtrDecl):
nstr = '(' + nstr + ')'
nstr += '(' + self.visit(modifier.args) + ')'

elif isinstance(modifier, FuncDeclExt):
if (i != 0 and isinstance(modifiers[i - 1], c_ast.PtrDecl)):
if i != 0 and isinstance(modifiers[i - 1], c_ast.PtrDecl):
nstr = '(' + nstr + ')'
nstr += '(' + self.visit(modifier.args) + ')'

Expand All @@ -89,20 +91,28 @@ def _generate_type(self, n, modifiers=[]):
quals = quals + ' '
nstr = '*' + quals + nstr

if hasattr(n, "asm") and n.asm:
nstr += self.visit(n.asm)

if hasattr(n, "attributes") and n.attributes.exprs:
nstr += ' __attribute__((' + self.visit(n.attributes) + '))'

if nstr:
s += ' ' + nstr
return s

elif typ == c_ast.Decl:
return self._generate_decl(n.type)

elif typ == c_ast.Typename:
return self._generate_type(n.type)

elif typ == c_ast.IdentifierType:
return ' '.join(n.names) + ' '

elif typ in (c_ast.ArrayDecl, c_ast.PtrDecl, c_ast.FuncDecl, FuncDeclExt):
return self._generate_type(n.type, modifiers + [n])

else:
return self.visit(n)

Expand Down
153 changes: 82 additions & 71 deletions pycparserext/ext_c_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ def __init__(self, **kwds):
kwds['yacctab'] = 'pycparserext.yacctab'
pycparser.c_parser.CParser.__init__(self, **kwds)

def parse(self, text, filename='', debuglevel=0,
initial_type_symbols=set()):
def parse(self, text, filename='', debuglevel=0, initial_type_symbols=set()):
self.clex.filename = filename
self.clex.reset_lineno()

Expand Down Expand Up @@ -190,7 +189,7 @@ def from_pycparser(td):
return TypeDeclExt(td.declname, td.quals, td.type, td.coord)


class ArrayDeclExt(c_ast.TypeDecl):
class ArrayDeclExt(c_ast.ArrayDecl):
@staticmethod
def from_pycparser(ad):
assert isinstance(ad, c_ast.ArrayDecl)
Expand Down Expand Up @@ -243,7 +242,6 @@ def __iter__(self):

# {{{ attributes

@template
class _AttributesMixin(object):
def p_attributes_opt_1(self, p):
""" attributes_opt : attribute_decl attributes_opt
Expand Down Expand Up @@ -283,65 +281,8 @@ def p_attribute_3(self, p):
"""
p[0] = p[1]

# {{{ /!\ names must match C parser to override

@parameterized(('id', 'ID'), ('typeid', 'TYPEID'), ('typeid_noparen', 'TYPEID'))
def p_xxx_declarator_1(self, p):
""" xxx_declarator : direct_xxx_declarator attributes_opt
"""
if p[2].exprs:
if isinstance(p[1], c_ast.ArrayDecl):
p[1].type = to_decl_ext(p[1].type)
p[1].type.attributes = p[2]
elif isinstance(p[1], c_ast.FuncDecl):
p[1].type = to_decl_ext(p[1].type)
p[1].type.attributes = p[2]
elif not isinstance(p[1], c_ast.TypeDecl):
raise NotImplementedError(
"cannot attach attributes to nodes of type '%s'"
% type(p[1]))
else:
p[1] = to_decl_ext(p[1])
p[1].attributes = p[2]

p[0] = p[1]

# }}}

@parameterized(('id', 'ID'), ('typeid', 'TYPEID'), ('typeid_noparen', 'TYPEID'))
def p_xxx_declarator_2(self, p):
""" xxx_declarator : pointer direct_xxx_declarator attributes_opt
| pointer attributes_opt direct_xxx_declarator
"""
if hasattr(p[3], "exprs"):
attr_decl = p[3]
decl = p[2]
else:
attr_decl = p[2]
decl = p[3]

if not attr_decl.exprs:
attr_decl = None

if attr_decl:
if isinstance(decl, c_ast.ArrayDecl):
decl.type = to_decl_ext(decl.type)
decl.type.attributes = attr_decl
elif isinstance(decl, c_ast.FuncDecl):
decl.type = to_decl_ext(decl.type)
decl.type.attributes = attr_decl
elif not isinstance(p[2], c_ast.TypeDecl):
raise NotImplementedError(
"cannot attach attributes to nodes of type '%s'"
% type(p[1]))
else:
decl = to_decl_ext(decl)
decl.attributes = attr_decl

p[0] = self._type_modify_decl(decl, p[1])

def p_function_specifier_attr(self, p):
""" function_specifier : attribute_decl
""" function_specifier : attribute_decl
"""
p[0] = AttributeSpecifier(p[1])

Expand Down Expand Up @@ -407,29 +348,99 @@ def p_asm_argument_expression_list(self, p):
"""
p[0] = p[1]

def p_statement_gnu(self, p):
""" statement : asm_no_semi
| asm_no_semi SEMI
def p_statement_asm(self, p):
""" statement : asm_no_semi
| asm_no_semi SEMI
"""
p[0] = p[1]

# def p_asm_with_semi(self, p):
# """ asm : asm SEMI
# """
# p[0] = p[1]
def p_asm_label_opt(self, p):
""" asm_label_opt : asm_keyword LPAREN unified_string_literal RPAREN
| empty
"""
if p[1] is None:
p[0] = None
else:
p[0] = Asm(p[1], p[3], None, None, None, coord=self._coord(p.lineno(2)))

# }}}


@template
class _AsmAndAttributesMixin(_AsmMixin, _AttributesMixin):
# {{{ /!\ names must match C parser to override

@parameterized(('id', 'ID'), ('typeid', 'TYPEID'), ('typeid_noparen', 'TYPEID'))
def p_xxx_declarator_1(self, p):
""" xxx_declarator : direct_xxx_declarator asm_label_opt attributes_opt
"""
if p[2] or p[3].exprs:
if isinstance(p[1], (c_ast.ArrayDecl, c_ast.FuncDecl)):
decl_ext = to_decl_ext(p[1].type)

elif isinstance(p[1], c_ast.TypeDecl):
decl_ext = to_decl_ext(p[1])

else:
raise NotImplementedError(
"cannot attach asm or attributes to nodes of type '%s'"
% type(p[1]))

if p[2]:
decl_ext.asm = p[2]

if p[3].exprs:
decl_ext.attributes = p[3]

p[1] = decl_ext

p[0] = p[1]

@parameterized(('id', 'ID'), ('typeid', 'TYPEID'), ('typeid_noparen', 'TYPEID'))
def p_xxx_declarator_2(self, p):
""" xxx_declarator : pointer direct_xxx_declarator asm_label_opt \
attributes_opt
| pointer attributes_opt direct_xxx_declarator \
asm_label_opt
"""
if hasattr(p[4], "exprs"):
attr_decl = p[4]
asm_label = p[3]
decl = p[2]
else:
attr_decl = p[2]
asm_label = p[4]
decl = p[3]

if asm_label or attr_decl.exprs:
if isinstance(decl, (c_ast.ArrayDecl, c_ast.FuncDecl)):
decl_ext = to_decl_ext(decl.type)

elif isinstance(decl, c_ast.TypeDecl):
decl_ext = to_decl_ext(decl)

else:
raise NotImplementedError(
"cannot attach asm or attributes to nodes of type '%s'"
% type(p[1]))

if asm_label:
decl_ext.asm = asm_label

if attr_decl.exprs:
decl_ext.attributes = attr_decl

p[1] = decl_ext

p[0] = self._type_modify_decl(decl, p[1])

@parameterized(('id', 'ID'), ('typeid', 'TYPEID'), ('typeid_noparen', 'TYPEID'))
def p_direct_xxx_declarator_6(self, p):
""" direct_xxx_declarator : direct_xxx_declarator LPAREN parameter_type_list \
RPAREN asm_opt attributes_opt
| direct_xxx_declarator \
LPAREN identifier_list_opt RPAREN \
asm_opt attributes_opt
asm_label_opt attributes_opt
"""
func = FuncDeclExt(
args=p[3],
Expand All @@ -442,7 +453,7 @@ def p_direct_xxx_declarator_6(self, p):

def p_direct_abstract_declarator_6(self, p):
""" direct_abstract_declarator : direct_abstract_declarator \
LPAREN parameter_type_list_opt RPAREN asm_opt attributes_opt
LPAREN parameter_type_list_opt RPAREN asm_label_opt attributes_opt
"""
func = FuncDeclExt(
args=p[3],
Expand Down
17 changes: 17 additions & 0 deletions test/test_pycparserext.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,23 @@ def test_asm_volatile_3():
print(GnuCGenerator().visit(ast))


def test_asm_label():
src = """
int foo asm("renamed_foo");
unsigned long bar asm("renamed_bar") __attribute__ ((aligned (16)));
unsigned long bar2 asm("renamed_bar2");
unsigned int * bar3 asm("renamed_bar3");
void func() {
static int var asm("renamed_var") = 5;
}
"""
assert _round_trip_matches(src)


def test_funky_header_code():
src = """
extern __inline int __attribute__ ((__nothrow__)) __signbitf (float __x)
Expand Down

0 comments on commit 36f1c04

Please # to comment.