summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pod/perlsub.pod24
-rw-r--r--pp.c3
-rw-r--r--toke.c4
3 files changed, 29 insertions, 2 deletions
diff --git a/pod/perlsub.pod b/pod/perlsub.pod
index 4329c161ff..efadf8f848 100644
--- a/pod/perlsub.pod
+++ b/pod/perlsub.pod
@@ -1194,6 +1194,30 @@ a properly written override. For a fully functional example of overriding
C<glob>, study the implementation of C<File::DosGlob> in the standard
library.
+When you override a built-in, your replacement should be consistent (if
+possible) with the built-in native syntax. You can achieve this by using
+a suitable prototype. To get the prototype of an overridable built-in,
+use the C<prototype> function with an argument of C<"CORE::builtin_name">
+(see L<perlfunc/prototype>).
+
+Note however that some built-ins can't have their syntax expressed by a
+prototype (such as C<system> or C<chomp>). If you override them you won't
+be able to fully mimic their original syntax.
+
+The built-ins C<do>, C<require> and C<glob> can also be overriden, but due
+to special magic, their original syntax is preserved, and you don't have
+to define a prototype for their replacements. (You can't override the
+C<do BLOCK> syntax, though).
+
+C<require> has special additional dark magic: if you invoke your
+C<require> replacement as C<require Foo::Bar>, it will actually receive
+the argument C<"Foo/Bar.pm"> in @_. See L<perlfunc/require>.
+
+And, as you'll have noticed from the previous example, if you override
+C<glob>, the C<E<lt>*E<gt>> glob operator is overriden as well.
+
+Finally, some built-ins (e.g. C<exists> or C<grep>) can't be overriden.
+
=head2 Autoloading
If you call a subroutine that is undefined, you would ordinarily
diff --git a/pp.c b/pp.c
index 9237a8b219..23bf1ffad2 100644
--- a/pp.c
+++ b/pp.c
@@ -15,6 +15,7 @@
#include "EXTERN.h"
#define PERL_IN_PP_C
#include "perl.h"
+#include "keywords.h"
/* variations on pp_null */
@@ -365,6 +366,8 @@ PP(pp_prototype)
I32 oa;
char str[ MAX_ARGS_OP * 2 + 2 ]; /* One ';', one '\0' */
+ if (code == -KEY_chop || code == -KEY_chomp)
+ goto set;
while (i < MAXO) { /* The slow way. */
if (strEQ(s + 6, PL_op_name[i])
|| strEQ(s + 6, PL_op_desc[i]))
diff --git a/toke.c b/toke.c
index 314753f584..1527daaff2 100644
--- a/toke.c
+++ b/toke.c
@@ -5330,12 +5330,12 @@ Perl_keyword(pTHX_ register char *d, I32 len)
if (strEQ(d,"cos")) return -KEY_cos;
break;
case 4:
- if (strEQ(d,"chop")) return KEY_chop;
+ if (strEQ(d,"chop")) return -KEY_chop;
break;
case 5:
if (strEQ(d,"close")) return -KEY_close;
if (strEQ(d,"chdir")) return -KEY_chdir;
- if (strEQ(d,"chomp")) return KEY_chomp;
+ if (strEQ(d,"chomp")) return -KEY_chomp;
if (strEQ(d,"chmod")) return -KEY_chmod;
if (strEQ(d,"chown")) return -KEY_chown;
if (strEQ(d,"crypt")) return -KEY_crypt;