@@ -122,6 +122,11 @@ def quoted_for_c_string(s):
122
122
s = s .replace (old , new )
123
123
return s
124
124
125
+ is_legal_c_identifier = re .compile ('^[A-Za-z_][A-Za-z0-9_]*$' ).match
126
+
127
+ def is_legal_py_identifier (s ):
128
+ return all (is_legal_c_identifier (field ) for field in s .split ('.' ))
129
+
125
130
# added "self", "cls", and "null" just to be safe
126
131
# (clinic will generate variables with these names)
127
132
c_keywords = set ("""
@@ -131,8 +136,11 @@ def quoted_for_c_string(s):
131
136
typeof union unsigned void volatile while
132
137
""" .strip ().split ())
133
138
134
- def legal_c_identifier (s ):
135
- # if we picked a C keyword, pick something else
139
+ def ensure_legal_c_identifier (s ):
140
+ # for now, just complain if what we're given isn't legal
141
+ if not is_legal_c_identifier (s ):
142
+ fail ("Illegal C identifier: {}" .format (s ))
143
+ # but if we picked a C keyword, pick something else
136
144
if s in c_keywords :
137
145
return s + "_value"
138
146
return s
@@ -1311,7 +1319,7 @@ def render(self, parameter, data):
1311
1319
parameter is a clinic.Parameter instance.
1312
1320
data is a CRenderData instance.
1313
1321
"""
1314
- name = legal_c_identifier (self .name )
1322
+ name = ensure_legal_c_identifier (self .name )
1315
1323
1316
1324
# declarations
1317
1325
d = self .declaration ()
@@ -1359,7 +1367,7 @@ def parse_argument(self, list):
1359
1367
if self .encoding :
1360
1368
list .append (self .encoding )
1361
1369
1362
- s = ("&" if self .parse_by_reference else "" ) + legal_c_identifier (self .name )
1370
+ s = ("&" if self .parse_by_reference else "" ) + ensure_legal_c_identifier (self .name )
1363
1371
list .append (s )
1364
1372
1365
1373
#
@@ -1377,7 +1385,7 @@ def simple_declaration(self, by_reference=False):
1377
1385
prototype .append (" " )
1378
1386
if by_reference :
1379
1387
prototype .append ('*' )
1380
- prototype .append (legal_c_identifier (self .name ))
1388
+ prototype .append (ensure_legal_c_identifier (self .name ))
1381
1389
return "" .join (prototype )
1382
1390
1383
1391
def declaration (self ):
@@ -1575,7 +1583,7 @@ def converter_init(self, *, str=False, zeroes=False, nullable=False, read_write=
1575
1583
self .format_unit = 'z*' if nullable else 's*'
1576
1584
1577
1585
def cleanup (self ):
1578
- return "PyBuffer_Release(&" + legal_c_identifier (self .name ) + ");\n "
1586
+ return "PyBuffer_Release(&" + ensure_legal_c_identifier (self .name ) + ");\n "
1579
1587
1580
1588
1581
1589
def add_c_return_converter (f , name = None ):
@@ -1895,6 +1903,11 @@ def state_modulename_name(self, line):
1895
1903
full_name = full_name .strip ()
1896
1904
c_basename = c_basename .strip () or None
1897
1905
1906
+ if not is_legal_py_identifier (full_name ):
1907
+ fail ("Illegal function name: {}" .format (full_name ))
1908
+ if c_basename and not is_legal_c_identifier (c_basename ):
1909
+ fail ("Illegal C basename: {}" .format (c_basename ))
1910
+
1898
1911
if not returns :
1899
1912
return_converter = CReturnConverter ()
1900
1913
else :
0 commit comments