@@ -348,6 +348,12 @@ def __init__(self):
348
348
# "goto exit" if there are any.
349
349
self .return_conversion = []
350
350
351
+ # The C statements required to do some operations
352
+ # after the end of parsing but before cleaning up.
353
+ # These operations may be, for example, memory deallocations which
354
+ # can only be done without any error happening during argument parsing.
355
+ self .post_parsing = []
356
+
351
357
# The C statements required to clean up after the impl call.
352
358
self .cleanup = []
353
359
@@ -820,6 +826,7 @@ def parser_body(prototype, *fields, declarations=''):
820
826
{modifications}
821
827
{return_value} = {c_basename}_impl({impl_arguments});
822
828
{return_conversion}
829
+ {post_parsing}
823
830
824
831
{exit_label}
825
832
{cleanup}
@@ -1460,6 +1467,7 @@ def render_function(self, clinic, f):
1460
1467
template_dict ['impl_parameters' ] = ", " .join (data .impl_parameters )
1461
1468
template_dict ['impl_arguments' ] = ", " .join (data .impl_arguments )
1462
1469
template_dict ['return_conversion' ] = format_escape ("" .join (data .return_conversion ).rstrip ())
1470
+ template_dict ['post_parsing' ] = format_escape ("" .join (data .post_parsing ).rstrip ())
1463
1471
template_dict ['cleanup' ] = format_escape ("" .join (data .cleanup ))
1464
1472
template_dict ['return_value' ] = data .return_value
1465
1473
@@ -1484,6 +1492,7 @@ def render_function(self, clinic, f):
1484
1492
return_conversion = template_dict ['return_conversion' ],
1485
1493
initializers = template_dict ['initializers' ],
1486
1494
modifications = template_dict ['modifications' ],
1495
+ post_parsing = template_dict ['post_parsing' ],
1487
1496
cleanup = template_dict ['cleanup' ],
1488
1497
)
1489
1498
@@ -2725,6 +2734,10 @@ def _render_non_self(self, parameter, data):
2725
2734
# parse_arguments
2726
2735
self .parse_argument (data .parse_arguments )
2727
2736
2737
+ # post_parsing
2738
+ if post_parsing := self .post_parsing ():
2739
+ data .post_parsing .append ('/* Post parse cleanup for ' + name + ' */\n ' + post_parsing .rstrip () + '\n ' )
2740
+
2728
2741
# cleanup
2729
2742
cleanup = self .cleanup ()
2730
2743
if cleanup :
@@ -2820,6 +2833,14 @@ def modify(self):
2820
2833
"""
2821
2834
return ""
2822
2835
2836
+ def post_parsing (self ):
2837
+ """
2838
+ The C statements required to do some operations after the end of parsing but before cleaning up.
2839
+ Return a string containing this code indented at column 0.
2840
+ If no operation is necessary, return an empty string.
2841
+ """
2842
+ return ""
2843
+
2823
2844
def cleanup (self ):
2824
2845
"""
2825
2846
The C statements required to clean up after this variable.
@@ -3416,10 +3437,10 @@ def converter_init(self, *, accept={str}, encoding=None, zeroes=False):
3416
3437
if NoneType in accept and self .c_default == "Py_None" :
3417
3438
self .c_default = "NULL"
3418
3439
3419
- def cleanup (self ):
3440
+ def post_parsing (self ):
3420
3441
if self .encoding :
3421
3442
name = self .name
3422
- return "" . join ([ "if (" , name , ") { \n PyMem_FREE(" , name , " );\n } \n " ])
3443
+ return f" PyMem_FREE({ name } );\n "
3423
3444
3424
3445
def parse_arg (self , argname , displayname ):
3425
3446
if self .format_unit == 's' :
0 commit comments