@@ -1102,98 +1102,44 @@ BEGIN { $build_subclass->('Param', # parent
1102
1102
)};
1103
1103
1104
1104
1105
- # $self->as_input_code():
1105
+ # Given a param with known type etc, extract its typemap INPUT template
1106
+ # and also create a hash of vars that can be used to eval that template.
1107
+ # An undef returned hash ref signifies that the returned template string
1108
+ # doesn't need to be evalled.
1106
1109
#
1107
- # Emit the param object as C code which declares and initialise the variable.
1108
- # See also the as_output_code() method, which emits code to return the value
1109
- # of that local var.
1110
+ # Returns ($expr, $eval_vars, $is_template)
1111
+ # or empty list on failure.
1112
+ #
1113
+ # $expr: text like '$var = SvIV($arg)'
1114
+ # $eval_vars: hash ref like { var => 'foo', arg => 'ST(0)', ... }
1115
+ # $is_template: $expr has '$arg' etc and needs evalling
1110
1116
1111
- sub as_input_code {
1117
+ sub lookup_input_typemap {
1112
1118
my __PACKAGE__ $self = shift ;
1113
1119
my ExtUtils::ParseXS $pxs = shift ;
1114
1120
my ExtUtils::ParseXS::Node::xsub $xsub = shift ;
1115
1121
my $xbody = shift ;
1116
1122
1117
- my ($type , $arg_num , $var , $init , $no_init , $defer , $ default )
1118
- = @{$self }{qw( type arg_num var init no_init defer default) };
1119
-
1123
+ my ($type , $arg_num , $var , $init , $no_init , $default )
1124
+ = @{$self }{qw( type arg_num var init no_init default) };
1125
+ $var = " XSauto_length_of_ $self ->{len_name} " if $self -> { is_length };
1120
1126
my $arg = $pxs -> ST($arg_num );
1121
1127
1122
- if ($self -> {is_length }) {
1123
- # Process length(foo) parameter.
1124
- # Basically for something like foo(char *s, int length(s)),
1125
- # create *two* local C vars: one with STRLEN type, and one with the
1126
- # type specified in the signature. Eventually, generate code looking
1127
- # something like:
1128
- # STRLEN STRLEN_length_of_s;
1129
- # int XSauto_length_of_s;
1130
- # char *s = (char *)SvPV(ST(0), STRLEN_length_of_s);
1131
- # XSauto_length_of_s = STRLEN_length_of_s;
1132
- # RETVAL = foo(s, XSauto_length_of_s);
1133
- #
1134
- # Note that the SvPV() code line is generated via a separate call to
1135
- # this sub with s as the var (as opposed to *this* call, which is
1136
- # handling length(s)), by overriding the normal T_PV typemap (which
1137
- # uses PV_nolen()).
1138
-
1139
- my $name = $self -> {len_name };
1140
-
1141
- print " \t STRLEN\t STRLEN_length_of_$name ;\n " ;
1142
- # defer this line until after all the other declarations
1143
- $xbody -> {input_part }{deferred_code_lines } .=
1144
- " \n\t XSauto_length_of_$name = STRLEN_length_of_$name ;\n " ;
1145
-
1146
- # this var will be declared using the normal typemap mechanism below
1147
- $var = " XSauto_length_of_$name " ;
1148
- }
1149
-
1150
- # Emit the variable's type and name.
1151
- #
1152
- # Includes special handling for function pointer types. An INPUT line
1153
- # always has the C type followed by the variable name. The C code
1154
- # which is emitted normally follows the same pattern. However for
1155
- # function pointers, the code is different: the variable name has to
1156
- # be embedded *within* the type. For example, these two INPUT lines:
1157
- #
1158
- # char * s
1159
- # int (*)(int) fn_ptr
1160
- #
1161
- # cause the following lines of C to be emitted;
1162
- #
1163
- # char * s = [something from a typemap]
1164
- # int (* fn_ptr)(int) = [something from a typemap]
1165
- #
1166
- # So handle specially the specific case of a type containing '(*)' by
1167
- # embedding the variable name *within* rather than *after* the type.
1168
-
1169
-
1170
- if ($type =~ / \( \s * \* \s * \) /x ) {
1171
- # for a fn ptr type, embed the var name in the type declaration
1172
- print " \t " . $pxs -> map_type($type , $var );
1173
- }
1174
- else {
1175
- print " \t " ,
1176
- ((defined ($xsub -> {decl }{class }) && $var eq ' CLASS' )
1177
- ? $type
1178
- : $pxs -> map_type($type , undef )),
1179
- " \t $var " ;
1180
- }
1181
-
1182
1128
# whitespace-tidy the type
1183
1129
$type = ExtUtils::Typemaps::tidy_type($type );
1184
1130
1185
1131
# Specify the environment for when the initialiser template is evaled.
1186
1132
# Only the common ones are specified here. Other fields may be added
1187
1133
# later.
1188
1134
my $eval_vars = {
1189
- type => $type ,
1190
- var => $var ,
1191
- num => $arg_num ,
1192
- arg => $arg ,
1193
- alias => $xsub -> {seen_ALIAS },
1194
- func_name => $xsub -> {decl }{name },
1195
- full_perl_name => $xsub -> {decl }{full_perl_name },
1196
- full_C_name => $xsub -> {decl }{full_C_name },
1135
+ type => $type ,
1136
+ var => $var ,
1137
+ num => $arg_num ,
1138
+ arg => $arg ,
1139
+ alias => $xsub -> {seen_ALIAS },
1140
+ func_name => $xsub -> {decl }{name },
1141
+ full_perl_name => $xsub -> {decl }{full_perl_name },
1142
+ full_C_name => $xsub -> {decl }{full_C_name },
1197
1143
};
1198
1144
1199
1145
# The type looked up in the eval is Foo__Bar rather than Foo::Bar
@@ -1254,10 +1200,10 @@ sub as_input_code {
1254
1200
# would emit SvPV_nolen(...) - and instead, emit SvPV(...,
1255
1201
# STRLEN_length_of_foo)
1256
1202
if ($xstype eq ' T_PV' and $self -> {has_length }) {
1257
- print " = ($type )SvPV($arg , STRLEN_length_of_$var );\n " ;
1258
1203
die " default value not supported with length(NAME) supplied"
1259
1204
if defined $default ;
1260
- return ;
1205
+ return " ($type )SvPV($arg , STRLEN_length_of_$var );" ,
1206
+ $eval_vars , 0;
1261
1207
}
1262
1208
1263
1209
# Get the ExtUtils::Typemaps::InputMap object associated with the
@@ -1312,8 +1258,6 @@ sub as_input_code {
1312
1258
}
1313
1259
1314
1260
if ($expr =~ m # /\* .*scope.*\* /# i ) { # "scope" in C comments
1315
- # XXX this really aught to be determined during parse rather
1316
- # than during code emitting.
1317
1261
$xsub -> {SCOPE_enabled } = 1;
1318
1262
}
1319
1263
@@ -1323,6 +1267,98 @@ sub as_input_code {
1323
1267
$init_template = $expr ;
1324
1268
}
1325
1269
1270
+ return ($init_template , $eval_vars , 1);
1271
+ }
1272
+
1273
+
1274
+ # $self->as_input_code():
1275
+ #
1276
+ # Emit the param object as C code which declares and initialise the variable.
1277
+ # See also the as_output_code() method, which emits code to return the value
1278
+ # of that local var.
1279
+
1280
+ sub as_input_code {
1281
+ my __PACKAGE__ $self = shift ;
1282
+ my ExtUtils::ParseXS $pxs = shift ;
1283
+ my ExtUtils::ParseXS::Node::xsub $xsub = shift ;
1284
+ my $xbody = shift ;
1285
+
1286
+ my ($type , $arg_num , $var , $init , $no_init , $defer , $default )
1287
+ = @{$self }{qw( type arg_num var init no_init defer default) };
1288
+
1289
+ my $arg = $pxs -> ST($arg_num );
1290
+
1291
+ if ($self -> {is_length }) {
1292
+ # Process length(foo) parameter.
1293
+ # Basically for something like foo(char *s, int length(s)),
1294
+ # create *two* local C vars: one with STRLEN type, and one with the
1295
+ # type specified in the signature. Eventually, generate code looking
1296
+ # something like:
1297
+ # STRLEN STRLEN_length_of_s;
1298
+ # int XSauto_length_of_s;
1299
+ # char *s = (char *)SvPV(ST(0), STRLEN_length_of_s);
1300
+ # XSauto_length_of_s = STRLEN_length_of_s;
1301
+ # RETVAL = foo(s, XSauto_length_of_s);
1302
+ #
1303
+ # Note that the SvPV() code line is generated via a separate call to
1304
+ # this sub with s as the var (as opposed to *this* call, which is
1305
+ # handling length(s)), by overriding the normal T_PV typemap (which
1306
+ # uses PV_nolen()).
1307
+
1308
+ my $name = $self -> {len_name };
1309
+
1310
+ print " \t STRLEN\t STRLEN_length_of_$name ;\n " ;
1311
+ # defer this line until after all the other declarations
1312
+ $xbody -> {input_part }{deferred_code_lines } .=
1313
+ " \n\t XSauto_length_of_$name = STRLEN_length_of_$name ;\n " ;
1314
+ $var = " XSauto_length_of_$name " ;
1315
+ }
1316
+
1317
+ # Emit the variable's type and name.
1318
+ #
1319
+ # Includes special handling for function pointer types. An INPUT line
1320
+ # always has the C type followed by the variable name. The C code
1321
+ # which is emitted normally follows the same pattern. However for
1322
+ # function pointers, the code is different: the variable name has to
1323
+ # be embedded *within* the type. For example, these two INPUT lines:
1324
+ #
1325
+ # char * s
1326
+ # int (*)(int) fn_ptr
1327
+ #
1328
+ # cause the following lines of C to be emitted;
1329
+ #
1330
+ # char * s = [something from a typemap]
1331
+ # int (* fn_ptr)(int) = [something from a typemap]
1332
+ #
1333
+ # So handle specially the specific case of a type containing '(*)' by
1334
+ # embedding the variable name *within* rather than *after* the type.
1335
+
1336
+
1337
+ if ($type =~ / \( \s * \* \s * \) /x ) {
1338
+ # for a fn ptr type, embed the var name in the type declaration
1339
+ print " \t " . $pxs -> map_type($type , $var );
1340
+ }
1341
+ else {
1342
+ print " \t " ,
1343
+ ((defined ($xsub -> {decl }{class }) && $var eq ' CLASS' )
1344
+ ? $type
1345
+ : $pxs -> map_type($type , undef )),
1346
+ " \t $var " ;
1347
+ }
1348
+
1349
+ my ($init_template , $eval_vars , $is_template ) =
1350
+ $self -> lookup_input_typemap($pxs , $xsub , $xbody );
1351
+
1352
+ return unless defined $init_template ; # an error occurred
1353
+ unless ($is_template ) {
1354
+ # template already expanded
1355
+ print " = $init_template \n " ;
1356
+ return ;
1357
+ }
1358
+
1359
+ # whitespace-tidy the type
1360
+ $type = ExtUtils::Typemaps::tidy_type($type );
1361
+
1326
1362
# Now finally, emit the actual variable declaration and initialisation
1327
1363
# line(s). The variable type and name will already have been emitted.
1328
1364
0 commit comments