3 * Copyright (C) 2021 by Paul Evans and others
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.
10 /* This file contains the code that implements functions in perl's "builtin::"
19 struct BuiltinFuncDescriptor {
22 OP *(*checker)(pTHX_ OP *, GV *, SV *);
26 #define warn_experimental_builtin(name, prefix) S_warn_experimental_builtin(aTHX_ name, prefix)
27 static void S_warn_experimental_builtin(pTHX_ const char *name, bool prefix)
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);
35 /* These three utilities might want to live elsewhere to be reused from other
38 #define prepare_export_lexical() S_prepare_export_lexical(aTHX)
39 static void S_prepare_export_lexical(pTHX)
43 /* We need to have PL_comppad / PL_curpad set correctly for lexical importing */
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);
50 #define export_lexical(name, sv) S_export_lexical(aTHX_ name, sv)
51 static void S_export_lexical(pTHX_ SV *name, SV *sv)
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);
58 #define finish_export_lexical() S_finish_export_lexical(aTHX)
59 static void S_finish_export_lexical(pTHX)
71 warn_experimental_builtin("true", true);
73 croak_xs_usage(cv, "");
81 warn_experimental_builtin("false", true);
83 croak_xs_usage(cv, "");
92 static OP *ck_builtin_const(pTHX_ OP *entersubop, GV *namegv, SV *ckobj)
94 const struct BuiltinFuncDescriptor *builtin = NUM2PTR(const struct BuiltinFuncDescriptor *, SvUV(ckobj));
96 warn_experimental_builtin(builtin->name, false);
98 SV *prototype = newSVpvs("");
99 SAVEFREESV(prototype);
101 assert(entersubop->op_type == OP_ENTERSUB);
103 entersubop = ck_entersub_args_proto(entersubop, namegv, prototype);
106 switch(builtin->ckval) {
107 case BUILTIN_CONST_FALSE: constval = &PL_sv_no; break;
108 case BUILTIN_CONST_TRUE: constval = &PL_sv_yes; break;
110 DIE(aTHX_ "panic: unrecognised builtin_const value %" IVdf,
117 return newSVOP(OP_CONST, 0, constval);
120 XS(XS_builtin_func1_scalar);
121 XS(XS_builtin_func1_scalar)
126 warn_experimental_builtin(PL_op_name[ix], true);
129 croak_xs_usage(cv, "arg");
133 Perl_pp_is_bool(aTHX);
137 Perl_pp_is_weak(aTHX);
141 Perl_pp_blessed(aTHX);
145 Perl_pp_refaddr(aTHX);
149 Perl_pp_reftype(aTHX);
161 Perl_pp_is_tainted(aTHX);
165 Perl_die(aTHX_ "panic: unhandled opcode %" IVdf
166 " for xs_builtin_func1_scalar()", (IV) ix);
177 warn_experimental_builtin("trim", true);
180 croak_xs_usage(cv, "arg");
192 start = (const U8*)SvPV_nomg_const(source, len);
194 if (ckWARN(WARN_UNINITIALIZED))
195 report_uninit(source);
196 start = (const U8*)"";
200 if (DO_UTF8(source)) {
201 const U8 *end = start + len;
203 /* Find the first non-space */
206 if (!isSPACE_utf8_safe(start, end))
208 start += (thislen = UTF8SKIP(start));
212 /* Find the final non-space */
214 const U8 *cur_end = end;
215 while ((thislen = is_SPACE_utf8_safe_backwards(cur_end, start))) {
218 len -= (end - cur_end);
222 if (!isSPACE_L1(*start))
229 if (!isSPACE_L1(start[len-1]))
237 if (SvPOK(dest) && (dest == source)) {
238 sv_chop(dest, (const char *)start);
239 SvCUR_set(dest, len);
242 SvUPGRADE(dest, SVt_PV);
243 SvGROW(dest, len + 1);
245 Copy(start, SvPVX(dest), len, U8);
246 SvPVX(dest)[len] = '\0';
248 SvCUR_set(dest, len);
255 if (SvTAINTED(source))
266 XS(XS_builtin_export_lexically);
267 XS(XS_builtin_export_lexically)
271 warn_experimental_builtin("export_lexically", true);
275 "export_lexically can only be called at compile time");
278 Perl_croak(aTHX_ "Odd number of elements in export_lexically");
280 for(int i = 0; i < items; i += 2) {
285 /* diag_listed_as: Expected %s reference in export_lexically */
286 Perl_croak(aTHX_ "Expected a reference in export_lexically");
288 char sigil = SvPVX(name)[0];
291 const char *bad = NULL;
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)));
300 if(SvTYPE(rv) != SVt_PVCV)
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)
313 if(SvTYPE(rv) != SVt_PVAV)
318 if(SvTYPE(rv) != SVt_PVHV)
324 Perl_croak(aTHX_ "Expected %s reference in export_lexically", bad);
327 prepare_export_lexical();
329 for(int i = 0; i < items; i += 2) {
333 export_lexical(name, SvRV(ref));
336 finish_export_lexical();
339 XS(XS_builtin_func1_void);
340 XS(XS_builtin_func1_void)
345 warn_experimental_builtin(PL_op_name[ix], true);
348 croak_xs_usage(cv, "arg");
352 Perl_pp_weaken(aTHX);
356 Perl_pp_unweaken(aTHX);
360 Perl_die(aTHX_ "panic: unhandled opcode %" IVdf
361 " for xs_builtin_func1_void()", (IV) ix);
367 XS(XS_builtin_created_as_string)
372 croak_xs_usage(cv, "arg");
377 /* SV was created as string if it has POK and isn't bool */
378 ST(0) = boolSV(SvPOK(arg) && !SvIsBOOL(arg));
382 XS(XS_builtin_created_as_number)
387 croak_xs_usage(cv, "arg");
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));
397 static OP *ck_builtin_func1(pTHX_ OP *entersubop, GV *namegv, SV *ckobj)
399 const struct BuiltinFuncDescriptor *builtin = NUM2PTR(const struct BuiltinFuncDescriptor *, SvUV(ckobj));
401 warn_experimental_builtin(builtin->name, false);
403 SV *prototype = newSVpvs("$");
404 SAVEFREESV(prototype);
406 assert(entersubop->op_type == OP_ENTERSUB);
408 entersubop = ck_entersub_args_proto(entersubop, namegv, prototype);
410 OPCODE opcode = builtin->ckval;
414 OP *parent = entersubop, *pushop, *argop;
416 pushop = cUNOPx(entersubop)->op_first;
417 if (!OpHAS_SIBLING(pushop)) {
418 pushop = cUNOPx(pushop)->op_first;
421 argop = OpSIBLING(pushop);
423 if (!argop || !OpHAS_SIBLING(argop) || OpHAS_SIBLING(OpSIBLING(argop)))
426 (void)op_sibling_splice(parent, pushop, 1, NULL);
428 U8 wantflags = entersubop->op_flags & OPf_WANT;
432 return newUNOP(opcode, wantflags, argop);
435 XS(XS_builtin_indexed)
441 Perl_ck_warner(aTHX_ packWARN(WARN_VOID),
442 "Useless use of %s in void context", "builtin::indexed");
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));
455 SSize_t retcount = items * 2;
456 EXTEND(SP, retcount);
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));
469 static OP *ck_builtin_funcN(pTHX_ OP *entersubop, GV *namegv, SV *ckobj)
471 const struct BuiltinFuncDescriptor *builtin = NUM2PTR(const struct BuiltinFuncDescriptor *, SvUV(ckobj));
473 warn_experimental_builtin(builtin->name, false);
475 SV *prototype = newSVpvs("@");
476 SAVEFREESV(prototype);
478 assert(entersubop->op_type == OP_ENTERSUB);
480 entersubop = ck_entersub_args_proto(entersubop, namegv, prototype);
484 static const char builtin_not_recognised[] = "'%" SVf "' is not recognised as a builtin function";
486 static const struct BuiltinFuncDescriptor builtins[] = {
488 { "builtin::true", &XS_builtin_true, &ck_builtin_const, BUILTIN_CONST_TRUE },
489 { "builtin::false", &XS_builtin_false, &ck_builtin_const, BUILTIN_CONST_FALSE },
491 /* unary functions */
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 },
502 { "builtin::trim", &XS_builtin_trim, &ck_builtin_func1, 0 },
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 },
508 { "builtin::indexed", &XS_builtin_indexed, &ck_builtin_funcN, 0 },
509 { "builtin::export_lexically", &XS_builtin_export_lexically, NULL, 0 },
513 XS(XS_builtin_import);
514 XS(XS_builtin_import)
520 "builtin::import can only be called at compile time");
522 prepare_export_lexical();
524 for(int i = 1; i < items; i++) {
526 if(strEQ(SvPV_nolen(sym), "import"))
527 Perl_croak(aTHX_ builtin_not_recognised, sym);
529 SV *ampname = sv_2mortal(Perl_newSVpvf(aTHX_ "&%" SVf, SVfARG(sym)));
530 SV *fqname = sv_2mortal(Perl_newSVpvf(aTHX_ "builtin::%" SVf, SVfARG(sym)));
532 CV *cv = get_cv(SvPV_nolen(fqname), SvUTF8(fqname) ? SVf_UTF8 : 0);
534 Perl_croak(aTHX_ builtin_not_recognised, sym);
536 export_lexical(ampname, (SV *)cv);
539 finish_export_lexical();
543 Perl_boot_core_builtin(pTHX)
546 for(i = 0; builtins[i].name; i++) {
547 const struct BuiltinFuncDescriptor *builtin = &builtins[i];
549 const char *proto = NULL;
550 if(builtin->checker == &ck_builtin_const)
552 else if(builtin->checker == &ck_builtin_func1)
555 CV *cv = newXS_flags(builtin->name, builtin->xsub, __FILE__, proto, 0);
556 XSANY.any_i32 = builtin->ckval;
558 if(builtin->checker) {
559 cv_set_call_checker_flags(cv, builtin->checker, newSVuv(PTR2UV(builtin)), 0);
563 newXS_flags("builtin::import", &XS_builtin_import, __FILE__, NULL, 0);
567 * ex: set ts=8 sts=4 sw=4 et: