#!/usr/bin/perl
-unlink "opcode.h";
+unlink "opcode.h", "opnames.h";
open(OC, ">opcode.h") || die "Can't create opcode.h: $!\n";
+open(ON, ">opnames.h") || die "Can't create opnames.h: $!\n";
select OC;
# Read data.
#define Perl_pp_i_postinc Perl_pp_postinc
#define Perl_pp_i_postdec Perl_pp_postdec
-typedef enum {
END
+
+print ON <<"END";
+/* !!!!!!! DO NOT EDIT THIS FILE !!!!!!!
+ This file is built by opcode.pl from its data. Any changes made here
+ will be lost!
+*/
+
+typedef enum opcode {
+END
+
for (@ops) {
- print "\t", &tab(3,"OP_\U$_,"), "/* ", $i++, " */\n";
+ print ON "\t", &tab(3,"OP_\U$_,"), "/* ", $i++, " */\n";
}
-print "\t", &tab(3,"OP_max"), "\n";
-print "} opcode;\n";
-print "\n#define MAXO ", scalar @ops, "\n\n";
+print ON "\t", &tab(3,"OP_max"), "\n";
+print ON "} opcode;\n";
+print ON "\n#define MAXO ", scalar @ops, "\n\n";
# Emit op names and descriptions.
END
for (@ops) {
- print qq(\t"$desc{$_}",\n);
+ my($safe_desc) = $desc{$_};
+
+ # Have to escape double quotes and escape characters.
+ $safe_desc =~ s/(^|[^\\])([\\"])/$1\\$2/g;
+
+ print qq(\t"$safe_desc",\n);
}
print <<END;
END
for (@ops) {
- print "\tPerl_pp_$_,\n";
+ print "\tMEMBER_TO_FPTR(Perl_pp_$_),\n";
}
print <<END;
END
for (@ops) {
- print "\t", &tab(3, "Perl_$check{$_},"), "/* $_ */\n";
+ print "\t", &tab(3, "MEMBER_TO_FPTR(Perl_$check{$_}),"), "\t/* $_ */\n";
}
print <<END;
'|', 3, # logop
'@', 4, # listop
'/', 5, # pmop
- '$', 6, # svop
- '*', 7, # gvop
+ '$', 6, # svop_or_padop
+ '#', 7, # padop
'"', 8, # pvop_or_svop
'{', 9, # loop
';', 10, # cop
END
close OC or die "Error closing opcode.h: $!";
+close ON or die "Error closing opnames.h: $!";
unlink "pp_proto.h";
unlink "pp.sym";
# lt and friends do SETs (including ncmp, but not scmp)
+# Additional mode of failure: the opcode can modify TARG before it "used"
+# all the arguments (or may call an external function which does the same).
+# If the target coincides with one of the arguments ==> kaboom.
+
# pp.c pos substr each not OK (RETPUSHUNDEF)
# substr vec also not OK due to LV to target (are they???)
# ref not OK (RETPUSHNO)
# trans not OK (dTARG; TARG = sv_newmortal();)
# ucfirst etc not OK: TMP arg processed inplace
+# quotemeta not OK (unsafe when TARG == arg)
# each repeat not OK too due to array context
# pack split - unknown whether they are safe
+# sprintf: is calling do_sprintf(TARG,...) which can act on TARG
+# before other args are processed.
+
+# Suspicious wrt "additional mode of failure" (and only it):
+# schop, chop, postinc/dec, bit_and etc, negate, complement.
+
+# Also suspicious: 4-arg substr, sprintf, uc/lc (POK_only), reverse, pack.
+
+# substr/vec: doing TAINT_off()???
# pp_hot.c
# readline - unknown whether it is safe
# match subst not OK (dTARG)
# grepwhile not OK (not always setting)
+# join not OK (unsafe when TARG == arg)
+
+# Suspicious wrt "additional mode of failure": concat (dealt with
+# in ck_sassign()), join (same).
# pp_ctl.c
# mapwhile flip caller not OK (not always setting)
# sselect shm* sem* msg* syscall - unknown whether they are safe
# gmtime not OK (list context)
+# Suspicious wrt "additional mode of failure": warn, die, select.
+
__END__
# New ops always go at the very end
const constant item ck_svconst s$
-gvsv scalar variable ck_null ds*
-gv glob value ck_null ds*
+gvsv scalar variable ck_null ds$
+gv glob value ck_null ds$
gelem glob elem ck_null d2 S S
padsv private variable ck_null ds0
padav private array ck_null d0
padhv private hash ck_null d0
-padany private something ck_null d0
+padany private value ck_null d0
pushre push regexp ck_null d/
# References and stuff.
rv2gv ref-to-glob cast ck_rvconst ds1
-rv2sv scalar deref ck_rvconst ds1
+rv2sv scalar dereference ck_rvconst ds1
av2arylen array length ck_null is1
-rv2cv subroutine deref ck_rvconst d1
+rv2cv subroutine dereference ck_rvconst d1
anoncode anonymous subroutine ck_anoncode $
prototype subroutine prototype ck_null s% S
refgen reference constructor ck_spair m1 L
# Pushy I/O.
-backtick backticks ck_null t%
+backtick quoted execution (``, qx) ck_open t%
# glob defaults its first arg to $_
-glob glob ck_glob t@ S? S?
+glob glob ck_glob t@ S?
readline <HANDLE> ck_null t%
rcatline append I/O operator ck_null t%
# Bindable operators.
-regcmaybe regexp comp once ck_fun s1 S
-regcreset regexp reset interpolation flag ck_fun s1 S
+regcmaybe regexp internal guard ck_fun s1 S
+regcreset regexp internal reset ck_fun s1 S
regcomp regexp compilation ck_null s| S
-match pattern match ck_match d/
-qr pattern quote ck_match s/
-subst substitution ck_null dis/ S
-substcont substitution cont ck_null dis|
-trans character translation ck_null is" S
+match pattern match (m//) ck_match d/
+qr pattern quote (qr//) ck_match s/
+subst substitution (s///) ck_null dis/ S
+substcont substitution iterator ck_null dis|
+trans transliteration (tr///) ck_null is" S
# Lvalue operators.
# sassign is special-cased for op class
sassign scalar assignment ck_sassign s0
aassign list assignment ck_null t2 L L
-chop chop ck_spair mTs% L
-schop scalar chop ck_null sTu% S?
-chomp safe chop ck_spair mTs% L
-schomp scalar safe chop ck_null sTu% S?
+chop chop ck_spair mts% L
+schop scalar chop ck_null stu% S?
+chomp chomp ck_spair mTs% L
+schomp scalar chomp ck_null sTu% S?
defined defined operator ck_defined isu% S?
undef undef operator ck_lfun s% S?
study study ck_fun su% S?
pos match position ck_lfun stu% S?
-preinc preincrement ck_lfun dIs1 S
-i_preinc integer preincrement ck_lfun dis1 S
-predec predecrement ck_lfun dIs1 S
-i_predec integer predecrement ck_lfun dis1 S
-postinc postincrement ck_lfun dIsT1 S
-i_postinc integer postincrement ck_lfun disT1 S
-postdec postdecrement ck_lfun dIsT1 S
-i_postdec integer postdecrement ck_lfun disT1 S
+preinc preincrement (++) ck_lfun dIs1 S
+i_preinc integer preincrement (++) ck_lfun dis1 S
+predec predecrement (--) ck_lfun dIs1 S
+i_predec integer predecrement (--) ck_lfun dis1 S
+postinc postincrement (++) ck_lfun dIst1 S
+i_postinc integer postincrement (++) ck_lfun disT1 S
+postdec postdecrement (--) ck_lfun dIst1 S
+i_postdec integer postdecrement (--) ck_lfun disT1 S
# Ordinary operators.
-pow exponentiation ck_null fsT2 S S
-
-multiply multiplication ck_null IfsT2 S S
-i_multiply integer multiplication ck_null ifsT2 S S
-divide division ck_null IfsT2 S S
-i_divide integer division ck_null ifsT2 S S
-modulo modulus ck_null IifsT2 S S
-i_modulo integer modulus ck_null ifsT2 S S
-repeat repeat ck_repeat mt2 L S
-
-add addition ck_null IfsT2 S S
-i_add integer addition ck_null ifsT2 S S
-subtract subtraction ck_null IfsT2 S S
-i_subtract integer subtraction ck_null ifsT2 S S
-concat concatenation ck_concat fsT2 S S
+pow exponentiation (**) ck_null fsT2 S S
+
+multiply multiplication (*) ck_null IfsT2 S S
+i_multiply integer multiplication (*) ck_null ifsT2 S S
+divide division (/) ck_null IfsT2 S S
+i_divide integer division (/) ck_null ifsT2 S S
+modulo modulus (%) ck_null IifsT2 S S
+i_modulo integer modulus (%) ck_null ifsT2 S S
+repeat repeat (x) ck_repeat mt2 L S
+
+add addition (+) ck_null IfsT2 S S
+i_add integer addition (+) ck_null ifsT2 S S
+subtract subtraction (-) ck_null IfsT2 S S
+i_subtract integer subtraction (-) ck_null ifsT2 S S
+concat concatenation (.) ck_concat fsT2 S S
stringify string ck_fun fsT@ S
-left_shift left bitshift ck_bitop fsT2 S S
-right_shift right bitshift ck_bitop fsT2 S S
-
-lt numeric lt ck_null Iifs2 S S
-i_lt integer lt ck_null ifs2 S S
-gt numeric gt ck_null Iifs2 S S
-i_gt integer gt ck_null ifs2 S S
-le numeric le ck_null Iifs2 S S
-i_le integer le ck_null ifs2 S S
-ge numeric ge ck_null Iifs2 S S
-i_ge integer ge ck_null ifs2 S S
-eq numeric eq ck_null Iifs2 S S
-i_eq integer eq ck_null ifs2 S S
-ne numeric ne ck_null Iifs2 S S
-i_ne integer ne ck_null ifs2 S S
-ncmp spaceship operator ck_null Iifst2 S S
-i_ncmp integer spaceship ck_null ifst2 S S
+left_shift left bitshift (<<) ck_bitop fsT2 S S
+right_shift right bitshift (>>) ck_bitop fsT2 S S
+
+lt numeric lt (<) ck_null Iifs2 S S
+i_lt integer lt (<) ck_null ifs2 S S
+gt numeric gt (>) ck_null Iifs2 S S
+i_gt integer gt (>) ck_null ifs2 S S
+le numeric le (<=) ck_null Iifs2 S S
+i_le integer le (<=) ck_null ifs2 S S
+ge numeric ge (>=) ck_null Iifs2 S S
+i_ge integer ge (>=) ck_null ifs2 S S
+eq numeric eq (==) ck_null Iifs2 S S
+i_eq integer eq (==) ck_null ifs2 S S
+ne numeric ne (!=) ck_null Iifs2 S S
+i_ne integer ne (!=) ck_null ifs2 S S
+ncmp numeric comparison (<=>) ck_null Iifst2 S S
+i_ncmp integer comparison (<=>) ck_null ifst2 S S
slt string lt ck_scmp ifs2 S S
sgt string gt ck_scmp ifs2 S S
sge string ge ck_scmp ifs2 S S
seq string eq ck_null ifs2 S S
sne string ne ck_null ifs2 S S
-scmp string comparison ck_scmp ifst2 S S
+scmp string comparison (cmp) ck_scmp ifst2 S S
-bit_and bitwise and ck_bitop fsT2 S S
-bit_xor bitwise xor ck_bitop fsT2 S S
-bit_or bitwise or ck_bitop fsT2 S S
+bit_and bitwise and (&) ck_bitop fst2 S S
+bit_xor bitwise xor (^) ck_bitop fst2 S S
+bit_or bitwise or (|) ck_bitop fst2 S S
-negate negate ck_null IfsT1 S
-i_negate integer negate ck_null ifsT1 S
+negate negation (-) ck_null Ifst1 S
+i_negate integer negation (-) ck_null ifsT1 S
not not ck_null ifs1 S
-complement 1's complement ck_bitop fsT1 S
+complement 1's complement (~) ck_bitop fst1 S
# High falutin' math.
index index ck_index isT@ S S S?
rindex rindex ck_index isT@ S S S?
-sprintf sprintf ck_fun_locale mfsT@ S L
+sprintf sprintf ck_fun_locale mfst@ S L
formline formline ck_fun ms@ S L
ord ord ck_fun ifsTu% S?
chr chr ck_fun fsTu% S?
crypt crypt ck_fun fsT@ S S
-ucfirst upper case first ck_fun_locale fstu% S?
-lcfirst lower case first ck_fun_locale fstu% S?
-uc upper case ck_fun_locale fstu% S?
-lc lower case ck_fun_locale fstu% S?
-quotemeta quote metachars ck_fun fsTu% S?
+ucfirst ucfirst ck_fun_locale fstu% S?
+lcfirst lcfirst ck_fun_locale fstu% S?
+uc uc ck_fun_locale fstu% S?
+lc lc ck_fun_locale fstu% S?
+quotemeta quotemeta ck_fun fstu% S?
# Arrays.
-rv2av array deref ck_rvconst dt1
-aelemfast known array element ck_null s* A S
+rv2av array dereference ck_rvconst dt1
+aelemfast constant array element ck_null s$ A S
aelem array element ck_null s2 A S
aslice array slice ck_null m@ A L
values values ck_fun t% H
keys keys ck_fun t% H
delete delete ck_delete % S
-exists exists operator ck_exists is% S
-rv2hv hash deref ck_rvconst dt1
-helem hash elem ck_null s2@ H S
+exists exists ck_exists is% S
+rv2hv hash dereference ck_rvconst dt1
+helem hash element ck_null s2@ H S
hslice hash slice ck_null m@ H L
# Explosives and implosives.
unpack unpack ck_fun @ S S
pack pack ck_fun mst@ S L
split split ck_split t@ S S S
-join join ck_fun msT@ S L
+join join ck_join mst@ S L
# List operators.
list list ck_null m@ L
lslice list slice ck_null 2 H L L
-anonlist anonymous list ck_fun ms@ L
-anonhash anonymous hash ck_fun ms@ L
+anonlist anonymous list ([]) ck_fun ms@ L
+anonhash anonymous hash ({}) ck_fun ms@ L
splice splice ck_fun m@ A S? S? L
push push ck_fun imsT@ A L
# Control.
-and logical and ck_null |
-or logical or ck_null |
-xor logical xor ck_null fs2 S S
-cond_expr conditional expression ck_null d|
-andassign logical and assignment ck_null s|
-orassign logical or assignment ck_null s|
+and logical and (&&) ck_null |
+or logical or (||) ck_null |
+xor logical xor ck_null fs2 S S
+cond_expr conditional expression ck_null d|
+andassign logical and assignment (&&=) ck_null s|
+orassign logical or assignment (||=) ck_null s|
method method lookup ck_method d1
entersub subroutine entry ck_subr dmt1 L
leavesub subroutine exit ck_null 1
+leavesublv lvalue subroutine exit ck_null 1
caller caller ck_fun t% S?
warn warn ck_fun imst@ L
die die ck_fun dimst@ L
-reset reset ck_fun is% S?
+reset symbol reset ck_fun is% S?
lineseq line sequence ck_null @
nextstate next statement ck_null s;
redo redo ck_null ds}
dump dump ck_null ds}
goto goto ck_null ds}
-exit exit ck_fun ds% S?
+exit exit ck_exit ds% S?
# continued below
-#nswitch numeric switch ck_null d
-#cswitch character switch ck_null d
+#nswitch numeric switch ck_null d
+#cswitch character switch ck_null d
# I/O.
-open open ck_fun ist@ F S? S?
+open open ck_open ist@ F S? L
close close ck_fun is% F?
pipe_op pipe ck_fun is@ F F
fileno fileno ck_fun ist% F
umask umask ck_fun ist% S?
-binmode binmode ck_fun s% F
+binmode binmode ck_fun s@ F S?
tie tie ck_fun idms@ R S L
untie untie ck_fun is% R
link link ck_fun isT@ S S
symlink symlink ck_fun isT@ S S
readlink readlink ck_fun stu% S?
-mkdir mkdir ck_fun isT@ S S
+mkdir mkdir ck_fun isT@ S S?
rmdir rmdir ck_fun isTu% S?
# Directory calls.
# Time calls.
+# NOTE: MacOS patches the 'i' of time() away later when the interpreter
+# is created because in MacOS time() is already returning times > 2**31-1,
+# that is, non-integers.
+
time time ck_null isT0
tms times ck_null 0
localtime localtime ck_fun t% S?
# Eval.
require require ck_require du% S?
-dofile do 'file' ck_fun d1 S
-entereval eval string ck_eval d% S
-leaveeval eval exit ck_null 1 S
+dofile do "file" ck_fun d1 S
+entereval eval "string" ck_eval d% S
+leaveeval eval "string" exit ck_null 1 S
#evalonce eval constant string ck_null d1 S
-entertry eval block ck_null |
-leavetry eval block exit ck_null @
+entertry eval {block} ck_null |
+leavetry eval {block} exit ck_null @
# Get system info.
# For multi-threading
lock lock ck_rfun s% S
-threadsv per-thread variable ck_null ds0
+threadsv per-thread value ck_null ds0
# Control (contd.)
setstate set statement info ck_null s;