X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=mg.c;h=4da7453c3c2015ad69ee019315429292e13d9e95;hb=1e73acc8af3eecb1b36ee831483e1e9a7b3d1662;hp=b7e2e56c08818800d901db3597f2a6569e0be790;hpb=b3ca2e834c3607fd8aa8736a51aa3a2b8bba1044;p=p5sagit%2Fp5-mst-13.2.git diff --git a/mg.c b/mg.c index b7e2e56..4da7453 100644 --- a/mg.c +++ b/mg.c @@ -152,7 +152,7 @@ Perl_mg_get(pTHX_ SV *sv) cause the SV's buffer to get stolen (and maybe other stuff). So restore it. */ - sv_2mortal(SvREFCNT_inc_simple(sv)); + sv_2mortal(SvREFCNT_inc_simple_NN(sv)); if (!was_temp) { SvTEMP_off(sv); } @@ -379,7 +379,7 @@ Perl_mg_copy(pTHX_ SV *sv, SV *nsv, const char *key, I32 klen) } else { const char type = mg->mg_type; - if (isUPPER(type)) { + if (isUPPER(type) && type != PERL_MAGIC_uvar) { sv_magic(nsv, (type == PERL_MAGIC_tied) ? SvTIED_obj(sv, mg) @@ -758,10 +758,13 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) SvTAINTED_off(sv); } else if (strEQ(remaining, "PEN")) { - if (!PL_compiling.cop_io) + if (!(CopHINTS_get(&PL_compiling) & HINT_LEXICAL_IO)) sv_setsv(sv, &PL_sv_undef); else { - sv_setsv(sv, PL_compiling.cop_io); + sv_setsv(sv, + Perl_refcounted_he_fetch(aTHX_ + PL_compiling.cop_hints_hash, + 0, "open", 4, 0, 0)); } } break; @@ -826,7 +829,8 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) } } else { - sv_setsv(sv, PL_compiling.cop_warnings); + sv_setpvn(sv, (char *) (PL_compiling.cop_warnings + 1), + *PL_compiling.cop_warnings); } SvPOK_only(sv); } @@ -963,7 +967,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) case '/': break; case '[': - WITH_THR(sv_setiv(sv, (IV)PL_curcop->cop_arybase)); + WITH_THR(sv_setiv(sv, (IV)CopARYBASE_get(PL_curcop))); break; case '|': if (GvIOp(PL_defoutgv)) @@ -1042,8 +1046,8 @@ int Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg) { dVAR; - STRLEN len, klen; - const char *s = SvPV_const(sv,len); + STRLEN len = 0, klen; + const char *s = SvOK(sv) ? SvPV_const(sv,len) : ""; const char * const ptr = MgPV_const(mg,klen); my_setenv(ptr, s); @@ -1053,7 +1057,7 @@ Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg) if (!len) { SV ** const valp = hv_fetch(GvHVn(PL_envgv), ptr, klen, FALSE); if (valp) - s = SvPV_const(*valp, len); + s = SvOK(*valp) ? SvPV_const(*valp, len) : ""; } #endif @@ -1093,16 +1097,25 @@ Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg) #endif /* VMS */ if (s && klen == 4 && strEQ(ptr,"PATH")) { const char * const strend = s + len; +#ifdef VMS /* Hmm. How do we get $Config{path_sep} from C? */ + const char path_sep = '|'; +#else + const char path_sep = ':'; +#endif while (s < strend) { char tmpbuf[256]; Stat_t st; I32 i; s = delimcpy(tmpbuf, tmpbuf + sizeof tmpbuf, - s, strend, ':', &i); + s, strend, path_sep, &i); s++; - if (i >= sizeof tmpbuf /* too long -- assume the worst */ - || *tmpbuf != '/' + if (i >= (I32)sizeof tmpbuf /* too long -- assume the worst */ +#ifdef VMS + || !strchr(tmpbuf, ':') /* no colon thus no device name -- assume relative path */ +#else + || *tmpbuf != '/' /* no starting slash -- assume relative path */ +#endif || (PerlLIO_stat(tmpbuf, &st) == 0 && (st.st_mode & 2)) ) { MgTAINTEDDIR_on(mg); return 0; @@ -1178,20 +1191,21 @@ Perl_magic_getsig(pTHX_ SV *sv, MAGIC *mg) if(PL_psig_ptr[i]) sv_setsv(sv,PL_psig_ptr[i]); else { - Sighandler_t sigstate; - sigstate = rsignal_state(i); + Sighandler_t sigstate = rsignal_state(i); #ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS - if (PL_sig_handlers_initted && PL_sig_ignoring[i]) sigstate = SIG_IGN; + if (PL_sig_handlers_initted && PL_sig_ignoring[i]) + sigstate = SIG_IGN; #endif #ifdef FAKE_DEFAULT_SIGNAL_HANDLERS - if (PL_sig_handlers_initted && PL_sig_defaulting[i]) sigstate = SIG_DFL; + if (PL_sig_handlers_initted && PL_sig_defaulting[i]) + sigstate = SIG_DFL; #endif /* cache state so we don't fetch it again */ if(sigstate == (Sighandler_t) SIG_IGN) sv_setpv(sv,"IGNORE"); else sv_setsv(sv,&PL_sv_undef); - PL_psig_ptr[i] = SvREFCNT_inc_simple(sv); + PL_psig_ptr[i] = SvREFCNT_inc_simple_NN(sv); SvTEMP_off(sv); } } @@ -1403,7 +1417,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) #endif SvREFCNT_dec(PL_psig_name[i]); to_dec = PL_psig_ptr[i]; - PL_psig_ptr[i] = SvREFCNT_inc_simple(sv); + PL_psig_ptr[i] = SvREFCNT_inc_simple_NN(sv); SvTEMP_off(sv); /* Make sure it doesn't go away on us */ PL_psig_name[i] = newSVpvn(s, len); SvREADONLY_on(PL_psig_name[i]); @@ -1454,7 +1468,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) if (i) (void)rsignal(i, PL_csighandlerp); else - *svp = SvREFCNT_inc_simple(sv); + *svp = SvREFCNT_inc_simple_NN(sv); } #ifdef HAS_SIGPROCMASK if(i) @@ -1657,7 +1671,7 @@ Perl_magic_nextpack(pTHX_ SV *sv, MAGIC *mg, SV *key) } int -Perl_magic_existspack(pTHX_ SV *sv, MAGIC *mg) +Perl_magic_existspack(pTHX_ SV *sv, const MAGIC *mg) { return magic_methpack(sv,mg,"EXISTS"); } @@ -1666,7 +1680,7 @@ SV * Perl_magic_scalarpack(pTHX_ HV *hv, MAGIC *mg) { dVAR; dSP; - SV *retval = &PL_sv_undef; + SV *retval; SV * const tied = SvTIED_obj((SV*)hv, mg); HV * const pkg = SvSTASH((SV*)SvRV(tied)); @@ -1692,6 +1706,8 @@ Perl_magic_scalarpack(pTHX_ HV *hv, MAGIC *mg) if (call_method("SCALAR", G_SCALAR)) retval = *PL_stack_sp--; + else + retval = &PL_sv_undef; POPSTACK; LEAVE; return retval; @@ -1724,7 +1740,7 @@ Perl_magic_getarylen(pTHX_ SV *sv, const MAGIC *mg) dVAR; const AV * const obj = (AV*)mg->mg_obj; if (obj) { - sv_setiv(sv, AvFILL(obj) + PL_curcop->cop_arybase); + sv_setiv(sv, AvFILL(obj) + CopARYBASE_get(PL_curcop)); } else { SvOK_off(sv); } @@ -1737,7 +1753,7 @@ Perl_magic_setarylen(pTHX_ SV *sv, MAGIC *mg) dVAR; AV * const obj = (AV*)mg->mg_obj; if (obj) { - av_fill(obj, SvIV(sv) - PL_curcop->cop_arybase); + av_fill(obj, SvIV(sv) - CopARYBASE_get(PL_curcop)); } else { if (ckWARN(WARN_MISC)) Perl_warner(aTHX_ packWARN(WARN_MISC), @@ -1773,14 +1789,15 @@ Perl_magic_getpos(pTHX_ SV *sv, MAGIC *mg) { dVAR; SV* const lsv = LvTARG(sv); + PERL_UNUSED_ARG(mg); if (SvTYPE(lsv) >= SVt_PVMG && SvMAGIC(lsv)) { - mg = mg_find(lsv, PERL_MAGIC_regex_global); - if (mg && mg->mg_len >= 0) { - I32 i = mg->mg_len; + MAGIC * const found = mg_find(lsv, PERL_MAGIC_regex_global); + if (found && found->mg_len >= 0) { + I32 i = found->mg_len; if (DO_UTF8(lsv)) sv_pos_b2u(lsv, &i); - sv_setiv(sv, i + PL_curcop->cop_arybase); + sv_setiv(sv, i + CopARYBASE_get(PL_curcop)); return 0; } } @@ -1796,28 +1813,31 @@ Perl_magic_setpos(pTHX_ SV *sv, MAGIC *mg) SSize_t pos; STRLEN len; STRLEN ulen = 0; + MAGIC *found; - mg = 0; + PERL_UNUSED_ARG(mg); if (SvTYPE(lsv) >= SVt_PVMG && SvMAGIC(lsv)) - mg = mg_find(lsv, PERL_MAGIC_regex_global); - if (!mg) { + found = mg_find(lsv, PERL_MAGIC_regex_global); + else + found = NULL; + if (!found) { if (!SvOK(sv)) return 0; #ifdef PERL_OLD_COPY_ON_WRITE if (SvIsCOW(lsv)) sv_force_normal_flags(lsv, 0); #endif - mg = sv_magicext(lsv, NULL, PERL_MAGIC_regex_global, &PL_vtbl_mglob, + found = sv_magicext(lsv, NULL, PERL_MAGIC_regex_global, &PL_vtbl_mglob, NULL, 0); } else if (!SvOK(sv)) { - mg->mg_len = -1; + found->mg_len = -1; return 0; } len = SvPOK(lsv) ? SvCUR(lsv) : sv_len(lsv); - pos = SvIV(sv) - PL_curcop->cop_arybase; + pos = SvIV(sv) - CopARYBASE_get(PL_curcop); if (DO_UTF8(lsv)) { ulen = sv_len_utf8(lsv); @@ -1839,8 +1859,8 @@ Perl_magic_setpos(pTHX_ SV *sv, MAGIC *mg) pos = p; } - mg->mg_len = pos; - mg->mg_flags &= ~MGf_MINMATCH; + found->mg_len = pos; + found->mg_flags &= ~MGf_MINMATCH; return 0; } @@ -1895,7 +1915,7 @@ Perl_magic_setsubstr(pTHX_ SV *sv, MAGIC *mg) { dVAR; STRLEN len; - const char *tmps = SvPV_const(sv, len); + const char * const tmps = SvPV_const(sv, len); SV * const lsv = LvTARG(sv); I32 lvoff = LvTARGOFF(sv); I32 lvlen = LvTARGLEN(sv); @@ -1909,11 +1929,12 @@ Perl_magic_setsubstr(pTHX_ SV *sv, MAGIC *mg) SvUTF8_on(lsv); } else if (lsv && SvUTF8(lsv)) { + const char *utf8; sv_pos_u2b(lsv, &lvoff, &lvlen); LvTARGLEN(sv) = len; - tmps = (char*)bytes_to_utf8((U8*)tmps, &len); - sv_insert(lsv, lvoff, lvlen, tmps, len); - Safefree(tmps); + utf8 = (char*)bytes_to_utf8((U8*)tmps, &len); + sv_insert(lsv, lvoff, lvlen, utf8, len); + Safefree(utf8); } else { sv_insert(lsv, lvoff, lvlen, tmps, len); @@ -1987,7 +2008,7 @@ Perl_magic_getdefelem(pTHX_ SV *sv, MAGIC *mg) if ((I32)LvTARGOFF(sv) <= AvFILL(av)) targ = AvARRAY(av)[LvTARGOFF(sv)]; } - if (targ && targ != &PL_sv_undef) { + if (targ && (targ != &PL_sv_undef)) { /* somebody else defined it for us */ SvREFCNT_dec(LvTARG(sv)); LvTARG(sv) = SvREFCNT_inc_simple_NN(targ); @@ -2140,7 +2161,7 @@ Perl_magic_setutf8(pTHX_ SV *sv, MAGIC *mg) PERL_UNUSED_CONTEXT; PERL_UNUSED_ARG(sv); Safefree(mg->mg_ptr); /* The mg_ptr holds the pos cache. */ - mg->mg_ptr = 0; + mg->mg_ptr = NULL; mg->mg_len = -1; /* The mg_len holds the len cache. */ return 0; } @@ -2157,7 +2178,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) sv_setsv(PL_bodytarget, sv); break; case '\003': /* ^C */ - PL_minus_c = (bool)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)); + PL_minus_c = (bool)SvIV(sv); break; case '\004': /* ^D */ @@ -2166,25 +2187,25 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) PL_debug = get_debug_opts(&s, 0) | DEBUG_TOP_FLAG; DEBUG_x(dump_all()); #else - PL_debug = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) | DEBUG_TOP_FLAG; + PL_debug = (SvIV(sv)) | DEBUG_TOP_FLAG; #endif break; case '\005': /* ^E */ if (*(mg->mg_ptr+1) == '\0') { #ifdef MACOS_TRADITIONAL - gMacPerl_OSErr = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); + gMacPerl_OSErr = SvIV(sv); #else # ifdef VMS - set_vaxc_errno(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)); + set_vaxc_errno(SvIV(sv)); # else # ifdef WIN32 SetLastError( SvIV(sv) ); # else # ifdef OS2 - os2_setsyserrno(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)); + os2_setsyserrno(SvIV(sv)); # else /* will anyone ever use this? */ - SETERRNO(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv), 4); + SETERRNO(SvIV(sv), 4); # endif # endif # endif @@ -2202,10 +2223,10 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) } break; case '\006': /* ^F */ - PL_maxsysfd = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); + PL_maxsysfd = SvIV(sv); break; case '\010': /* ^H */ - PL_hints = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); + PL_hints = SvIV(sv); break; case '\011': /* ^I */ /* NOT \t in EBCDIC */ Safefree(PL_inplace); @@ -2221,14 +2242,15 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) } } else if (strEQ(mg->mg_ptr, "\017PEN")) { - if (!PL_compiling.cop_io) - PL_compiling.cop_io = newSVsv(sv); - else - sv_setsv(PL_compiling.cop_io,sv); + PL_compiling.cop_hints |= HINT_LEXICAL_IO; + PL_hints |= HINT_LOCALIZE_HH | HINT_LEXICAL_IO; + PL_compiling.cop_hints_hash + = Perl_refcounted_he_new(aTHX_ PL_compiling.cop_hints_hash, + sv_2mortal(newSVpvs("open")), sv); } break; case '\020': /* ^P */ - PL_perldb = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); + PL_perldb = SvIV(sv); if (PL_perldb && !PL_DBsingle) init_debugger(); break; @@ -2236,7 +2258,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) #ifdef BIG_TIME PL_basetime = (Time_t)(SvNOK(sv) ? SvNVX(sv) : sv_2nv(sv)); #else - PL_basetime = (Time_t)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)); + PL_basetime = (Time_t)SvIV(sv); #endif break; case '\025': /* ^UTF8CACHE */ @@ -2247,7 +2269,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) case '\027': /* ^W & $^WARNING_BITS */ if (*(mg->mg_ptr+1) == '\0') { if ( ! (PL_dowarn & G_WARN_ALL_MASK)) { - i = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); + i = SvIV(sv); PL_dowarn = (PL_dowarn & ~G_WARN_ON) | (i ? G_WARN_ON : G_WARN_OFF) ; } @@ -2270,15 +2292,20 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) } if (!accumulate) PL_compiling.cop_warnings = pWARN_NONE; - else if (isWARN_on(sv, WARN_ALL) && !any_fatals) { + /* Yuck. I can't see how to abstract this: */ + else if (isWARN_on(((STRLEN *)SvPV_nolen_const(sv)) - 1, + WARN_ALL) && !any_fatals) { PL_compiling.cop_warnings = pWARN_ALL; PL_dowarn |= G_WARN_ONCE ; } else { - if (specialWARN(PL_compiling.cop_warnings)) - PL_compiling.cop_warnings = newSVsv(sv) ; - else - sv_setsv(PL_compiling.cop_warnings, sv); + STRLEN len; + const char *const p = SvPV_const(sv, len); + + PL_compiling.cop_warnings + = Perl_new_warnings_bitfield(aTHX_ PL_compiling.cop_warnings, + p, len); + if (isWARN_on(PL_compiling.cop_warnings, WARN_ONCE)) PL_dowarn |= G_WARN_ONCE ; } @@ -2306,22 +2333,22 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) IoFMT_GV(GvIOp(PL_defoutgv)) = gv_fetchsv(sv, GV_ADD, SVt_PVIO); break; case '=': - IoPAGE_LEN(GvIOp(PL_defoutgv)) = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)); + IoPAGE_LEN(GvIOp(PL_defoutgv)) = (SvIV(sv)); break; case '-': - IoLINES_LEFT(GvIOp(PL_defoutgv)) = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)); + IoLINES_LEFT(GvIOp(PL_defoutgv)) = (SvIV(sv)); if (IoLINES_LEFT(GvIOp(PL_defoutgv)) < 0L) IoLINES_LEFT(GvIOp(PL_defoutgv)) = 0L; break; case '%': - IoPAGE(GvIOp(PL_defoutgv)) = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)); + IoPAGE(GvIOp(PL_defoutgv)) = (SvIV(sv)); break; case '|': { IO * const io = GvIOp(PL_defoutgv); if(!io) break; - if ((SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) == 0) + if ((SvIV(sv)) == 0) IoFLAGS(io) &= ~IOf_FLUSH; else { if (!(IoFLAGS(io) & IOf_FLUSH)) { @@ -2358,7 +2385,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) } break; case '[': - PL_compiling.cop_arybase = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); + CopARYBASE_set(&PL_compiling, SvIV(sv)); break; case '?': #ifdef COMPLEX_STATUS @@ -2373,7 +2400,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) STATUS_NATIVE_CHILD_SET((U32)SvIV(sv)); else #endif - STATUS_UNIX_EXIT_SET(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)); + STATUS_UNIX_EXIT_SET(SvIV(sv)); break; case '!': { @@ -2387,7 +2414,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) } break; case '<': - PL_uid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); + PL_uid = SvIV(sv); if (PL_delaymagic) { PL_delaymagic |= DM_RUID; break; /* don't do magic till later */ @@ -2419,7 +2446,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) PL_tainting |= (PL_uid && (PL_euid != PL_uid || PL_egid != PL_gid)); break; case '>': - PL_euid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); + PL_euid = SvIV(sv); if (PL_delaymagic) { PL_delaymagic |= DM_EUID; break; /* don't do magic till later */ @@ -2446,7 +2473,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) PL_tainting |= (PL_uid && (PL_euid != PL_uid || PL_egid != PL_gid)); break; case '(': - PL_gid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); + PL_gid = SvIV(sv); if (PL_delaymagic) { PL_delaymagic |= DM_RGID; break; /* don't do magic till later */ @@ -2500,7 +2527,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) Safefree(gary); } #else /* HAS_SETGROUPS */ - PL_egid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); + PL_egid = SvIV(sv); #endif /* HAS_SETGROUPS */ if (PL_delaymagic) { PL_delaymagic |= DM_EGID; @@ -2841,8 +2868,9 @@ S_unwind_handler_stack(pTHX_ const void *p) =for apidoc magic_sethint Triggered by a store to %^H, records the key/value pair to -C. It is assumed that hints aren't storing anything -that would need a deep copy. Maybe we should warn if we find a reference. +C. It is assumed that hints aren't storing +anything that would need a deep copy. Maybe we should warn if we find a +reference. =cut */ @@ -2852,16 +2880,26 @@ Perl_magic_sethint(pTHX_ SV *sv, MAGIC *mg) dVAR; assert(mg->mg_len == HEf_SVKEY); - PL_compiling.cop_hints - = Perl_refcounted_he_new(aTHX_ PL_compiling.cop_hints, - (SV *)mg->mg_ptr, newSVsv(sv)); + /* mg->mg_obj isn't being used. If needed, it would be possible to store + an alternative leaf in there, with PL_compiling.cop_hints being used if + it's NULL. If needed for threads, the alternative could lock a mutex, + or take other more complex action. */ + + /* Something changed in %^H, so it will need to be restored on scope exit. + Doing this here saves a lot of doing it manually in perl code (and + forgetting to do it, and consequent subtle errors. */ + PL_hints |= HINT_LOCALIZE_HH; + PL_compiling.cop_hints_hash + = Perl_refcounted_he_new(aTHX_ PL_compiling.cop_hints_hash, + (SV *)mg->mg_ptr, sv); return 0; } /* =for apidoc magic_sethint -Triggered by a delete from %^H, records the key to C. +Triggered by a delete from %^H, records the key to +C. =cut */ @@ -2871,8 +2909,11 @@ Perl_magic_clearhint(pTHX_ SV *sv, MAGIC *mg) dVAR; assert(mg->mg_len == HEf_SVKEY); - PL_compiling.cop_hints - = Perl_refcounted_he_new(aTHX_ PL_compiling.cop_hints, + PERL_UNUSED_ARG(sv); + + PL_hints |= HINT_LOCALIZE_HH; + PL_compiling.cop_hints_hash + = Perl_refcounted_he_new(aTHX_ PL_compiling.cop_hints_hash, (SV *)mg->mg_ptr, &PL_sv_placeholder); return 0; }