This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Promote v5.36 usage and feature bundles doc
[perl5.git] / builtin.c
CommitLineData
6a2e756f
PE
1/* builtin.c
2 *
3 * Copyright (C) 2021 by Paul Evans and others
4 *
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
7 *
8 */
9
10/* This file contains the code that implements functions in perl's "builtin::"
11 * namespace
12 */
13
14#include "EXTERN.h"
15#include "perl.h"
16
17#include "XSUB.h"
18
852c1a84
PE
19struct BuiltinFuncDescriptor {
20 const char *name;
21 XSUBADDR_t xsub;
22 OP *(*checker)(pTHX_ OP *, GV *, SV *);
23 IV ckval;
24};
25
929db505
DIM
26#define warn_experimental_builtin(name, prefix) S_warn_experimental_builtin(aTHX_ name, prefix)
27static void S_warn_experimental_builtin(pTHX_ const char *name, bool prefix)
28{
29 /* diag_listed_as: Built-in function '%s' is experimental */
30 Perl_ck_warner_d(aTHX_ packWARN(WARN_EXPERIMENTAL__BUILTIN),
31 "Built-in function '%s%s' is experimental",
32 prefix ? "builtin::" : "", name);
33}
34
bb0dc1a9
PE
35/* These three utilities might want to live elsewhere to be reused from other
36 * code sometime
37 */
38#define prepare_export_lexical() S_prepare_export_lexical(aTHX)
39static void S_prepare_export_lexical(pTHX)
40{
41 assert(PL_compcv);
42
43 /* We need to have PL_comppad / PL_curpad set correctly for lexical importing */
44 ENTER;
45 SAVESPTR(PL_comppad_name); PL_comppad_name = PadlistNAMES(CvPADLIST(PL_compcv));
46 SAVESPTR(PL_comppad); PL_comppad = PadlistARRAY(CvPADLIST(PL_compcv))[1];
47 SAVESPTR(PL_curpad); PL_curpad = PadARRAY(PL_comppad);
48}
49
50#define export_lexical(name, sv) S_export_lexical(aTHX_ name, sv)
51static void S_export_lexical(pTHX_ SV *name, SV *sv)
52{
53 PADOFFSET off = pad_add_name_sv(name, padadd_STATE, 0, 0);
54 SvREFCNT_dec(PL_curpad[off]);
55 PL_curpad[off] = SvREFCNT_inc(sv);
56}
57
58#define finish_export_lexical() S_finish_export_lexical(aTHX)
59static void S_finish_export_lexical(pTHX)
60{
61 intro_my();
62
63 LEAVE;
64}
65
66
6a2e756f
PE
67XS(XS_builtin_true);
68XS(XS_builtin_true)
69{
70 dXSARGS;
929db505 71 warn_experimental_builtin("true", true);
6a2e756f
PE
72 if(items)
73 croak_xs_usage(cv, "");
74 XSRETURN_YES;
75}
76
77XS(XS_builtin_false);
78XS(XS_builtin_false)
79{
80 dXSARGS;
929db505 81 warn_experimental_builtin("false", true);
6a2e756f
PE
82 if(items)
83 croak_xs_usage(cv, "");
84 XSRETURN_NO;
85}
86
852c1a84
PE
87enum {
88 BUILTIN_CONST_FALSE,
89 BUILTIN_CONST_TRUE,
90};
91
92static OP *ck_builtin_const(pTHX_ OP *entersubop, GV *namegv, SV *ckobj)
93{
94 const struct BuiltinFuncDescriptor *builtin = NUM2PTR(const struct BuiltinFuncDescriptor *, SvUV(ckobj));
95
929db505 96 warn_experimental_builtin(builtin->name, false);
cc4aa213 97
852c1a84
PE
98 SV *prototype = newSVpvs("");
99 SAVEFREESV(prototype);
100
101 assert(entersubop->op_type == OP_ENTERSUB);
102
103 entersubop = ck_entersub_args_proto(entersubop, namegv, prototype);
104
105 SV *constval;
106 switch(builtin->ckval) {
107 case BUILTIN_CONST_FALSE: constval = &PL_sv_no; break;
108 case BUILTIN_CONST_TRUE: constval = &PL_sv_yes; break;
109 default:
c0e63b13
KW
110 DIE(aTHX_ "panic: unrecognised builtin_const value %" IVdf,
111 builtin->ckval);
852c1a84
PE
112 break;
113 }
114
115 op_free(entersubop);
116
117 return newSVOP(OP_CONST, 0, constval);
118}
119
6ac93b49
PE
120XS(XS_builtin_func1_scalar);
121XS(XS_builtin_func1_scalar)
6a2e756f
PE
122{
123 dXSARGS;
852c1a84
PE
124 dXSI32;
125
929db505
DIM
126 warn_experimental_builtin(PL_op_name[ix], true);
127
6a2e756f 128 if(items != 1)
852c1a84
PE
129 croak_xs_usage(cv, "arg");
130
131 switch(ix) {
5a94615f
PE
132 case OP_IS_BOOL:
133 Perl_pp_is_bool(aTHX);
852c1a84 134 break;
6a2e756f 135
5a94615f
PE
136 case OP_IS_WEAK:
137 Perl_pp_is_weak(aTHX);
6ac93b49
PE
138 break;
139
d2817bd7
PE
140 case OP_BLESSED:
141 Perl_pp_blessed(aTHX);
142 break;
143
144 case OP_REFADDR:
145 Perl_pp_refaddr(aTHX);
146 break;
147
148 case OP_REFTYPE:
149 Perl_pp_reftype(aTHX);
150 break;
151
17a8df70
JR
152 case OP_CEIL:
153 Perl_pp_ceil(aTHX);
154 break;
155
156 case OP_FLOOR:
157 Perl_pp_floor(aTHX);
158 break;
159
a02b8151
JR
160 case OP_IS_TAINTED:
161 Perl_pp_is_tainted(aTHX);
162 break;
163
852c1a84 164 default:
c0e63b13 165 Perl_die(aTHX_ "panic: unhandled opcode %" IVdf
730f927d 166 " for xs_builtin_func1_scalar()", (IV) ix);
852c1a84
PE
167 }
168
169 XSRETURN(1);
170}
171
42a429a3
KW
172XS(XS_builtin_trim);
173XS(XS_builtin_trim)
174{
175 dXSARGS;
176
177 warn_experimental_builtin("trim", true);
178
179 if (items != 1) {
180 croak_xs_usage(cv, "arg");
181 }
182
183 dTARGET;
184 SV *source = TOPs;
185 STRLEN len;
186 const U8 *start;
187 SV *dest;
188
189 SvGETMAGIC(source);
190
191 if (SvOK(source))
192 start = (const U8*)SvPV_nomg_const(source, len);
193 else {
194 if (ckWARN(WARN_UNINITIALIZED))
195 report_uninit(source);
196 start = (const U8*)"";
197 len = 0;
198 }
199
200 if (DO_UTF8(source)) {
201 const U8 *end = start + len;
202
203 /* Find the first non-space */
204 while(len) {
205 STRLEN thislen;
206 if (!isSPACE_utf8_safe(start, end))
207 break;
208 start += (thislen = UTF8SKIP(start));
209 len -= thislen;
210 }
211
212 /* Find the final non-space */
213 STRLEN thislen;
214 const U8 *cur_end = end;
215 while ((thislen = is_SPACE_utf8_safe_backwards(cur_end, start))) {
216 cur_end -= thislen;
217 }
218 len -= (end - cur_end);
219 }
220 else if (len) {
221 while(len) {
222 if (!isSPACE_L1(*start))
223 break;
224 start++;
225 len--;
226 }
227
228 while(len) {
229 if (!isSPACE_L1(start[len-1]))
230 break;
231 len--;
232 }
233 }
234
235 dest = TARG;
236
237 if (SvPOK(dest) && (dest == source)) {
238 sv_chop(dest, (const char *)start);
239 SvCUR_set(dest, len);
240 }
241 else {
242 SvUPGRADE(dest, SVt_PV);
243 SvGROW(dest, len + 1);
244
245 Copy(start, SvPVX(dest), len, U8);
246 SvPVX(dest)[len] = '\0';
247 SvPOK_on(dest);
248 SvCUR_set(dest, len);
249
250 if (DO_UTF8(source))
251 SvUTF8_on(dest);
252 else
253 SvUTF8_off(dest);
254
255 if (SvTAINTED(source))
256 SvTAINT(dest);
257 }
258
259 SvSETMAGIC(dest);
260
261 SETs(dest);
262
263 XSRETURN(1);
264}
265
f846dd12
PE
266XS(XS_builtin_export_lexically);
267XS(XS_builtin_export_lexically)
268{
269 dXSARGS;
270
271 warn_experimental_builtin("export_lexically", true);
272
273 if(!PL_compcv)
274 Perl_croak(aTHX_
275 "export_lexically can only be called at compile time");
276
277 if(items % 2)
278 Perl_croak(aTHX_ "Odd number of elements in export_lexically");
279
280 for(int i = 0; i < items; i += 2) {
281 SV *name = ST(i);
282 SV *ref = ST(i+1);
283
284 if(!SvROK(ref))
285 /* diag_listed_as: Expected %s reference in export_lexically */
286 Perl_croak(aTHX_ "Expected a reference in export_lexically");
287
288 char sigil = SvPVX(name)[0];
289 SV *rv = SvRV(ref);
290
291 const char *bad = NULL;
292 switch(sigil) {
293 default:
294 /* overwrites the pointer on the stack; but this is fine, the
295 * caller's value isn't modified */
296 ST(i) = name = sv_2mortal(Perl_newSVpvf(aTHX_ "&%" SVf, SVfARG(name)));
297
298 /* FALLTHROUGH */
299 case '&':
300 if(SvTYPE(rv) != SVt_PVCV)
301 bad = "a CODE";
302 break;
303
304 case '$':
305 /* Permit any of SVt_NULL to SVt_PVMG. Technically this also
306 * includes SVt_INVLIST but it isn't thought possible for pureperl
307 * code to ever manage to see one of those. */
308 if(SvTYPE(rv) > SVt_PVMG)
309 bad = "a SCALAR";
310 break;
311
312 case '@':
313 if(SvTYPE(rv) != SVt_PVAV)
314 bad = "an ARRAY";
315 break;
316
317 case '%':
318 if(SvTYPE(rv) != SVt_PVHV)
319 bad = "a HASH";
320 break;
321 }
322
323 if(bad)
324 Perl_croak(aTHX_ "Expected %s reference in export_lexically", bad);
325 }
326
327 prepare_export_lexical();
328
329 for(int i = 0; i < items; i += 2) {
330 SV *name = ST(i);
331 SV *ref = ST(i+1);
332
333 export_lexical(name, SvRV(ref));
334 }
335
336 finish_export_lexical();
337}
338
6ac93b49
PE
339XS(XS_builtin_func1_void);
340XS(XS_builtin_func1_void)
341{
342 dXSARGS;
343 dXSI32;
344
929db505
DIM
345 warn_experimental_builtin(PL_op_name[ix], true);
346
6ac93b49
PE
347 if(items != 1)
348 croak_xs_usage(cv, "arg");
349
350 switch(ix) {
351 case OP_WEAKEN:
352 Perl_pp_weaken(aTHX);
353 break;
354
355 case OP_UNWEAKEN:
356 Perl_pp_unweaken(aTHX);
357 break;
358
359 default:
730f927d
KW
360 Perl_die(aTHX_ "panic: unhandled opcode %" IVdf
361 " for xs_builtin_func1_void()", (IV) ix);
6ac93b49
PE
362 }
363
364 XSRETURN(0);
365}
366
bd79e3f7
PE
367XS(XS_builtin_created_as_string)
368{
369 dXSARGS;
370
371 if(items != 1)
372 croak_xs_usage(cv, "arg");
373
374 SV *arg = ST(0);
375 SvGETMAGIC(arg);
376
377 /* SV was created as string if it has POK and isn't bool */
378 ST(0) = boolSV(SvPOK(arg) && !SvIsBOOL(arg));
379 XSRETURN(1);
380}
381
382XS(XS_builtin_created_as_number)
383{
384 dXSARGS;
385
386 if(items != 1)
387 croak_xs_usage(cv, "arg");
388
389 SV *arg = ST(0);
390 SvGETMAGIC(arg);
391
392 /* SV was created as number if it has NOK or IOK but not POK and is not bool */
393 ST(0) = boolSV(SvNIOK(arg) && !SvPOK(arg) && !SvIsBOOL(arg));
394 XSRETURN(1);
395}
396
852c1a84
PE
397static OP *ck_builtin_func1(pTHX_ OP *entersubop, GV *namegv, SV *ckobj)
398{
399 const struct BuiltinFuncDescriptor *builtin = NUM2PTR(const struct BuiltinFuncDescriptor *, SvUV(ckobj));
400
929db505 401 warn_experimental_builtin(builtin->name, false);
cc4aa213 402
852c1a84
PE
403 SV *prototype = newSVpvs("$");
404 SAVEFREESV(prototype);
405
406 assert(entersubop->op_type == OP_ENTERSUB);
407
408 entersubop = ck_entersub_args_proto(entersubop, namegv, prototype);
409
bd79e3f7
PE
410 OPCODE opcode = builtin->ckval;
411 if(!opcode)
412 return entersubop;
413
852c1a84
PE
414 OP *parent = entersubop, *pushop, *argop;
415
416 pushop = cUNOPx(entersubop)->op_first;
417 if (!OpHAS_SIBLING(pushop)) {
418 pushop = cUNOPx(pushop)->op_first;
419 }
420
421 argop = OpSIBLING(pushop);
422
423 if (!argop || !OpHAS_SIBLING(argop) || OpHAS_SIBLING(OpSIBLING(argop)))
424 return entersubop;
425
426 (void)op_sibling_splice(parent, pushop, 1, NULL);
427
1c57e396 428 U8 wantflags = entersubop->op_flags & OPf_WANT;
852c1a84
PE
429
430 op_free(entersubop);
431
1c57e396 432 return newUNOP(opcode, wantflags, argop);
6a2e756f
PE
433}
434
10bccff2
PE
435XS(XS_builtin_indexed)
436{
437 dXSARGS;
438
439 switch(GIMME_V) {
440 case G_VOID:
441 Perl_ck_warner(aTHX_ packWARN(WARN_VOID),
442 "Useless use of %s in void context", "builtin::indexed");
443 XSRETURN(0);
444
445 case G_SCALAR:
446 Perl_ck_warner(aTHX_ packWARN(WARN_SCALAR),
447 "Useless use of %s in scalar context", "builtin::indexed");
448 ST(0) = sv_2mortal(newSViv(items * 2));
449 XSRETURN(1);
450
451 case G_LIST:
452 break;
453 }
454
455 SSize_t retcount = items * 2;
456 EXTEND(SP, retcount);
457
458 /* Copy from [items-1] down to [0] so we don't have to make
459 * temporary copies */
460 for(SSize_t index = items - 1; index >= 0; index--) {
461 /* Copy, not alias */
462 ST(index * 2 + 1) = sv_mortalcopy(ST(index));
463 ST(index * 2) = sv_2mortal(newSViv(index));
464 }
465
466 XSRETURN(retcount);
467}
468
469static OP *ck_builtin_funcN(pTHX_ OP *entersubop, GV *namegv, SV *ckobj)
470{
471 const struct BuiltinFuncDescriptor *builtin = NUM2PTR(const struct BuiltinFuncDescriptor *, SvUV(ckobj));
472
473 warn_experimental_builtin(builtin->name, false);
474
475 SV *prototype = newSVpvs("@");
476 SAVEFREESV(prototype);
477
478 assert(entersubop->op_type == OP_ENTERSUB);
479
480 entersubop = ck_entersub_args_proto(entersubop, namegv, prototype);
481 return entersubop;
482}
483
a64a1b91
DIM
484static const char builtin_not_recognised[] = "'%" SVf "' is not recognised as a builtin function";
485
852c1a84
PE
486static const struct BuiltinFuncDescriptor builtins[] = {
487 /* constants */
488 { "builtin::true", &XS_builtin_true, &ck_builtin_const, BUILTIN_CONST_TRUE },
489 { "builtin::false", &XS_builtin_false, &ck_builtin_const, BUILTIN_CONST_FALSE },
490
491 /* unary functions */
a02b8151
JR
492 { "builtin::is_bool", &XS_builtin_func1_scalar, &ck_builtin_func1, OP_IS_BOOL },
493 { "builtin::weaken", &XS_builtin_func1_void, &ck_builtin_func1, OP_WEAKEN },
494 { "builtin::unweaken", &XS_builtin_func1_void, &ck_builtin_func1, OP_UNWEAKEN },
495 { "builtin::is_weak", &XS_builtin_func1_scalar, &ck_builtin_func1, OP_IS_WEAK },
496 { "builtin::blessed", &XS_builtin_func1_scalar, &ck_builtin_func1, OP_BLESSED },
497 { "builtin::refaddr", &XS_builtin_func1_scalar, &ck_builtin_func1, OP_REFADDR },
498 { "builtin::reftype", &XS_builtin_func1_scalar, &ck_builtin_func1, OP_REFTYPE },
499 { "builtin::ceil", &XS_builtin_func1_scalar, &ck_builtin_func1, OP_CEIL },
500 { "builtin::floor", &XS_builtin_func1_scalar, &ck_builtin_func1, OP_FLOOR },
501 { "builtin::is_tainted", &XS_builtin_func1_scalar, &ck_builtin_func1, OP_IS_TAINTED },
35c98d68 502 { "builtin::trim", &XS_builtin_trim, &ck_builtin_func1, 0 },
10bccff2 503
bd79e3f7
PE
504 { "builtin::created_as_string", &XS_builtin_created_as_string, &ck_builtin_func1, 0 },
505 { "builtin::created_as_number", &XS_builtin_created_as_number, &ck_builtin_func1, 0 },
506
10bccff2
PE
507 /* list functions */
508 { "builtin::indexed", &XS_builtin_indexed, &ck_builtin_funcN, 0 },
f846dd12 509 { "builtin::export_lexically", &XS_builtin_export_lexically, NULL, 0 },
852c1a84
PE
510 { 0 }
511};
512
6a2e756f
PE
513XS(XS_builtin_import);
514XS(XS_builtin_import)
515{
516 dXSARGS;
517
518 if(!PL_compcv)
519 Perl_croak(aTHX_
2302ea7b 520 "builtin::import can only be called at compile time");
6a2e756f 521
bb0dc1a9 522 prepare_export_lexical();
6a2e756f
PE
523
524 for(int i = 1; i < items; i++) {
525 SV *sym = ST(i);
a64a1b91
DIM
526 if(strEQ(SvPV_nolen(sym), "import"))
527 Perl_croak(aTHX_ builtin_not_recognised, sym);
6a2e756f
PE
528
529 SV *ampname = sv_2mortal(Perl_newSVpvf(aTHX_ "&%" SVf, SVfARG(sym)));
bb0dc1a9 530 SV *fqname = sv_2mortal(Perl_newSVpvf(aTHX_ "builtin::%" SVf, SVfARG(sym)));
6a2e756f
PE
531
532 CV *cv = get_cv(SvPV_nolen(fqname), SvUTF8(fqname) ? SVf_UTF8 : 0);
a64a1b91
DIM
533 if(!cv)
534 Perl_croak(aTHX_ builtin_not_recognised, sym);
6a2e756f 535
bb0dc1a9 536 export_lexical(ampname, (SV *)cv);
6a2e756f
PE
537 }
538
bb0dc1a9 539 finish_export_lexical();
6a2e756f
PE
540}
541
542void
543Perl_boot_core_builtin(pTHX)
544{
852c1a84
PE
545 I32 i;
546 for(i = 0; builtins[i].name; i++) {
547 const struct BuiltinFuncDescriptor *builtin = &builtins[i];
548
549 const char *proto = NULL;
550 if(builtin->checker == &ck_builtin_const)
551 proto = "";
552 else if(builtin->checker == &ck_builtin_func1)
553 proto = "$";
554
555 CV *cv = newXS_flags(builtin->name, builtin->xsub, __FILE__, proto, 0);
556 XSANY.any_i32 = builtin->ckval;
557
558 if(builtin->checker) {
559 cv_set_call_checker_flags(cv, builtin->checker, newSVuv(PTR2UV(builtin)), 0);
560 }
561 }
6a2e756f
PE
562
563 newXS_flags("builtin::import", &XS_builtin_import, __FILE__, NULL, 0);
564}
565
566/*
567 * ex: set ts=8 sts=4 sw=4 et:
568 */