implement STOP blocks and fix compiler to use them (minimally
Gurusamy Sarathy [Thu, 4 Nov 1999 17:28:29 +0000 (17:28 +0000)]
tested)

p4raw-id: //depot/perl@4515

19 files changed:
embedvar.h
ext/B/B/Lint.pm
ext/B/B/Stash.pm
ext/B/NOTES
ext/B/O.pm
intrpvar.h
keywords.h
keywords.pl
objXSUB.h
op.c
perl.c
pod/perldelta.pod
pod/perldiag.pod
pod/perlfunc.pod
pod/perlmod.pod
pod/perlrun.pod
pod/perlsub.pod
pod/perltodo.pod
toke.c

index 3795432..556e4d0 100644 (file)
 #define PL_statusvalue_vms     (PERL_GET_INTERP->Istatusvalue_vms)
 #define PL_stderrgv            (PERL_GET_INTERP->Istderrgv)
 #define PL_stdingv             (PERL_GET_INTERP->Istdingv)
+#define PL_stopav              (PERL_GET_INTERP->Istopav)
 #define PL_strtab              (PERL_GET_INTERP->Istrtab)
 #define PL_strtab_mutex                (PERL_GET_INTERP->Istrtab_mutex)
 #define PL_sub_generation      (PERL_GET_INTERP->Isub_generation)
 #define PL_statusvalue_vms     (vTHX->Istatusvalue_vms)
 #define PL_stderrgv            (vTHX->Istderrgv)
 #define PL_stdingv             (vTHX->Istdingv)
+#define PL_stopav              (vTHX->Istopav)
 #define PL_strtab              (vTHX->Istrtab)
 #define PL_strtab_mutex                (vTHX->Istrtab_mutex)
 #define PL_sub_generation      (vTHX->Isub_generation)
 #define PL_Istatusvalue_vms    PL_statusvalue_vms
 #define PL_Istderrgv           PL_stderrgv
 #define PL_Istdingv            PL_stdingv
+#define PL_Istopav             PL_stopav
 #define PL_Istrtab             PL_strtab
 #define PL_Istrtab_mutex       PL_strtab_mutex
 #define PL_Isub_generation     PL_sub_generation
index 3a47142..41d3c5a 100644 (file)
@@ -241,7 +241,7 @@ sub B::SVOP::lint {
     }
     if ($check{private_names}) {
        my $opname = $op->name;
-       if (($opname eq "gv" || $opname eq "gvsv") {
+       if ($opname eq "gv" || $opname eq "gvsv") {
            my $gv = $op->gv;
            if ($gv->NAME =~ /^_./ && $gv->STASH->NAME ne $curstash) {
                warning('Illegal reference to private name %s', $gv->NAME);
index 828ffac..d992a89 100644 (file)
@@ -4,7 +4,7 @@ package B::Stash;
 
 BEGIN { %Seen = %INC }
 
-END {
+STOP {
        my @arr=scan($main::{"main::"});
        @arr=map{s/\:\:$//;$_;}  @arr;
        print "-umain,-u", join (",-u",@arr) ,"\n";
index ee10ba0..8309892 100644 (file)
@@ -161,8 +161,8 @@ O module
        it should return a sub ref (usually a closure) to perform the
        actual compilation. When O regains control, it ensures that the
        "-c" option is forced (so that the program being compiled doesn't
-       end up running) and registers an END block to call back the sub ref
+       end up running) and registers a STOP block to call back the sub ref
        returned from the backend's compile(). Perl then continues by
        parsing prog.pl (just as it would with "perl -c prog.pl") and after
-       doing so, assuming there are no parse-time errors, the END block
+       doing so, assuming there are no parse-time errors, the STOP block
        of O gets called and the actual backend compilation happens. Phew.
index ad391a3..d07c4a5 100644 (file)
@@ -11,7 +11,7 @@ sub import {
     my $compilesub = &{"B::${backend}::compile"}(@options);
     if (ref($compilesub) eq "CODE") {
        minus_c;
-       eval 'END { &$compilesub() }';
+       eval 'STOP { &$compilesub() }';
     } else {
        die $compilesub;
     }
@@ -59,7 +59,7 @@ C<B::Backend> module and calls the C<compile> function in that
 package, passing it OPTIONS. That function is expected to return
 a sub reference which we'll call CALLBACK. Next, the "compile-only"
 flag is switched on (equivalent to the command-line option C<-c>)
-and an END block is registered which calls CALLBACK. Thus the main
+and a STOP block is registered which calls CALLBACK. Thus the main
 Perl program mentioned on the command-line is read in, parsed and
 compiled into internal syntax tree form. Since the C<-c> flag is
 set, the program does not start running (excepting BEGIN blocks of
index 24ff54e..9f6f3b2 100644 (file)
@@ -92,6 +92,7 @@ PERLVAR(Iglobalstash, HV *)           /* global keyword overrides imported here */
 PERLVAR(Icurstname,    SV *)           /* name of current package */
 PERLVAR(Ibeginav,      AV *)           /* names of BEGIN subroutines */
 PERLVAR(Iendav,                AV *)           /* names of END subroutines */
+PERLVAR(Istopav,       AV *)           /* names of STOP subroutines */
 PERLVAR(Iinitav,       AV *)           /* names of INIT subroutines */
 PERLVAR(Istrtab,       HV *)           /* shared string table */
 PERLVARI(Isub_generation,U32,1)                /* incr to invalidate method cache */
index f6b98aa..972240f 100644 (file)
 #define KEY_LE                 15
 #define KEY_LT                 16
 #define KEY_NE                 17
-#define KEY_abs                        18
-#define KEY_accept             19
-#define KEY_alarm              20
-#define KEY_and                        21
-#define KEY_atan2              22
-#define KEY_bind               23
-#define KEY_binmode            24
-#define KEY_bless              25
-#define KEY_caller             26
-#define KEY_chdir              27
-#define KEY_chmod              28
-#define KEY_chomp              29
-#define KEY_chop               30
-#define KEY_chown              31
-#define KEY_chr                        32
-#define KEY_chroot             33
-#define KEY_close              34
-#define KEY_closedir           35
-#define KEY_cmp                        36
-#define KEY_connect            37
-#define KEY_continue           38
-#define KEY_cos                        39
-#define KEY_crypt              40
-#define KEY_dbmclose           41
-#define KEY_dbmopen            42
-#define KEY_defined            43
-#define KEY_delete             44
-#define KEY_die                        45
-#define KEY_do                 46
-#define KEY_dump               47
-#define KEY_each               48
-#define KEY_else               49
-#define KEY_elsif              50
-#define KEY_endgrent           51
-#define KEY_endhostent         52
-#define KEY_endnetent          53
-#define KEY_endprotoent                54
-#define KEY_endpwent           55
-#define KEY_endservent         56
-#define KEY_eof                        57
-#define KEY_eq                 58
-#define KEY_eval               59
-#define KEY_exec               60
-#define KEY_exists             61
-#define KEY_exit               62
-#define KEY_exp                        63
-#define KEY_fcntl              64
-#define KEY_fileno             65
-#define KEY_flock              66
-#define KEY_for                        67
-#define KEY_foreach            68
-#define KEY_fork               69
-#define KEY_format             70
-#define KEY_formline           71
-#define KEY_ge                 72
-#define KEY_getc               73
-#define KEY_getgrent           74
-#define KEY_getgrgid           75
-#define KEY_getgrnam           76
-#define KEY_gethostbyaddr      77
-#define KEY_gethostbyname      78
-#define KEY_gethostent         79
-#define KEY_getlogin           80
-#define KEY_getnetbyaddr       81
-#define KEY_getnetbyname       82
-#define KEY_getnetent          83
-#define KEY_getpeername                84
-#define KEY_getpgrp            85
-#define KEY_getppid            86
-#define KEY_getpriority                87
-#define KEY_getprotobyname     88
-#define KEY_getprotobynumber   89
-#define KEY_getprotoent                90
-#define KEY_getpwent           91
-#define KEY_getpwnam           92
-#define KEY_getpwuid           93
-#define KEY_getservbyname      94
-#define KEY_getservbyport      95
-#define KEY_getservent         96
-#define KEY_getsockname                97
-#define KEY_getsockopt         98
-#define KEY_glob               99
-#define KEY_gmtime             100
-#define KEY_goto               101
-#define KEY_grep               102
-#define KEY_gt                 103
-#define KEY_hex                        104
-#define KEY_if                 105
-#define KEY_index              106
-#define KEY_int                        107
-#define KEY_ioctl              108
-#define KEY_join               109
-#define KEY_keys               110
-#define KEY_kill               111
-#define KEY_last               112
-#define KEY_lc                 113
-#define KEY_lcfirst            114
-#define KEY_le                 115
-#define KEY_length             116
-#define KEY_link               117
-#define KEY_listen             118
-#define KEY_local              119
-#define KEY_localtime          120
-#define KEY_lock               121
-#define KEY_log                        122
-#define KEY_lstat              123
-#define KEY_lt                 124
-#define KEY_m                  125
-#define KEY_map                        126
-#define KEY_mkdir              127
-#define KEY_msgctl             128
-#define KEY_msgget             129
-#define KEY_msgrcv             130
-#define KEY_msgsnd             131
-#define KEY_my                 132
-#define KEY_ne                 133
-#define KEY_next               134
-#define KEY_no                 135
-#define KEY_not                        136
-#define KEY_oct                        137
-#define KEY_open               138
-#define KEY_opendir            139
-#define KEY_or                 140
-#define KEY_ord                        141
-#define KEY_our                        142
-#define KEY_pack               143
-#define KEY_package            144
-#define KEY_pipe               145
-#define KEY_pop                        146
-#define KEY_pos                        147
-#define KEY_print              148
-#define KEY_printf             149
-#define KEY_prototype          150
-#define KEY_push               151
-#define KEY_q                  152
-#define KEY_qq                 153
-#define KEY_qr                 154
-#define KEY_quotemeta          155
-#define KEY_qw                 156
-#define KEY_qx                 157
-#define KEY_rand               158
-#define KEY_read               159
-#define KEY_readdir            160
-#define KEY_readline           161
-#define KEY_readlink           162
-#define KEY_readpipe           163
-#define KEY_recv               164
-#define KEY_redo               165
-#define KEY_ref                        166
-#define KEY_rename             167
-#define KEY_require            168
-#define KEY_reset              169
-#define KEY_return             170
-#define KEY_reverse            171
-#define KEY_rewinddir          172
-#define KEY_rindex             173
-#define KEY_rmdir              174
-#define KEY_s                  175
-#define KEY_scalar             176
-#define KEY_seek               177
-#define KEY_seekdir            178
-#define KEY_select             179
-#define KEY_semctl             180
-#define KEY_semget             181
-#define KEY_semop              182
-#define KEY_send               183
-#define KEY_setgrent           184
-#define KEY_sethostent         185
-#define KEY_setnetent          186
-#define KEY_setpgrp            187
-#define KEY_setpriority                188
-#define KEY_setprotoent                189
-#define KEY_setpwent           190
-#define KEY_setservent         191
-#define KEY_setsockopt         192
-#define KEY_shift              193
-#define KEY_shmctl             194
-#define KEY_shmget             195
-#define KEY_shmread            196
-#define KEY_shmwrite           197
-#define KEY_shutdown           198
-#define KEY_sin                        199
-#define KEY_sleep              200
-#define KEY_socket             201
-#define KEY_socketpair         202
-#define KEY_sort               203
-#define KEY_splice             204
-#define KEY_split              205
-#define KEY_sprintf            206
-#define KEY_sqrt               207
-#define KEY_srand              208
-#define KEY_stat               209
-#define KEY_study              210
-#define KEY_sub                        211
-#define KEY_substr             212
-#define KEY_symlink            213
-#define KEY_syscall            214
-#define KEY_sysopen            215
-#define KEY_sysread            216
-#define KEY_sysseek            217
-#define KEY_system             218
-#define KEY_syswrite           219
-#define KEY_tell               220
-#define KEY_telldir            221
-#define KEY_tie                        222
-#define KEY_tied               223
-#define KEY_time               224
-#define KEY_times              225
-#define KEY_tr                 226
-#define KEY_truncate           227
-#define KEY_uc                 228
-#define KEY_ucfirst            229
-#define KEY_umask              230
-#define KEY_undef              231
-#define KEY_unless             232
-#define KEY_unlink             233
-#define KEY_unpack             234
-#define KEY_unshift            235
-#define KEY_untie              236
-#define KEY_until              237
-#define KEY_use                        238
-#define KEY_utime              239
-#define KEY_values             240
-#define KEY_vec                        241
-#define KEY_wait               242
-#define KEY_waitpid            243
-#define KEY_wantarray          244
-#define KEY_warn               245
-#define KEY_while              246
-#define KEY_write              247
-#define KEY_x                  248
-#define KEY_xor                        249
-#define KEY_y                  250
+#define KEY_STOP               18
+#define KEY_abs                        19
+#define KEY_accept             20
+#define KEY_alarm              21
+#define KEY_and                        22
+#define KEY_atan2              23
+#define KEY_bind               24
+#define KEY_binmode            25
+#define KEY_bless              26
+#define KEY_caller             27
+#define KEY_chdir              28
+#define KEY_chmod              29
+#define KEY_chomp              30
+#define KEY_chop               31
+#define KEY_chown              32
+#define KEY_chr                        33
+#define KEY_chroot             34
+#define KEY_close              35
+#define KEY_closedir           36
+#define KEY_cmp                        37
+#define KEY_connect            38
+#define KEY_continue           39
+#define KEY_cos                        40
+#define KEY_crypt              41
+#define KEY_dbmclose           42
+#define KEY_dbmopen            43
+#define KEY_defined            44
+#define KEY_delete             45
+#define KEY_die                        46
+#define KEY_do                 47
+#define KEY_dump               48
+#define KEY_each               49
+#define KEY_else               50
+#define KEY_elsif              51
+#define KEY_endgrent           52
+#define KEY_endhostent         53
+#define KEY_endnetent          54
+#define KEY_endprotoent                55
+#define KEY_endpwent           56
+#define KEY_endservent         57
+#define KEY_eof                        58
+#define KEY_eq                 59
+#define KEY_eval               60
+#define KEY_exec               61
+#define KEY_exists             62
+#define KEY_exit               63
+#define KEY_exp                        64
+#define KEY_fcntl              65
+#define KEY_fileno             66
+#define KEY_flock              67
+#define KEY_for                        68
+#define KEY_foreach            69
+#define KEY_fork               70
+#define KEY_format             71
+#define KEY_formline           72
+#define KEY_ge                 73
+#define KEY_getc               74
+#define KEY_getgrent           75
+#define KEY_getgrgid           76
+#define KEY_getgrnam           77
+#define KEY_gethostbyaddr      78
+#define KEY_gethostbyname      79
+#define KEY_gethostent         80
+#define KEY_getlogin           81
+#define KEY_getnetbyaddr       82
+#define KEY_getnetbyname       83
+#define KEY_getnetent          84
+#define KEY_getpeername                85
+#define KEY_getpgrp            86
+#define KEY_getppid            87
+#define KEY_getpriority                88
+#define KEY_getprotobyname     89
+#define KEY_getprotobynumber   90
+#define KEY_getprotoent                91
+#define KEY_getpwent           92
+#define KEY_getpwnam           93
+#define KEY_getpwuid           94
+#define KEY_getservbyname      95
+#define KEY_getservbyport      96
+#define KEY_getservent         97
+#define KEY_getsockname                98
+#define KEY_getsockopt         99
+#define KEY_glob               100
+#define KEY_gmtime             101
+#define KEY_goto               102
+#define KEY_grep               103
+#define KEY_gt                 104
+#define KEY_hex                        105
+#define KEY_if                 106
+#define KEY_index              107
+#define KEY_int                        108
+#define KEY_ioctl              109
+#define KEY_join               110
+#define KEY_keys               111
+#define KEY_kill               112
+#define KEY_last               113
+#define KEY_lc                 114
+#define KEY_lcfirst            115
+#define KEY_le                 116
+#define KEY_length             117
+#define KEY_link               118
+#define KEY_listen             119
+#define KEY_local              120
+#define KEY_localtime          121
+#define KEY_lock               122
+#define KEY_log                        123
+#define KEY_lstat              124
+#define KEY_lt                 125
+#define KEY_m                  126
+#define KEY_map                        127
+#define KEY_mkdir              128
+#define KEY_msgctl             129
+#define KEY_msgget             130
+#define KEY_msgrcv             131
+#define KEY_msgsnd             132
+#define KEY_my                 133
+#define KEY_ne                 134
+#define KEY_next               135
+#define KEY_no                 136
+#define KEY_not                        137
+#define KEY_oct                        138
+#define KEY_open               139
+#define KEY_opendir            140
+#define KEY_or                 141
+#define KEY_ord                        142
+#define KEY_our                        143
+#define KEY_pack               144
+#define KEY_package            145
+#define KEY_pipe               146
+#define KEY_pop                        147
+#define KEY_pos                        148
+#define KEY_print              149
+#define KEY_printf             150
+#define KEY_prototype          151
+#define KEY_push               152
+#define KEY_q                  153
+#define KEY_qq                 154
+#define KEY_qr                 155
+#define KEY_quotemeta          156
+#define KEY_qw                 157
+#define KEY_qx                 158
+#define KEY_rand               159
+#define KEY_read               160
+#define KEY_readdir            161
+#define KEY_readline           162
+#define KEY_readlink           163
+#define KEY_readpipe           164
+#define KEY_recv               165
+#define KEY_redo               166
+#define KEY_ref                        167
+#define KEY_rename             168
+#define KEY_require            169
+#define KEY_reset              170
+#define KEY_return             171
+#define KEY_reverse            172
+#define KEY_rewinddir          173
+#define KEY_rindex             174
+#define KEY_rmdir              175
+#define KEY_s                  176
+#define KEY_scalar             177
+#define KEY_seek               178
+#define KEY_seekdir            179
+#define KEY_select             180
+#define KEY_semctl             181
+#define KEY_semget             182
+#define KEY_semop              183
+#define KEY_send               184
+#define KEY_setgrent           185
+#define KEY_sethostent         186
+#define KEY_setnetent          187
+#define KEY_setpgrp            188
+#define KEY_setpriority                189
+#define KEY_setprotoent                190
+#define KEY_setpwent           191
+#define KEY_setservent         192
+#define KEY_setsockopt         193
+#define KEY_shift              194
+#define KEY_shmctl             195
+#define KEY_shmget             196
+#define KEY_shmread            197
+#define KEY_shmwrite           198
+#define KEY_shutdown           199
+#define KEY_sin                        200
+#define KEY_sleep              201
+#define KEY_socket             202
+#define KEY_socketpair         203
+#define KEY_sort               204
+#define KEY_splice             205
+#define KEY_split              206
+#define KEY_sprintf            207
+#define KEY_sqrt               208
+#define KEY_srand              209
+#define KEY_stat               210
+#define KEY_study              211
+#define KEY_sub                        212
+#define KEY_substr             213
+#define KEY_symlink            214
+#define KEY_syscall            215
+#define KEY_sysopen            216
+#define KEY_sysread            217
+#define KEY_sysseek            218
+#define KEY_system             219
+#define KEY_syswrite           220
+#define KEY_tell               221
+#define KEY_telldir            222
+#define KEY_tie                        223
+#define KEY_tied               224
+#define KEY_time               225
+#define KEY_times              226
+#define KEY_tr                 227
+#define KEY_truncate           228
+#define KEY_uc                 229
+#define KEY_ucfirst            230
+#define KEY_umask              231
+#define KEY_undef              232
+#define KEY_unless             233
+#define KEY_unlink             234
+#define KEY_unpack             235
+#define KEY_unshift            236
+#define KEY_untie              237
+#define KEY_until              238
+#define KEY_use                        239
+#define KEY_utime              240
+#define KEY_values             241
+#define KEY_vec                        242
+#define KEY_wait               243
+#define KEY_waitpid            244
+#define KEY_wantarray          245
+#define KEY_warn               246
+#define KEY_while              247
+#define KEY_write              248
+#define KEY_x                  249
+#define KEY_xor                        250
+#define KEY_y                  251
index 438849a..acdf807 100755 (executable)
@@ -42,6 +42,7 @@ INIT
 LE
 LT
 NE
+STOP
 abs
 accept
 alarm
index 7b3a0a0..f7d1fd4 100644 (file)
--- a/objXSUB.h
+++ b/objXSUB.h
 #define PL_stderrgv            (*Perl_Istderrgv_ptr(aTHXo))
 #undef  PL_stdingv
 #define PL_stdingv             (*Perl_Istdingv_ptr(aTHXo))
+#undef  PL_stopav
+#define PL_stopav              (*Perl_Istopav_ptr(aTHXo))
 #undef  PL_strtab
 #define PL_strtab              (*Perl_Istrtab_ptr(aTHXo))
 #undef  PL_strtab_mutex
diff --git a/op.c b/op.c
index cb868a4..6fd669a 100644 (file)
--- a/op.c
+++ b/op.c
@@ -4411,6 +4411,13 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
            av_store(PL_endav, 0, (SV *)cv);
            GvCV(gv) = 0;
        }
+       else if (strEQ(s, "STOP") && !PL_error_count) {
+           if (!PL_stopav)
+               PL_stopav = newAV();
+           av_unshift(PL_stopav, 1);
+           av_store(PL_stopav, 0, (SV *)cv);
+           GvCV(gv) = 0;
+       }
        else if (strEQ(s, "INIT") && !PL_error_count) {
            if (!PL_initav)
                PL_initav = newAV();
@@ -4522,6 +4529,13 @@ Perl_newXS(pTHX_ char *name, XSUBADDR_t subaddr, char *filename)
            av_store(PL_endav, 0, (SV *)cv);
            GvCV(gv) = 0;
        }
+       else if (strEQ(s, "STOP")) {
+           if (!PL_stopav)
+               PL_stopav = newAV();
+           av_unshift(PL_stopav, 1);
+           av_store(PL_stopav, 0, (SV *)cv);
+           GvCV(gv) = 0;
+       }
        else if (strEQ(s, "INIT")) {
            if (!PL_initav)
                PL_initav = newAV();
diff --git a/perl.c b/perl.c
index ce73fe9..6e907eb 100644 (file)
--- a/perl.c
+++ b/perl.c
@@ -433,9 +433,11 @@ perl_destruct(pTHXx)
     /* startup and shutdown function lists */
     SvREFCNT_dec(PL_beginav);
     SvREFCNT_dec(PL_endav);
+    SvREFCNT_dec(PL_stopav);
     SvREFCNT_dec(PL_initav);
     PL_beginav = Nullav;
     PL_endav = Nullav;
+    PL_stopav = Nullav;
     PL_initav = Nullav;
 
     /* shortcuts just get cleared */
@@ -660,6 +662,8 @@ setuid perl scripts securely.\n");
                env, xsinit);
     switch (ret) {
     case 0:
+       if (PL_stopav)
+           call_list(oldscope, PL_stopav);
        return 0;
     case 1:
        STATUS_ALL_FAILURE;
@@ -670,8 +674,8 @@ setuid perl scripts securely.\n");
            LEAVE;
        FREETMPS;
        PL_curstash = PL_defstash;
-       if (PL_endav && !PL_minus_c)
-           call_list(oldscope, PL_endav);
+       if (PL_stopav)
+           call_list(oldscope, PL_stopav);
        return STATUS_NATIVE_EXPORT;
     case 3:
        PerlIO_printf(Perl_error_log, "panic: top_env\n");
@@ -3075,7 +3079,11 @@ Perl_call_list(pTHX_ I32 oldscope, AV *paramList)
                if (paramList == PL_beginav)
                    sv_catpv(atsv, "BEGIN failed--compilation aborted");
                else
-                   sv_catpv(atsv, "END failed--cleanup aborted");
+                   Perl_sv_catpvf(aTHX_ atsv,
+                                  "%s failed--call queue aborted",
+                                  paramList == PL_stopav ? "STOP"
+                                  : paramList == PL_initav ? "INIT"
+                                  : "END");
                while (PL_scopestack_ix > oldscope)
                    LEAVE;
                Perl_croak(aTHX_ "%s", SvPVX(atsv));
@@ -3090,15 +3098,16 @@ Perl_call_list(pTHX_ I32 oldscope, AV *paramList)
                LEAVE;
            FREETMPS;
            PL_curstash = PL_defstash;
-           if (PL_endav && !PL_minus_c)
-               call_list(oldscope, PL_endav);
            PL_curcop = &PL_compiling;
            PL_curcop->cop_line = oldline;
            if (PL_statusvalue) {
                if (paramList == PL_beginav)
                    Perl_croak(aTHX_ "BEGIN failed--compilation aborted");
                else
-                   Perl_croak(aTHX_ "END failed--cleanup aborted");
+                   Perl_croak(aTHX_ "%s failed--call queue aborted",
+                              paramList == PL_stopav ? "STOP"
+                              : paramList == PL_initav ? "INIT"
+                              : "END");
            }
            my_exit_jump();
            /* NOTREACHED */
index da1425e..e46df77 100644 (file)
@@ -24,6 +24,12 @@ responsibility to ensure that warnings are enabled judiciously.
 
 =over 4
 
+=item STOP is a new keyword
+
+In addition to C<BEGIN>, C<INIT> and C<END>, subroutines named
+C<STOP> are now special.  They are queued up for execution at the
+end of compilation, and cannot be called directly.
+
 =item Treatment of list slices of undef has changed
 
 When taking a slice of a literal list (as opposed to a slice of
@@ -603,6 +609,13 @@ BEGIN blocks are executed under such conditions, this variable
 enables perl code to determine whether actions that make sense
 only during normal running are warranted.  See L<perlvar>.
 
+=head2 STOP blocks
+
+Arbitrary code can be queued for execution when Perl has finished
+parsing the program (i.e. when the compile phase ends) using STOP
+blocks.  These behave similar to END blocks, except for being
+called at the end of compilation rather than at the end of execution.
+
 =head2 Optional Y2K warnings
 
 If Perl is built with the cpp macro C<PERL_Y2KWARN> defined,
@@ -789,9 +802,7 @@ run in compile-only mode.  Since this is typically not the expected
 behavior, END blocks are not executed anymore when the C<-c> switch
 is used.
 
-Note that something resembling the previous behavior can still be
-obtained by putting C<BEGIN { $^C = 0; exit; }> at the very end of
-the top level source file.
+See L<STOP blocks> for how to run things when the compile phase ends.
 
 =head2 Potential to leak DATA filehandles
 
index 0b1f68e..277e634 100644 (file)
@@ -1316,10 +1316,11 @@ ugly.  Your code will be interpreted as an attempt to call a method
 named "elseif" for the class returned by the following block.  This is
 unlikely to be what you want.
 
-=item END failed--cleanup aborted
+=item %s failed--call queue aborted
 
-(F) An untrapped exception was raised while executing an END subroutine.
-The interpreter is immediately exited.
+(F) An untrapped exception was raised while executing a STOP, INIT, or
+END subroutine.  Processing of the remainder of the queue of such
+routines has been prematurely ended.
 
 =item entering effective %s failed
 
index f8efd7e..e061e29 100644 (file)
@@ -3767,7 +3767,9 @@ array by 1 and moving everything down.  If there are no elements in the
 array, returns the undefined value.  If ARRAY is omitted, shifts the
 C<@_> array within the lexical scope of subroutines and formats, and the
 C<@ARGV> array at file scopes or within the lexical scopes established by
-the C<eval ''>, C<BEGIN {}>, C<END {}>, and C<INIT {}> constructs.
+the C<eval ''>, C<BEGIN {}>, C<INIT {}>, C<STOP {}>, and C<END {}>
+constructs.
+
 See also C<unshift>, C<push>, and C<pop>.  C<Shift()> and C<unshift> do the
 same thing to the left end of an array that C<pop> and C<push> do to the
 right end.
index fc81fdf..45a82ad 100644 (file)
@@ -213,8 +213,8 @@ This also has implications for the use of the SUPER:: qualifier
 =head2 Package Constructors and Destructors
 
 Three special subroutines act as package
-constructors and destructors.  These are the C<BEGIN>, C<INIT>, and
-C<END> routines.  The C<sub> is optional for these routines.
+constructors and destructors.  These are the C<BEGIN>, C<STOP>, C<INIT>,
+and C<END> routines.  The C<sub> is optional for these routines.
 
 A C<BEGIN> subroutine is executed as soon as possible, that is, the moment
 it is completely defined, even before the rest of the containing file
@@ -225,24 +225,31 @@ files in time to be visible to the rest of the file.  Once a C<BEGIN>
 has run, it is immediately undefined and any code it used is returned to
 Perl's memory pool.  This means you can't ever explicitly call a C<BEGIN>.
 
-Similar to C<BEGIN> blocks, C<INIT> blocks are run just before the
-Perl runtime begins execution.  For example, the code generators
-documented in L<perlcc> make use of C<INIT> blocks to initialize
-and resolve pointers to XSUBs.
-
-An C<END> subroutine is executed as late as possible, that is, when
-the interpreter is being exited, even if it is exiting as a result of
-a die() function.  (But not if it's polymorphing into another program
-via C<exec>, or being blown out of the water by a signal--you have to
-trap that yourself (if you can).)  You may have multiple C<END> blocks
-within a file--they will execute in reverse order of definition; that is:
-last in, first out (LIFO).
+An C<END> subroutine is executed as late as possible, that is, after
+perl has finished running the program and just before the interpreter
+is being exited, even if it is exiting as a result of a die() function.
+(But not if it's polymorphing into another program via C<exec>, or
+being blown out of the water by a signal--you have to trap that yourself
+(if you can).)  You may have multiple C<END> blocks within a file--they
+will execute in reverse order of definition; that is: last in, first
+out (LIFO).  C<END> blocks are not executed when you run perl with the
+C<-c> switch.
 
 Inside an C<END> subroutine, C<$?> contains the value that the program is
 going to pass to C<exit()>.  You can modify C<$?> to change the exit
 value of the program.  Beware of changing C<$?> by accident (e.g. by
 running something via C<system>).
 
+Similar to C<BEGIN> blocks, C<INIT> blocks are run just before the
+Perl runtime begins execution, in "first in, first out" (FIFO) order.
+For example, the code generators documented in L<perlcc> make use of
+C<INIT> blocks to initialize and resolve pointers to XSUBs.
+
+Similar to C<END> blocks, C<STOP> blocks are run just after the
+Perl compile phase ends and before the run time begins, in
+LIFO order.  C<STOP> blocks are again useful in the Perl compiler
+suite to save the compiled state of the program.
+
 When you use the B<-n> and B<-p> switches to Perl, C<BEGIN> and
 C<END> work just as they do in B<awk>, as a degenerate case.  As currently
 implemented (and subject to change, since its inconvenient at best),
index 0c3fcad..8fec7c3 100644 (file)
@@ -268,9 +268,10 @@ An alternate delimiter may be specified using B<-F>.
 =item B<-c>
 
 causes Perl to check the syntax of the program and then exit without
-executing it.  Actually, it I<will> execute C<BEGIN>, C<END>, and C<use> blocks,
-because these are considered as occurring outside the execution of
-your program.  C<INIT> blocks, however, will be skipped.
+executing it.  Actually, it I<will> execute C<BEGIN>, C<STOP>, and
+C<use> blocks, because these are considered as occurring outside the
+execution of your program.  C<INIT> and C<END> blocks, however, will
+be skipped.
 
 =item B<-d>
 
index 4abdc39..416763f 100644 (file)
@@ -207,9 +207,8 @@ core, as are modules whose names are in all lower case.  A
 function in all capitals is a loosely-held convention meaning it
 will be called indirectly by the run-time system itself, usually
 due to a triggered event.  Functions that do special, pre-defined
-things include C<BEGIN>, C<END>, C<AUTOLOAD>, and C<DESTROY>--plus
-all functions mentioned in L<perltie>.  The 5.005 release adds
-C<INIT> to this list.
+things include C<BEGIN>, C<STOP>, C<INIT>, C<END>, C<AUTOLOAD>, and
+C<DESTROY>--plus all functions mentioned in L<perltie>.
 
 =head2 Private Variables via my()
 
@@ -455,7 +454,7 @@ starts to run:
     }
 
 See L<perlmod/"Package Constructors and Destructors"> about the
-special triggered functions, C<BEGIN> and C<INIT>.
+special triggered functions, C<BEGIN>, C<STOP>, C<INIT> and C<END>.
 
 If declared at the outermost scope (the file scope), then lexicals
 work somewhat like C's file statics.  They are available to all
index 4b2ed48..7836acf 100644 (file)
@@ -824,7 +824,8 @@ Workarounds to help Win32 dynamic loading.
 
 =head2 END blocks
 
-END blocks need saving in compiled output.
+END blocks need saving in compiled output, now that STOP blocks
+are available.
 
 =head2 _AUTOLOAD
 
diff --git a/toke.c b/toke.c
index 253db35..019765b 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -3776,6 +3776,7 @@ Perl_yylex(pTHX)
        case KEY_DESTROY:
        case KEY_BEGIN:
        case KEY_END:
+       case KEY_STOP:
        case KEY_INIT:
            if (PL_expect == XSTATE) {
                s = PL_bufptr;
@@ -5214,6 +5215,9 @@ Perl_keyword(pTHX_ register char *d, I32 len)
            break;
        }
        break;
+    case 'S':
+       if (strEQ(d,"STOP"))                    return KEY_STOP;
+       break;
     case 's':
        switch (d[1]) {
        case 0:                                 return KEY_s;