summaryrefslogtreecommitdiff
path: root/toke.c
diff options
context:
space:
mode:
authorKarl Williamson <public@khwilliamson.com>2011-12-18 20:45:14 -0700
committerKarl Williamson <public@khwilliamson.com>2011-12-20 22:02:42 -0700
commitfbb93542d6662666a88828fb4c15803f8ba377f0 (patch)
tree300d9b114ad07a3281c6575d2abb02b7645389b7 /toke.c
parentf8988b416c244747b17eb3004ac6f8bbcf366e7a (diff)
downloadperl-fbb93542d6662666a88828fb4c15803f8ba377f0.tar.gz
Autoload charnames for \N{name}
This autoloads charnames.pm when needed. It uses the :full and :short options. :loose is not used because of its relative unfamiliarity in the Perl community, and is slower. (If someone later added a typical "use charnames qw(:full)", things that previously matched under :loose would start to fail, causing confustion. If :loose does become more common, we can change this in the future to use it; the converse isn't true.) The callable functions in the module are not automatically loaded. To access them, an explicity "use charnames" must be provided. Thanks to Tony Cook for doing a code inspection and finding a missing SPAGAIN.
Diffstat (limited to 'toke.c')
-rw-r--r--toke.c64
1 files changed, 39 insertions, 25 deletions
diff --git a/toke.c b/toke.c
index 40790d16a2..643928ddae 100644
--- a/toke.c
+++ b/toke.c
@@ -8610,7 +8610,7 @@ S_new_constant(pTHX_ const char *s, STRLEN len, const char *key, STRLEN keylen,
SV *sv, SV *pv, const char *type, STRLEN typelen)
{
dVAR; dSP;
- HV * const table = GvHV(PL_hintgv); /* ^H */
+ HV * table = GvHV(PL_hintgv); /* ^H */
SV *res;
SV **cvp;
SV *cv, *typesv;
@@ -8622,39 +8622,53 @@ S_new_constant(pTHX_ const char *s, STRLEN len, const char *key, STRLEN keylen,
if (PL_error_count > 0 && strEQ(key,"charnames"))
return &PL_sv_undef;
- if (!table || !(PL_hints & HINT_LOCALIZE_HH)) {
+ if (!table
+ || ! (PL_hints & HINT_LOCALIZE_HH)
+ || ! (cvp = hv_fetch(table, key, keylen, FALSE))
+ || ! SvOK(*cvp))
+ {
SV *msg;
- why2 = (const char *)
- (strEQ(key,"charnames")
- ? "(possibly a missing \"use charnames ...\")"
- : "");
- msg = Perl_newSVpvf(aTHX_ "Constant(%s) unknown: %s",
- (type ? type: "undef"), why2);
-
- /* This is convoluted and evil ("goto considered harmful")
- * but I do not understand the intricacies of all the different
- * failure modes of %^H in here. The goal here is to make
- * the most probable error message user-friendly. --jhi */
-
- goto msgdone;
-
+ /* Here haven't found what we're looking for. If it is charnames,
+ * perhaps it needs to be loaded. Try doing that before giving up */
+ if (strEQ(key,"charnames")) {
+ Perl_load_module(aTHX_
+ 0,
+ newSVpvs("_charnames"),
+ /* version parameter; no need to specify it, as if
+ * we get too early a version, will fail anyway,
+ * not being able to find '_charnames' */
+ NULL,
+ newSVpvs(":full"),
+ newSVpvs(":short"),
+ NULL);
+ SPAGAIN;
+ table = GvHV(PL_hintgv);
+ if (table
+ && (PL_hints & HINT_LOCALIZE_HH)
+ && (cvp = hv_fetch(table, key, keylen, FALSE))
+ && SvOK(*cvp))
+ {
+ goto now_ok;
+ }
+ }
+ if (!table || !(PL_hints & HINT_LOCALIZE_HH)) {
+ msg = Perl_newSVpvf(aTHX_
+ "Constant(%s) unknown", (type ? type: "undef"));
+ }
+ else {
+ why1 = "$^H{";
+ why2 = key;
+ why3 = "} is not defined";
report:
msg = Perl_newSVpvf(aTHX_ "Constant(%s): %s%s%s",
(type ? type: "undef"), why1, why2, why3);
- msgdone:
+ }
yyerror(SvPVX_const(msg));
SvREFCNT_dec(msg);
return sv;
}
-
- cvp = hv_fetch(table, key, keylen, FALSE);
- if (!cvp || !SvOK(*cvp)) {
- why1 = "$^H{";
- why2 = key;
- why3 = "} is not defined";
- goto report;
- }
+now_ok:
sv_2mortal(sv); /* Parent created it permanently */
cv = *cvp;
if (!pv && s)