[inseparable changes from patch from perl5.003_08 to perl5.003_09]
Perl 5 Porters [Tue, 26 Nov 1996 08:48:00 +0000 (20:48 +1200)]
 CORE LANGUAGE CHANGES

Subject: Lexical locales
From: Chip Salzenberg <chip@atlantic.net>
Files: too many to list

    make effectiveness of locales depend on C<use locale>

Subject: Lexical scoping cleanup
From: Chip Salzenberg <chip@atlantic.net>
Files: many... but mostly perly.y and toke.c

    tighten scoping of lexical variables, somewhat on the
    new constructs and somewhat on the old

Subject: memory corruption / security bug in sysread,syswrite + patch
Date: Mon, 25 Nov 1996 21:46:31 +0200 (EET)
From: Jarkko Hietaniemi <jhi@cc.hut.fi>
Files: MANIFEST pod/perldiag.pod pod/perlfunc.pod pp_sys.c t/op/sysio.t
Msg-ID: <199611251946.VAA30459@alpha.hut.fi>

    (applied based on p5p patch as commit d7090df90a9cb89c83787d916e40d92a616b146d)

 DOCUMENTATION

Subject: perldiag documentation patch.
Date: Wed, 20 Nov 96 16:07:28 GMT
From: Paul Marquess <pmarquess@bfsec.bt.co.uk>
Files: pod/perldiag.pod

    private-msgid: <9611201607.AA12729@claudius.bfsec.bt.co.uk>

Subject: a missing perldiag entry
Date: Thu, 21 Nov 1996 15:24:02 -0500
From: Gurusamy Sarathy <gsar@engin.umich.edu>
Files: pod/perldiag.pod

    private-msgid: <199611212024.PAA15758@aatma.engin.umich.edu>

Subject: perlfunc patch
Date: Wed, 20 Nov 96 14:04:08 GMT
From: Paul Marquess <pmarquess@bfsec.bt.co.uk>
Files: pod/perlfunc.pod

    Following on from the patch to make uc, lc etc default to $_ (as per
    Camel II), here is a followup patch to perlfunc that documents the
    change. I think I have documented all the other cases where $_
    defaulting works as well.

    p5p-msgid: <9611201404.AA12477@claudius.bfsec.bt.co.uk>

 OTHER CORE CHANGES

Subject: Properly prototype safe{malloc,calloc,realloc,free}.
From: Chip Salzenberg <chip@atlantic.net>
Files: proto.h

Subject: UnixWare 2.1 fix for perl5.003_08 - cope with fp->_cnt < -1, allow debugging
Date: Wed, 20 Nov 1996 14:27:06 +0100
From: John Hughes <john@AtlanTech.COM>
Files: sv.c

    UnixWare 2.1 has no fp->_base so most of the debugging stuff in sv_gets just
    core dumps.

    Also, for some unknown reason fp->_cnt is sometimes < -1, screwing up the
    initial SvGROW in svgets.

    Appart from that its io is std.

    p5p-msgid: <01BBD6EE.E915C860@malvinas.AtlanTech.COM>

Subject: die -> croak
Date: Thu, 21 Nov 1996 16:11:21 -0500
From: Gurusamy Sarathy <gsar@engin.umich.edu>
Files: pp_ctl.c

    private-msgid: <199611212111.QAA17070@aatma.engin.umich.edu>

Subject: Cleanup of {,un}pack('w').
From: Chip Salzenberg <chip@atlantic.net>
Files: pp.c

Subject: Cleanups from Ilya.
From: Chip Salzenberg <chip@atlantic.net>
Files: gv.c malloc.c pod/perlguts.pod pp_ctl.c

Subject: Fix for unpack('w') on 64-bit systems.
From: Chip Salzenberg <chip@atlantic.net>
Files: pp.c

Subject: Re: LC_NUMERIC support is ready + performance
Date: Mon, 25 Nov 1996 22:08:27 -0500 (EST)
From: Ilya Zakharevich <ilya@math.ohio-state.edu>
Files: sv.c

    Chip Salzenberg writes:
    >
    > Having thought about the use of our own gcvt() and atof(), I've run
    > away in horror.  It's just too hairy.
    >
    > So I've implemented the only viable alternative I know of: Toggling
    > LC_NUMERIC to/from "C" as needed.
    >
    > Patch follows.
    >
    > I think _09 is *very* close.

    Since _09 is going to be alpha anyway, I reiterate my question:
     Is there any reason to not include my hash/array performance
     patches in _09?

    Btw, here is the next performance patch. It makes PADTMP values
    stealable too. I do not do by setting TEMP flags on them, since it
    would be a very distributed patch, and it would break some places
    which check for TEMP for some other reasons (yes, I checked ;-).

    This patch decreases *twice* the memory usage of
     perl -e '$a = "a" x 1e6; 1'

    Enjoy,

    p5p-msgid: <199611260308.WAA02677@monk.mps.ohio-state.edu>

Subject: Hash key sharing improvements from Ilya.
From: Chip Salzenberg <chip@atlantic.net>
Files: hv.c hv.h proto.h

Subject: Mortal stack pre-allocation from Ilya.
From: Chip Salzenberg <chip@atlantic.net>
Files: pp.c pp.h pp_ctl.c pp_hot.c pp_sys.c

 PORTABILITY

Subject: VMS patches post-5.003_08
Date: Fri, 22 Nov 1996 18:16:31 -0500 (EST)
From: Charles Bailey <bailey@hmivax.humgen.upenn.edu>
Files: lib/ExtUtils/MM_Unix.pm lib/ExtUtils/MM_VMS.pm lib/ExtUtils/MakeMaker.pm lib/File/Path.pm mg.c pp_ctl.c utils/h2xs.PL vms/config.vms vms/descrip.mms vms/gen_shrfls.pl vms/genconfig.pl vms/perlvms.pod vms/vms.c vms/vmsish.h

    Here're diffs to bring a base 5.003_08 up to the current VMS working
    sources.  Nearly all of the changes are VMS-specific, and comprise
    miscellaneous bugfixes accumulated since 5.003_07, rather than any
    particular problem with 5.003_08.  I'm posting them here since some
    of the patches change core files, and I'd like to insure that I
    haven't accidentally created problems for anyone else.

    With these and a couple of of the small patches already send to p5p,
    5.003_08 builds clean and passes all tests under VMS.

    Thanks, Chip, for all the work.

    p5p-msgid: <1996Nov22.181631.1603238@hmivax.humgen.upenn.edu>

57 files changed:
MANIFEST
doio.c
doop.c
dump.c
embed.h
ext/POSIX/POSIX.xs
gv.c
handy.h
hv.c
hv.h
interp.sym
lib/ExtUtils/MM_Unix.pm
lib/ExtUtils/MM_VMS.pm
lib/ExtUtils/MakeMaker.pm
lib/File/Path.pm
lib/locale.pm [new file with mode: 0644]
malloc.c
mg.c
op.c
op.h
opcode.h
opcode.pl
patchlevel.h
perl.c
perl.h
perl_exp.SH
perly.c
perly.c.diff
perly.y
pod/perldiag.pod
pod/perlfunc.pod
pod/perlguts.pod
pp.c
pp.h
pp_ctl.c
pp_hot.c
pp_sys.c
proto.h
regcomp.c
regcomp.h
regexec.c
regexp.h
sv.c
sv.h
t/op/re_tests
t/op/sysio.t
taint.c
toke.c
util.c
utils/h2xs.PL
vms/config.vms
vms/descrip.mms
vms/gen_shrfls.pl
vms/genconfig.pl
vms/perlvms.pod
vms/vms.c
vms/vmsish.h

index c2c8609..80a439b 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -335,6 +335,7 @@ lib/assert.pl               assertion and panic with stack trace
 lib/bigfloat.pl                An arbitrary precision floating point package
 lib/bigint.pl          An arbitrary precision integer arithmetic package
 lib/bigrat.pl          An arbitrary precision rational arithmetic package
+lib/blib.pm            For "use blib"
 lib/cacheout.pl                Manages output filehandles when you need too many
 lib/chat2.inter                A chat2 with interaction
 lib/chat2.pl           Randal's famous expect-ish routines
@@ -357,6 +358,7 @@ lib/importenv.pl    Perl routine to get environment into variables
 lib/integer.pm         For "use integer"
 lib/less.pm            For "use less"
 lib/lib.pm             For "use lib"
+lib/locale.pm          For "use locale"
 lib/look.pl            A "look" equivalent
 lib/newgetopt.pl       A perl library supporting long option parsing
 lib/open2.pl           Open a two-ended pipe
@@ -653,6 +655,7 @@ t/op/stat.t         See if stat works
 t/op/study.t           See if study works
 t/op/subst.t           See if substitution works
 t/op/substr.t          See if substr works
+t/op/sysio.t           See if sysread and syswrite work
 t/op/tie.t             See if tie/untie functions work
 t/op/time.t            See if time functions work
 t/op/undef.t           See if undef works
diff --git a/doio.c b/doio.c
index 6bb3fa5..5ad1e28 100644 (file)
--- a/doio.c
+++ b/doio.c
@@ -1073,9 +1073,10 @@ register SV **sp;
 
     if (tainting) {
        while (++mark <= sp) {
-           MAGIC *mg;
-           if (SvMAGICAL(*mark) && (mg = mg_find(*mark, 't')) && mg->mg_len & 1)
-               tainted = TRUE;
+           if (SvTAINTED(*mark)) {
+               TAINT;
+               break;
+           }
        }
        mark = oldmark;
     }
diff --git a/doop.c b/doop.c
index 0d8538c..ddcaf36 100644 (file)
--- a/doop.c
+++ b/doop.c
@@ -273,6 +273,11 @@ register SV **sarg;
                *t = '\0';
                (void)sprintf(xs,f,SvNV(arg));
                xlen = strlen(xs);
+#ifdef LC_NUMERIC
+               /* User-defined locales may include arbitrary characters */
+               if (! numeric_standard)
+                   SvTAINTED_on(sv);
+#endif
                break;
            case 's':
                ch = *(++t);
diff --git a/dump.c b/dump.c
index 8366f5f..064641f 100644 (file)
--- a/dump.c
+++ b/dump.c
@@ -357,8 +357,6 @@ register PMOP *pm;
            (void)strcat(buf,"ALL,");
        if (pm->op_pmflags & PMf_SKIPWHITE)
            (void)strcat(buf,"SKIPWHITE,");
-       if (pm->op_pmflags & PMf_FOLD)
-           (void)strcat(buf,"FOLD,");
        if (pm->op_pmflags & PMf_CONST)
            (void)strcat(buf,"CONST,");
        if (pm->op_pmflags & PMf_KEEP)
diff --git a/embed.h b/embed.h
index edad009..faa1d5a 100644 (file)
--- a/embed.h
+++ b/embed.h
 #define bufptr         Perl_bufptr
 #define bxor_amg       Perl_bxor_amg
 #define check          Perl_check
+#define collation_ix   Perl_collation_ix
+#define collation_name Perl_collation_name
+#define collation_standard     Perl_collation_standard
+#define collxfrm_base  Perl_collxfrm_base
+#define collxfrm_mult  Perl_collxfrm_mult
 #define compcv         Perl_compcv
 #define compiling      Perl_compiling
 #define compl_amg      Perl_compl_amg
@@ -79,6 +84,7 @@
 #define filter_del     Perl_filter_del
 #define filter_read    Perl_filter_read
 #define fold           Perl_fold
+#define fold_locale    Perl_fold_locale
 #define freq           Perl_freq
 #define ge_amg         Perl_ge_amg
 #define gid            Perl_gid
@@ -92,7 +98,6 @@
 #define last_lop       Perl_last_lop
 #define last_lop_op    Perl_last_lop_op
 #define last_uni       Perl_last_uni
-#define lc_collate_active      Perl_lc_collate_active
 #define le_amg         Perl_le_amg
 #define lex_brackets   Perl_lex_brackets
 #define lex_brackstack Perl_lex_brackstack
 #define nomemok                Perl_nomemok
 #define nomethod_amg   Perl_nomethod_amg
 #define not_amg                Perl_not_amg
+#define numeric_local  Perl_numeric_local
+#define numeric_name   Perl_numeric_name
+#define numeric_standard       Perl_numeric_standard
 #define numer_amg      Perl_numer_amg
 #define oldbufptr      Perl_oldbufptr
 #define oldoldbufptr   Perl_oldoldbufptr
 #define regendp                Perl_regendp
 #define regeol         Perl_regeol
 #define regflags       Perl_regflags
-#define regfold                Perl_regfold
 #define reginput       Perl_reginput
 #define regkind                Perl_regkind
 #define reglastparen   Perl_reglastparen
 #define vtbl_amagicelem        Perl_vtbl_amagicelem
 #define vtbl_arylen    Perl_vtbl_arylen
 #define vtbl_bm                Perl_vtbl_bm
+#define vtbl_collxfrm  Perl_vtbl_collxfrm
 #define vtbl_dbline    Perl_vtbl_dbline
 #define vtbl_env       Perl_vtbl_env
 #define vtbl_envelem   Perl_vtbl_envelem
 #define ck_eof         Perl_ck_eof
 #define ck_eval                Perl_ck_eval
 #define ck_exec                Perl_ck_exec
-#define ck_formline    Perl_ck_formline
 #define ck_ftst                Perl_ck_ftst
 #define ck_fun         Perl_ck_fun
+#define ck_fun_locale  Perl_ck_fun_locale
 #define ck_glob                Perl_ck_glob
 #define ck_grep                Perl_ck_grep
 #define ck_gvconst     Perl_ck_gvconst
 #define ck_retarget    Perl_ck_retarget
 #define ck_rfun                Perl_ck_rfun
 #define ck_rvconst     Perl_ck_rvconst
+#define ck_scmp                Perl_ck_scmp
 #define ck_select      Perl_ck_select
 #define ck_shift       Perl_ck_shift
 #define ck_sort                Perl_ck_sort
 #define hv_store_ent   Perl_hv_store_ent
 #define hv_undef       Perl_hv_undef
 #define ibcmp          Perl_ibcmp
+#define ibcmp_locale   Perl_ibcmp_locale
 #define ingroup                Perl_ingroup
 #define instr          Perl_instr
+#define intro_my       Perl_intro_my
 #define intuit_more    Perl_intuit_more
 #define invert         Perl_invert
 #define jmaybe         Perl_jmaybe
 #define magic_setamagic        Perl_magic_setamagic
 #define magic_setarylen        Perl_magic_setarylen
 #define magic_setbm    Perl_magic_setbm
+#define magic_setcollxfrm      Perl_magic_setcollxfrm
 #define magic_setdbline        Perl_magic_setdbline
 #define magic_setenv   Perl_magic_setenv
 #define magic_setfm    Perl_magic_setfm
 #define sv_clean_objs  Perl_sv_clean_objs
 #define sv_clear       Perl_sv_clear
 #define sv_cmp         Perl_sv_cmp
+#define sv_cmp_locale  Perl_sv_cmp_locale
+#define sv_collxfrm    Perl_sv_collxfrm
 #define sv_dec         Perl_sv_dec
 #define sv_derived_from        Perl_sv_derived_from
 #define sv_dump                Perl_sv_dump
 #define sv_setref_pvn  Perl_sv_setref_pvn
 #define sv_setsv       Perl_sv_setsv
 #define sv_setuv       Perl_sv_setuv
+#define sv_taint       Perl_sv_taint
+#define sv_tainted     Perl_sv_tainted
 #define sv_unmagic     Perl_sv_unmagic
 #define sv_unref       Perl_sv_unref
+#define sv_untaint     Perl_sv_untaint
 #define sv_upgrade     Perl_sv_upgrade
 #define sv_usepvn      Perl_sv_usepvn
 #define taint_env      Perl_taint_env
-#define taint_not      Perl_taint_not
 #define taint_proper   Perl_taint_proper
 #define too_few_arguments      Perl_too_few_arguments
 #define too_many_arguments     Perl_too_many_arguments
 #define rs             (curinterp->Irs)
 #define runlevel       (curinterp->Irunlevel)
 #define sawampersand   (curinterp->Isawampersand)
-#define sawi           (curinterp->Isawi)
 #define sawstudy       (curinterp->Isawstudy)
 #define sawvec         (curinterp->Isawvec)
 #define screamfirst    (curinterp->Iscreamfirst)
 #define Irs            rs
 #define Irunlevel      runlevel
 #define Isawampersand  sawampersand
-#define Isawi          sawi
 #define Isawstudy      sawstudy
 #define Isawvec                sawvec
 #define Iscreamfirst   screamfirst
 #define Iunsafe                unsafe
 #define Iwarnhook      warnhook
 
+#ifdef EMBED
+
 #define Argv           Perl_Argv
 #define Cmd            Perl_Cmd
 #define DBgv           Perl_DBgv
 #define rs             Perl_rs
 #define runlevel       Perl_runlevel
 #define sawampersand   Perl_sawampersand
-#define sawi           Perl_sawi
 #define sawstudy       Perl_sawstudy
 #define sawvec         Perl_sawvec
 #define screamfirst    Perl_screamfirst
 #define unsafe         Perl_unsafe
 #define warnhook       Perl_warnhook
 
+#endif /* EMBED */
+
 #endif /* MULTIPLICITY */
index 808ef8e..a94c942 100644 (file)
@@ -2736,8 +2736,59 @@ setlocale(category, locale = 0)
        char *          locale
     CODE:
        RETVAL = setlocale(category, locale);
-       if (RETVAL)
-           perl_init_fold();
+       if (RETVAL) {
+#ifdef LC_CTYPE
+           if (category == LC_CTYPE
+#ifdef LC_ALL
+               || category == LC_ALL
+#endif
+               )
+           {
+               char *newctype;
+#ifdef LC_ALL
+               if (category == LC_ALL)
+                   newctype = setlocale(LC_CTYPE, NULL);
+               else
+#endif
+                   newctype = RETVAL;
+               perl_new_ctype(newctype);
+           }
+#endif /* LC_CTYPE */
+#ifdef LC_COLLATE
+           if (category == LC_COLLATE
+#ifdef LC_ALL
+               || category == LC_ALL
+#endif
+               )
+           {
+               char *newcoll;
+#ifdef LC_ALL
+               if (category == LC_ALL)
+                   newcoll = setlocale(LC_COLLATE, NULL);
+               else
+#endif
+                   newcoll = RETVAL;
+               perl_new_collate(newcoll);
+           }
+#endif /* LC_COLLATE */
+#ifdef LC_NUMERIC
+           if (category == LC_NUMERIC
+#ifdef LC_ALL
+               || category == LC_ALL
+#endif
+               )
+           {
+               char *newnum;
+#ifdef LC_ALL
+               if (category == LC_ALL)
+                   newnum = setlocale(LC_NUMERIC, NULL);
+               else
+#endif
+                   newnum = RETVAL;
+               perl_new_numeric(newnum);
+           }
+#endif /* LC_NUMERIC */
+       }
     OUTPUT:
        RETVAL
 
@@ -2962,8 +3013,7 @@ read(fd, buffer, nbytes)
             SvCUR(sv_buffer) = RETVAL;
             SvPOK_only(sv_buffer);
             *SvEND(sv_buffer) = '\0';
-            if (tainting)
-                sv_magic(sv_buffer, 0, 't', 0, 0);
+            SvTAINTED_on(sv_buffer);
         }
 
 SysRet
@@ -3053,6 +3103,7 @@ strtod(str)
        double num;
        char *unparsed;
     PPCODE:
+       NUMERIC_LOCAL();
        num = strtod(str, &unparsed);
        PUSHs(sv_2mortal(newSVnv(num)));
        if (GIMME == G_ARRAY) {
diff --git a/gv.c b/gv.c
index e825187..95efca8 100644 (file)
--- a/gv.c
+++ b/gv.c
@@ -285,8 +285,7 @@ char* name;
                sv_catpvn(tmpstr,"::", 2);
                sv_catpvn(tmpstr, name, nend - name);
                sv_setsv(GvSV(CvGV(cv)), tmpstr);
-               if (tainting)
-                   sv_unmagic(GvSV(CvGV(cv)), 't');
+               SvTAINTED_off(GvSV(CvGV(cv)));
            }
        }
     }
@@ -1231,7 +1230,7 @@ int flags;
        ans=SvIV(res)!=0; break;
       case inc_amg:
       case dec_amg:
-       SvSetSV(left,res); return res; break;
+       SvSetSV(left,res); return left;
       case not_amg:
 ans=!SvOK(res); break;
       }
diff --git a/handy.h b/handy.h
index 99d07f0..2db267d 100644 (file)
--- a/handy.h
+++ b/handy.h
@@ -124,46 +124,87 @@ typedef unsigned short    U16;
 #define strnNE(s1,s2,l) (strncmp(s1,s2,l))
 #define strnEQ(s1,s2,l) (!strncmp(s1,s2,l))
 
+/*
+ * Character classes.
+ *
+ * Unfortunately, the introduction of locales means that we
+ * can't trust isupper(), etc. to tell the truth.  And when
+ * it comes to /\w+/ with tainting enabled, we *must* be able
+ * to trust our character classes.
+ *
+ * Therefore, the default tests in the text of Perl will be
+ * independent of locale.  Any code that wants to depend on
+ * the current locale will use the tests that begin with "lc".
+ */
+
 #ifdef HAS_SETLOCALE  /* XXX Is there a better test for this? */
 #  ifndef CTYPE256
 #    define CTYPE256
 #  endif
 #endif
 
-#ifdef USE_NEXT_CTYPE 
-#define isALNUM(c)   (NXIsAlpha((unsigned int)c) || NXIsDigit((unsigned int)c) || c == '_')
-#define isIDFIRST(c) (NXIsAlpha((unsigned int)c) || c == '_')
-#define isALPHA(c)   NXIsAlpha((unsigned int)c)
-#define isSPACE(c)   NXIsSpace((unsigned int)c)
-#define isDIGIT(c)   NXIsDigit((unsigned int)c)
-#define isUPPER(c)   NXIsUpper((unsigned int)c)
-#define isLOWER(c)   NXIsLower((unsigned int)c)
-#define toUPPER(c)   NXToUpper((unsigned int)c)
-#define toLOWER(c)   NXToLower((unsigned int)c)
-#else /* USE_NEXT_CTYPE */
-#if defined(CTYPE256) || (!defined(isascii) && !defined(HAS_ISASCII))
-#define isALNUM(c)   (isalpha((unsigned char)(c)) || isdigit((unsigned char)(c)) || c == '_')
-#define isIDFIRST(c) (isalpha((unsigned char)(c)) || (c) == '_')
-#define isALPHA(c)   isalpha((unsigned char)(c))
-#define isSPACE(c)   isspace((unsigned char)(c))
-#define isDIGIT(c)   isdigit((unsigned char)(c))
-#define isUPPER(c)   isupper((unsigned char)(c))
-#define isLOWER(c)   islower((unsigned char)(c))
-#define toUPPER(c)   toupper((unsigned char)(c))
-#define toLOWER(c)   tolower((unsigned char)(c))
-#else
-#define isALNUM(c)   (isascii(c) && (isalpha(c) || isdigit(c) || c == '_'))
-#define isIDFIRST(c) (isascii(c) && (isalpha(c) || (c) == '_'))
-#define isALPHA(c)   (isascii(c) && isalpha(c))
-#define isSPACE(c)   (isascii(c) && isspace(c))
-#define isDIGIT(c)   (isascii(c) && isdigit(c))
-#define isUPPER(c)   (isascii(c) && isupper(c))
-#define isLOWER(c)   (isascii(c) && islower(c))
-#define toUPPER(c)   toupper(c)
-#define toLOWER(c)   tolower(c)
-#endif
+#define isALNUM(c)     (isALPHA(c) || isDIGIT(c) || (c) == '_')
+#define isIDFIRST(c)   (isALPHA(c) || (c) == '_')
+#define isALPHA(c)     (isUPPER(c) || isLOWER(c))
+#define isSPACE(c) \
+       ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) =='\r' || (c) == '\f')
+#define isDIGIT(c)     ((c) >= '0' && (c) <= '9')
+#define isUPPER(c)     ((c) >= 'A' && (c) <= 'Z')
+#define isLOWER(c)     ((c) >= 'a' && (c) <= 'z')
+#define isPRINT(c)     (((c) > 32 && (c) < 127) || isSPACE(c))
+#define toUPPER(c)     (isLOWER(c) ? (c) - ('a' - 'A') : (c))
+#define toLOWER(c)     (isUPPER(c) ? (c) + ('a' - 'A') : (c))
+
+#ifdef USE_NEXT_CTYPE
+
+#  define isALNUM_LC(c) \
+       (NXIsAlpha((unsigned int)c) || NXIsDigit((unsigned int)c) || c == '_')
+#  define isIDFIRST_LC(c)      (NXIsAlpha((unsigned int)c) || c == '_')
+#  define isALPHA_LC(c)                NXIsAlpha((unsigned int)c)
+#  define isSPACE_LC(c)                NXIsSpace((unsigned int)c)
+#  define isDIGIT_LC(c)                NXIsDigit((unsigned int)c)
+#  define isUPPER_LC(c)                NXIsUpper((unsigned int)c)
+#  define isLOWER_LC(c)                NXIsLower((unsigned int)c)
+#  define isPRINT_LC(c)                NXIsPrint((unsigned int)c)
+#  define toUPPER_LC(c)                NXToUpper((unsigned int)c)
+#  define toLOWER_LC(c)                NXToLower((unsigned int)c)
+
+#else /* !USE_NEXT_CTYPE */
+#  if defined(CTYPE256) || (!defined(isascii) && !defined(HAS_ISASCII))
+
+#    define isALNUM_LC(c) \
+       (isalpha((unsigned char)(c)) || \
+        isdigit((unsigned char)(c)) || c == '_')
+#    define isIDFIRST_LC(c)    (isalpha((unsigned char)(c)) || (c) == '_')
+#    define isALPHA_LC(c)      isalpha((unsigned char)(c))
+#    define isSPACE_LC(c)      isspace((unsigned char)(c))
+#    define isDIGIT_LC(c)      isdigit((unsigned char)(c))
+#    define isUPPER_LC(c)      isupper((unsigned char)(c))
+#    define isLOWER_LC(c)      islower((unsigned char)(c))
+#    define isPRINT_LC(c)      isprint((unsigned char)(c))
+#    define toUPPER_LC(c)      toupper((unsigned char)(c))
+#    define toLOWER_LC(c)      tolower((unsigned char)(c))
+
+#  else
+
+#    define isALNUM_LC(c) \
+       (isascii(c) && (isalpha(c) || isdigit(c) || c == '_'))
+#    define isIDFIRST_LC(c)    (isascii(c) && (isalpha(c) || (c) == '_'))
+#    define isALPHA_LC(c)      (isascii(c) && isalpha(c))
+#    define isSPACE_LC(c)      (isascii(c) && isspace(c))
+#    define isDIGIT_LC(c)      (isascii(c) && isdigit(c))
+#    define isUPPER_LC(c)      (isascii(c) && isupper(c))
+#    define isLOWER_LC(c)      (isascii(c) && islower(c))
+#    define isPRINT_LC(c)      (isascii(c) && isprint(c))
+#    define toUPPER_LC(c)      toupper(c)
+#    define toLOWER_LC(c)      tolower(c)
+
+#  endif
 #endif /* USE_NEXT_CTYPE */
 
+/* This conversion works both ways, strangely enough. */
+#define toCTRL(c)    (toUPPER(c) ^ 64)
+
 /* Line numbers are unsigned, 16 bits. */
 typedef U16 line_t;
 #ifdef lint
diff --git a/hv.c b/hv.c
index 9547f2c..50d5881 100644 (file)
--- a/hv.c
+++ b/hv.c
@@ -55,6 +55,31 @@ more_he()
     return new_he();
 }
 
+static HEK *
+save_hek(str, len, hash)
+char *str;
+I32 len;
+U32 hash;
+{
+    char *k;
+    register HEK *hek;
+    
+    New(54, k, sizeof(U32) + sizeof(I32) + len + 1, char);
+    hek = (HEK*)k;
+    Copy(str, HK_KEY(hek), len, char);
+    (HK_KEY(hek))[len] = '\0';
+    HK_LEN(hek) = len;
+    HK_HASH(hek) = hash;
+    return hek;
+}
+
+void
+unshare_hek(hek)
+HEK *hek;
+{
+    unsharepvn(HK_KEY(hek),HK_LEN(hek),HK_HASH(hek));
+}
+
 /* (klen == HEf_SVKEY) is special for MAGICAL hv entries, meaning key slot
  * contains an SV* */
 
@@ -143,13 +168,16 @@ register U32 hash;
        return 0;
 
     if (SvRMAGICAL(hv) && mg_find((SV*)hv,'P')) {
+       HEK *hek;
+       Newz(74, hek, 1, HEK);
        sv = sv_newmortal();
        keysv = sv_2mortal(newSVsv(keysv));
        mg_copy((SV*)hv, sv, (char*)keysv, HEf_SVKEY);
        entry = &He;
        HeVAL(entry) = sv;
-       HeKEY(entry) = (char*)keysv;
-       HeKLEN(entry) = HEf_SVKEY;              /* hent_key is holding an SV* */
+       HeKEY_hk(entry) = hek;
+       HeSVKEY_set(entry, keysv);
+       HeKLEN(entry) = HEf_SVKEY;      /* hent_key is holding an SV* */
        return entry;
     }
 
@@ -248,13 +276,11 @@ register U32 hash;
     }
 
     entry = new_he();
-    HeKLEN(entry) = klen;
     if (HvSHAREKEYS(hv))
-       HeKEY(entry) = sharepvn(key, klen, hash);
+       HeKEY_hk(entry) = share_hek(key, klen, hash);
     else                                       /* gotta do the real thing */
-       HeKEY(entry) = savepvn(key,klen);
+       HeKEY_hk(entry) = save_hek(key, klen, hash);
     HeVAL(entry) = val;
-    HeHASH(entry) = hash;
     HeNEXT(entry) = *oentry;
     *oentry = entry;
 
@@ -323,13 +349,11 @@ register U32 hash;
     }
 
     entry = new_he();
-    HeKLEN(entry) = klen;
     if (HvSHAREKEYS(hv))
-       HeKEY(entry) = sharepvn(key, klen, hash);
+       HeKEY_hk(entry) = share_hek(key, klen, hash);
     else                                       /* gotta do the real thing */
-       HeKEY(entry) = savepvn(key,klen);
+       HeKEY_hk(entry) = save_hek(key, klen, hash);
     HeVAL(entry) = val;
-    HeHASH(entry) = hash;
     HeNEXT(entry) = *oentry;
     *oentry = entry;
 
@@ -726,12 +750,13 @@ I32 shared;
     if (!hent)
        return;
     SvREFCNT_dec(HeVAL(hent));
-    if (HeKLEN(hent) == HEf_SVKEY)
-       SvREFCNT_dec((SV*)HeKEY(hent));
-    else if (shared)
-       unsharepvn(HeKEY(hent), HeKLEN(hent), HeHASH(hent));
+    if (HeKLEN(hent) == HEf_SVKEY) {
+       SvREFCNT_dec(HeKEY_sv(hent));
+        Safefree(HeKEY_hk(hent));
+    } else if (shared)
+       unshare_hek(HeKEY_hk(hent));
     else
-       Safefree(HeKEY(hent));
+       Safefree(HeKEY_hk(hent));
     del_he(hent);
 }
 
@@ -743,12 +768,13 @@ I32 shared;
     if (!hent)
        return;
     sv_2mortal(HeVAL(hent));   /* free between statements */
-    if (HeKLEN(hent) == HEf_SVKEY)
-       sv_2mortal((SV*)HeKEY(hent));
-    else if (shared)
-       unsharepvn(HeKEY(hent), HeKLEN(hent), HeHASH(hent));
+    if (HeKLEN(hent) == HEf_SVKEY) {
+       sv_2mortal(HeKEY_sv(hent));
+       Safefree(HeKEY_hk(hent));
+    } else if (shared)
+       unshare_hek(HeKEY_hk(hent));
     else
-       Safefree(HeKEY(hent));
+       Safefree(HeKEY_hk(hent));
     del_he(hent);
 }
 
@@ -868,18 +894,22 @@ HV *hv;
            SvREFCNT_dec(HeSVKEY(entry));       /* get rid of previous key */
        }
        else {
+           HEK *hek;
            xhv->xhv_eiter = entry = new_he();  /* only one HE per MAGICAL hash */
            Zero(entry, 1, HE);
+           Newz(74, hek, 1, HEK);
+           HeKEY_hk(entry) = hek;
            HeKLEN(entry) = HEf_SVKEY;
        }
        magic_nextpack((SV*) hv,mg,key);
         if (SvOK(key)) {
            /* force key to stay around until next time */
-           HeKEY(entry) = (char*)SvREFCNT_inc(key);
-           return entry;                       /* beware, hent_val is not set */
+           HeSVKEY_set(entry, SvREFCNT_inc(key));
+           return entry;               /* beware, hent_val is not set */
         }
        if (HeVAL(entry))
            SvREFCNT_dec(HeVAL(entry));
+       Safefree(HeKEY_hk(entry));
        del_he(entry);
        xhv->xhv_eiter = Null(HE*);
        return Null(HE*);
@@ -913,7 +943,7 @@ register HE *entry;
 I32 *retlen;
 {
     if (HeKLEN(entry) == HEf_SVKEY) {
-       return SvPV((SV*)HeKEY(entry), *(STRLEN*)retlen);
+       return SvPV(HeKEY_sv(entry), *(STRLEN*)retlen);
     }
     else {
        *retlen = HeKLEN(entry);
@@ -927,7 +957,7 @@ hv_iterkeysv(entry)
 register HE *entry;
 {
     if (HeKLEN(entry) == HEf_SVKEY)
-       return sv_mortalcopy((SV*)HeKEY(entry));
+       return sv_mortalcopy(HeKEY_sv(entry));
     else
        return sv_2mortal(newSVpv((HeKLEN(entry) ? HeKEY(entry) : ""),
                                  HeKLEN(entry)));
@@ -941,7 +971,9 @@ register HE *entry;
     if (SvRMAGICAL(hv)) {
        if (mg_find((SV*)hv,'P')) {
            SV* sv = sv_newmortal();
-           mg_copy((SV*)hv, sv, HeKEY(entry), HeKLEN(entry));
+           if (HeKLEN(entry) == HEf_SVKEY)
+               mg_copy((SV*)hv, sv, (char*)HeKEY_sv(entry), HEf_SVKEY);
+           else mg_copy((SV*)hv, sv, HeKEY(entry), HeKLEN(entry));
            return sv;
        }
     }
@@ -970,31 +1002,39 @@ int how;
     sv_magic((SV*)hv, (SV*)gv, how, Nullch, 0);
 }
 
-/* get a (constant) string ptr from the global string table
- * string will get added if it is not already there.
+char*  
+sharepvn(sv, len, hash)
+char* sv;
+I32 len;
+U32 hash;
+{
+    return share_hek(sv, len, hash)->hk_key;
+}
+
+/* possibly free a shared string if no one has access to it
  * len and hash must both be valid for str.
  */
-char *
-sharepvn(str, len, hash)
-char *str;
+void
+unsharepvn(str, len, hash)
+char* str;
 I32 len;
-register U32 hash;
+U32 hash;
 {
     register XPVHV* xhv;
     register HE *entry;
     register HE **oentry;
     register I32 i = 1;
     I32 found = 0;
-
+    
     /* what follows is the moral equivalent of:
-       
-    if (!(Svp = hv_fetch(strtab, str, len, FALSE)))
-       hv_store(strtab, str, len, Nullsv, hash);
-    */
+    if ((Svp = hv_fetch(strtab, tmpsv, FALSE, hash))) {
+       if (--*Svp == Nullsv)
+           hv_delete(strtab, str, len, G_DISCARD, hash);
+    } */
     xhv = (XPVHV*)SvANY(strtab);
     /* assert(xhv_array != 0) */
     oentry = &((HE**)xhv->xhv_array)[hash & (I32) xhv->xhv_max];
-    for (entry = *oentry; entry; i=0, entry = HeNEXT(entry)) {
+    for (entry = *oentry; entry; i=0, oentry = &HeNEXT(entry), entry = *oentry) {
        if (HeHASH(entry) != hash)              /* strings can't be equal */
            continue;
        if (HeKLEN(entry) != len)
@@ -1002,33 +1042,27 @@ register U32 hash;
        if (memcmp(HeKEY(entry),str,len))               /* is this it? */
            continue;
        found = 1;
-       break;
-    }
-    if (!found) {
-       entry = new_he();
-       HeKLEN(entry) = len;
-       HeKEY(entry) = savepvn(str,len);
-       HeVAL(entry) = Nullsv;
-       HeHASH(entry) = hash;
-       HeNEXT(entry) = *oentry;
-       *oentry = entry;
-       xhv->xhv_keys++;
-       if (i) {                                /* initial entry? */
-           ++xhv->xhv_fill;
-           if (xhv->xhv_keys > xhv->xhv_max)
-               hsplit(strtab);
+       if (--HeVAL(entry) == Nullsv) {
+           *oentry = HeNEXT(entry);
+           if (i && !*oentry)
+               xhv->xhv_fill--;
+           Safefree(HeKEY_hk(entry));
+           del_he(entry);
+           --xhv->xhv_keys;
        }
+       break;
     }
-
-    ++HeVAL(entry);                            /* use value slot as REFCNT */
-    return HeKEY(entry);
+    
+    if (!found)
+       warn("Attempt to free non-existent shared string");    
 }
 
-/* possibly free a shared string if no one has access to it
+/* get a (constant) string ptr from the global string table
+ * string will get added if it is not already there.
  * len and hash must both be valid for str.
  */
-void
-unsharepvn(str, len, hash)
+HEK *
+share_hek(str, len, hash)
 char *str;
 I32 len;
 register U32 hash;
@@ -1038,16 +1072,16 @@ register U32 hash;
     register HE **oentry;
     register I32 i = 1;
     I32 found = 0;
-    
+
     /* what follows is the moral equivalent of:
-    if ((Svp = hv_fetch(strtab, tmpsv, FALSE, hash))) {
-       if (--*Svp == Nullsv)
-           hv_delete(strtab, str, len, G_DISCARD, hash);
-    } */
+       
+    if (!(Svp = hv_fetch(strtab, str, len, FALSE)))
+       hv_store(strtab, str, len, Nullsv, hash);
+    */
     xhv = (XPVHV*)SvANY(strtab);
     /* assert(xhv_array != 0) */
     oentry = &((HE**)xhv->xhv_array)[hash & (I32) xhv->xhv_max];
-    for (entry = *oentry; entry; i=0, oentry = &HeNEXT(entry), entry = *oentry) {
+    for (entry = *oentry; entry; i=0, entry = HeNEXT(entry)) {
        if (HeHASH(entry) != hash)              /* strings can't be equal */
            continue;
        if (HeKLEN(entry) != len)
@@ -1055,18 +1089,24 @@ register U32 hash;
        if (memcmp(HeKEY(entry),str,len))               /* is this it? */
            continue;
        found = 1;
-       if (--HeVAL(entry) == Nullsv) {
-           *oentry = HeNEXT(entry);
-           if (i && !*oentry)
-               xhv->xhv_fill--;
-           Safefree(HeKEY(entry));
-           del_he(entry);
-           --xhv->xhv_keys;
-       }
        break;
     }
-    
-    if (!found)
-       warn("Attempt to free non-existent shared string");    
+    if (!found) {
+       entry = new_he();
+       HeKEY_hk(entry) = save_hek(str, len, hash);
+       HeVAL(entry) = Nullsv;
+       HeNEXT(entry) = *oentry;
+       *oentry = entry;
+       xhv->xhv_keys++;
+       if (i) {                                /* initial entry? */
+           ++xhv->xhv_fill;
+           if (xhv->xhv_keys > xhv->xhv_max)
+               hsplit(strtab);
+       }
+    }
+
+    ++HeVAL(entry);                            /* use value slot as REFCNT */
+    return HeKEY_hk(entry);
 }
 
+
diff --git a/hv.h b/hv.h
index 5c41309..746e428 100644 (file)
--- a/hv.h
+++ b/hv.h
@@ -8,13 +8,18 @@
  */
 
 typedef struct he HE;
+typedef struct he_key HEK;
 
 struct he {
     HE         *hent_next;
-    char       *hent_key;
+    HEK                *hent_hk;
     SV         *hent_val;
-    U32                hent_hash;
-    I32                hent_klen;
+};
+
+struct he_key {
+    U32                hk_hash;
+    I32                hk_len;
+    char       hk_key[1];
 };
 
 struct xpvhv {
@@ -84,20 +89,27 @@ struct xpvhv {
 
 #define Nullhe Null(HE*)
 #define HeNEXT(he)             (he)->hent_next
-#define HeKEY(he)              (he)->hent_key
-#define HeKLEN(he)             (he)->hent_klen
+#define HeKEY_hk(he)           (he)->hent_hk
+#define HeKEY(he)              HK_KEY(HeKEY_hk(he))
+#define HeKEY_sv(he)           (*(SV**)HeKEY(he))
+#define HeKLEN(he)             HK_LEN(HeKEY_hk(he))
 #define HeVAL(he)              (he)->hent_val
-#define HeHASH(he)             (he)->hent_hash
-#define HePV(he)               ((he)->hent_klen == HEf_SVKEY) ?                \
-                               SvPV((SV*)((he)->hent_key),na) :                \
-                               (he)->hent_key))
-#define HeSVKEY(he)            (((he)->hent_key &&                             \
-                                 (he)->hent_klen == HEf_SVKEY) ?               \
-                                (SV*)((he)->hent_key) : Nullsv)
-
-#define HeSVKEY_force(he)      ((he)->hent_key ?                               \
-                                (((he)->hent_klen == HEf_SVKEY) ?              \
-                                 (SV*)((he)->hent_key) :                       \
-                                 sv_2mortal(newSVpv((he)->hent_key,            \
-                                                    (he)->hent_klen))) :       \
+#define HeHASH(he)             HK_HASH(HeKEY_hk(he))
+#define HePV(he)               ((HeKLEN(he) == HEf_SVKEY) ?            \
+                                SvPV(HeKEY_sv(he),na) :                \
+                                HeKEY(he))
+#define HeSVKEY(he)            ((HeKEY(he) &&                          \
+                                 HeKLEN(he) == HEf_SVKEY) ?            \
+                                HeKEY_sv(he) : Nullsv)
+
+#define HeSVKEY_force(he)      (HeKEY(he) ?                            \
+                                ((HeKLEN(he) == HEf_SVKEY) ?           \
+                                 HeKEY_sv(he) :                        \
+                                 sv_2mortal(newSVpv(HeKEY(he),         \
+                                                    HeKLEN(he)))) :    \
                                 &sv_undef)
+#define HeSVKEY_set(he,sv)     (HeKEY_sv(he) = sv)
+
+#define HK_LEN(hk)             (hk)->hk_len
+#define HK_KEY(hk)             (hk)->hk_key
+#define HK_HASH(hk)            (hk)->hk_hash
index 33fb2c7..55b5338 100644 (file)
@@ -115,7 +115,6 @@ rightgv
 rs
 runlevel
 sawampersand
-sawi
 sawstudy
 sawvec
 screamfirst
index 5d97956..ea4741f 100644 (file)
@@ -2370,12 +2370,14 @@ sub pasthru {
     my(@m,$key);
 
     my(@pasthru);
+    my($sep) = $Is_VMS ? ',' : '';
+    $sep .= "\\\n\t";
 
     foreach $key (qw(LIBPERL_A LINKTYPE PREFIX OPTIMIZE)){
        push @pasthru, "$key=\"\$($key)\"";
     }
 
-    push @m, "\nPASTHRU = ", join ("\\\n\t", @pasthru), "\n";
+    push @m, "\nPASTHRU = ", join ($sep, @pasthru), "\n";
     join "", @m;
 }
 
index 1a63f21..13383e9 100644 (file)
@@ -6,7 +6,7 @@
 #   Author:  Charles Bailey  bailey@genetics.upenn.edu
 
 package ExtUtils::MM_VMS;
-$ExtUtils::MM_VMS::Revision=$ExtUtils::MM_VMS::Revision = '5.38 (22-Oct-1996)';
+$ExtUtils::MM_VMS::Revision=$ExtUtils::MM_VMS::Revision = '5.38 (19-Nov-1996)';
 unshift @MM::ISA, 'ExtUtils::MM_VMS';
 
 use Config;
@@ -162,6 +162,30 @@ sub catfile {
     $rslt;
 }
 
+=item wraplist
+
+Converts a list into a string wrapped at approximately 80 columns.
+
+=cut
+
+sub wraplist {
+    my($self) = shift;
+    my($line,$hlen) = ('',0);
+    my($word);
+
+    foreach $word (@_) {
+      # Perl bug -- seems to occasionally insert extra elements when
+      # traversing array (scalar(@array) doesn't show them, but
+      # foreach(@array) does) (5.00307)
+      next unless $word =~ /\w/;
+      $line .= ', ' if length($line);
+      if ($hlen > 80) { $line .= "\\\n\t"; $hlen = 0; }
+      $line .= $word;
+      $hlen += length($word) + 2;
+    }
+    $line;
+}
+
 =item curdir (override)
 
 Returns a string representing of the current directory.
@@ -428,7 +452,7 @@ sub path {
 Follows VMS naming conventions for executable files.
 If the name passed in doesn't exactly match an executable file,
 appends F<.Exe> to check for executable image, and F<.Com> to check
-for DCL procedure.  If this fails, checks F<Sys$Share:> for an
+for DCL procedure.  If this fails, checks F<Sys$System:> for an
 executable file having the name specified.  Finally, appends F<.Exe>
 and checks again.
 
@@ -440,7 +464,7 @@ sub maybe_command {
     return "$file.exe" if -x "$file.exe";
     return "$file.com" if -x "$file.com";
     if ($file !~ m![/:>\]]!) {
-       my($shrfile) = 'Sys$Share:' . $file;
+       my($shrfile) = 'Sys$System:' . $file;
        return $file if -x $shrfile && ! -d _;
        return "$file.exe" if -x "$shrfile.exe";
     }
@@ -506,6 +530,8 @@ Checks for VMS directory spec as well as Unix separators.
 
 sub file_name_is_absolute {
     my($self,$file) = @_;
+    # If it's a logical name, expand it.
+    $file = $ENV{$file} while $file =~ /^[\w\$\-]+$/ and $ENV{$file};
     $file =~ m!^/! or $file =~ m![<\[][^.\-\]>]! or $file =~ /:[^<\[]/;
 }
 
@@ -571,7 +597,7 @@ sub constants {
 
     if ($self->{OBJECT} =~ /\s/) {
        $self->{OBJECT} =~ s/(\\)?\n+\s+/ /g;
-       $self->{OBJECT} = map($self->fixpath($_),split(/,?\s+/,$self->{OBJECT}));
+       $self->{OBJECT} = join(' ',map($self->fixpath($_),split(/,?\s+/,$self->{OBJECT})));
     }
     $self->{LDFROM} = join(' ',map($self->fixpath($_),split(/,?\s+/,$self->{LDFROM})));
 
@@ -665,12 +691,12 @@ MM_VMS_REVISION = $ExtUtils::MM_VMS::Revision
     push @m,'
 
 # Handy lists of source code files:
-XS_FILES = ',join(', ', sort keys %{$self->{XS}}),'
-C_FILES  = ',join(', ', @{$self->{C}}),'
-O_FILES  = ',join(', ', @{$self->{O_FILES}} ),'
-H_FILES  = ',join(', ', @{$self->{H}}),'
-MAN1PODS = ',join(', ', sort keys %{$self->{MAN1PODS}}),'
-MAN3PODS = ',join(', ', sort keys %{$self->{MAN3PODS}}),'
+XS_FILES = ',$self->wraplist(', ', sort keys %{$self->{XS}}),'
+C_FILES  = ',$self->wraplist(', ', @{$self->{C}}),'
+O_FILES  = ',$self->wraplist(', ', @{$self->{O_FILES}} ),'
+H_FILES  = ',$self->wraplist(', ', @{$self->{H}}),'
+MAN1PODS = ',$self->wraplist(', ', sort keys %{$self->{MAN1PODS}}),'
+MAN3PODS = ',$self->wraplist(', ', sort keys %{$self->{MAN3PODS}}),'
 
 ';
 
@@ -714,9 +740,9 @@ PERL_ARCHIVE = ',($ENV{'PERLSHR'} ? $ENV{'PERLSHR'} : 'Sys$Share:PerlShr.Exe'),'
     $self->{TO_INST_PM} = [ sort keys %{$self->{PM}} ];
     $self->{PM_TO_BLIB} = [ %{$self->{PM}} ];
     push @m,'
-TO_INST_PM = ',join(', ',@{$self->{TO_INST_PM}}),'
+TO_INST_PM = ',$self->wraplist(', ',@{$self->{TO_INST_PM}}),'
 
-PM_TO_BLIB = ',join(', ',@{$self->{PM_TO_BLIB}}),'
+PM_TO_BLIB = ',$self->wraplist(', ',@{$self->{PM_TO_BLIB}}),'
 ';
 
     join('',@m);
@@ -1416,9 +1442,7 @@ qq[POD2MAN_EXE = $pod2man_exe\n],
 q[POD2MAN = $(PERL) -we "%m=@ARGV;for (keys %m){" -
 -e "system(""MCR $^X $(POD2MAN_EXE) $_ >$m{$_}"");}"
 ];
-    push @m, "\nmanifypods : ";
-    push @m, join " ", keys %{$self->{MAN1PODS}}, keys %{$self->{MAN3PODS}};
-    push(@m,"\n");
+    push @m, "\nmanifypods : \$(MAN1PODS) \$(MAN3PODS)\n";
     if (%{$self->{MAN1PODS}} || %{$self->{MAN3PODS}}) {
        my($pod);
        foreach $pod (sort keys %{$self->{MAN1PODS}}) {
@@ -1444,12 +1468,14 @@ sub processPL {
     return "" unless $self->{PL_FILES};
     my(@m, $plfile);
     foreach $plfile (sort keys %{$self->{PL_FILES}}) {
+       my $vmsplfile = vmsify($plfile);
+       my $vmsfile = vmsify($self->{PL_FILES}->{$plfile});
        push @m, "
-all :: $self->{PL_FILES}->{$plfile}
+all :: $vmsfile
        \$(NOECHO) \$(NOOP)
 
-$self->{PL_FILES}->{$plfile} :: $plfile
-",'    $(PERL) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" '," $plfile
+$vmsfile :: $vmsplfile
+",'    $(PERL) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" '," $vmsplfile
 ";
     }
     join "", @m;
@@ -1468,16 +1494,17 @@ sub installbin {
     return '' unless $self->{EXE_FILES} && ref $self->{EXE_FILES} eq "ARRAY";
     return '' unless @{$self->{EXE_FILES}};
     my(@m, $from, $to, %fromto, @to, $line);
-    for $from (@{$self->{EXE_FILES}}) {
+    my(@exefiles) = map { vmsify($_) } @{$self->{EXE_FILES}};
+    for $from (@exefiles) {
        my($path) = '$(INST_SCRIPT)' . basename($from);
        local($_) = $path;  # backward compatibility
        $to = $self->libscan($path);
        print "libscan($from) => '$to'\n" if ($Verbose >=2);
-       $fromto{$from}=$to;
+       $fromto{$from} = vmsify($to);
     }
-    @to   = values %fromto;
+    @to = values %fromto;
     push @m, "
-EXE_FILES = @{$self->{EXE_FILES}}
+EXE_FILES = @exefiles
 
 all :: @to
        \$(NOECHO) \$(NOOP)
@@ -1745,11 +1772,11 @@ sub install {
        foreach $file (@{$self->{EXE_FILES}}) {
            $line .= "$file ";
            if (length($line) > 128) {
-               push(@docfiles,qq[\t\$(PERL) -e "print $line" >>.MM_tmp\n]);
+               push(@docfiles,qq[\t\$(PERL) -e "print '$line'" >>.MM_tmp\n]);
                $line = '';
            }
        }
-       push(@docfiles,qq[\t\$(PERL) -e "print $line" >>.MM_tmp\n]) if $line;
+       push(@docfiles,qq[\t\$(PERL) -e "print '$line'" >>.MM_tmp\n]) if $line;
     }
 
     push @m, q[
index 027c1fe..f6da518 100644 (file)
@@ -299,7 +299,7 @@ sub full_setup {
     # we will use all these variables in the Makefile
     @Get_from_Config = 
        qw(
-          ar cc cccdlflags ccdlflags ccflags dlext dlsrc ld lddlflags ldflags libc
+          ar cc cccdlflags ccdlflags dlext dlsrc ld lddlflags ldflags libc
           lib_ext obj_ext ranlib sitelibexp sitearchexp so
          );
 
@@ -430,8 +430,12 @@ sub ExtUtils::MakeMaker::new {
        for $key (keys %Prepend_dot_dot) {
            next unless defined $self->{PARENT}{$key};
            $self->{$key} = $self->{PARENT}{$key};
+               # PERL and FULLPERL may be command verbs instead of full
+               # file specifications under VMS.  If so, don't turn them
+               # into a filespec.
            $self->{$key} = $self->catdir("..",$self->{$key})
-               unless $self->file_name_is_absolute($self->{$key});
+               unless $self->file_name_is_absolute($self->{$key})
+               || ($^O eq 'VMS' and ($key =~ /PERL$/ && $self->{key} =~ /^[\w\-\$]$/));
        }
        $self->{PARENT}->{CHILDREN}->{$newclass} = $self if $self->{PARENT};
     } else {
@@ -554,10 +558,10 @@ sub parse_args{
                 ]ex;
        }
        # This may go away, in mid 1996
-       if ($self->{Correct_relativ_directories}){
-           $value = $self->catdir("..",$value)
-               if $Prepend_dot_dot{$name} && ! $self->file_name_is_absolute($value);
-       }
+#      if ($self->{Correct_relativ_directories}){
+#          $value = $self->catdir("..",$value)
+#              if $Prepend_dot_dot{$name} && ! $self->file_name_is_absolute($value);
+#      }
        $self->{uc($name)} = $value;
     }
     # This may go away, in mid 1996
index 8d775d5..62f3b50 100644 (file)
@@ -131,9 +131,13 @@ sub rmtree {
        $root =~ s#/$##;
        if (not -l $root and -d _) { 
            opendir(D,$root);
-           ($root = VMS::Filespec::unixify($root)) =~ s#\.dir$## if $Is_VMS;
-           @files = map("$root/$_", grep $_!~/^\.{1,2}$/, readdir(D));
+           @files = readdir(D);
            closedir(D);
+           # Deleting large numbers of files from VMS Files-11 filesystems
+           # is faster if done in reverse ASCIIbetical order 
+           @files = reverse @files if $Is_VMS;
+           ($root = VMS::Filespec::unixify($root)) =~ s#\.dir$## if $Is_VMS;
+           @files = map("$root/$_", grep $_!~/^\.{1,2}$/,@files);
            $count += rmtree(\@files,$verbose,$safe);
            if ($safe &&
                ($Is_VMS ? !&VMS::Filespec::candelete($root) : !-w $root)) {
diff --git a/lib/locale.pm b/lib/locale.pm
new file mode 100644 (file)
index 0000000..48213ab
--- /dev/null
@@ -0,0 +1,33 @@
+package locale;
+
+=head1 NAME
+
+locale - Perl pragma to use and avoid POSIX locales for built-in operations
+
+=head1 SYNOPSIS
+
+    @x = sort @y;      # ASCII sorting order
+    {
+        use locale;
+        @x = sort @y;   # Locale-defined sorting order
+    }
+    @x = sort @y;      # ASCII sorting order again
+
+=head1 DESCRIPTION
+
+This pragma tells the compiler to enable (or disable) the use of POSIX
+locales for built-in operations (LC_CTYPE for regular expressions, and
+LC_COLLATE for string comparison).  Each "use locale" or "no locale"
+affects statements to the end of the enclosing BLOCK.
+
+=cut
+
+sub import {
+    $^H |= 0x800;
+}
+
+sub unimport {
+    $^H &= ~0x800;
+}
+
+1;
index 042c233..170ae3e 100644 (file)
--- a/malloc.c
+++ b/malloc.c
@@ -193,11 +193,11 @@ emergency_sbrk(size)
            return (char *)-1;          /* Now die die die... */
 
        /* Got it, now detach SvPV: */
-       pv = SvPV(sv);
+       pv = SvPV(sv, na);
        /* Check alignment: */
        if ((pv - M_OVERHEAD) & (1<<11 - 1)) {
            PerlIO_puts(PerlIO_stderr(),"Bad alignment of $^M!\n");
-           return -1;                  /* die die die */
+           return (char *)-1;          /* die die die */
        }
 
        emergency_buffer = pv - M_OVERHEAD;
@@ -362,7 +362,7 @@ morecore(bucket)
        register union overhead *op;
        register int rnu;       /* 2^rnu bytes will be requested */
        register int nblks;     /* become nblks blocks of the desired size */
-       register MEM_SIZE siz;
+       register MEM_SIZE siz, needed;
        int slack = 0;
 
        if (nextf[bucket])
@@ -402,15 +402,11 @@ morecore(bucket)
        rnu = (bucket <= 11) ? 14 : bucket + 3;
 #endif
        nblks = 1 << (rnu - (bucket + 3));  /* how many blocks to get */
-       /* if (rnu < bucket)
-               rnu = bucket;   Why anyone needs this? */
+       needed = (MEM_SIZE)1 << rnu;
 #ifdef TWO_POT_OPTIMIZE
-       op = (union overhead *)sbrk((1L << rnu) 
-                                   + ( bucket >= (FIRST_BIG_TWO_POT - 3) 
-                                       ? PERL_PAGESIZE : 0));
-#else
-       op = (union overhead *)sbrk(1L << rnu);
+       needed += (bucket >= (FIRST_BIG_TWO_POT - 3) ? PERL_PAGESIZE : 0);
 #endif 
+       op = (union overhead *)sbrk(needed);
        /* no more room! */
        if ((int)op == -1 &&
            (int)(op = (union overhead *)emergency_sbrk(size)) == -1)
diff --git a/mg.c b/mg.c
index c2a006b..8c678f4 100644 (file)
--- a/mg.c
+++ b/mg.c
 #  endif
 #endif
 
+#define TAINT_FROM_REGEX(sv,rx) \
+       if ((rx)->exec_tainted) {       \
+           SvTAINTED_on(sv);           \
+       } else                          \
+           SvTAINTED_off(sv);
+
 /*
  * Use the "DESTRUCTOR" scope cleanup to reinstate magic.
  */
@@ -269,28 +275,31 @@ MAGIC *mg;
     register I32 paren;
     register char *s;
     register I32 i;
+    register REGEXP *rx;
     char *t;
 
     switch (*mg->mg_ptr) {
     case '1': case '2': case '3': case '4':
     case '5': case '6': case '7': case '8': case '9': case '&':
-       if (curpm) {
+       if (curpm && (rx = curpm->op_pmregexp)) {
            paren = atoi(mg->mg_ptr);
          getparen:
-           if (curpm->op_pmregexp &&
-             paren <= curpm->op_pmregexp->nparens &&
-             (s = curpm->op_pmregexp->startp[paren]) &&
-             (t = curpm->op_pmregexp->endp[paren]) ) {
+           if (paren <= rx->nparens &&
+               (s = rx->startp[paren]) &&
+               (t = rx->endp[paren]))
+           {
                i = t - s;
-               if (i >= 0)
+               if (i >= 0) {
+                   TAINT_IF(rx->exec_tainted);
                    return i;
+               }
            }
        }
        return 0;
        break;
     case '+':
-       if (curpm) {
-           paren = curpm->op_pmregexp->lastparen;
+       if (curpm && (rx = curpm->op_pmregexp)) {
+           paren = rx->lastparen;
            if (!paren)
                return 0;
            goto getparen;
@@ -298,20 +307,21 @@ MAGIC *mg;
        return 0;
        break;
     case '`':
-       if (curpm) {
-           if (curpm->op_pmregexp &&
-             (s = curpm->op_pmregexp->subbeg) ) {
-               i = curpm->op_pmregexp->startp[0] - s;
-               if (i >= 0)
+       if (curpm && (rx = curpm->op_pmregexp)) {
+           if ((s = rx->subbeg)) {
+               i = rx->startp[0] - s;
+               if (i >= 0) {
+                   TAINT_IF(rx->exec_tainted);
                    return i;
+               }
            }
        }
        return 0;
     case '\'':
-       if (curpm) {
-           if (curpm->op_pmregexp &&
-             (s = curpm->op_pmregexp->endp[0]) ) {
-               return (STRLEN) (curpm->op_pmregexp->subend - s);
+       if (curpm && (rx = curpm->op_pmregexp)) {
+           if ((s = rx->endp[0])) {
+               TAINT_IF(rx->exec_tainted);
+               return (STRLEN) (rx->subend - s);
            }
        }
        return 0;
@@ -336,6 +346,7 @@ MAGIC *mg;
     register I32 paren;
     register char *s;
     register I32 i;
+    register REGEXP *rx;
     char *t;
 
     switch (*mg->mg_ptr) {
@@ -399,19 +410,17 @@ MAGIC *mg;
        break;
     case '1': case '2': case '3': case '4':
     case '5': case '6': case '7': case '8': case '9': case '&':
-       if (curpm) {
+       if (curpm && (rx = curpm->op_pmregexp)) {
            paren = atoi(GvENAME((GV*)mg->mg_obj));
          getparen:
-           if (curpm->op_pmregexp &&
-             paren <= curpm->op_pmregexp->nparens &&
-             (s = curpm->op_pmregexp->startp[paren]) &&
-             (t = curpm->op_pmregexp->endp[paren]) ) {
+           if (paren <= rx->nparens &&
+               (s = rx->startp[paren]) &&
+               (t = rx->endp[paren]))
+           {
                i = t - s;
                if (i >= 0) {
-                   MAGIC *tmg;
                    sv_setpvn(sv,s,i);
-                   if (tainting && (tmg = mg_find(sv,'t')))
-                       tmg->mg_len = 0;        /* guarantee $1 untainted */
+                   TAINT_FROM_REGEX(sv,rx);
                    break;
                }
            }
@@ -419,20 +428,20 @@ MAGIC *mg;
        sv_setsv(sv,&sv_undef);
        break;
     case '+':
-       if (curpm) {
-           paren = curpm->op_pmregexp->lastparen;
+       if (curpm && (rx = curpm->op_pmregexp)) {
+           paren = rx->lastparen;
            if (paren)
                goto getparen;
        }
        sv_setsv(sv,&sv_undef);
        break;
     case '`':
-       if (curpm) {
-           if (curpm->op_pmregexp &&
-             (s = curpm->op_pmregexp->subbeg) ) {
-               i = curpm->op_pmregexp->startp[0] - s;
+       if (curpm && (rx = curpm->op_pmregexp)) {
+           if ((s = rx->subbeg)) {
+               i = rx->startp[0] - s;
                if (i >= 0) {
                    sv_setpvn(sv,s,i);
+                   TAINT_FROM_REGEX(sv,rx);
                    break;
                }
            }
@@ -440,10 +449,10 @@ MAGIC *mg;
        sv_setsv(sv,&sv_undef);
        break;
     case '\'':
-       if (curpm) {
-           if (curpm->op_pmregexp &&
-             (s = curpm->op_pmregexp->endp[0]) ) {
-               sv_setpvn(sv,s, curpm->op_pmregexp->subend - s);
+       if (curpm && (rx = curpm->op_pmregexp)) {
+           if ((s = rx->endp[0])) {
+               sv_setpvn(sv,s, rx->subend - s);
+               TAINT_FROM_REGEX(sv,rx);
                break;
            }
        }
@@ -1106,10 +1115,8 @@ magic_gettaint(sv,mg)
 SV* sv;
 MAGIC* mg;
 {
-    if (mg->mg_len & 1)
-       tainted = TRUE;
-    else if (mg->mg_len & 2 && mg->mg_obj == sv)       /* kludge */
-       tainted = TRUE;
+    TAINT_IF((mg->mg_len & 1) ||
+            (mg->mg_len & 2) && mg->mg_obj == sv);     /* kludge */
     return 0;
 }
 
@@ -1183,6 +1190,19 @@ MAGIC* mg;
 }
 
 int
+magic_setcollxfrm(sv,mg)
+SV* sv;
+MAGIC* mg;
+{
+    /*
+     * René Descartes said "I think not."
+     * and vanished with a faint plop.
+     */
+    sv_unmagic(sv, 'o');
+    return 0;
+}
+
+int
 magic_set(sv,mg)
 SV* sv;
 MAGIC* mg;
@@ -1436,7 +1456,8 @@ MAGIC* mg;
                if (origargv[i] == s + 1)
                    s += strlen(++s);   /* this one is ok too */
            }
-           if (origenviron[0] == s + 1) {      /* can grab env area too? */
+           /* can grab env area too? */
+           if (origenviron && origenviron[0] == s + 1) {
                my_setenv("NoNeSuCh", Nullch);
                                            /* force copy of environment */
                for (i = 0; origenviron[i]; i++)
diff --git a/op.c b/op.c
index a73e429..8527ccc 100644 (file)
--- a/op.c
+++ b/op.c
@@ -41,7 +41,7 @@ static OP *scalarboolean _((OP *op));
 static OP *too_few_arguments _((OP *op, char* name));
 static OP *too_many_arguments _((OP *op, char* name));
 static void null _((OP* op));
-static PADOFFSET pad_findlex _((char* name, PADOFFSET newoff, I32 seq,
+static PADOFFSET pad_findlex _((char* name, PADOFFSET newoff, U32 seq,
        CV* startcv, I32 cx_ix));
 
 static char*
@@ -120,8 +120,8 @@ char *name;
     SV *sv;
 
     if (!(isALPHA(name[1]) || name[1] == '_' && (int)strlen(name) > 2)) {
-       if (!isprint(name[1]))
-           sprintf(name+1, "^%c", name[1] ^ 64); /* XXX is tokenbuf, really */
+       if (!isPRINT(name[1]))
+           sprintf(name+1, "^%c", toCTRL(name[1])); /* XXX tokenbuf, really */
        croak("Can't use global %s in \"my\"",name);
     }
     if (AvFILL(comppad_name) >= 0) {
@@ -160,11 +160,11 @@ static PADOFFSET
 pad_findlex(name, newoff, seq, startcv, cx_ix)
 char *name;
 PADOFFSET newoff;
-I32 seq;
+U32 seq;
 CV* startcv;
 I32 cx_ix;
 #else
-pad_findlex(char *name, PADOFFSET newoff, I32 seq, CV* startcv, I32 cx_ix)
+pad_findlex(char *name, PADOFFSET newoff, U32 seq, CV* startcv, I32 cx_ix)
 #endif
 {
     CV *cv;
@@ -253,7 +253,7 @@ char *name;
     I32 off;
     SV *sv;
     SV **svp = AvARRAY(comppad_name);
-    I32 seq = cop_seqmax;
+    U32 seq = cop_seqmax;
 
     /* The one we're looking for is probably just before comppad_name_fill. */
     for (off = AvFILL(comppad_name); off > 0; off--) {
@@ -314,9 +314,21 @@ U32 tmptype;
        retval = AvFILL(comppad);
     }
     else {
-       do {
-           sv = *av_fetch(comppad, ++padix, TRUE);
-       } while (SvFLAGS(sv) & (SVs_PADTMP|SVs_PADMY));
+       SV **names = AvARRAY(comppad_name);
+       SSize_t names_fill = AvFILL(comppad_name);
+       for (;;) {
+           /*
+            * "foreach" index vars temporarily become aliases to non-"my"
+            * values.  Thus we must skip, not just pad values that are
+            * marked as current pad values, but also those with names.
+            */
+           if (++padix <= names_fill &&
+                  (sv = names[padix]) && sv != &sv_undef)
+               continue;
+           sv = *av_fetch(comppad, padix, TRUE);
+           if (!(SvFLAGS(sv) & (SVs_PADTMP|SVs_PADMY)))
+               break;
+       }
        retval = padix;
     }
     SvFLAGS(sv) |= tmptype;
@@ -1307,6 +1319,7 @@ OP* seq;
     if (needblockscope)
        hints |= HINT_BLOCK_SCOPE; /* propagate out */
     pad_leavemy(comppad_name_fill);
+    cop_seqmax++;
     return retval;
 }
 
@@ -2302,23 +2315,9 @@ I32 flags;
 char *label;
 OP *op;
 {
+    U32 seq = intro_my();
     register COP *cop;
 
-    /* Introduce my variables. */
-    if (min_intro_pending) {
-       SV **svp = AvARRAY(comppad_name);
-       I32 i;
-       SV *sv;
-       for (i = min_intro_pending; i <= max_intro_pending; i++) {
-           if ((sv = svp[i]) && sv != &sv_undef && !SvIVX(sv)) {
-               SvIVX(sv) = 999999999;  /* Don't know scope end yet. */
-               SvNVX(sv) = (double)cop_seqmax;
-           }
-       }
-       min_intro_pending = 0;
-       comppad_name_fill = max_intro_pending;  /* Needn't search higher */
-    }
-
     Newz(1101, cop, 1, COP);
     if (perldb && curcop->cop_line && curstash != debstash) {
        cop->op_type = OP_DBSTATE;
@@ -2336,7 +2335,7 @@ OP *op;
        cop->cop_label = label;
        hints |= HINT_BLOCK_SCOPE;
     }
-    cop->cop_seq = cop_seqmax++;
+    cop->cop_seq = seq;
     cop->cop_arybase = curcop->cop_arybase;
 
     if (copline == NOLINE)
@@ -2360,6 +2359,29 @@ OP *op;
     return prepend_elem(OP_LINESEQ, (OP*)cop, op);
 }
 
+/* "Introduce" my variables to visible status. */
+U32
+intro_my()
+{
+    SV **svp;
+    SV *sv;
+    I32 i;
+
+    if (! min_intro_pending)
+       return cop_seqmax;
+
+    svp = AvARRAY(comppad_name);
+    for (i = min_intro_pending; i <= max_intro_pending; i++) {
+       if ((sv = svp[i]) && sv != &sv_undef && !SvIVX(sv)) {
+           SvIVX(sv) = 999999999;      /* Don't know scope end yet. */
+           SvNVX(sv) = (double)cop_seqmax;
+       }
+    }
+    min_intro_pending = 0;
+    comppad_name_fill = max_intro_pending;     /* Needn't search higher */
+    return cop_seqmax++;
+}
+
 OP *
 newLOGOP(type, flags, first, other)
 I32 type;
@@ -3458,13 +3480,6 @@ register OP *op;
 }
 
 OP *
-ck_formline(op)
-OP *op;
-{
-    return ck_fun(op);
-}
-
-OP *
 ck_ftst(op)
 OP *op;
 {
@@ -3713,7 +3728,7 @@ OP *op;
     if (op->op_flags & OPf_KIDS) {
        OP *kid = cLISTOP->op_first->op_sibling;        /* get past pushmark */
        if (kid && kid->op_type == OP_CONST)
-           fbm_compile(((SVOP*)kid)->op_sv, 0);
+           fbm_compile(((SVOP*)kid)->op_sv);
     }
     return ck_fun(op);
 }
@@ -3768,7 +3783,42 @@ OP *op;
     if (!kid)
        append_elem(op->op_type, op, newSVREF(newGVOP(OP_GV, 0, defgv)) );
 
-    return listkids(op);
+    op = listkids(op);
+
+    op->op_private = 0;
+#ifdef HAS_SETLOCALE
+    if (hints & HINT_LOCALE)
+       op->op_private |= OPpLOCALE;
+#endif
+
+    return op;
+}
+
+OP *
+ck_fun_locale(op)
+OP *op;
+{
+    op = ck_fun(op);
+
+    op->op_private = 0;
+#ifdef HAS_SETLOCALE
+    if (hints & HINT_LOCALE)
+       op->op_private |= OPpLOCALE;
+#endif
+
+    return op;
+}
+
+OP *
+ck_scmp(op)
+OP *op;
+{
+    op->op_private = 0;
+#ifdef LC_COLLATE
+    if (hints & HINT_LOCALE)
+       op->op_private |= OPpLOCALE;
+#endif
+    return op;
 }
 
 OP *
@@ -3873,6 +3923,12 @@ OP *
 ck_sort(op)
 OP *op;
 {
+    op->op_private = 0;
+#ifdef LC_COLLATE
+    if (hints & HINT_LOCALE)
+       op->op_private |= OPpLOCALE;
+#endif
+
     if (op->op_flags & OPf_STACKED) {
        OP *kid = cLISTOP->op_first->op_sibling;        /* get past pushmark */
        OP *k;
@@ -3909,6 +3965,7 @@ OP *op;
            op->op_flags |= OPf_SPECIAL;
        }
     }
+
     return op;
 }
 
diff --git a/op.h b/op.h
index 7c210bc..eb26f9c 100644 (file)
--- a/op.h
+++ b/op.h
@@ -103,6 +103,9 @@ typedef U32 PADOFFSET;
 /* Private for OP_LEAVE and friends */
 #define OPpLEAVE_VOID          64      /* No need to copy out values. */
 
+/* Private for OP_SORT, OP_PRTF, OP_SPRINTF, string cmp'n, and case changers */
+#define OPpLOCALE              64      /* Use locale */
+
 struct op {
     BASEOP
 };
@@ -167,7 +170,7 @@ struct pmop {
 #define PMf_WHITE      0x0800          /* pattern is \s+ */
 #define PMf_MULTILINE  0x1000          /* assume multiple lines */
 #define PMf_SINGLELINE 0x2000          /* assume single line */
-#define PMf_UNUSED     0x4000          /* (unused) */
+#define PMf_LOCALE     0x4000          /* use locale for character types */
 #define PMf_EXTENDED   0x8000          /* chuck embedded whitespace */
 
 struct svop {
index c4902ef..97b3034 100644 (file)
--- a/opcode.h
+++ b/opcode.h
@@ -1058,9 +1058,9 @@ OP *      ck_delete       _((OP* op));
 OP *   ck_eof          _((OP* op));
 OP *   ck_eval         _((OP* op));
 OP *   ck_exec         _((OP* op));
-OP *   ck_formline     _((OP* op));
 OP *   ck_ftst         _((OP* op));
 OP *   ck_fun          _((OP* op));
+OP *   ck_fun_locale   _((OP* op));
 OP *   ck_glob         _((OP* op));
 OP *   ck_grep         _((OP* op));
 OP *   ck_index        _((OP* op));
@@ -1073,6 +1073,7 @@ OP *      ck_repeat       _((OP* op));
 OP *   ck_require      _((OP* op));
 OP *   ck_rfun         _((OP* op));
 OP *   ck_rvconst      _((OP* op));
+OP *   ck_scmp         _((OP* op));
 OP *   ck_select       _((OP* op));
 OP *   ck_shift        _((OP* op));
 OP *   ck_sort         _((OP* op));
@@ -1862,13 +1863,13 @@ EXT OP * (*check[]) _((OP *op)) = {
        ck_null,        /* i_ne */
        ck_null,        /* ncmp */
        ck_null,        /* i_ncmp */
-       ck_null,        /* slt */
-       ck_null,        /* sgt */
-       ck_null,        /* sle */
-       ck_null,        /* sge */
-       ck_null,        /* seq */
-       ck_null,        /* sne */
-       ck_null,        /* scmp */
+       ck_scmp,        /* slt */
+       ck_scmp,        /* sgt */
+       ck_scmp,        /* sle */
+       ck_scmp,        /* sge */
+       ck_scmp,        /* seq */
+       ck_scmp,        /* sne */
+       ck_scmp,        /* scmp */
        ck_bitop,       /* bit_and */
        ck_bitop,       /* bit_xor */
        ck_bitop,       /* bit_or */
@@ -1893,15 +1894,15 @@ EXT OP * (*check[]) _((OP *op)) = {
        ck_fun,         /* vec */
        ck_index,       /* index */
        ck_index,       /* rindex */
-       ck_fun,         /* sprintf */
-       ck_formline,    /* formline */
+       ck_fun_locale,  /* sprintf */
+       ck_fun,         /* formline */
        ck_fun,         /* ord */
        ck_fun,         /* chr */
        ck_fun,         /* crypt */
-       ck_fun,         /* ucfirst */
-       ck_fun,         /* lcfirst */
-       ck_fun,         /* uc */
-       ck_fun,         /* lc */
+       ck_fun_locale,  /* ucfirst */
+       ck_fun_locale,  /* lcfirst */
+       ck_fun_locale,  /* uc */
+       ck_fun_locale,  /* lc */
        ck_fun,         /* quotemeta */
        ck_rvconst,     /* rv2av */
        ck_null,        /* aelemfast */
index 93fcbd7..d679d8a 100755 (executable)
--- a/opcode.pl
+++ b/opcode.pl
@@ -296,13 +296,13 @@ i_ne              integer ne              ck_null         ifs     S S
 ncmp           spaceship operator      ck_null         Iifst   S S
 i_ncmp         integer spaceship       ck_null         ifst    S S
 
-slt            string lt               ck_null         ifs     S S
-sgt            string gt               ck_null         ifs     S S
-sle            string le               ck_null         ifs     S S
-sge            string ge               ck_null         ifs     S S
-seq            string eq               ck_null         ifs     S S
-sne            string ne               ck_null         ifs     S S
-scmp           string comparison       ck_null         ifst    S S
+slt            string lt               ck_scmp         ifs     S S
+sgt            string gt               ck_scmp         ifs     S S
+sle            string le               ck_scmp         ifs     S S
+sge            string ge               ck_scmp         ifs     S S
+seq            string eq               ck_scmp         ifs     S S
+sne            string ne               ck_scmp         ifs     S S
+scmp           string comparison       ck_scmp         ifst    S S
 
 bit_and                bitwise and             ck_bitop        fst     S S
 bit_xor                bitwise xor             ck_bitop        fst     S S
@@ -338,15 +338,15 @@ vec               vec                     ck_fun          ist     S S S
 index          index                   ck_index        ist     S S S?
 rindex         rindex                  ck_index        ist     S S S?
 
-sprintf                sprintf                 ck_fun          mst     S L
-formline       formline                ck_formline     ms      S L
+sprintf                sprintf                 ck_fun_locale   mst     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          fstu    S?
-lcfirst                lower case first        ck_fun          fstu    S?
-uc             upper case              ck_fun          fstu    S?
-lc             lower case              ck_fun          fstu    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?
 
 # Arrays.
index e1a4da8..8dc52bc 100644 (file)
@@ -1,5 +1,5 @@
 #define PATCHLEVEL 3
-#define SUBVERSION 8
+#define SUBVERSION 9
 
 /*
        local_patches -- list of locally applied less-than-subversion patches.
diff --git a/perl.c b/perl.c
index 9255258..0bb3e8f 100644 (file)
--- a/perl.c
+++ b/perl.c
@@ -35,6 +35,7 @@ dEXT char rcsid[] = "perl.c\nPatch level: ###\n";
 #endif
 
 static void find_beginning _((void));
+static void forbid_setid _((char *));
 static void incpush _((char *));
 static void init_ids _((void));
 static void init_debugger _((void));
@@ -120,6 +121,7 @@ register PerlInterpreter *sv_interp;
 
     init_ids();
 
+    NUMERIC_STANDARD();
 #if defined(SUBVERSION) && SUBVERSION > 0
     sprintf(patchlevel, "%7.5f",   (double) 5 
                                + ((double) PATCHLEVEL / (double) 1000)
@@ -414,7 +416,7 @@ setuid perl scripts securely.\n");
            (void)PerlIO_putc(e_fp,'\n');
            break;
        case 'I':
-           taint_not("-I");
+           forbid_setid("-I");
            sv_catpv(sv,"-");
            sv_catpv(sv,s);
            sv_catpv(sv," ");
@@ -429,12 +431,12 @@ setuid perl scripts securely.\n");
            }
            break;
        case 'P':
-           taint_not("-P");
+           forbid_setid("-P");
            preprocess = TRUE;
            s++;
            goto reswitch;
        case 'S':
-           taint_not("-S");
+           forbid_setid("-S");
            dosearch = TRUE;
            s++;
            goto reswitch;
@@ -1152,7 +1154,7 @@ char *s;
        s++;
        return s;
     case 'd':
-       taint_not("-d");
+       forbid_setid("-d");
        s++;
        if (*s == ':' || *s == '=')  {
            sprintf(buf, "use Devel::%s;", ++s);
@@ -1166,7 +1168,7 @@ char *s;
        return s;
     case 'D':
 #ifdef DEBUGGING
-       taint_not("-D");
+       forbid_setid("-D");
        if (isALPHA(s[1])) {
            static char debopts[] = "psltocPmfrxuLHXD";
            char *d;
@@ -1197,7 +1199,7 @@ char *s;
        *s = '\0';
        break;
     case 'I':
-       taint_not("-I");
+       forbid_setid("-I");
        if (*++s) {
            char *e;
            for (e = s; *e && !isSPACE(*e); e++) ;
@@ -1230,10 +1232,10 @@ char *s;
        }
        return s;
     case 'M':
-       taint_not("-M");        /* XXX ? */
+       forbid_setid("-M");     /* XXX ? */
        /* FALL THROUGH */
     case 'm':
-       taint_not("-m");        /* XXX ? */
+       forbid_setid("-m");     /* XXX ? */
        if (*++s) {
            char *start;
            char *use = "use ";
@@ -1273,7 +1275,7 @@ char *s;
        s++;
        return s;
     case 's':
-       taint_not("-s");
+       forbid_setid("-s");
        doswitches = TRUE;
        s++;
        return s;
@@ -1589,7 +1591,7 @@ sed %s -e \"/^[^#]/b\" \
        rsfp = my_popen(buf,"r");
     }
     else if (!*scriptname) {
-       taint_not("program input from stdin");
+       forbid_setid("program input from stdin");
        rsfp = PerlIO_stdin();
     }
     else {
@@ -1867,7 +1869,7 @@ find_beginning()
 
     /* skip forward in input to the real script? */
 
-    taint_not("-x");
+    forbid_setid("-x");
     while (doextract) {
        if ((s = sv_gets(linestr, rsfp, 0)) == Nullch)
            croak("No Perl script found in input\n");
@@ -1904,6 +1906,16 @@ init_ids()
 }
 
 static void
+forbid_setid(s)
+char *s;
+{
+    if (euid != uid)
+        croak("No %s allowed while running setuid", s);
+    if (egid != gid)
+        croak("No %s allowed while running setgid", s);
+}
+
+static void
 init_debugger()
 {
     curstash = debstash;
@@ -2069,7 +2081,7 @@ register char **env;
     sv_setpvn(bodytarget, "", 0);
     formtarget = bodytarget;
 
-    tainted = 1;
+    TAINT;
     if (tmpgv = gv_fetchpv("0",TRUE, SVt_PV)) {
        sv_setpv(GvSV(tmpgv),origfilename);
        magicname("0", "0", 1);
@@ -2118,10 +2130,9 @@ register char **env;
 #endif
        hv_magic(hv, envgv, 'E');
     }
-    tainted = 0;
+    TAINT_NOT;
     if (tmpgv = gv_fetchpv("$",TRUE, SVt_PV))
        sv_setiv(GvSV(tmpgv),(I32)getpid());
-
 }
 
 static void
diff --git a/perl.h b/perl.h
index a779886..f740c9a 100644 (file)
--- a/perl.h
+++ b/perl.h
 #   define VOL
 #endif
 
-#define TAINT_IF(c)    (tainted |= (c))
-#define TAINT_NOT      (tainted = 0)
-#define TAINT_PROPER(s)        if (tainting) taint_proper(no_security, s)
-#define TAINT_ENV()    if (tainting) taint_env()
+#define TAINT          (tainted = TRUE)
+#define TAINT_NOT      (tainted = FALSE)
+#define TAINT_IF(c)    if (c) { tainted = TRUE; }
+#define TAINT_ENV()    if (tainting) { taint_env(); }
+#define TAINT_PROPER(s)        if (tainting) { taint_proper(no_security, s); }
 
 /* XXX All process group stuff is handled in pp_sys.c.  Should these 
    defines move there?  If so, I could simplify this a lot. --AD  9/96.
@@ -1192,7 +1193,6 @@ EXT char *** environ_pointer;
 #  endif
 #endif /* environ processing */
 
-EXT int                lc_collate_active;
 EXT int                uid;            /* current real user id */
 EXT int                euid;           /* current effective user id */
 EXT int                gid;            /* current real group id */
@@ -1322,8 +1322,10 @@ EXT SV  * psig_ptr[];
 EXT SV  * psig_name[];
 #endif
 
+/* fast case folding tables */
+
 #ifdef DOINIT
-EXT unsigned char fold[] = {   /* fast case folding table */
+EXT const unsigned char fold[] = {
        0,      1,      2,      3,      4,      5,      6,      7,
        8,      9,      10,     11,     12,     13,     14,     15,
        16,     17,     18,     19,     20,     21,     22,     23,
@@ -1362,6 +1364,45 @@ EXT unsigned char fold[];
 #endif
 
 #ifdef DOINIT
+EXT unsigned char fold_locale[] = {
+       0,      1,      2,      3,      4,      5,      6,      7,
+       8,      9,      10,     11,     12,     13,     14,     15,
+       16,     17,     18,     19,     20,     21,     22,     23,
+       24,     25,     26,     27,     28,     29,     30,     31,
+       32,     33,     34,     35,     36,     37,     38,     39,
+       40,     41,     42,     43,     44,     45,     46,     47,
+       48,     49,     50,     51,     52,     53,     54,     55,
+       56,     57,     58,     59,     60,     61,     62,     63,
+       64,     'a',    'b',    'c',    'd',    'e',    'f',    'g',
+       'h',    'i',    'j',    'k',    'l',    'm',    'n',    'o',
+       'p',    'q',    'r',    's',    't',    'u',    'v',    'w',
+       'x',    'y',    'z',    91,     92,     93,     94,     95,
+       96,     'A',    'B',    'C',    'D',    'E',    'F',    'G',
+       'H',    'I',    'J',    'K',    'L',    'M',    'N',    'O',
+       'P',    'Q',    'R',    'S',    'T',    'U',    'V',    'W',
+       'X',    'Y',    'Z',    123,    124,    125,    126,    127,
+       128,    129,    130,    131,    132,    133,    134,    135,
+       136,    137,    138,    139,    140,    141,    142,    143,
+       144,    145,    146,    147,    148,    149,    150,    151,
+       152,    153,    154,    155,    156,    157,    158,    159,
+       160,    161,    162,    163,    164,    165,    166,    167,
+       168,    169,    170,    171,    172,    173,    174,    175,
+       176,    177,    178,    179,    180,    181,    182,    183,
+       184,    185,    186,    187,    188,    189,    190,    191,
+       192,    193,    194,    195,    196,    197,    198,    199,
+       200,    201,    202,    203,    204,    205,    206,    207,
+       208,    209,    210,    211,    212,    213,    214,    215,
+       216,    217,    218,    219,    220,    221,    222,    223,    
+       224,    225,    226,    227,    228,    229,    230,    231,
+       232,    233,    234,    235,    236,    237,    238,    239,
+       240,    241,    242,    243,    244,    245,    246,    247,
+       248,    249,    250,    251,    252,    253,    254,    255
+};
+#else
+EXT unsigned char fold_locale[];
+#endif
+
+#ifdef DOINIT
 EXT unsigned char freq[] = {   /* letter frequencies for mixed English/C */
        1,      2,      84,     151,    154,    155,    156,    157,
        165,    246,    250,    3,      158,    7,      18,     29,
@@ -1439,6 +1480,7 @@ EXT I32           lex_formbrack;  /* bracket count at outer format level */
 EXT I32                lex_fakebrack;  /* outer bracket is mere delimiter */
 EXT I32                lex_casemods;   /* casemod count */
 EXT I32                lex_dojoin;     /* doing an array interpolation */
+EXT I32                lex_endscope;   /* maybe end of scope; defer lexical vars */
 EXT I32                lex_starts;     /* how many interps done on level */
 EXT SV *       lex_stuff;      /* runtime pattern from m// or s/// */
 EXT SV *       lex_repl;       /* runtime replacement from s/// */
@@ -1503,6 +1545,7 @@ EXT U32           hints;          /* various compilation flags */
 #define HINT_BLOCK_SCOPE       0x00000100
 #define HINT_STRICT_SUBS       0x00000200
 #define HINT_STRICT_VARS       0x00000400
+#define HINT_LOCALE            0x00000800
 
 /**************************************************************************/
 /* This regexp stuff is global since it always happens within 1 expr eval */
@@ -1577,7 +1620,6 @@ IEXT bool Idowarn;
 IEXT bool      Idoextract;
 IEXT bool      Isawampersand;  /* must save all match strings */
 IEXT bool      Isawstudy;      /* do fbm_instr on all strings */
-IEXT bool      Isawi;          /* study must assume case insensitive */
 IEXT bool      Isawvec;
 IEXT bool      Iunsafe;
 IEXT char *    Iinplace;
@@ -1765,6 +1807,7 @@ extern "C" {
 /* The following must follow proto.h */
 
 #ifdef DOINIT
+
 EXT MGVTBL vtbl_sv =   {magic_get,
                                magic_set,
                                        magic_len,
@@ -1817,6 +1860,12 @@ EXT MGVTBL vtbl_uvar =   {magic_getuvar,
                                magic_setuvar,
                                        0,      0,      0};
 
+#ifdef LC_COLLATE
+EXT MGVTBL vtbl_collxfrm = {0,
+                               magic_setcollxfrm,
+                                       0,      0,      0};
+#endif
+
 #ifdef OVERLOAD
 EXT MGVTBL vtbl_amagic =       {0,     magic_setamagic,
                                         0,      0,      magic_setamagic};
@@ -1824,7 +1873,8 @@ EXT MGVTBL vtbl_amagicelem =   {0,     magic_setamagic,
                                         0,      0,      magic_setamagic};
 #endif /* OVERLOAD */
 
-#else
+#else /* !DOINIT */
+
 EXT MGVTBL vtbl_sv;
 EXT MGVTBL vtbl_env;
 EXT MGVTBL vtbl_envelem;
@@ -1847,12 +1897,16 @@ EXT MGVTBL vtbl_bm;
 EXT MGVTBL vtbl_fm;
 EXT MGVTBL vtbl_uvar;
 
+#ifdef HAS_STRXFRM
+EXT MGVTBL vtbl_collxfrm;
+#endif
+
 #ifdef OVERLOAD
 EXT MGVTBL vtbl_amagic;
 EXT MGVTBL vtbl_amagicelem;
 #endif /* OVERLOAD */
 
-#endif
+#endif /* !DOINIT */
 
 #ifdef OVERLOAD
 EXT long amagic_generation;
@@ -1938,6 +1992,32 @@ enum {
   copy_amg,    neg_amg
 };
 #endif /* OVERLOAD */
+  
+#ifdef LC_COLLATE
+EXT U32                collation_ix;           /* Collation generation index */
+EXT char *     collation_name;         /* Name of current collation */
+EXT bool       collation_standard INIT(TRUE); /* Assume simple collation */
+EXT Size_t     collxfrm_base;          /* Basic overhead in *xfrm() */
+EXT Size_t     collxfrm_mult INIT(2);  /* Expansion factor in *xfrm() */
+#endif /* LC_COLLATE */
+
+#ifdef LC_NUMERIC
+
+EXT char *     numeric_name;           /* Name of current numeric locale */
+EXT bool       numeric_standard INIT(TRUE); /* Assume simple numerics */
+EXT bool       numeric_local INIT(TRUE);    /* Assume local numerics */
+
+#define NUMERIC_STANDARD() \
+    STMT_START { if (! numeric_standard) perl_numeric_standard(); } STMT_END
+#define NUMERIC_LOCAL() \
+    STMT_START { if (! numeric_local) perl_numeric_local(); } STMT_END
+
+#else /* !LC_NUMERIC */
+
+#define NUMERIC_STANDARD()  /**/
+#define NUMERIC_LOCAL()     /**/
+
+#endif /* !LC_NUMERIC */
 
 #if !defined(PERLIO_IS_STDIO) && defined(HAS_ATTRIBUTE)
 /* 
index 821c4d5..1c1848b 100755 (executable)
@@ -26,9 +26,10 @@ sed -n '/^[A-Za-z]/ p' interp.sym >> perl.exp
 
 # extra globals not included above.
 cat <<END >> perl.exp
-perl_init_ext
-perl_init_fold
 perl_init_i18nl10n
+perl_init_i18nl14n
+perl_new_collate
+perl_new_ctype
 perl_alloc
 perl_construct
 perl_destruct
@@ -44,8 +45,4 @@ perl_call_pv
 perl_call_method
 perl_call_sv
 perl_requirepv
-safecalloc
-safemalloc
-saferealloc
-safefree
 END
diff --git a/perly.c b/perly.c
index 6aff359..280069f 100644 (file)
--- a/perly.c
+++ b/perly.c
@@ -14,1024 +14,1066 @@ dep()
 
 #define YYERRCODE 256
 short yylhs[] = {                                        -1,
-   40,    0,    7,    5,    8,    9,    6,   10,   10,   10,
-   11,   11,   11,   11,   23,   23,   23,   23,   23,   23,
-   14,   14,   14,   13,   13,   13,   13,   37,   37,   12,
-   12,   12,   12,   12,   12,   12,   41,   42,   12,   12,
-   25,   25,   26,   26,   27,   28,   29,   30,   39,   39,
-    1,    1,    1,    1,    3,    3,   43,   43,   36,   36,
-    4,   44,   44,   45,   15,   15,   15,   24,   24,   24,
-   34,   34,   34,   34,   34,   34,   34,   34,   35,   35,
-   16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
-   16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
-   16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
-   16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
-   16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
-   16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
-   16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
-   16,   16,   16,   16,   31,   31,   32,   32,   32,    2,
-    2,   38,   22,   17,   18,   19,   20,   21,   33,   33,
-   33,   33,
+   40,    0,    7,    5,    8,    6,    9,    9,    9,   10,
+   10,   10,   10,   22,   22,   22,   22,   22,   22,   13,
+   13,   13,   12,   12,   12,   12,   37,   37,   11,   11,
+   11,   11,   11,   11,   11,   11,   11,   24,   24,   25,
+   25,   26,   27,   28,   29,   30,   39,   39,    1,    1,
+    1,    1,    3,    3,   41,   41,   36,   36,    4,   42,
+   42,   43,   14,   14,   14,   23,   23,   23,   34,   34,
+   34,   34,   34,   34,   34,   34,   35,   35,   15,   15,
+   15,   15,   15,   15,   15,   15,   15,   15,   15,   15,
+   15,   15,   15,   15,   15,   15,   15,   15,   15,   15,
+   15,   15,   15,   15,   15,   15,   15,   15,   15,   15,
+   15,   15,   15,   15,   15,   15,   15,   15,   15,   15,
+   15,   15,   15,   15,   15,   15,   15,   15,   15,   15,
+   15,   15,   15,   15,   15,   15,   15,   15,   15,   15,
+   15,   15,   15,   15,   15,   15,   15,   15,   15,   15,
+   15,   15,   31,   31,   32,   32,   32,    2,    2,   38,
+   21,   16,   17,   18,   19,   20,   33,   33,   33,   33,
 };
 short yylen[] = {                                         2,
-    0,    2,    4,    0,    5,    0,    0,    0,    2,    2,
-    2,    1,    2,    3,    1,    1,    3,    3,    3,    3,
-    0,    2,    6,    7,    7,    4,    4,    0,    2,    8,
-    8,    5,    5,   10,    8,    8,    0,    0,   13,    3,
-    0,    1,    0,    1,    1,    1,    1,    1,    0,    1,
-    1,    1,    1,    1,    4,    3,    5,    5,    0,    1,
-    0,    3,    2,    6,    3,    3,    1,    2,    3,    1,
-    3,    5,    6,    3,    5,    2,    4,    4,    1,    1,
+    0,    2,    4,    0,    4,    0,    0,    2,    2,    2,
+    1,    2,    3,    1,    1,    3,    3,    3,    3,    0,
+    2,    6,    7,    7,    4,    4,    0,    2,    8,    8,
+    5,    5,   10,    9,    8,   11,    3,    0,    1,    0,
+    1,    1,    1,    1,    1,    1,    0,    1,    1,    1,
+    1,    1,    4,    3,    5,    5,    0,    1,    0,    3,
+    2,    6,    3,    3,    1,    2,    3,    1,    3,    5,
+    6,    3,    5,    2,    4,    4,    1,    1,    3,    3,
     3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
-    3,    3,    5,    3,    2,    2,    2,    2,    2,    2,
-    2,    2,    2,    2,    3,    2,    3,    2,    4,    3,
-    4,    1,    5,    1,    4,    5,    4,    1,    1,    1,
-    5,    6,    5,    6,    5,    4,    5,    1,    1,    3,
-    4,    3,    2,    2,    4,    5,    4,    5,    1,    2,
-    2,    1,    2,    2,    2,    1,    3,    1,    3,    4,
-    4,    6,    1,    1,    0,    1,    0,    1,    2,    1,
-    1,    1,    2,    2,    2,    2,    2,    2,    1,    1,
-    1,    1,
+    5,    3,    2,    2,    2,    2,    2,    2,    2,    2,
+    2,    2,    3,    2,    3,    2,    4,    3,    4,    1,
+    5,    1,    4,    5,    4,    1,    1,    1,    5,    6,
+    5,    6,    5,    4,    5,    1,    1,    3,    4,    3,
+    2,    2,    4,    5,    4,    5,    1,    2,    2,    1,
+    2,    2,    2,    1,    3,    1,    3,    4,    4,    6,
+    1,    1,    0,    1,    0,    1,    2,    1,    1,    1,
+    2,    2,    2,    2,    2,    2,    1,    1,    1,    1,
 };
 short yydefred[] = {                                      1,
-    0,    8,    0,   50,   61,   61,    0,   61,    9,   51,
-   10,   12,    0,   52,   53,   54,    0,    0,    0,   63,
-    0,   15,    4,  153,    0,    0,  128,    0,  148,    0,
-   61,   61,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,  160,  161,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,   13,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,   11,    0,    0,
-    0,    0,  118,  120,    0,    0,    0,    0,  154,    0,
-   56,    0,   62,    0,    8,  169,  172,  171,  170,    0,
+    0,    7,    0,   48,   59,   59,    0,   59,    8,   49,
+    9,   11,    0,   50,   51,   52,    0,    0,    0,   61,
+    0,   14,    4,  151,    0,    0,  126,    0,  146,    0,
+   59,   59,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,  158,  159,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,   12,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,   10,    0,    0,
+    0,    0,  116,  118,    0,    0,    0,    0,  152,    0,
+   54,    0,   60,    0,    7,  167,  170,  169,  168,    0,
     0,    0,    0,    0,    0,    4,    0,    4,    0,    4,
     0,    4,    0,    4,    4,    0,    0,    0,    0,    0,
-  167,    0,  134,    0,    0,    0,    0,    0,  163,    0,
-    0,    0,    0,   76,    0,  143,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,  108,    0,  164,  165,
-  166,  168,    0,    0,   40,    0,    0,    0,    0,    0,
+  165,    0,  132,    0,    0,    0,    0,    0,  161,    0,
+    0,    0,    0,   74,    0,  141,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,  106,    0,  162,  163,
+  164,  166,    0,    0,   37,    0,    0,    0,    0,    0,
     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,  100,  101,    0,    0,
-    0,    0,    0,    0,    0,    0,   14,    0,   55,   60,
-    0,    0,    0,   74,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,    0,  147,
-  149,    0,    0,    0,    0,    0,    0,  110,    0,  132,
-    0,    0,    0,  107,   29,    0,    0,   20,    0,    0,
-    0,   65,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,   79,    0,
-   80,    0,    0,    0,    0,    0,    0,    0,  130,    0,
-    0,   58,   57,    0,    3,    0,  151,    0,   78,  111,
-    0,   47,    0,   32,   48,    0,   33,    0,    0,    0,
-    0,   26,    0,   27,  162,    0,    0,   42,    0,    0,
-  150,  159,   77,    0,  135,    0,  137,    0,  109,    0,
-    0,    0,    0,    0,    0,    0,  117,    0,  115,    0,
-  126,    0,  131,   64,   75,    0,    0,    0,    0,    6,
-   22,    0,    0,    0,    0,   37,    0,   72,  136,  138,
-  125,    0,  123,    0,    0,  116,    0,  121,  127,  113,
-  152,    0,    0,    0,    7,    0,    0,    0,    0,    0,
-    0,  124,  122,   73,   30,   31,   24,    8,    0,   25,
-    0,   36,    0,   35,    0,    0,    0,   38,    5,   23,
-   34,    0,    0,    0,   39,
+    0,    0,    0,    0,    0,    0,   98,   99,    0,    0,
+    0,    0,    0,    0,    0,    0,   13,    0,   53,   58,
+    0,    0,    0,   72,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    4,  145,
+  147,    0,    0,    0,    0,    0,    0,  108,    0,  130,
+    0,    0,    0,  105,   28,    0,    0,   19,    0,    0,
+    0,   63,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,   77,    0,
+   78,    0,    0,    0,    0,    0,    0,    0,  128,    0,
+    0,   56,   55,    0,    3,    0,  149,    0,   76,  109,
+    0,   45,    0,   31,   46,    0,   32,    0,    0,    0,
+    0,   25,    0,   26,  160,    0,    0,   39,   44,    0,
+    0,    0,  148,  157,   75,    0,  133,    0,  135,    0,
+  107,    0,    0,    0,    0,    0,    0,    0,  115,    0,
+  113,    0,  124,    0,  129,   62,   73,    0,    0,    0,
+    0,    6,   21,    0,    0,    0,    0,    0,    0,   70,
+  134,  136,  123,    0,  121,    0,    0,  114,    0,  119,
+  125,  111,  150,    0,    0,    0,    7,    0,    0,    0,
+    0,    0,    0,  122,  120,   71,   29,   30,   23,    0,
+    0,   24,    0,   35,    0,    0,    5,    0,    0,    0,
+   34,   22,   33,    0,   36,
 };
 short yydgoto[] = {                                       1,
-    9,   66,   10,   17,   85,  348,   88,  311,  335,    3,
-   11,   12,   68,  272,  203,   70,   71,   72,   73,   74,
-   75,   76,  278,   78,  279,  262,  265,  269,  263,  266,
+    9,   66,   10,   17,   85,  337,   88,  313,    3,   11,
+   12,   68,  272,  268,   70,   71,   72,   73,   74,   75,
+   76,  278,   78,  279,  262,  265,  269,  281,  263,  266,
   124,  204,   90,   79,  242,  181,  145,  276,   13,    2,
-  340,  362,   14,   15,   16,
+   14,   15,   16,
 };
 short yysindex[] = {                                      0,
-    0,    0,  408,    0,    0,    0,  -36,    0,    0,    0,
-    0,    0,  618,    0,    0,    0, -116, -216,  -12,    0,
- -203,    0,    0,    0,   68,   68,    0,   16,    0, 1972,
-    0,    0,   -6,    5,    6,   21,  -34, 1972,   22,   26,
-   31,   68,  950, 1006, -176,    0,    0,   68, 1972,  -21,
- 1070, 1972, 1972, 1972, 1972, 1972, 1346,    0, 1972, 1972,
- 1402,   68,   68,   68,   68, 1972, -202,    0,  287, 3838,
-  -59,  -56,    0,    0,  -35,   57,   41,   63,    0,   -9,
-    0, -150,    0, -145,    0,    0,    0,    0,    0, 1972,
-   87, 1972, 3838,   -9, -150,    0,   -9,    0,   -9,    0,
-   -9,    0,   -9,    0,    0,   90, 3838,   91, 1461,  -21,
-    0,  103,    0,  267,   -7,   23,  -50, 1972,    0,   63,
-    0,  -59,   63,    0, 1972,    0,  267,  611,  611,  611,
-  -86,  -86,   62,  -38,  611,  611,    0,  -83,    0,    0,
-    0,    0,  267,   -9,    0, 1972, 1972, 1972, 1972, 1972,
- 1972, 1972, 1972, 1972, 1972, 1972, 1972, 1972, 1972, 1972,
- 1972, 1972, 1972, 1972, 1972, 1972,    0,    0,  -28, 1972,
- 1972, 1972, 1972, 1972, 1972, 1521,    0, 1972,    0,    0,
-  -33, 1972,  225,    0, 1972, 2008, 1972,   -9, 1972, -202,
- 1972, -202, 1972, -208, 1972, -208,   95, 1797, 1972,    0,
-    0,  -30,    7,  114, 1972, 1853, 1909,    0,   25,    0,
-   63, 1972,   73,    0,    0, -173, -173,    0, -173, -173,
- -140,    0,  -46, 3340,  267, 2662,  374, 1221, 3838, 3801,
- 3898, 1616, 3272,  320,  383,  611,  611, 1972,    0, 1972,
-    0,  127,  -79,  -41,  -73,   40,  -43,   59,    0,  -16,
- 3838,    0,    0,  111,    0,  130,    0, 1972,    0,    0,
- -173,    0,  136,    0,    0,  138,    0, -173,  142,   58,
-  144,    0,  146,    0,    0,  149,  369,    0,  131,  -14,
-    0,    0,    0,  -11,    0,   -3,    0,   -1,    0,  113,
- 1972,   70, 1972,   66,  140, 1972,    0,   71,    0,   72,
-    0,   79,    0,    0,    0, 1675,   58,   58,   58,    0,
-    0, 1972,   58, 1972,   58,    0,   -9,    0,    0,    0,
-    0,  182,    0, 3868,   84,    0,  170,    0,    0,    0,
-    0, -202, -202, -208,    0,  173, -208,    1, -202, 1972,
- -202,    0,    0,    0,    0,    0,    0,    0,   58,    0,
-   58,    0,  156,    0,  343, -208, -202,    0,    0,    0,
-    0, 1797,  177,   58,    0,
+    0,    0, -118,    0,    0,    0,  -52,    0,    0,    0,
+    0,    0,  616,    0,    0,    0, -117, -225,  -12,    0,
+ -219,    0,    0,    0,  -28,  -28,    0,   32,    0, 2245,
+    0,    0,   -7,   -6,    3,   22,  -35, 2245,   38,   44,
+   48,  -28, 1004, 1067, -196,    0,    0,  -28, 2245,  948,
+ 1343, 2245, 2245, 2245, 2245, 2245, 1399,    0, 2245, 2245,
+ 1455,  -28,  -28,  -28,  -28, 2245, -215,    0,  192, 3934,
+  -67,  -50,    0,    0,  -10,   71,   64,   81,    0,    4,
+    0, -114,    0, -115,    0,    0,    0,    0,    0, 2245,
+  115, 2245, 3934,    4, -114,    0,    4,    0,    4,    0,
+    4,    0,    4,    0,    0,  125, 3934,  126, 1518,  948,
+    0,  130,    0, 2305,  -24,   46,  -56, 2245,    0,   81,
+    0,  -67,   81,    0, 2245,    0, 2305,  -77,  -77,  -77,
+  -81,  -81,   83,  -21,  -77,  -77,    0,  -84,    0,    0,
+    0,    0, 2305,    4,    0, 2245, 2245, 2245, 2245, 2245,
+ 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245, 2245,
+ 2245, 2245, 2245, 2245, 2245, 2245,    0,    0,  -17, 2245,
+ 2245, 2245, 2245, 2245, 2245, 1794,    0, 2245,    0,    0,
+  -36, 2245,  -49,    0, 2245,  326, 2245,    4, 2245, -215,
+ 2245, -215, 2245, -156, 2245, -156,  143, 1850,    0,    0,
+    0,   -2,   13,  140, 2245, 1906, 1969,    0,   58,    0,
+   81, 2245,   95,    0,    0, -164, -164,    0, -164, -164,
+ -109,    0,  -48, 2384, 2305, 2819,  941, 1031, 3934, 3894,
+ 3965, 3724,  359,  435, 1190,  -77,  -77, 2245,    0, 2245,
+    0,  149,  -80,   21,  -65,   23,   82,   56,    0,    8,
+ 3934,    0,    0,  136,    0,  155,    0, 2245,    0,    0,
+ -164,    0,  167,    0,    0,  169,    0, -164,  172,  101,
+  174,    0,  185,    0,    0,  198,  192,    0,    0,  201,
+  202, 2245,    0,    0,    0,   11,    0,   17,    0,   19,
+    0,   84, 2245,  139, 2245,   69,   91, 2245,    0,  153,
+    0,  158,    0,  161,    0,    0,    0,  400,  101,  101,
+  101,    0,    0, 2245,  101, 2245,  101, 2245,  247,    0,
+    0,    0,    0,  105,    0, 1734,  175,    0,  261,    0,
+    0,    0,    0, -215, -215, -156,    0,  269, -156,  279,
+ -215,  268,  101,    0,    0,    0,    0,    0,    0,  278,
+  101,    0,  101,    0, 1850, -215,    0, -156, -215,  300,
+    0,    0,    0,  101,    0,
 };
 short yyrindex[] = {                                      0,
-    0,    0,  165,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,  220,    0,    0,    0,    0,    0,    0,    0,
     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0, 2164,  426,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,    0, 2786,
- 2862,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,   49,    0,   18,  293,
- 2907, 2987,    0,    0, 2209, 2062,    0,  373,    0,    0,
-    0,  -20,    0,    0,    0,    0,    0,    0,    0, 2260,
-    0,    0, 1179,    0,   96,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0, 1299,    0,    0,  179,
-    0, 2121,    0, 3614, 2907,    0,    0, 2260,    0, 2319,
-  493,  559, 2461,    0,    0,    0, 3653, 3142, 3183, 3222,
- 3049, 3097, 2523,    0, 3268, 3316,    0,    0,    0,    0,
-    0,    0, 3727,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0, 2453, 2118,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0, 3021,
+ 3064,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,   65,    0,  -14,  -29,
+ 3121, 3189,    0,    0, 2353, 2177,    0,  309,    0,    0,
+    0,  -33,    0,    0,    0,    0,    0,    0,    0, 2520,
+    0,    0,  843,    0,  230,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0, 1177,    0,    0,  319,
+    0, 2285,    0, 1241, 3121,    0,    0, 2520,    0, 2588,
+  496,  557, 2651,    0,    0,    0, 1692,  674, 3387, 3470,
+  110, 3299, 2719,    0, 3518, 3592,    0,    0,    0,    0,
+    0,    0, 2038,    0,    0,    0,    0,    0,    0,    0,
     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0, 2582,    0,    0,
-    0,  167,  894,    0,  179,    0, 2260,    0,  190,   49,
-    0,   49,    0,  109,    0,  109,    0,  188,    0,    0,
-    0,    0,  210,    0,    0,    0,    0,    0,    0,    0,
- 2627,    0, 2724,    0,    0,   24,   39,    0,   52,   60,
- 1307,    0,    0, 1046, 1187, 1243, 1131, 3503, 1575,    0,
- 3770, 1639, 1583, 2399, 3551, 3418, 3457,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0, 2786,    0,    0,
+    0,  302,  892,    0,  319,    0, 2520,    0,  325,   65,
+    0,   65,    0,  164,    0,  164,    0,  312,    0,    0,
+    0,    0,  331,    0,    0,    0,    0,    0,    0,    0,
+ 2886,    0, 2954,    0,    0,   10,   12,    0,   34,   53,
+ 1047,    0,    0, 1185, 3811, 3827, 3719, 3767, 1294,    0,
+ 1636, 1580, 1129, 3871,   -4, 3636, 3674,    0,    0,    0,
     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
- 1729,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-   65,    0,    0,    0,    0,    0,    0,  226,    0,    0,
-    0,    0,    0,    0,    0,    0,  215,    0,    0,    0,
+ 1572,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+   59,    0,    0,    0,    0,    0,    0,  333,    0,    0,
+    0,    0,    0,    0,    0,    0,   63,    0,    0,    0,
     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,  179,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,  319,    0,    0,
     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,  845,    0,    0,    0,    0,    0,    0,
-    0,   49,   49,  109,    0,    0,  109,    0,   49,  227,
-   49,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,  894,  109,   49,    0,    0,    0,
-    0,  257,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,  322,    0,    0,
+    0,    0,    0,    0,    0,  -23,    0,    0,    0,    0,
+    0,    0,    0,   65,   65,  164,    0,    0,  164,    0,
+   65,    0,    0,    0,    0,    0,    0,    0,    0,  892,
+    0,    0,    0,    0,  347,   65,    0,  164,   65,    0,
+    0,    0,    0,    0,    0,
 };
 short yygindex[] = {                                      0,
-    0,    0,    0,   47,  416,    0,  447,  194,    0,  -84,
-    0,    0,    0, -168,  -13, 3819,  917,    0,    0,    0,
-    0,    0,  291,  901,  -62,  -29,  197,   14,    0,  150,
-  -61, -181,   10,    0,    0,  253,  637,    0,    0,    0,
-    0,    0,    0,    0,    0,
+    0,    0,    0,   60,  -19,    0, 4247,  768,  -83,    0,
+    0,    0, -192,  -13, 3466, 2324,    0,    0,    0,    0,
+    0,  377,  955,    0,    0,  245, -173,   39,   75,  204,
+  -68, -168,  966,    0,    0,  313,  335,    0,    0,    0,
+    0,    0,    0,
 };
-#define YYTABLESIZE 4212
+#define YYTABLESIZE 4435
 short yytable[] = {                                      69,
-  183,   62,  213,  256,  170,  105,   23,   62,  209,  214,
-  281,   52,  292,  297,   62,   64,   48,  298,   57,  299,
-   65,   60,   20,   59,  303,  252,  317,  274,  184,  318,
-  117,  172,  207,   96,  174,   91,  152,  319,   59,  320,
-   82,  351,   63,  134,   98,  100,   83,  138,   28,  301,
-  282,  111,   18,   84,   21,   92,  210,  119,   16,  125,
-  102,  108,  240,  171,   19,  109,  173,  270,  271,   61,
-  110,  139,  140,  141,  142,  144,   16,   94,   95,   45,
-  118,   28,   19,  172,   28,   28,   28,  175,   28,   23,
-   28,   28,   17,   28,  238,  202,  176,   45,  300,  177,
-   18,   23,   59,   62,   53,   44,  178,   28,   21,  180,
-   17,  182,   28,   23,  327,  171,   23,  302,   18,  205,
-  254,  150,  151,   44,  325,  259,  185,   23,   23,  199,
-   62,  200,  216,  217,  219,  220,  221,  222,  223,   28,
-   80,   21,  206,   23,   21,   21,   21,  208,   21,  289,
-   21,   21,  212,   21,  283,  151,  243,  244,  245,  246,
-  247,  248,  250,  291,    2,  347,  296,   21,  350,  304,
-  305,   28,   21,   28,   28,  261,  307,  217,  308,  268,
-  310,  217,  309,  312,  277,  280,  313,  360,  314,  316,
-   23,  284,  286,  288,  323,  328,  329,   49,  290,   21,
-   49,   49,   49,  330,   49,  321,   49,   49,  343,   49,
-  344,  150,  151,  349,  358,  150,  151,  364,   59,  157,
-   19,  150,  151,   49,  294,  155,  295,  169,   49,  239,
-   43,   21,  326,   21,   21,  121,   25,   26,   27,   28,
-   87,   29,   30,   31,  150,  151,   41,   32,  150,  151,
-  158,  150,  151,  150,  151,   49,  150,  151,   38,  104,
-   39,   40,   41,  355,  150,  151,   46,   42,   43,   44,
-   45,   46,   47,   16,  342,   49,   50,  322,  150,  151,
-  150,  151,   51,  150,  151,   43,   54,   49,   55,   56,
-   49,  150,  151,  150,  151,  150,  151,   41,  268,  363,
-  338,  150,  151,   77,   28,   28,   28,   28,   28,   28,
-  353,   28,   28,   28,   28,   28,   28,   28,   28,   28,
-   28,   28,   28,   28,   86,  336,  261,   28,   28,   87,
-   28,   28,   28,   70,  150,  151,   70,   28,   28,   28,
-   28,   28,   28,  218,  273,   28,   28,  188,   69,  255,
-   70,   70,   28,  150,  151,    0,   28,  170,   28,   28,
-  150,  151,    0,    0,   21,   21,   21,   21,   21,   21,
-    0,   21,   21,   21,   21,   21,   21,   21,   21,   21,
-   21,   21,   21,   21,    0,   70,    0,   21,   21,  152,
-   21,   21,   21,    0,    0,    0,    0,   21,   21,   21,
-   21,   21,   21,    0,    0,   21,   21,  150,  151,  315,
-  170,    0,   21,   67,    0,    0,   21,    0,   21,   21,
-   49,   49,   49,   49,   49,   49,    0,   49,   49,   49,
-    0,   67,    0,   49,  150,  151,   49,   49,   49,   49,
-    0,    0,  152,   49,   49,    0,   49,   49,   49,    0,
-    0,    0,    0,   49,   49,   49,   49,   49,   49,   67,
-    0,   49,   49,   81,  170,   67,  146,  359,   49,  146,
-    0,    0,   49,  170,   49,   49,  150,  151,    0,   97,
-   99,  101,  103,  146,  146,    0,    0,    0,  146,  113,
-    4,    5,    6,    0,    7,    8,  152,  126,    0,    0,
-  332,  333,  334,    0,    0,  152,  337,    0,  339,    0,
-    0,  189,    0,  191,    0,  193,  146,  195,  146,  197,
-  198,    0,    0,    0,    0,  169,  179,    0,  169,  169,
-  169,    0,  169,  153,  169,  169,  153,  169,    0,    0,
-  187,    0,  356,  190,  357,  192,    0,  194,  146,  196,
-  153,  153,    0,  156,  157,  153,  169,  365,  146,  147,
-  148,  149,    0,    0,   70,   70,   70,   70,    0,    0,
-    0,  164,  165,    0,    0,  166,    0,    0,  167,  168,
-  169,  150,  151,  153,    0,  153,    0,   70,   70,    0,
-  215,  170,    0,    0,  170,  170,  170,    0,  170,  112,
-  170,  170,  112,  170,  154,  155,  156,  157,    4,    5,
-    6,    0,    7,    8,    0,  153,  112,  112,  169,    0,
-    0,  112,  170,    0,  164,  165,    0,  253,  166,    0,
-    0,  167,  168,  169,  260,    0,    0,    0,    0,    0,
-  146,  147,  148,  149,   67,   67,   67,   67,    0,    0,
-   52,  112,    0,   62,   64,   48,    0,   57,    0,   65,
-   60,    0,   59,  150,  151,    0,    0,   67,   67,  156,
-  157,    0,    0,    4,    5,    6,   58,    7,    8,  165,
-    0,   63,  166,    0,  170,  167,  168,  169,  165,    0,
-    0,  166,    0,    0,  167,  168,  169,  146,  146,  146,
-  146,  170,    0,    0,    0,    0,  146,    0,   61,    0,
-  146,  146,  146,  146,    0,    0,    0,    0,    0,    0,
-  146,  146,    0,    0,  146,  146,  146,  146,  146,    0,
-  146,  146,    0,  152,  146,    0,    0,  146,  146,  146,
-   23,    0,    0,   53,    0,    0,    0,    0,    0,  169,
-  169,  169,  169,  169,    0,  169,  169,  169,    0,    0,
-    0,  169,    0,  341,  153,  153,  153,  153,    0,    0,
-    0,    0,  169,  153,  169,  169,  169,  153,  153,  153,
-  153,  169,  169,  169,  169,  169,  169,  153,  153,  169,
-  169,  153,  153,  153,  153,  153,  169,  153,  153,    0,
-  169,  153,  169,  169,  153,  153,  153,    0,    0,    0,
-    0,    0,    0,    0,    0,  170,  170,  170,  170,  170,
-    0,  170,  170,  170,    0,    0,  264,  170,  267,    0,
-  112,  112,  112,  112,    0,    0,    0,    0,  170,  112,
-  170,  170,  170,  112,  112,  112,  112,  170,  170,  170,
-  170,  170,  170,  112,  112,  170,  170,  112,  112,  112,
-  112,  112,  170,  112,  112,    0,  170,  112,  170,  170,
-  112,  112,  112,   22,   24,   25,   26,   27,   28,    0,
-   29,   30,   31,    0,    0,   93,   32,    0,   93,   33,
-   34,   35,   36,    0,    0,    0,   37,   38,    0,   39,
-   40,   41,   93,   93,    0,    0,   42,   43,   44,   45,
-   46,   47,    0,    0,   49,   50,    0,    0,    0,  166,
-    0,   51,  167,  168,  169,   54,   49,   55,   56,   49,
-   49,   49,    0,   49,    0,   49,   49,   93,   49,    0,
-    0,   89,   89,    0,    0,    0,    0,    0,    0,  120,
-  123,    0,   49,  106,    0,    0,    0,   49,   89,  115,
-    0,    0,    0,    0,   89,    0,  122,    0,  345,  346,
-    0,    0,    0,    0,    0,  352,    0,  354,   89,   89,
-   89,   89,   52,    0,   49,   62,   64,   48,    0,   57,
-  123,   65,   60,  361,   59,    0,    0,    0,    0,    0,
+   62,  183,  209,  274,  105,   23,   20,   62,  214,  170,
+  294,   68,  299,  170,   68,  207,  256,   91,   62,  213,
+   91,  184,  252,  172,  280,   57,   15,  301,   68,   68,
+  117,   82,   96,   98,   91,   91,   83,   84,  283,   83,
+  174,  152,  100,  134,   15,  152,   83,  138,  305,  210,
+   18,  320,   42,   83,   83,  171,  284,  321,   83,  322,
+  118,  102,  144,   68,   27,   18,  172,   21,   18,   91,
+   42,   92,  173,  240,   16,  255,  189,  108,  191,  300,
+  193,  302,  195,  109,  197,  198,   23,  110,   83,   57,
+   94,   95,   16,   17,   23,  202,  203,   27,  171,   41,
+   27,   27,   27,   43,   27,  238,   27,   27,  319,   27,
+  176,   17,  175,  254,  304,   23,   23,   41,  259,  270,
+  271,   15,  177,   27,  178,   23,   23,  327,   27,  329,
+  150,  151,  216,  217,  219,  220,  221,  222,  223,   80,
+  338,  182,  340,  349,   23,  180,  352,    4,    5,    6,
+  100,    7,    8,  100,  185,   27,  243,  244,  245,  246,
+  247,  248,  250,   20,  199,  362,  200,  100,  100,  206,
+  208,  203,  100,  212,  303,  261,  323,  217,   62,  282,
+  285,  217,  291,  328,  277,  293,  151,   27,  298,   27,
+   27,  286,  288,  290,  306,  307,   20,  344,  292,   20,
+   20,   20,  100,   20,   19,   20,   20,  309,   20,  310,
+  150,  151,  311,  314,  150,  151,    4,    5,    6,    2,
+    7,    8,   20,  312,  296,  315,  297,   20,   86,  150,
+  151,  166,  169,   87,  167,  168,  169,  316,  150,  151,
+  239,  317,   68,   68,   68,   68,  150,  151,   91,   91,
+   91,   91,   47,  350,   20,   47,   47,   47,  104,   47,
+  318,   47,   47,  325,   47,   68,   68,   83,   83,   83,
+   83,   91,   91,  150,  151,   91,   83,  330,   47,  324,
+   83,   83,  331,   47,  203,  332,   20,  343,   20,   20,
+   83,   83,  150,  151,   83,   83,   83,   83,   83,  345,
+   83,  346,  150,  151,  261,  150,  151,  150,  151,  351,
+   47,  150,  151,  150,  151,  150,  151,  150,  151,  353,
+   27,   27,   27,   27,   27,   27,  355,   27,   27,   27,
+   27,   27,   27,   27,   27,   27,   27,   27,   27,   27,
+  364,   69,   47,   27,   27,   47,   27,   27,   27,   65,
+  150,  151,   57,   27,   27,   27,   27,   27,   27,  155,
+  153,   27,   27,  150,  151,   40,  257,   65,   27,  258,
+   38,  156,   27,   43,   27,   27,  150,  151,  150,  151,
+   40,  100,  100,  100,  100,  150,  151,   38,  159,   77,
+  100,  218,  342,  360,  100,  100,  100,  100,  273,  150,
+  151,   65,  357,    0,  100,  100,    0,  188,  100,  100,
+  100,  100,  100,    0,  100,  100,  170,    0,  100,   20,
+   20,   20,   20,   20,   20,    0,   20,   20,   20,   20,
+   20,   20,   20,   20,   20,   20,   20,   20,   20,    0,
+  333,    0,   20,   20,    0,   20,   20,   20,  152,  170,
+    0,    0,   20,   20,   20,   20,   20,   20,    0,    0,
+   20,   20,  159,  146,  147,  148,  149,   20,    0,    0,
+    0,   20,    0,   20,   20,   47,   47,   47,   47,   47,
+   47,  152,   47,   47,   47,    0,  150,  151,   47,    0,
+  170,   47,   47,   47,   47,    0,    0,    0,   47,   47,
+    0,   47,   47,   47,    0,    0,    0,    0,   47,   47,
+   47,   47,   47,   47,    0,    0,   47,   47,    0,    0,
+    0,    0,  152,   47,  264,  170,  267,   47,  167,   47,
+   47,  167,  167,  167,    0,  167,  151,  167,  167,  151,
+  167,    0,    0,    4,    5,    6,    0,    7,    8,    0,
+    0,    0,    0,  151,  151,    0,    0,  152,  151,  167,
     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,   63,    0,    0,   49,    0,  123,   49,
-    0,    0,    0,    0,    0,  211,  122,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,   52,    0,
-   61,   62,   64,   48,    0,   57,    0,   65,   60,    0,
-   59,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,  116,    0,    0,    0,    0,   63,
-    0,    0,   23,    0,    0,   53,    0,    0,    0,    0,
-    0,    0,  123,    0,    0,  241,   90,  123,    0,   90,
-    0,    0,    0,    0,    0,    0,   61,    0,    0,    0,
-    0,    0,   52,   90,   90,   62,   64,   48,   90,   57,
-    0,   65,   60,  275,   59,    0,   93,   93,   93,   93,
     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,   53,    0,   63,    0,    0,    0,    0,   90,   93,
-   93,    0,    0,   93,    0,    0,    0,    0,    0,   49,
-   49,   49,   49,   49,   49,    0,   49,   49,   49,    0,
-   61,    0,   49,    0,    0,   49,   49,   49,   49,    0,
-    0,   83,   49,   49,   83,   49,   49,   49,    0,    0,
-    0,    0,   49,   49,   49,   49,   49,   49,   83,   83,
-   49,   49,   23,   83,    0,   53,    0,   49,    0,    0,
-    0,   49,    0,   49,   49,    0,  112,   25,   26,   27,
-   28,    0,   29,   30,   31,    0,    0,    0,   32,  145,
-    0,    0,  145,   83,    0,    0,    0,   86,    0,   38,
-   86,   39,   40,   41,    0,    0,  145,  145,   42,   43,
-   44,   45,   46,   47,   86,   86,   49,   50,    0,   86,
-    0,    0,    0,   51,    0,    0,    0,   54,    0,   55,
-   56,    0,   24,   25,   26,   27,   28,    0,   29,   30,
-   31,  145,    0,    0,   32,    0,    0,    0,    0,   86,
-    0,    0,    0,   87,    0,   38,   87,   39,   40,   41,
-    0,    0,    0,    0,   42,   43,   44,   45,   46,   47,
-   87,   87,   49,   50,    0,   87,    0,    0,    0,   51,
-    0,  170,    0,   54,    0,   55,   56,   90,   90,   90,
-   90,    0,    0,    0,    0,    0,   24,   25,   26,   27,
-   28,    0,   29,   30,   31,   87,    0,    0,   32,  140,
-   90,   90,  140,  152,   90,    0,    0,   66,    0,   38,
-   66,   39,   40,   41,    0,    0,  140,  140,   42,   43,
-   44,   45,   46,   47,    0,   66,   49,   50,    0,    0,
-    0,    0,    0,   51,    0,    0,    0,   54,   52,   55,
-   56,   62,   64,   48,    0,   57,  133,   65,   60,    0,
-   59,  140,    0,    0,    0,    0,    0,    0,    0,   66,
-    0,    0,   83,   83,   83,   83,    0,    0,    0,   63,
-    0,   83,    0,    0,    0,   83,   83,   83,   83,    0,
-    0,    0,    0,    0,    0,   83,   83,    0,    0,   83,
-   83,   83,   83,   83,   52,   83,   61,   62,   64,   48,
-    0,   57,    0,   65,   60,    0,   59,    0,    0,    0,
-  145,  145,  145,  145,    0,    0,    0,    0,   86,   86,
-   86,   86,    0,    0,    0,   63,    0,   86,    0,    0,
-    0,   53,   86,  145,  145,    0,    0,    0,    0,    0,
-    0,   86,   86,    0,    0,   86,   86,   86,   86,   86,
-    0,    0,   61,   52,  137,    0,   62,   64,   48,    0,
-   57,  201,   65,   60,    0,   59,    0,  156,    0,    0,
-    0,    0,    0,    0,   87,   87,   87,   87,    0,    0,
-    0,    0,    0,   87,   63,    0,  165,   53,    0,  166,
-    0,    0,  167,  168,  169,    0,    0,   87,   87,    0,
-    0,   87,   87,   87,   87,   87,    0,    0,    0,    0,
-    0,   61,    0,   52,    0,    0,   62,   64,   48,    0,
-   57,  249,   65,   60,    0,   59,    0,    0,    0,    0,
-  140,  140,  140,  140,    0,    0,    0,    0,   66,   66,
-   66,   66,    0,    0,   63,    0,   53,    0,    0,    0,
-    0,    0,    0,  140,  140,    0,    0,    0,    0,    0,
-    0,   66,   24,   25,   26,   27,   28,    0,   29,   30,
-   31,   61,    0,    0,   32,   81,    0,    0,   81,    0,
-    0,    0,    0,   89,    0,   38,   89,   39,   40,   41,
-    0,    0,   81,   81,   42,   43,   44,   45,   46,   47,
-   89,   89,   49,   50,    0,   89,   53,    0,    0,   51,
-    0,    0,    0,   54,    0,   55,   56,    0,   24,   25,
-   26,   27,   28,    0,   29,   30,   31,   81,    0,    0,
-   32,    0,    0,    0,    0,   89,    0,    0,    0,   91,
-    0,   38,   91,   39,   40,   41,    0,    0,    0,    0,
-   42,   43,   44,   45,   46,   47,   91,   91,   49,   50,
-    0,   91,    0,    0,    0,   51,  170,    0,    0,   54,
-    0,   55,   56,    0,    0,  331,    0,   24,   25,   26,
-   27,   28,    0,   29,   30,   31,    0,    0,    0,   32,
-    0,   91,    0,    0,    0,    0,    0,  159,  152,    0,
-   38,    0,   39,   40,   41,    0,    0,    0,    0,   42,
-   43,   44,   45,   46,   47,    0,    0,   49,   50,    0,
-    0,    0,    0,    0,   51,  170,    0,    0,   54,   69,
-   55,   56,   69,    0,    0,    0,    0,   24,   25,   26,
-   27,   28,    0,   29,   30,   31,   69,   69,    0,   32,
-    0,    0,    0,    0,    0,    0,    0,  152,    0,    0,
-   38,    0,   39,   40,   41,    0,    0,    0,    0,   42,
-   43,   44,   45,   46,   47,    0,    0,   49,   50,    0,
-    0,   69,    0,    0,   51,    0,    0,    0,   54,   52,
-   55,   56,   62,   64,   48,    0,   57,    0,   65,   60,
-    0,   59,    0,    0,    0,    0,   81,   81,   81,   81,
-    0,    0,    0,    0,   89,   89,   89,   89,    0,    0,
-   63,    0,    0,   89,    0,    0,    0,    0,    0,   81,
-   81,    0,    0,    0,    0,    0,    0,   89,   89,    0,
-    0,   89,   89,   89,   89,   52,    0,   61,   62,   64,
-   48,    0,   57,  285,   65,   60,    0,   59,    0,    0,
-  154,  155,  156,  157,    0,    0,    0,    0,    0,    0,
-   91,   91,   91,   91,    0,    0,   63,  162,  163,   91,
-  164,  165,   53,    0,  166,    0,    0,  167,  168,  169,
-    0,    0,    0,   91,   91,    0,    0,   91,   91,   91,
-    0,   52,    0,   61,   62,   64,   48,    0,   57,  287,
-   65,   60,    0,   59,    0,  153,    0,    0,    0,  154,
+   65,   65,   65,   65,    0,    0,  151,    0,  151,  168,
+    0,    0,  168,  168,  168,    0,  168,  110,  168,  168,
+  110,  168,    0,   65,   65,    0,  153,    0,    0,    0,
+  154,  155,  156,  157,  110,  110,    0,    0,  151,  110,
+  168,  167,    0,    0,  158,  160,  161,  162,  163,    0,
+  164,  165,    0,    0,  166,    0,    0,  167,  168,  169,
+    0,    0,    0,  154,  155,  156,  157,    0,   52,  110,
+    0,   62,   64,   48,    0,   57,    0,   65,   60,    0,
+   59,  163,    0,  164,  165,    0,    0,  166,  347,  348,
+  167,  168,  169,    0,   58,  354,    0,    0,    0,   63,
+  153,    0,  168,    0,  154,  155,  156,  157,    0,    0,
+  361,    0,    0,  363,    0,    0,    0,    0,  158,  160,
+  161,  162,  163,    0,  164,  165,   61,    0,  166,    0,
+    0,  167,  168,  169,   95,    0,    0,   95,    0,  154,
   155,  156,  157,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,   63,  158,  160,  161,  162,  163,   53,  164,
-  165,    0,    0,  166,    0,    0,  167,  168,  169,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,    0,   61,
-   69,   69,   69,   69,   52,    0,    0,   62,   64,   48,
-    0,   57,    0,   65,   60,    0,   59,    0,    0,    0,
-    0,    0,    0,   69,   69,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,   53,   63,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,  257,    0,
-    0,  258,   22,   24,   25,   26,   27,   28,    0,   29,
-   30,   31,   61,    0,    0,   32,    0,    0,    0,    0,
-  159,    0,    0,    0,    0,    0,   38,    0,   39,   40,
-   41,    0,    0,    0,    0,   42,   43,   44,   45,   46,
-   47,    0,    0,   49,   50,    0,    0,   53,  170,    0,
-   51,    0,  129,    0,   54,  129,   55,   56,    0,   24,
-   25,   26,   27,   28,    0,   29,   30,   31,    0,  129,
-  129,   32,    0,    0,  129,    0,    0,    0,    0,    0,
-  152,    0,   38,    0,   39,   40,   41,    0,    0,    0,
-    0,   42,   43,   44,   45,   46,   47,    0,    0,   49,
-   50,    0,  129,    0,  129,    0,   51,    0,    0,    0,
-   54,  153,   55,   56,  153,   24,   25,   26,   27,   28,
-    0,   29,   30,   31,    0,    0,    0,   32,  153,  153,
-    0,    0,    0,  153,  129,    0,    0,    0,   38,    0,
+    0,   95,   95,    0,    0,    0,   95,    0,   23,  164,
+  165,   53,    0,  166,    0,    0,  167,  168,  169,    0,
+    0,    0,  167,  167,  167,  167,  167,    0,  167,  167,
+  167,    0,    0,    0,  167,    0,   95,  151,  151,  151,
+  151,    0,    0,    0,    0,  167,  151,  167,  167,  167,
+  151,  151,  151,  151,  167,  167,  167,  167,  167,  167,
+  151,  151,  167,  167,  151,  151,  151,  151,  151,  167,
+  151,  151,    0,  167,  151,  167,  167,  151,  151,  151,
+    0,    0,    0,  168,  168,  168,  168,  168,    0,  168,
+  168,  168,    0,    0,    0,  168,    0,    0,  110,  110,
+  110,  110,    0,    0,    0,    0,  168,  110,  168,  168,
+  168,  110,  110,  110,  110,  168,  168,  168,  168,  168,
+  168,  110,  110,  168,  168,  110,  110,  110,  110,  110,
+  168,  110,  110,    0,  168,  110,  168,  168,  110,  110,
+  110,   22,   24,   25,   26,   27,   28,    0,   29,   30,
+   31,    0,    0,  143,   32,    0,  143,   33,   34,   35,
+   36,    0,    0,    0,   37,   38,    0,   39,   40,   41,
+  143,  143,    0,    0,   42,   43,   44,   45,   46,   47,
+    0,    0,   49,   50,    0,    0,    0,    0,    0,   51,
+    0,    0,    0,   54,   47,   55,   56,   47,   47,   47,
+    0,   47,    0,   47,   47,  143,   47,    0,    0,    0,
+    0,    0,    0,    0,    0,   95,   95,   95,   95,    0,
+   47,    0,    0,    0,   95,   47,    0,    0,   95,   95,
+   95,   95,    0,    0,    0,    0,    0,    0,   95,   95,
+    0,    0,   95,   95,   95,   95,   95,    0,   95,   95,
+   52,    0,   47,   62,   64,   48,    0,   57,    0,   65,
+   60,   91,   59,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,  120,  123,    0,    0,  111,    0,    0,
+    0,   63,    0,  119,   47,  125,    0,   47,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,  139,  140,  141,
+  142,  170,    0,    0,    0,    0,   52,    0,   61,   62,
+   64,   48,    0,   57,  123,   65,   60,    0,   59,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,  152,    0,    0,    0,   63,    0,    0,
+   23,    0,  123,   53,    0,  205,  334,  335,  336,  211,
+    0,    0,  339,    0,  341,    0,    0,   64,    0,    0,
+   64,    0,    0,    0,   61,    0,    0,    0,    0,   52,
+    0,    0,   62,   64,   48,   64,   57,    0,   65,   60,
+  356,   59,    0,    0,  143,  143,  143,  143,  358,    0,
+  359,  170,    0,    0,    0,  116,   23,    0,    0,   53,
+   63,  365,    0,    0,    0,    0,  123,  143,  143,   64,
+    0,  123,    0,    0,    0,    0,    0,   47,   47,   47,
+   47,   47,   47,  152,   47,   47,   47,   61,    0,    0,
+   47,    0,    0,   47,   47,   47,   47,    0,    0,   87,
+   47,   47,   87,   47,   47,   47,    0,    0,    0,    0,
+   47,   47,   47,   47,   47,   47,   87,   87,   47,   47,
+    0,   87,   53,    0,    0,   47,    0,    0,    0,   47,
+    0,   47,   47,    0,  121,   25,   26,   27,   28,   87,
+   29,   30,   31,    0,    0,    0,   32,  138,    0,    0,
+  138,   87,    0,    0,    0,   88,    0,   38,   88,   39,
+   40,   41,    0,    0,  138,  138,   42,   43,   44,   45,
+   46,   47,   88,   88,   49,   50,  165,   88,    0,  166,
+    0,   51,  167,  168,  169,   54,    0,   55,   56,    0,
+  112,   25,   26,   27,   28,    0,   29,   30,   31,  138,
+    0,    0,   32,    0,    0,    0,    0,   88,    0,    0,
+  170,  131,    0,   38,  131,   39,   40,   41,    0,    0,
+    0,    0,   42,   43,   44,   45,   46,   47,  131,  131,
+   49,   50,    0,  131,    0,    0,    0,   51,    0,    0,
+    0,   54,  152,   55,   56,    0,    0,  156,   64,   64,
+   64,   64,    0,   24,   25,   26,   27,   28,    0,   29,
+   30,   31,    0,  131,   79,   32,  165,   79,    0,  166,
+    0,   64,  167,  168,  169,    0,   38,    0,   39,   40,
+   41,   79,   79,    0,    0,   42,   43,   44,   45,   46,
+   47,    0,    0,   49,   50,    0,    0,    0,    0,    0,
+   51,    0,    0,    0,   54,   52,   55,   56,   62,   64,
+   48,    0,   57,    0,   65,   60,   79,   59,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+   87,   87,   87,   87,    0,    0,   63,    0,    0,   87,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,   87,   87,    0,    0,   87,   87,   87,
+   87,   52,    0,   61,   62,   64,   48,    0,   57,  133,
+   65,   60,    0,   59,    0,    0,    0,    0,  138,  138,
+  138,  138,    0,    0,    0,    0,   88,   88,   88,   88,
+    0,    0,   63,    0,    0,   23,    0,    0,   53,    0,
+    0,  138,  138,    0,    0,    0,  156,  157,    0,   88,
+   88,    0,    0,   88,    0,    0,    0,   52,    0,   61,
+   62,   64,   48,    0,   57,  165,   65,   60,  166,   59,
+    0,  167,  168,  169,    0,    0,    0,    0,    0,    0,
+    0,    0,  131,  131,  131,  131,    0,    0,   63,    0,
+    0,  131,    0,    0,   53,  131,  131,    0,    0,    0,
+    0,    0,    0,    0,    0,  131,  131,    0,    0,  131,
+  131,  131,  131,  131,    0,   61,    0,  137,    0,    0,
+   52,    0,    0,   62,   64,   48,    0,   57,  201,   65,
+   60,    0,   59,    0,    0,   79,   79,   79,   79,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+   53,   63,    0,    0,    0,    0,    0,    0,   79,   79,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,   24,
+   25,   26,   27,   28,    0,   29,   30,   31,   61,    0,
+    0,   32,   67,    0,    0,   67,    0,    0,    0,    0,
+   89,    0,   38,   89,   39,   40,   41,    0,    0,   67,
+   67,   42,   43,   44,   45,   46,   47,   89,   89,   49,
+   50,    0,   89,   53,    0,    0,   51,    0,    0,    0,
+   54,    0,   55,   56,    0,   24,   25,   26,   27,   28,
+    0,   29,   30,   31,   67,    0,    0,   32,    0,    0,
+    0,    0,   89,    0,    0,    0,   90,    0,   38,   90,
+   39,   40,   41,    0,    0,    0,    0,   42,   43,   44,
+   45,   46,   47,   90,   90,   49,   50,    0,   90,    0,
+    0,    0,   51,    0,    0,    0,   54,    0,   55,   56,
+    0,   24,   25,   26,   27,   28,    0,   29,   30,   31,
+    0,    0,    0,   32,    0,    0,    0,    0,   90,    0,
+    0,    0,  142,    0,   38,  142,   39,   40,   41,    0,
+    0,    0,    0,   42,   43,   44,   45,   46,   47,  142,
+  142,   49,   50,    0,  142,    0,    0,    0,   51,    0,
+    0,    0,   54,    0,   55,   56,    0,    0,    0,    0,
+    0,    0,    0,    0,   24,   25,   26,   27,   28,    0,
+   29,   30,   31,    0,  142,    0,   32,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,  159,   38,    0,   39,
+   40,   41,    0,    0,    0,    0,   42,   43,   44,   45,
+   46,   47,    0,    0,   49,   50,    0,    0,    0,    0,
+    0,   51,    0,    0,  170,   54,   52,   55,   56,   62,
+   64,   48,    0,   57,  249,   65,   60,    0,   59,    0,
+    0,    0,    0,   67,   67,   67,   67,    0,    0,    0,
+    0,   89,   89,   89,   89,    0,  152,   63,    0,    0,
+   89,    0,    0,    0,    0,    0,   67,   67,    0,    0,
+    0,    0,    0,    0,   89,   89,    0,    0,   89,   89,
+   89,    0,   52,    0,   61,   62,   64,   48,    0,   57,
+    0,   65,   60,    0,   59,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,   90,   90,   90,
+   90,    0,    0,   63,    0,    0,   90,    0,    0,   53,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+   90,   90,    0,    0,   90,   90,    0,    0,   52,    0,
+   61,   62,   64,   48,    0,   57,  287,   65,   60,    0,
+   59,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,  142,  142,  142,  142,    0,    0,   63,
+    0,    0,  142,    0,    0,   53,  142,  142,    0,    0,
+    0,    0,    0,    0,    0,    0,  142,  142,    0,    0,
+  142,  142,  142,  142,  142,    0,   61,    0,    0,    0,
+    0,   52,    0,    0,   62,   64,   48,    0,   57,  289,
+   65,   60,    0,   59,  153,    0,    0,    0,  154,  155,
+  156,  157,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   53,   63,  160,  161,  162,  163,    0,  164,  165,
+    0,    0,  166,    0,    0,  167,  168,  169,    0,    0,
+   24,   25,   26,   27,   28,    0,   29,   30,   31,   61,
+    0,    0,   32,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,   38,    0,   39,   40,   41,  102,    0,
+    0,  102,   42,   43,   44,   45,   46,   47,    0,    0,
+   49,   50,    0,    0,   53,  102,  102,   51,    0,    0,
+  102,   54,    0,   55,   56,   22,   24,   25,   26,   27,
+   28,    0,   29,   30,   31,    0,    0,    0,   32,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,   38,
+  102,   39,   40,   41,    0,    0,    0,    0,   42,   43,
+   44,   45,   46,   47,    0,    0,   49,   50,    0,    0,
+    0,    0,    0,   51,    0,    0,    0,   54,  144,   55,
+   56,  144,   24,   25,   26,   27,   28,    0,   29,   30,
+   31,    0,    0,    0,   32,  144,  144,    0,    0,    0,
+  144,    0,    0,    0,    0,   38,    0,   39,   40,   41,
+    0,    0,    0,    0,   42,   43,   44,   45,   46,   47,
+    0,    0,   49,   50,    0,    0,    0,    0,  144,   51,
+  144,    0,    0,   54,    0,   55,   56,  127,    0,    0,
+  127,    0,    0,    0,    0,   24,   25,   26,   27,   28,
+    0,   29,   30,   31,  127,  127,    0,   32,    0,  127,
+  144,    0,    0,    0,    0,    0,    0,    0,   38,    0,
    39,   40,   41,    0,    0,    0,    0,   42,   43,   44,
-   45,   46,   47,    0,  139,   49,   50,  139,    0,    0,
-    0,  153,   51,  153,    0,    0,   54,    0,   55,   56,
-    0,  139,  139,    0,    0,    0,  139,    0,   24,   25,
-   26,   27,   28,    0,   29,   30,   31,    0,    0,    0,
-   32,    0,    0,  153,    0,    0,    0,    0,    0,  114,
-    0,   38,  114,   39,   40,   41,  139,    0,    0,    0,
-   42,   43,   44,   45,   46,   47,  114,  114,   49,   50,
-    0,  114,    0,    0,    0,   51,    0,    0,    0,   54,
-    0,   55,   56,    0,    0,    0,  139,    0,  153,    0,
-    0,    0,  154,  155,  156,  157,    0,    0,    0,  114,
-  155,  114,    0,  155,    0,    0,  158,  160,  161,  162,
-  163,    0,  164,  165,    0,    0,  166,  155,  155,  167,
-  168,  169,  155,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,  129,  129,  129,  129,    0,    0,    0,
-    0,    0,  129,    0,    0,    0,  129,  129,  129,  129,
-    0,    0,  155,    0,    0,    0,  129,  129,    0,  141,
-  129,  129,  129,  129,  129,    0,  129,  129,    0,    0,
-  129,    0,    0,  129,  129,  129,  141,  141,    0,    0,
-    0,  141,  155,    0,    0,    0,    0,    0,    0,    0,
+   45,   46,   47,    0,    0,   49,   50,  127,    0,  127,
+    0,    0,   51,    0,    0,    0,   54,   52,   55,   56,
+   62,   64,   48,    0,   57,    0,   65,   60,    0,   59,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,  127,
+    0,    0,    0,    0,    0,    0,    0,    0,   63,  102,
+  102,  102,  102,    0,    0,    0,    0,    0,  102,    0,
+    0,    0,  102,  102,    0,  151,    0,    0,  151,    0,
+    0,    0,  102,  102,    0,   61,  102,  102,  102,  102,
+  102,    0,  151,  151,    0,    0,    0,  151,   89,   89,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+  106,    0,    0,    0,    0,   89,  115,    0,    0,    0,
+   53,   89,    0,  122,    0,  151,    0,  151,    0,    0,
+    0,    0,    0,    0,    0,   89,   89,   89,   89,  144,
+  144,  144,  144,  112,    0,  170,  112,    0,  144,    0,
+    0,    0,  144,  144,  144,  144,    0,  151,    0,    0,
+  112,  112,  144,  144,    0,  112,  144,  144,  144,  144,
+  144,    0,  144,  144,    0,    0,  144,  152,    0,  144,
+  144,  144,    0,  122,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,  112,    0,  112,    0,    0,  127,  127,
+  127,  127,    0,    0,    0,    0,    0,  127,    0,    0,
+    0,  127,  127,  127,  127,    0,    0,    0,    0,    0,
+    0,  127,  127,    0,  170,  127,  127,  127,  127,  127,
+    0,  127,  127,    0,    0,  127,    0,    0,  127,  127,
+  127,    0,  241,  137,    0,    0,  137,    0,    0,    0,
+    0,   24,   25,   26,   27,   28,  152,   29,   30,   31,
+  137,  137,    0,   32,    0,  137,    0,    0,    0,    0,
+  275,    0,    0,    0,   38,    0,   39,   40,   41,    0,
+    0,    0,    0,   42,   43,   44,   45,   46,   47,    0,
+    0,   49,   50,    0,    0,  137,    0,    0,   51,    0,
+    0,    0,   54,    0,   55,   56,  151,  151,  151,  151,
+  153,    0,    0,  153,    0,  151,    0,    0,    0,  151,
+  151,  151,  151,    0,    0,  137,    0,  153,  153,  151,
+  151,    0,  153,  151,  151,  151,  151,  151,    0,  151,
+  151,  156,  157,  151,    0,    0,  151,  151,  151,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,  164,
+  165,    0,  153,  166,    0,    0,  167,  168,  169,    0,
+    0,    0,    0,    0,  112,  112,  112,  112,  139,    0,
+    0,    0,    0,  112,    0,    0,    0,  112,  112,  112,
+  112,    0,  153,    0,    0,  139,  139,  112,  112,    0,
+  139,  112,  112,  112,  112,  112,    0,  112,  112,    0,
+    0,  112,    0,    0,  112,  112,  112,    0,  154,  155,
+  156,  157,    0,    0,    0,    0,    0,    0,  139,    0,
+  139,    0,    0,  160,  161,  162,  163,    0,  164,  165,
+    0,  154,  166,    0,    0,  167,  168,  169,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,  154,  154,
+  139,    0,    0,  154,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,  137,  137,  137,  137,    0,    0,
+    0,    0,    0,  137,    0,    0,    0,  137,  137,  137,
+  137,  154,    0,  154,    0,    0,    0,  137,  137,    0,
+    0,  137,  137,  137,  137,  137,    0,  137,  137,  104,
+    0,  137,  104,    0,  137,  137,  137,    0,    0,    0,
+    0,    0,    0,  154,    0,    0,  104,  104,    0,    0,
+    0,  104,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,  153,  153,  153,  153,    0,    0,    0,    0,    0,
+  153,    0,    0,    0,  153,  153,  153,  153,    0,    0,
+    0,  104,    0,    0,  153,  153,    0,    0,  153,  153,
+  153,  153,  153,    0,  153,  153,   66,    0,  153,   66,
+    0,  153,  153,  153,    0,    0,    0,    0,    0,    0,
+    0,  104,    0,   66,   66,    0,    0,    0,   66,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,  139,
+  139,  139,  139,    0,    0,    0,    0,    0,  139,    0,
+    0,    0,  139,  139,  139,  139,    0,    0,   66,    0,
+    0,    0,  139,  139,    0,    0,  139,  139,  139,  139,
+  139,    0,  139,  139,    0,    0,  139,    0,    0,  139,
+  139,  139,    0,    0,    0,    0,    0,    0,   66,  170,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,  154,  154,  154,  154,   69,    0,    0,    0,
+    0,  154,    0,    0,    0,  154,  154,  154,  154,    0,
+    0,  152,    0,   69,   69,  154,  154,    0,   69,  154,
+  154,  154,  154,  154,    0,  154,  154,    0,    0,  154,
+    0,    0,  154,  154,  154,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,   69,    0,   69,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+  104,  104,  104,  104,  103,    0,    0,  103,    0,  104,
+    0,    0,    0,  104,  104,  104,  104,    0,   69,    0,
+    0,  103,  103,  104,  104,    0,  103,  104,  104,  104,
+  104,  104,    0,  104,  104,    0,    0,  104,    0,    0,
+  104,  104,  104,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,  103,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,   66,   66,   66,
+   66,  153,    0,    0,  153,    0,   66,    0,    0,    0,
+   66,   66,   66,   66,    0,    0,  103,    0,  153,  153,
+   66,   66,    0,  153,   66,   66,   66,   66,   66,    0,
+   66,   66,    0,    0,   66,    0,    0,   66,   66,   66,
+    0,    0,    0,  154,  140,  156,  157,  140,    0,    0,
+    0,    0,    0,  153,    0,    0,    0,    0,    0,    0,
+    0,  140,  140,  164,  165,    0,  140,  166,    0,    0,
+  167,  168,  169,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,  140,   69,   69,   69,
+   69,  110,    0,    0,  110,    0,   69,    0,    0,    0,
+   69,   69,   69,   69,    0,    0,    0,    0,  110,  110,
+   69,   69,    0,  110,   69,   69,   69,   69,   69,    0,
+   69,   69,    0,    0,   69,    0,    0,   69,   69,   69,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,  110,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,  103,  103,  103,  103,  117,
+    0,    0,  117,    0,  103,    0,    0,    0,  103,  103,
+  103,  103,    0,    0,    0,    0,  117,  117,  103,  103,
+    0,  117,  103,  103,  103,  103,  103,    0,  103,  103,
+    0,    0,  103,    0,    0,  103,  103,  103,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,  117,    0,    0,    0,    0,    0,    0,    0,    0,
     0,    0,  153,  153,  153,  153,    0,    0,    0,    0,
-    0,  153,    0,    0,    0,  153,  153,  153,  153,  141,
-    0,  141,    0,    0,    0,  153,  153,    0,    0,  153,
+    0,  153,    0,    0,    0,  153,  153,  153,  153,    0,
+    0,    0,    0,    0,    0,  153,  153,    0,    0,  153,
   153,  153,  153,  153,    0,  153,  153,    0,    0,  153,
-    0,    0,  153,  153,  153,  139,  139,  139,  139,   88,
-    0,  141,   88,    0,  139,    0,    0,    0,  139,  139,
-  139,  139,    0,    0,    0,    0,   88,   88,  139,  139,
-    0,   88,  139,  139,  139,  139,  139,    0,  139,  139,
-    0,    0,  139,    0,    0,  139,  139,  139,    0,    0,
-  114,  114,  114,  114,    0,    0,    0,    0,    0,  114,
-    0,   88,    0,  114,  114,  114,  114,    0,    0,    0,
-    0,  156,    0,  114,  114,    0,    0,  114,  114,  114,
-  114,  114,    0,  114,  114,    0,    0,  114,  156,  156,
-  114,  114,  114,  156,    0,    0,    0,    0,    0,    0,
-    0,  155,  155,  155,  155,    0,    0,    0,    0,    0,
-  155,    0,    0,    0,  155,  155,  155,  155,    0,    0,
-    0,  156,    0,  156,  155,  155,    0,    0,  155,  155,
-  155,  155,  155,  106,  155,  155,  106,    0,  155,    0,
-    0,  155,  155,  155,    0,    0,    0,    0,    0,    0,
-  106,  106,    0,  156,    0,  106,    0,    0,    0,    0,
-  141,  141,  141,  141,    0,    0,    0,    0,    0,  141,
-    0,    0,    0,  141,  141,  141,  141,    0,    0,    0,
-    0,    0,    0,  141,  141,  106,    0,  141,  141,  141,
-  141,  141,   68,  141,  141,   68,    0,  141,    0,    0,
-  141,  141,  141,    0,    0,    0,    0,    0,    0,   68,
-   68,    0,    0,    0,   68,  106,    0,    0,    0,    0,
+    0,    0,  153,  153,  153,  140,  140,  140,  140,  101,
+    0,    0,  101,    0,  140,    0,    0,    0,  140,  140,
+  140,  140,    0,    0,    0,    0,  101,  101,  140,  140,
+    0,  101,  140,  140,  140,  140,  140,    0,  140,  140,
+    0,    0,  140,    0,    0,  140,  140,  140,    0,    0,
     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,   71,    0,    0,
-   88,   88,   88,   88,   68,    0,    0,    0,    0,   88,
-    0,    0,    0,    0,   71,   71,    0,    0,    0,   71,
-    0,    0,    0,   88,   88,    0,    0,   88,   88,   88,
-   88,   88,    0,    0,   68,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,   71,    0,   71,
+    0,  101,  110,  110,  110,  110,    0,    0,    0,    0,
+    0,  110,    0,    0,    0,  110,  110,  110,  110,    0,
+    0,    0,    0,    0,    0,  110,  110,    0,    0,  110,
+  110,  110,  110,  110,    0,  110,  110,   96,    0,  110,
+   96,    0,  110,  110,  110,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,   96,   96,    0,    0,    0,   96,
     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,  156,  156,  156,  156,    0,    0,    0,    0,
-    0,  156,    0,    0,    0,  156,  156,  156,  156,   71,
-    0,    0,  170,    0,    0,  156,  156,    0,    0,  156,
-  156,  156,  156,  156,  105,  156,  156,  105,    0,  156,
-    0,    0,  156,  156,  156,    0,    0,    0,    0,    0,
-    0,  105,  105,    0,  152,    0,  105,    0,    0,    0,
-    0,    0,    0,    0,  106,  106,  106,  106,    0,    0,
-    0,    0,    0,  106,    0,    0,    0,  106,  106,  106,
-  106,    0,    0,    0,    0,    0,  105,  106,  106,    0,
-    0,  106,  106,  106,  106,  106,  155,  106,  106,  155,
-    0,  106,    0,    0,  106,  106,  106,    0,    0,    0,
-    0,    0,    0,  155,  155,    0,  105,    0,  155,    0,
-    0,    0,    0,   68,   68,   68,   68,    0,    0,    0,
-    0,    0,   68,    0,    0,    0,   68,   68,   68,   68,
-    0,    0,    0,    0,    0,    0,   68,   68,  155,    0,
-   68,   68,   68,   68,   68,    0,   68,   68,    0,    0,
-   68,    0,    0,   68,   68,   68,    0,    0,   71,   71,
-   71,   71,  142,    0,    0,  142,    0,   71,    0,    0,
-    0,   71,   71,   71,   71,    0,    0,    0,    0,  142,
-  142,   71,   71,    0,  142,   71,   71,   71,   71,   71,
-    0,   71,   71,    0,    0,   71,    0,    0,   71,   71,
-   71,    0,    0,    0,    0,    0,  154,  112,  156,  157,
-  112,    0,    0,    0,  142,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,  112,  112,  164,  165,    0,  112,
-  166,    0,    0,  167,  168,  169,    0,    0,    0,    0,
+  117,  117,  117,  117,    0,    0,    0,    0,    0,  117,
+    0,    0,    0,  117,  117,  117,  117,    0,    0,   96,
+    0,    0,    0,  117,  117,    0,    0,  117,  117,  117,
+  117,  117,    0,  117,  117,   93,    0,  117,    0,    0,
+  117,  117,  117,  107,    0,    0,    0,    0,  114,    0,
+   97,    0,    0,   97,    0,    0,  127,  128,  129,  130,
+  131,  132,    0,    0,  135,  136,    0,   97,   97,    0,
+    0,  143,   97,    0,    0,    0,    0,    0,    0,    0,
     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,  105,  105,  105,  105,  112,
-    0,    0,    0,    0,  105,    0,    0,    0,  105,  105,
-  105,  105,    0,    0,    0,    0,    0,    0,  105,  105,
-    0,    0,  105,  105,  105,  105,  105,  119,  105,  105,
-  119,    0,  105,    0,    0,  105,  105,  105,    0,    0,
-    0,    0,    0,    0,  119,  119,    0,    0,    0,  119,
-    0,    0,    0,    0,    0,    0,    0,  155,  155,  155,
-  155,    0,    0,    0,    0,    0,  155,    0,    0,    0,
-  155,  155,  155,  155,    0,    0,    0,    0,    0,  119,
-  155,  155,    0,    0,  155,  155,  155,  155,  155,  102,
-  155,  155,  102,    0,  155,    0,    0,  155,  155,  155,
-    0,    0,    0,    0,    0,    0,  102,  102,    0,    0,
-    0,  102,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,  186,   93,    0,
+    0,   93,   97,    0,    0,    0,    0,    0,    0,    0,
+  101,  101,  101,  101,    0,   93,   93,    0,    0,  101,
+   93,    0,    0,  101,  101,  101,  101,    0,    0,    0,
+    0,    0,    0,  101,  101,    0,    0,  101,  101,  101,
+  101,  101,    0,  101,  101,    0,    0,  101,    0,    0,
+   93,    0,    0,    0,    0,    0,    0,    0,  224,  225,
+  226,  227,  228,  229,  230,  231,  232,  233,  234,  235,
+  236,  237,   94,    0,    0,   94,    0,    0,    0,    0,
+    0,    0,    0,  251,    0,    0,    0,    0,    0,   94,
+   94,    0,    0,    0,   94,    0,    0,    0,   96,   96,
+   96,   96,    0,    0,    0,    0,    0,   96,    0,    0,
+    0,   96,   96,   96,   96,    0,   92,    0,    0,   92,
+    0,   96,   96,    0,   94,   96,   96,   96,   96,   96,
+    0,   96,   96,   92,   92,    0,    0,    0,   92,    0,
     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,  142,  142,  142,  142,  103,    0,    0,
-  103,  102,  142,    0,    0,    0,  142,  142,  142,  142,
-    0,    0,    0,    0,  103,  103,  142,  142,    0,  103,
-  142,  142,  142,  142,  142,    0,  142,  142,    0,    0,
-  142,    0,    0,  142,  142,  142,    0,    0,  112,  112,
-  112,  112,   97,    0,    0,   97,    0,  112,    0,  103,
-    0,  112,  112,  112,  112,    0,    0,    0,    0,   97,
-   97,  112,  112,    0,   97,  112,  112,  112,  112,  112,
-    0,  112,  112,    0,    0,  112,    0,    0,  112,  112,
-  112,    0,    0,   98,    0,    0,   98,    0,    0,    0,
-    0,    0,    0,    0,   97,    0,    0,    0,    0,    0,
-   98,   98,    0,    0,    0,   98,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,  119,  119,
-  119,  119,   99,    0,    0,   99,    0,  119,    0,    0,
-    0,  119,  119,  119,  119,   98,    0,    0,    0,   99,
-   99,  119,  119,    0,   99,  119,  119,  119,  119,  119,
-    0,  119,  119,    0,    0,  119,    0,    0,  119,  119,
-  119,    0,    0,    0,    0,    0,    0,    0,   95,    0,
-    0,   95,    0,    0,   99,    0,    0,    0,    0,    0,
-  102,  102,  102,  102,    0,   95,   95,    0,    0,  102,
-   95,    0,    0,  102,  102,  102,  102,    0,    0,    0,
-    0,    0,    0,  102,  102,    0,    0,  102,  102,  102,
-  102,  102,    0,  102,  102,    0,   96,  102,    0,   96,
-   95,    0,  170,    0,    0,    0,    0,    0,  103,  103,
-  103,  103,    0,   96,   96,    0,    0,  103,   96,    0,
-    0,  103,  103,  103,  103,    0,    0,    0,    0,    0,
-    0,  103,  103,    0,  152,  103,  103,  103,  103,  103,
-    0,  103,  103,    0,    0,  103,    0,    0,   96,    0,
-    0,    0,    0,   97,   97,   97,   97,    0,    0,    0,
-    0,    0,   97,    0,    0,    0,   97,   97,   97,   97,
-  170,    0,    0,    0,    0,    0,   97,   97,    0,    0,
-   97,   97,   97,   97,   97,    0,   97,   97,    0,    0,
-    0,    0,    0,    0,   98,   98,   98,   98,   94,    0,
-    0,   94,  152,   98,    0,    0,    0,   98,   98,   98,
-   98,    0,    0,    0,    0,   94,   94,   98,   98,    0,
-   94,   98,   98,   98,   98,   98,    0,   98,   98,    0,
-    0,    0,    0,   99,   99,   99,   99,   82,    0,    0,
-   82,    0,   99,    0,    0,    0,   99,   99,   99,   99,
-   94,    0,    0,    0,   82,   82,   99,   99,    0,   82,
-   99,   99,   99,   99,   99,    0,   99,   99,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,    0,   95,
-   95,   95,   95,   84,    0,    0,   84,    0,   95,   82,
-    0,    0,   95,   95,   95,   95,  154,  155,  156,  157,
-   84,   84,   95,   95,    0,   84,   95,   95,   95,   95,
-   95,    0,   95,   95,  163,    0,  164,  165,    0,    0,
-  166,    0,    0,  167,  168,  169,    0,   96,   96,   96,
-   96,   85,    0,    0,   85,   84,   96,    0,    0,    0,
-   96,   96,   96,   96,    0,    0,    0,    0,   85,   85,
-   96,   96,    0,   85,   96,   96,   96,   96,   96,    0,
-   96,   96,    0,    0,  154,  155,  156,  157,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,    0,  160,
-  161,  162,  163,   85,  164,  165,    0,    0,  166,    0,
-    0,  167,  168,  169,  133,    0,    0,  133,    0,    0,
+    0,    0,    0,    0,   80,    0,    0,   80,    0,    0,
+    0,    0,    0,  308,    0,    0,    0,    0,   92,    0,
+    0,   80,   80,    0,    0,    0,   80,    0,    0,    0,
+    0,   97,   97,   97,   97,    0,    0,    0,    0,    0,
+   97,    0,    0,    0,   97,   97,   97,   97,    0,   81,
+  326,    0,   81,    0,   97,   97,   80,    0,   97,   97,
+   97,   97,   97,    0,   97,   97,   81,   81,    0,    0,
+    0,   81,    0,    0,    0,    0,    0,    0,    0,   93,
+   93,   93,   93,    0,    0,    0,    0,    0,   93,    0,
+    0,    0,   93,   93,   93,   93,    0,   82,    0,    0,
+   82,   81,   93,   93,  170,    0,   93,   93,   93,   93,
+   93,    0,   93,   93,   82,   82,    0,    0,    0,   82,
     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,  133,  133,    0,    0,    0,  133,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,    0,   94,
-   94,   94,   94,  144,    0,    0,  144,    0,   94,    0,
-    0,    0,   94,   94,   94,   94,  133,    0,    0,    0,
-  144,  144,   94,   94,    0,  144,   94,   94,   94,   94,
-   94,    0,   94,   94,    0,    0,    0,    0,   82,   82,
+    0,    0,    0,    0,    0,    0,  152,    0,    0,    0,
+    0,   84,    0,    0,   84,    0,    0,    0,    0,   82,
+    0,    0,    0,   94,   94,   94,   94,   85,   84,   84,
+   85,    0,   94,   84,    0,    0,   94,   94,   94,   94,
+    0,    0,    0,    0,   85,   85,   94,   94,    0,   85,
+   94,   94,   94,   94,   94,    0,   94,   94,    0,    0,
+    0,    0,    0,   84,    0,    0,    0,   92,   92,   92,
+   92,   86,    0,    0,   86,    0,   92,    0,    0,   85,
+   92,   92,   92,   92,    0,    0,    0,    0,   86,   86,
+   92,   92,    0,   86,   92,   92,   92,   92,   92,    0,
+   92,   92,    0,    0,    0,   80,   80,   80,   80,    0,
+    0,  295,    0,    0,   80,    0,  159,    0,   80,   80,
+   80,   80,    0,   86,    0,    0,    0,    0,   80,   80,
+    0,    0,   80,   80,   80,   80,   80,    0,   80,   80,
+    0,    0,    0,    0,  170,    0,    0,    0,    0,    0,
+   81,   81,   81,   81,    0,    0,  159,    0,    0,   81,
+    0,    0,    0,   81,   81,   81,   81,    0,  154,  155,
+  156,  157,    0,   81,   81,    0,  152,   81,   81,   81,
+   81,   81,    0,   81,  170,  162,  163,    0,  164,  165,
+    0,    0,  166,    0,    0,  167,  168,  169,   82,   82,
    82,   82,    0,    0,    0,    0,    0,   82,    0,    0,
-    0,   82,   82,   82,   82,  144,    0,    0,    0,    0,
+    0,   82,   82,    0,   82,  170,  152,    0,    0,    0,
     0,   82,   82,    0,    0,   82,   82,   82,   82,   82,
-    0,   82,   82,    0,    0,    0,    0,  104,    0,    0,
-  104,    0,    0,    0,   84,   84,   84,   84,    0,    0,
-    0,    0,    0,   84,  104,  104,    0,   84,   84,  104,
-   84,    0,    0,    0,    0,    0,    0,   84,   84,    0,
-    0,   84,   84,   84,   84,   84,    0,   84,    0,    0,
-   92,    0,    0,   92,    0,    0,    0,    0,    0,  104,
-    0,    0,   85,   85,   85,   85,    0,   92,   92,    0,
-    0,   85,   92,    0,    0,   85,   85,    0,    0,    0,
-    0,    0,    0,    0,    0,   85,   85,    0,   93,   85,
-   85,   85,   85,   85,    0,   85,  107,    0,  293,    0,
-    0,  114,   92,  159,    0,    0,    0,    0,    0,  127,
-  128,  129,  130,  131,  132,    0,    0,  135,  136,    0,
-    0,    0,    0,    0,  143,  133,  133,  133,  133,    0,
-    0,  170,    0,    0,  133,    0,    0,    0,  133,  133,
-  159,    0,    0,    0,    0,    0,    0,    0,  133,  133,
-  186,    0,  133,  133,  133,  133,  133,    0,    0,    0,
-    0,    0,    0,  152,  144,  144,  144,  144,  170,    0,
-  159,    0,    0,  144,    0,    0,    0,  144,  144,    0,
-    0,    0,    0,    0,    0,    0,    0,  144,  144,    0,
-    0,  144,  144,  144,  144,  144,    0,    0,  170,    0,
-  152,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,  224,  225,  226,  227,  228,  229,  230,  231,  232,
-  233,  234,  235,  236,  237,    0,    0,    0,  170,    0,
-  152,    0,    0,    0,    0,    0,  251,    0,  104,  104,
-  104,  104,    0,    0,    0,    0,    0,  104,    0,    0,
-    0,  104,  104,    0,    0,    0,    0,    0,    0,    0,
-  152,  104,  104,    0,    0,  104,  104,  104,  104,  104,
+    0,   82,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,   84,   84,   84,   84,    0,  152,    0,    0,
+    0,   84,    0,    0,    0,    0,   84,    0,   85,   85,
+   85,   85,    0,    0,    0,   84,   84,   85,    0,   84,
+   84,   84,   84,   84,    0,    0,    0,    0,    0,    0,
+    0,   85,   85,    0,    0,   85,   85,   85,   85,   85,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,   86,   86,   86,   86,    0,    0,    0,    0,
+    0,   86,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,   86,   86,    0,    0,   86,
+   86,   86,   86,   86,  153,    0,    0,    0,  154,  155,
+  156,  157,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,  158,  160,  161,  162,  163,    0,  164,  165,
+    0,    0,  166,    0,    0,  167,  168,  169,    0,    0,
+    0,    0,    0,    0,  153,    0,    0,    0,  154,  155,
+  156,  157,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,  158,  160,  161,  162,  163,    0,  164,  165,
+    0,    0,  166,    0,    0,  167,  168,  169,    0,  154,
+  155,  156,  157,    0,    0,    0,    0,    0,    0,   67,
+    0,    0,    0,   81,    0,  161,  162,  163,    0,  164,
+  165,    0,    0,  166,    0,    0,  167,  168,  169,   97,
+   99,  101,  103,    0,    0,    0,    0,    0,    0,  113,
+    0,    0,    0,    0,    0,    0,    0,  126,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,  179,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+  187,    0,    0,  190,    0,  192,    0,  194,    0,  196,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,   92,   92,   92,   92,    0,    0,    0,    0,    0,
-   92,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-    0,    0,    0,    0,   92,   92,    0,    0,   92,   92,
-    0,    0,    0,    0,    0,    0,  306,    0,    0,    0,
-    0,  153,    0,    0,    0,  154,  155,  156,  157,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,    0,  158,
-  160,  161,  162,  163,    0,  164,  165,    0,    0,  166,
-    0,  324,  167,  168,  169,    0,    0,    0,  153,    0,
-    0,    0,  154,  155,  156,  157,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,  158,  160,  161,  162,
-  163,    0,  164,  165,    0,    0,  166,    0,  153,  167,
-  168,  169,  154,  155,  156,  157,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,  160,  161,  162,
-  163,    0,  164,  165,    0,    0,  166,    0,    0,  167,
-  168,  169,  154,  155,  156,  157,    0,    0,    0,    0,
-    0,    0,    0,    0,    0,    0,    0,    0,  161,  162,
-  163,    0,  164,  165,    0,    0,  166,    0,    0,  167,
-  168,  169,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+  215,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,  253,    0,    0,
+    0,    0,    0,    0,  260,
 };
 short yycheck[] = {                                      13,
-   85,   36,   41,  185,   91,   40,  123,   36,   59,   93,
-   41,   33,   59,   93,   36,   37,   38,   59,   40,   93,
-   42,   43,   59,   45,   41,   59,   41,  196,   90,   41,
-   44,   91,   40,   40,   91,   26,  123,   41,   59,   41,
-  257,   41,   64,   57,   40,   40,   59,   61,    0,   93,
-   44,   42,    6,  257,    8,   40,  118,   48,   41,   50,
-   40,   40,   91,  123,   41,   40,  123,  276,  277,   91,
-   40,   62,   63,   64,   65,  278,   59,   31,   32,   41,
-  257,   33,   59,   91,   36,   37,   38,  123,   40,  123,
-   42,   43,   41,   45,  123,  109,   40,   59,   59,   59,
-   41,  123,  123,   36,  126,   41,   44,   59,    0,  260,
-   59,  257,   64,  123,  296,  123,  123,   59,   59,  110,
-  182,  295,  296,   59,   59,  187,   40,  123,  123,   40,
-   36,   41,  146,  147,  148,  149,  150,  151,  152,   91,
-  257,   33,   40,  123,   36,   37,   38,  125,   40,  125,
-   42,   43,   91,   45,   41,  296,  170,  171,  172,  173,
-  174,  175,  176,   91,    0,  334,   40,   59,  337,   59,
-   41,  123,   64,  125,  126,  189,   41,  191,   41,  193,
-  123,  195,   41,   40,  198,  199,   41,  356,   40,   59,
-  123,  205,  206,  207,  125,  125,  125,   33,  212,   91,
-   36,   37,   38,  125,   40,   93,   42,   43,  125,   45,
-   41,  295,  296,   41,   59,  295,  296,   41,  123,   41,
-  257,  295,  296,   59,  238,   59,  240,  314,   64,  258,
-   41,  123,   93,  125,  126,  257,  258,  259,  260,  261,
-  262,  263,  264,  265,  295,  296,   59,  269,  295,  296,
-   41,  295,  296,  295,  296,   91,  295,  296,  280,  294,
-  282,  283,  284,  348,  295,  296,   41,  289,  290,  291,
-  292,  293,  294,   59,   93,  297,  298,  291,  295,  296,
-  295,  296,  304,  295,  296,   59,  308,  123,  310,  311,
-  126,  295,  296,  295,  296,  295,  296,   41,  312,  362,
-  314,  295,  296,   13,  256,  257,  258,  259,  260,  261,
-  340,  263,  264,  265,  266,  267,  268,  269,  270,  271,
-  272,  273,  274,  275,  257,  312,  340,  279,  280,  262,
-  282,  283,  284,   41,  295,  296,   44,  289,  290,  291,
-  292,  293,  294,  147,  195,  297,  298,   95,  362,  125,
-   58,   59,  304,  295,  296,   -1,  308,   91,  310,  311,
-  295,  296,   -1,   -1,  256,  257,  258,  259,  260,  261,
-   -1,  263,  264,  265,  266,  267,  268,  269,  270,  271,
-  272,  273,  274,  275,   -1,   93,   -1,  279,  280,  123,
-  282,  283,  284,   -1,   -1,   -1,   -1,  289,  290,  291,
-  292,  293,  294,   -1,   -1,  297,  298,  295,  296,   41,
-   91,   -1,  304,   41,   -1,   -1,  308,   -1,  310,  311,
-  256,  257,  258,  259,  260,  261,   -1,  263,  264,  265,
-   -1,   59,   -1,  269,  295,  296,  272,  273,  274,  275,
-   -1,   -1,  123,  279,  280,   -1,  282,  283,  284,   -1,
-   -1,   -1,   -1,  289,  290,  291,  292,  293,  294,   13,
-   -1,  297,  298,   17,   91,   93,   41,  125,  304,   44,
-   -1,   -1,  308,   91,  310,  311,  295,  296,   -1,   33,
-   34,   35,   36,   58,   59,   -1,   -1,   -1,   63,   43,
-  266,  267,  268,   -1,  270,  271,  123,   51,   -1,   -1,
-  307,  308,  309,   -1,   -1,  123,  313,   -1,  315,   -1,
-   -1,   96,   -1,   98,   -1,  100,   91,  102,   93,  104,
-  105,   -1,   -1,   -1,   -1,   33,   80,   -1,   36,   37,
-   38,   -1,   40,   41,   42,   43,   44,   45,   -1,   -1,
-   94,   -1,  349,   97,  351,   99,   -1,  101,  123,  103,
-   58,   59,   -1,  287,  288,   63,   64,  364,  272,  273,
-  274,  275,   -1,   -1,  272,  273,  274,  275,   -1,   -1,
-   -1,  305,  306,   -1,   -1,  309,   -1,   -1,  312,  313,
-  314,  295,  296,   91,   -1,   93,   -1,  295,  296,   -1,
-  144,   33,   -1,   -1,   36,   37,   38,   -1,   40,   41,
-   42,   43,   44,   45,  285,  286,  287,  288,  266,  267,
-  268,   -1,  270,  271,   -1,  123,   58,   59,  126,   -1,
-   -1,   63,   64,   -1,  305,  306,   -1,  181,  309,   -1,
-   -1,  312,  313,  314,  188,   -1,   -1,   -1,   -1,   -1,
-  272,  273,  274,  275,  272,  273,  274,  275,   -1,   -1,
-   33,   93,   -1,   36,   37,   38,   -1,   40,   -1,   42,
-   43,   -1,   45,  295,  296,   -1,   -1,  295,  296,  287,
-  288,   -1,   -1,  266,  267,  268,   59,  270,  271,  306,
-   -1,   64,  309,   -1,  126,  312,  313,  314,  306,   -1,
-   -1,  309,   -1,   -1,  312,  313,  314,  272,  273,  274,
-  275,   91,   -1,   -1,   -1,   -1,  281,   -1,   91,   -1,
-  285,  286,  287,  288,   -1,   -1,   -1,   -1,   -1,   -1,
-  295,  296,   -1,   -1,  299,  300,  301,  302,  303,   -1,
-  305,  306,   -1,  123,  309,   -1,   -1,  312,  313,  314,
-  123,   -1,   -1,  126,   -1,   -1,   -1,   -1,   -1,  257,
-  258,  259,  260,  261,   -1,  263,  264,  265,   -1,   -1,
-   -1,  269,   -1,  317,  272,  273,  274,  275,   -1,   -1,
-   -1,   -1,  280,  281,  282,  283,  284,  285,  286,  287,
-  288,  289,  290,  291,  292,  293,  294,  295,  296,  297,
-  298,  299,  300,  301,  302,  303,  304,  305,  306,   -1,
-  308,  309,  310,  311,  312,  313,  314,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,  257,  258,  259,  260,  261,
-   -1,  263,  264,  265,   -1,   -1,  190,  269,  192,   -1,
-  272,  273,  274,  275,   -1,   -1,   -1,   -1,  280,  281,
-  282,  283,  284,  285,  286,  287,  288,  289,  290,  291,
-  292,  293,  294,  295,  296,  297,  298,  299,  300,  301,
-  302,  303,  304,  305,  306,   -1,  308,  309,  310,  311,
-  312,  313,  314,  256,  257,  258,  259,  260,  261,   -1,
-  263,  264,  265,   -1,   -1,   41,  269,   -1,   44,  272,
-  273,  274,  275,   -1,   -1,   -1,  279,  280,   -1,  282,
-  283,  284,   58,   59,   -1,   -1,  289,  290,  291,  292,
-  293,  294,   -1,   -1,  297,  298,   -1,   -1,   -1,  309,
-   -1,  304,  312,  313,  314,  308,   33,  310,  311,   36,
-   37,   38,   -1,   40,   -1,   42,   43,   93,   45,   -1,
-   -1,   25,   26,   -1,   -1,   -1,   -1,   -1,   -1,   49,
-   50,   -1,   59,   37,   -1,   -1,   -1,   64,   42,   43,
-   -1,   -1,   -1,   -1,   48,   -1,   50,   -1,  332,  333,
-   -1,   -1,   -1,   -1,   -1,  339,   -1,  341,   62,   63,
-   64,   65,   33,   -1,   91,   36,   37,   38,   -1,   40,
-   90,   42,   43,  357,   45,   -1,   -1,   -1,   -1,   -1,
+   36,   85,   59,  196,   40,  123,   59,   36,   93,   91,
+   59,   41,   93,   91,   44,   40,  185,   41,   36,   41,
+   44,   90,   59,   91,  198,   59,   41,   93,   58,   59,
+   44,  257,   40,   40,   58,   59,   41,  257,   41,   44,
+   91,  123,   40,   57,   59,  123,   59,   61,   41,  118,
+   41,   41,   41,   58,   59,  123,   44,   41,   63,   41,
+  257,   40,  278,   93,    0,    6,   91,    8,   59,   93,
+   59,   40,  123,   91,   41,  125,   96,   40,   98,   59,
+  100,   59,  102,   40,  104,  105,  123,   40,   93,  123,
+   31,   32,   59,   41,  123,  109,  110,   33,  123,   41,
+   36,   37,   38,   41,   40,  123,   42,   43,  282,   45,
+   40,   59,  123,  182,   59,  123,  123,   59,  187,  276,
+  277,   59,   59,   59,   44,  123,  123,   59,   64,  298,
+  295,  296,  146,  147,  148,  149,  150,  151,  152,  257,
+  314,  257,  316,  336,  123,  260,  339,  266,  267,  268,
+   41,  270,  271,   44,   40,   91,  170,  171,  172,  173,
+  174,  175,  176,    0,   40,  358,   41,   58,   59,   40,
+  125,  185,   63,   91,   93,  189,   93,  191,   36,  199,
+   41,  195,  125,   93,  198,   91,  296,  123,   40,  125,
+  126,  205,  206,  207,   59,   41,   33,   93,  212,   36,
+   37,   38,   93,   40,  257,   42,   43,   41,   45,   41,
+  295,  296,   41,   40,  295,  296,  266,  267,  268,    0,
+  270,  271,   59,  123,  238,   41,  240,   64,  257,  295,
+  296,  309,  314,  262,  312,  313,  314,   40,  295,  296,
+  258,   41,  272,  273,  274,  275,  295,  296,  272,  273,
+  274,  275,   33,  337,   91,   36,   37,   38,  294,   40,
+   59,   42,   43,  125,   45,  295,  296,  272,  273,  274,
+  275,  295,  296,  295,  296,  299,  281,  125,   59,  293,
+  285,  286,  125,   64,  298,  125,  123,   41,  125,  126,
+  295,  296,  295,  296,  299,  300,  301,  302,  303,  125,
+  305,   41,  295,  296,  318,  295,  296,  295,  296,   41,
+   91,  295,  296,  295,  296,  295,  296,  295,  296,   41,
+  256,  257,  258,  259,  260,  261,   59,  263,  264,  265,
+  266,  267,  268,  269,  270,  271,  272,  273,  274,  275,
+   41,  355,  123,  279,  280,  126,  282,  283,  284,   41,
+  295,  296,  123,  289,  290,  291,  292,  293,  294,   41,
+   59,  297,  298,  295,  296,   41,   41,   59,  304,   44,
+   59,   41,  308,   41,  310,  311,  295,  296,  295,  296,
+   59,  272,  273,  274,  275,  295,  296,   41,   63,   13,
+  281,  147,  318,  355,  285,  286,  287,  288,  195,  295,
+  296,   93,  125,   -1,  295,  296,   -1,   95,  299,  300,
+  301,  302,  303,   -1,  305,  306,   91,   -1,  309,  256,
+  257,  258,  259,  260,  261,   -1,  263,  264,  265,  266,
+  267,  268,  269,  270,  271,  272,  273,  274,  275,   -1,
+   41,   -1,  279,  280,   -1,  282,  283,  284,  123,   91,
+   -1,   -1,  289,  290,  291,  292,  293,  294,   -1,   -1,
+  297,  298,   63,  272,  273,  274,  275,  304,   -1,   -1,
+   -1,  308,   -1,  310,  311,  256,  257,  258,  259,  260,
+  261,  123,  263,  264,  265,   -1,  295,  296,  269,   -1,
+   91,  272,  273,  274,  275,   -1,   -1,   -1,  279,  280,
+   -1,  282,  283,  284,   -1,   -1,   -1,   -1,  289,  290,
+  291,  292,  293,  294,   -1,   -1,  297,  298,   -1,   -1,
+   -1,   -1,  123,  304,  190,   91,  192,  308,   33,  310,
+  311,   36,   37,   38,   -1,   40,   41,   42,   43,   44,
+   45,   -1,   -1,  266,  267,  268,   -1,  270,  271,   -1,
+   -1,   -1,   -1,   58,   59,   -1,   -1,  123,   63,   64,
    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   64,   -1,   -1,  123,   -1,  118,  126,
-   -1,   -1,   -1,   -1,   -1,  125,  110,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   33,   -1,
-   91,   36,   37,   38,   -1,   40,   -1,   42,   43,   -1,
-   45,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   59,   -1,   -1,   -1,   -1,   64,
-   -1,   -1,  123,   -1,   -1,  126,   -1,   -1,   -1,   -1,
-   -1,   -1,  182,   -1,   -1,  169,   41,  187,   -1,   44,
-   -1,   -1,   -1,   -1,   -1,   -1,   91,   -1,   -1,   -1,
-   -1,   -1,   33,   58,   59,   36,   37,   38,   63,   40,
-   -1,   42,   43,  197,   45,   -1,  272,  273,  274,  275,
    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,  126,   -1,   64,   -1,   -1,   -1,   -1,   93,  295,
-  296,   -1,   -1,  299,   -1,   -1,   -1,   -1,   -1,  256,
-  257,  258,  259,  260,  261,   -1,  263,  264,  265,   -1,
-   91,   -1,  269,   -1,   -1,  272,  273,  274,  275,   -1,
-   -1,   41,  279,  280,   44,  282,  283,  284,   -1,   -1,
-   -1,   -1,  289,  290,  291,  292,  293,  294,   58,   59,
-  297,  298,  123,   63,   -1,  126,   -1,  304,   -1,   -1,
-   -1,  308,   -1,  310,  311,   -1,  257,  258,  259,  260,
-  261,   -1,  263,  264,  265,   -1,   -1,   -1,  269,   41,
-   -1,   -1,   44,   93,   -1,   -1,   -1,   41,   -1,  280,
-   44,  282,  283,  284,   -1,   -1,   58,   59,  289,  290,
-  291,  292,  293,  294,   58,   59,  297,  298,   -1,   63,
-   -1,   -1,   -1,  304,   -1,   -1,   -1,  308,   -1,  310,
-  311,   -1,  257,  258,  259,  260,  261,   -1,  263,  264,
-  265,   93,   -1,   -1,  269,   -1,   -1,   -1,   -1,   93,
-   -1,   -1,   -1,   41,   -1,  280,   44,  282,  283,  284,
-   -1,   -1,   -1,   -1,  289,  290,  291,  292,  293,  294,
-   58,   59,  297,  298,   -1,   63,   -1,   -1,   -1,  304,
-   -1,   91,   -1,  308,   -1,  310,  311,  272,  273,  274,
-  275,   -1,   -1,   -1,   -1,   -1,  257,  258,  259,  260,
-  261,   -1,  263,  264,  265,   93,   -1,   -1,  269,   41,
-  295,  296,   44,  123,  299,   -1,   -1,   41,   -1,  280,
-   44,  282,  283,  284,   -1,   -1,   58,   59,  289,  290,
-  291,  292,  293,  294,   -1,   59,  297,  298,   -1,   -1,
-   -1,   -1,   -1,  304,   -1,   -1,   -1,  308,   33,  310,
-  311,   36,   37,   38,   -1,   40,   41,   42,   43,   -1,
-   45,   93,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   93,
-   -1,   -1,  272,  273,  274,  275,   -1,   -1,   -1,   64,
-   -1,  281,   -1,   -1,   -1,  285,  286,  287,  288,   -1,
-   -1,   -1,   -1,   -1,   -1,  295,  296,   -1,   -1,  299,
-  300,  301,  302,  303,   33,  305,   91,   36,   37,   38,
-   -1,   40,   -1,   42,   43,   -1,   45,   -1,   -1,   -1,
-  272,  273,  274,  275,   -1,   -1,   -1,   -1,  272,  273,
-  274,  275,   -1,   -1,   -1,   64,   -1,  281,   -1,   -1,
-   -1,  126,  286,  295,  296,   -1,   -1,   -1,   -1,   -1,
-   -1,  295,  296,   -1,   -1,  299,  300,  301,  302,  303,
-   -1,   -1,   91,   33,   93,   -1,   36,   37,   38,   -1,
-   40,   41,   42,   43,   -1,   45,   -1,  287,   -1,   -1,
-   -1,   -1,   -1,   -1,  272,  273,  274,  275,   -1,   -1,
-   -1,   -1,   -1,  281,   64,   -1,  306,  126,   -1,  309,
-   -1,   -1,  312,  313,  314,   -1,   -1,  295,  296,   -1,
-   -1,  299,  300,  301,  302,  303,   -1,   -1,   -1,   -1,
-   -1,   91,   -1,   33,   -1,   -1,   36,   37,   38,   -1,
-   40,   41,   42,   43,   -1,   45,   -1,   -1,   -1,   -1,
-  272,  273,  274,  275,   -1,   -1,   -1,   -1,  272,  273,
-  274,  275,   -1,   -1,   64,   -1,  126,   -1,   -1,   -1,
-   -1,   -1,   -1,  295,  296,   -1,   -1,   -1,   -1,   -1,
-   -1,  295,  257,  258,  259,  260,  261,   -1,  263,  264,
-  265,   91,   -1,   -1,  269,   41,   -1,   -1,   44,   -1,
-   -1,   -1,   -1,   41,   -1,  280,   44,  282,  283,  284,
-   -1,   -1,   58,   59,  289,  290,  291,  292,  293,  294,
-   58,   59,  297,  298,   -1,   63,  126,   -1,   -1,  304,
-   -1,   -1,   -1,  308,   -1,  310,  311,   -1,  257,  258,
-  259,  260,  261,   -1,  263,  264,  265,   93,   -1,   -1,
-  269,   -1,   -1,   -1,   -1,   93,   -1,   -1,   -1,   41,
-   -1,  280,   44,  282,  283,  284,   -1,   -1,   -1,   -1,
+  272,  273,  274,  275,   -1,   -1,   91,   -1,   93,   33,
+   -1,   -1,   36,   37,   38,   -1,   40,   41,   42,   43,
+   44,   45,   -1,  295,  296,   -1,  281,   -1,   -1,   -1,
+  285,  286,  287,  288,   58,   59,   -1,   -1,  123,   63,
+   64,  126,   -1,   -1,  299,  300,  301,  302,  303,   -1,
+  305,  306,   -1,   -1,  309,   -1,   -1,  312,  313,  314,
+   -1,   -1,   -1,  285,  286,  287,  288,   -1,   33,   93,
+   -1,   36,   37,   38,   -1,   40,   -1,   42,   43,   -1,
+   45,  303,   -1,  305,  306,   -1,   -1,  309,  334,  335,
+  312,  313,  314,   -1,   59,  341,   -1,   -1,   -1,   64,
+  281,   -1,  126,   -1,  285,  286,  287,  288,   -1,   -1,
+  356,   -1,   -1,  359,   -1,   -1,   -1,   -1,  299,  300,
+  301,  302,  303,   -1,  305,  306,   91,   -1,  309,   -1,
+   -1,  312,  313,  314,   41,   -1,   -1,   44,   -1,  285,
+  286,  287,  288,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   58,   59,   -1,   -1,   -1,   63,   -1,  123,  305,
+  306,  126,   -1,  309,   -1,   -1,  312,  313,  314,   -1,
+   -1,   -1,  257,  258,  259,  260,  261,   -1,  263,  264,
+  265,   -1,   -1,   -1,  269,   -1,   93,  272,  273,  274,
+  275,   -1,   -1,   -1,   -1,  280,  281,  282,  283,  284,
+  285,  286,  287,  288,  289,  290,  291,  292,  293,  294,
+  295,  296,  297,  298,  299,  300,  301,  302,  303,  304,
+  305,  306,   -1,  308,  309,  310,  311,  312,  313,  314,
+   -1,   -1,   -1,  257,  258,  259,  260,  261,   -1,  263,
+  264,  265,   -1,   -1,   -1,  269,   -1,   -1,  272,  273,
+  274,  275,   -1,   -1,   -1,   -1,  280,  281,  282,  283,
+  284,  285,  286,  287,  288,  289,  290,  291,  292,  293,
+  294,  295,  296,  297,  298,  299,  300,  301,  302,  303,
+  304,  305,  306,   -1,  308,  309,  310,  311,  312,  313,
+  314,  256,  257,  258,  259,  260,  261,   -1,  263,  264,
+  265,   -1,   -1,   41,  269,   -1,   44,  272,  273,  274,
+  275,   -1,   -1,   -1,  279,  280,   -1,  282,  283,  284,
+   58,   59,   -1,   -1,  289,  290,  291,  292,  293,  294,
+   -1,   -1,  297,  298,   -1,   -1,   -1,   -1,   -1,  304,
+   -1,   -1,   -1,  308,   33,  310,  311,   36,   37,   38,
+   -1,   40,   -1,   42,   43,   93,   45,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,  272,  273,  274,  275,   -1,
+   59,   -1,   -1,   -1,  281,   64,   -1,   -1,  285,  286,
+  287,  288,   -1,   -1,   -1,   -1,   -1,   -1,  295,  296,
+   -1,   -1,  299,  300,  301,  302,  303,   -1,  305,  306,
+   33,   -1,   91,   36,   37,   38,   -1,   40,   -1,   42,
+   43,   26,   45,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   49,   50,   -1,   -1,   42,   -1,   -1,
+   -1,   64,   -1,   48,  123,   50,   -1,  126,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   62,   63,   64,
+   65,   91,   -1,   -1,   -1,   -1,   33,   -1,   91,   36,
+   37,   38,   -1,   40,   90,   42,   43,   -1,   45,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,  123,   -1,   -1,   -1,   64,   -1,   -1,
+  123,   -1,  118,  126,   -1,  110,  309,  310,  311,  125,
+   -1,   -1,  315,   -1,  317,   -1,   -1,   41,   -1,   -1,
+   44,   -1,   -1,   -1,   91,   -1,   -1,   -1,   -1,   33,
+   -1,   -1,   36,   37,   38,   59,   40,   -1,   42,   43,
+  343,   45,   -1,   -1,  272,  273,  274,  275,  351,   -1,
+  353,   91,   -1,   -1,   -1,   59,  123,   -1,   -1,  126,
+   64,  364,   -1,   -1,   -1,   -1,  182,  295,  296,   93,
+   -1,  187,   -1,   -1,   -1,   -1,   -1,  256,  257,  258,
+  259,  260,  261,  123,  263,  264,  265,   91,   -1,   -1,
+  269,   -1,   -1,  272,  273,  274,  275,   -1,   -1,   41,
+  279,  280,   44,  282,  283,  284,   -1,   -1,   -1,   -1,
   289,  290,  291,  292,  293,  294,   58,   59,  297,  298,
-   -1,   63,   -1,   -1,   -1,  304,   91,   -1,   -1,  308,
-   -1,  310,  311,   -1,   -1,   41,   -1,  257,  258,  259,
-  260,  261,   -1,  263,  264,  265,   -1,   -1,   -1,  269,
-   -1,   93,   -1,   -1,   -1,   -1,   -1,   63,  123,   -1,
-  280,   -1,  282,  283,  284,   -1,   -1,   -1,   -1,  289,
-  290,  291,  292,  293,  294,   -1,   -1,  297,  298,   -1,
-   -1,   -1,   -1,   -1,  304,   91,   -1,   -1,  308,   41,
-  310,  311,   44,   -1,   -1,   -1,   -1,  257,  258,  259,
-  260,  261,   -1,  263,  264,  265,   58,   59,   -1,  269,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,  123,   -1,   -1,
-  280,   -1,  282,  283,  284,   -1,   -1,   -1,   -1,  289,
-  290,  291,  292,  293,  294,   -1,   -1,  297,  298,   -1,
-   -1,   93,   -1,   -1,  304,   -1,   -1,   -1,  308,   33,
-  310,  311,   36,   37,   38,   -1,   40,   -1,   42,   43,
-   -1,   45,   -1,   -1,   -1,   -1,  272,  273,  274,  275,
-   -1,   -1,   -1,   -1,  272,  273,  274,  275,   -1,   -1,
-   64,   -1,   -1,  281,   -1,   -1,   -1,   -1,   -1,  295,
-  296,   -1,   -1,   -1,   -1,   -1,   -1,  295,  296,   -1,
-   -1,  299,  300,  301,  302,   33,   -1,   91,   36,   37,
-   38,   -1,   40,   41,   42,   43,   -1,   45,   -1,   -1,
-  285,  286,  287,  288,   -1,   -1,   -1,   -1,   -1,   -1,
-  272,  273,  274,  275,   -1,   -1,   64,  302,  303,  281,
-  305,  306,  126,   -1,  309,   -1,   -1,  312,  313,  314,
+   -1,   63,  126,   -1,   -1,  304,   -1,   -1,   -1,  308,
+   -1,  310,  311,   -1,  257,  258,  259,  260,  261,  262,
+  263,  264,  265,   -1,   -1,   -1,  269,   41,   -1,   -1,
+   44,   93,   -1,   -1,   -1,   41,   -1,  280,   44,  282,
+  283,  284,   -1,   -1,   58,   59,  289,  290,  291,  292,
+  293,  294,   58,   59,  297,  298,  306,   63,   -1,  309,
+   -1,  304,  312,  313,  314,  308,   -1,  310,  311,   -1,
+  257,  258,  259,  260,  261,   -1,  263,  264,  265,   93,
+   -1,   -1,  269,   -1,   -1,   -1,   -1,   93,   -1,   -1,
+   91,   41,   -1,  280,   44,  282,  283,  284,   -1,   -1,
+   -1,   -1,  289,  290,  291,  292,  293,  294,   58,   59,
+  297,  298,   -1,   63,   -1,   -1,   -1,  304,   -1,   -1,
+   -1,  308,  123,  310,  311,   -1,   -1,  287,  272,  273,
+  274,  275,   -1,  257,  258,  259,  260,  261,   -1,  263,
+  264,  265,   -1,   93,   41,  269,  306,   44,   -1,  309,
+   -1,  295,  312,  313,  314,   -1,  280,   -1,  282,  283,
+  284,   58,   59,   -1,   -1,  289,  290,  291,  292,  293,
+  294,   -1,   -1,  297,  298,   -1,   -1,   -1,   -1,   -1,
+  304,   -1,   -1,   -1,  308,   33,  310,  311,   36,   37,
+   38,   -1,   40,   -1,   42,   43,   93,   45,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+  272,  273,  274,  275,   -1,   -1,   64,   -1,   -1,  281,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
    -1,   -1,   -1,  295,  296,   -1,   -1,  299,  300,  301,
-   -1,   33,   -1,   91,   36,   37,   38,   -1,   40,   41,
-   42,   43,   -1,   45,   -1,  281,   -1,   -1,   -1,  285,
-  286,  287,  288,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   64,  299,  300,  301,  302,  303,  126,  305,
-  306,   -1,   -1,  309,   -1,   -1,  312,  313,  314,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   91,
-  272,  273,  274,  275,   33,   -1,   -1,   36,   37,   38,
-   -1,   40,   -1,   42,   43,   -1,   45,   -1,   -1,   -1,
-   -1,   -1,   -1,  295,  296,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,  126,   64,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   41,   -1,
-   -1,   44,  256,  257,  258,  259,  260,  261,   -1,  263,
-  264,  265,   91,   -1,   -1,  269,   -1,   -1,   -1,   -1,
-   63,   -1,   -1,   -1,   -1,   -1,  280,   -1,  282,  283,
-  284,   -1,   -1,   -1,   -1,  289,  290,  291,  292,  293,
-  294,   -1,   -1,  297,  298,   -1,   -1,  126,   91,   -1,
-  304,   -1,   41,   -1,  308,   44,  310,  311,   -1,  257,
-  258,  259,  260,  261,   -1,  263,  264,  265,   -1,   58,
-   59,  269,   -1,   -1,   63,   -1,   -1,   -1,   -1,   -1,
-  123,   -1,  280,   -1,  282,  283,  284,   -1,   -1,   -1,
-   -1,  289,  290,  291,  292,  293,  294,   -1,   -1,  297,
-  298,   -1,   91,   -1,   93,   -1,  304,   -1,   -1,   -1,
-  308,   41,  310,  311,   44,  257,  258,  259,  260,  261,
-   -1,  263,  264,  265,   -1,   -1,   -1,  269,   58,   59,
-   -1,   -1,   -1,   63,  123,   -1,   -1,   -1,  280,   -1,
+  302,   33,   -1,   91,   36,   37,   38,   -1,   40,   41,
+   42,   43,   -1,   45,   -1,   -1,   -1,   -1,  272,  273,
+  274,  275,   -1,   -1,   -1,   -1,  272,  273,  274,  275,
+   -1,   -1,   64,   -1,   -1,  123,   -1,   -1,  126,   -1,
+   -1,  295,  296,   -1,   -1,   -1,  287,  288,   -1,  295,
+  296,   -1,   -1,  299,   -1,   -1,   -1,   33,   -1,   91,
+   36,   37,   38,   -1,   40,  306,   42,   43,  309,   45,
+   -1,  312,  313,  314,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,  272,  273,  274,  275,   -1,   -1,   64,   -1,
+   -1,  281,   -1,   -1,  126,  285,  286,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,  295,  296,   -1,   -1,  299,
+  300,  301,  302,  303,   -1,   91,   -1,   93,   -1,   -1,
+   33,   -1,   -1,   36,   37,   38,   -1,   40,   41,   42,
+   43,   -1,   45,   -1,   -1,  272,  273,  274,  275,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+  126,   64,   -1,   -1,   -1,   -1,   -1,   -1,  295,  296,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  257,
+  258,  259,  260,  261,   -1,  263,  264,  265,   91,   -1,
+   -1,  269,   41,   -1,   -1,   44,   -1,   -1,   -1,   -1,
+   41,   -1,  280,   44,  282,  283,  284,   -1,   -1,   58,
+   59,  289,  290,  291,  292,  293,  294,   58,   59,  297,
+  298,   -1,   63,  126,   -1,   -1,  304,   -1,   -1,   -1,
+  308,   -1,  310,  311,   -1,  257,  258,  259,  260,  261,
+   -1,  263,  264,  265,   93,   -1,   -1,  269,   -1,   -1,
+   -1,   -1,   93,   -1,   -1,   -1,   41,   -1,  280,   44,
   282,  283,  284,   -1,   -1,   -1,   -1,  289,  290,  291,
-  292,  293,  294,   -1,   41,  297,  298,   44,   -1,   -1,
-   -1,   91,  304,   93,   -1,   -1,  308,   -1,  310,  311,
-   -1,   58,   59,   -1,   -1,   -1,   63,   -1,  257,  258,
-  259,  260,  261,   -1,  263,  264,  265,   -1,   -1,   -1,
-  269,   -1,   -1,  123,   -1,   -1,   -1,   -1,   -1,   41,
-   -1,  280,   44,  282,  283,  284,   93,   -1,   -1,   -1,
-  289,  290,  291,  292,  293,  294,   58,   59,  297,  298,
-   -1,   63,   -1,   -1,   -1,  304,   -1,   -1,   -1,  308,
-   -1,  310,  311,   -1,   -1,   -1,  123,   -1,  281,   -1,
-   -1,   -1,  285,  286,  287,  288,   -1,   -1,   -1,   91,
-   41,   93,   -1,   44,   -1,   -1,  299,  300,  301,  302,
-  303,   -1,  305,  306,   -1,   -1,  309,   58,   59,  312,
-  313,  314,   63,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+  292,  293,  294,   58,   59,  297,  298,   -1,   63,   -1,
+   -1,   -1,  304,   -1,   -1,   -1,  308,   -1,  310,  311,
+   -1,  257,  258,  259,  260,  261,   -1,  263,  264,  265,
+   -1,   -1,   -1,  269,   -1,   -1,   -1,   -1,   93,   -1,
+   -1,   -1,   41,   -1,  280,   44,  282,  283,  284,   -1,
+   -1,   -1,   -1,  289,  290,  291,  292,  293,  294,   58,
+   59,  297,  298,   -1,   63,   -1,   -1,   -1,  304,   -1,
+   -1,   -1,  308,   -1,  310,  311,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,  257,  258,  259,  260,  261,   -1,
+  263,  264,  265,   -1,   93,   -1,  269,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   63,  280,   -1,  282,
+  283,  284,   -1,   -1,   -1,   -1,  289,  290,  291,  292,
+  293,  294,   -1,   -1,  297,  298,   -1,   -1,   -1,   -1,
+   -1,  304,   -1,   -1,   91,  308,   33,  310,  311,   36,
+   37,   38,   -1,   40,   41,   42,   43,   -1,   45,   -1,
    -1,   -1,   -1,  272,  273,  274,  275,   -1,   -1,   -1,
-   -1,   -1,  281,   -1,   -1,   -1,  285,  286,  287,  288,
-   -1,   -1,   93,   -1,   -1,   -1,  295,  296,   -1,   41,
-  299,  300,  301,  302,  303,   -1,  305,  306,   -1,   -1,
-  309,   -1,   -1,  312,  313,  314,   58,   59,   -1,   -1,
-   -1,   63,  123,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,  272,  273,  274,  275,   -1,   -1,   -1,   -1,
-   -1,  281,   -1,   -1,   -1,  285,  286,  287,  288,   91,
-   -1,   93,   -1,   -1,   -1,  295,  296,   -1,   -1,  299,
-  300,  301,  302,  303,   -1,  305,  306,   -1,   -1,  309,
-   -1,   -1,  312,  313,  314,  272,  273,  274,  275,   41,
-   -1,  123,   44,   -1,  281,   -1,   -1,   -1,  285,  286,
-  287,  288,   -1,   -1,   -1,   -1,   58,   59,  295,  296,
-   -1,   63,  299,  300,  301,  302,  303,   -1,  305,  306,
+   -1,  272,  273,  274,  275,   -1,  123,   64,   -1,   -1,
+  281,   -1,   -1,   -1,   -1,   -1,  295,  296,   -1,   -1,
+   -1,   -1,   -1,   -1,  295,  296,   -1,   -1,  299,  300,
+  301,   -1,   33,   -1,   91,   36,   37,   38,   -1,   40,
+   -1,   42,   43,   -1,   45,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,  272,  273,  274,
+  275,   -1,   -1,   64,   -1,   -1,  281,   -1,   -1,  126,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+  295,  296,   -1,   -1,  299,  300,   -1,   -1,   33,   -1,
+   91,   36,   37,   38,   -1,   40,   41,   42,   43,   -1,
+   45,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,  272,  273,  274,  275,   -1,   -1,   64,
+   -1,   -1,  281,   -1,   -1,  126,  285,  286,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,  295,  296,   -1,   -1,
+  299,  300,  301,  302,  303,   -1,   91,   -1,   -1,   -1,
+   -1,   33,   -1,   -1,   36,   37,   38,   -1,   40,   41,
+   42,   43,   -1,   45,  281,   -1,   -1,   -1,  285,  286,
+  287,  288,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,  126,   64,  300,  301,  302,  303,   -1,  305,  306,
    -1,   -1,  309,   -1,   -1,  312,  313,  314,   -1,   -1,
-  272,  273,  274,  275,   -1,   -1,   -1,   -1,   -1,  281,
-   -1,   93,   -1,  285,  286,  287,  288,   -1,   -1,   -1,
-   -1,   41,   -1,  295,  296,   -1,   -1,  299,  300,  301,
-  302,  303,   -1,  305,  306,   -1,   -1,  309,   58,   59,
-  312,  313,  314,   63,   -1,   -1,   -1,   -1,   -1,   -1,
+  257,  258,  259,  260,  261,   -1,  263,  264,  265,   91,
+   -1,   -1,  269,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,  280,   -1,  282,  283,  284,   41,   -1,
+   -1,   44,  289,  290,  291,  292,  293,  294,   -1,   -1,
+  297,  298,   -1,   -1,  126,   58,   59,  304,   -1,   -1,
+   63,  308,   -1,  310,  311,  256,  257,  258,  259,  260,
+  261,   -1,  263,  264,  265,   -1,   -1,   -1,  269,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  280,
+   93,  282,  283,  284,   -1,   -1,   -1,   -1,  289,  290,
+  291,  292,  293,  294,   -1,   -1,  297,  298,   -1,   -1,
+   -1,   -1,   -1,  304,   -1,   -1,   -1,  308,   41,  310,
+  311,   44,  257,  258,  259,  260,  261,   -1,  263,  264,
+  265,   -1,   -1,   -1,  269,   58,   59,   -1,   -1,   -1,
+   63,   -1,   -1,   -1,   -1,  280,   -1,  282,  283,  284,
+   -1,   -1,   -1,   -1,  289,  290,  291,  292,  293,  294,
+   -1,   -1,  297,  298,   -1,   -1,   -1,   -1,   91,  304,
+   93,   -1,   -1,  308,   -1,  310,  311,   41,   -1,   -1,
+   44,   -1,   -1,   -1,   -1,  257,  258,  259,  260,  261,
+   -1,  263,  264,  265,   58,   59,   -1,  269,   -1,   63,
+  123,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  280,   -1,
+  282,  283,  284,   -1,   -1,   -1,   -1,  289,  290,  291,
+  292,  293,  294,   -1,   -1,  297,  298,   91,   -1,   93,
+   -1,   -1,  304,   -1,   -1,   -1,  308,   33,  310,  311,
+   36,   37,   38,   -1,   40,   -1,   42,   43,   -1,   45,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  123,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   64,  272,
+  273,  274,  275,   -1,   -1,   -1,   -1,   -1,  281,   -1,
+   -1,   -1,  285,  286,   -1,   41,   -1,   -1,   44,   -1,
+   -1,   -1,  295,  296,   -1,   91,  299,  300,  301,  302,
+  303,   -1,   58,   59,   -1,   -1,   -1,   63,   25,   26,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   37,   -1,   -1,   -1,   -1,   42,   43,   -1,   -1,   -1,
+  126,   48,   -1,   50,   -1,   91,   -1,   93,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   62,   63,   64,   65,  272,
+  273,  274,  275,   41,   -1,   91,   44,   -1,  281,   -1,
+   -1,   -1,  285,  286,  287,  288,   -1,  123,   -1,   -1,
+   58,   59,  295,  296,   -1,   63,  299,  300,  301,  302,
+  303,   -1,  305,  306,   -1,   -1,  309,  123,   -1,  312,
+  313,  314,   -1,  110,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   91,   -1,   93,   -1,   -1,  272,  273,
+  274,  275,   -1,   -1,   -1,   -1,   -1,  281,   -1,   -1,
+   -1,  285,  286,  287,  288,   -1,   -1,   -1,   -1,   -1,
+   -1,  295,  296,   -1,   91,  299,  300,  301,  302,  303,
+   -1,  305,  306,   -1,   -1,  309,   -1,   -1,  312,  313,
+  314,   -1,  169,   41,   -1,   -1,   44,   -1,   -1,   -1,
+   -1,  257,  258,  259,  260,  261,  123,  263,  264,  265,
+   58,   59,   -1,  269,   -1,   63,   -1,   -1,   -1,   -1,
+  197,   -1,   -1,   -1,  280,   -1,  282,  283,  284,   -1,
+   -1,   -1,   -1,  289,  290,  291,  292,  293,  294,   -1,
+   -1,  297,  298,   -1,   -1,   93,   -1,   -1,  304,   -1,
+   -1,   -1,  308,   -1,  310,  311,  272,  273,  274,  275,
+   41,   -1,   -1,   44,   -1,  281,   -1,   -1,   -1,  285,
+  286,  287,  288,   -1,   -1,  123,   -1,   58,   59,  295,
+  296,   -1,   63,  299,  300,  301,  302,  303,   -1,  305,
+  306,  287,  288,  309,   -1,   -1,  312,  313,  314,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  305,
+  306,   -1,   93,  309,   -1,   -1,  312,  313,  314,   -1,
+   -1,   -1,   -1,   -1,  272,  273,  274,  275,   41,   -1,
+   -1,   -1,   -1,  281,   -1,   -1,   -1,  285,  286,  287,
+  288,   -1,  123,   -1,   -1,   58,   59,  295,  296,   -1,
+   63,  299,  300,  301,  302,  303,   -1,  305,  306,   -1,
+   -1,  309,   -1,   -1,  312,  313,  314,   -1,  285,  286,
+  287,  288,   -1,   -1,   -1,   -1,   -1,   -1,   91,   -1,
+   93,   -1,   -1,  300,  301,  302,  303,   -1,  305,  306,
+   -1,   41,  309,   -1,   -1,  312,  313,  314,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   58,   59,
+  123,   -1,   -1,   63,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,  272,  273,  274,  275,   -1,   -1,
+   -1,   -1,   -1,  281,   -1,   -1,   -1,  285,  286,  287,
+  288,   91,   -1,   93,   -1,   -1,   -1,  295,  296,   -1,
+   -1,  299,  300,  301,  302,  303,   -1,  305,  306,   41,
+   -1,  309,   44,   -1,  312,  313,  314,   -1,   -1,   -1,
+   -1,   -1,   -1,  123,   -1,   -1,   58,   59,   -1,   -1,
+   -1,   63,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
    -1,  272,  273,  274,  275,   -1,   -1,   -1,   -1,   -1,
   281,   -1,   -1,   -1,  285,  286,  287,  288,   -1,   -1,
-   -1,   91,   -1,   93,  295,  296,   -1,   -1,  299,  300,
-  301,  302,  303,   41,  305,  306,   44,   -1,  309,   -1,
+   -1,   93,   -1,   -1,  295,  296,   -1,   -1,  299,  300,
+  301,  302,  303,   -1,  305,  306,   41,   -1,  309,   44,
    -1,  312,  313,  314,   -1,   -1,   -1,   -1,   -1,   -1,
-   58,   59,   -1,  123,   -1,   63,   -1,   -1,   -1,   -1,
-  272,  273,  274,  275,   -1,   -1,   -1,   -1,   -1,  281,
-   -1,   -1,   -1,  285,  286,  287,  288,   -1,   -1,   -1,
-   -1,   -1,   -1,  295,  296,   93,   -1,  299,  300,  301,
-  302,  303,   41,  305,  306,   44,   -1,  309,   -1,   -1,
-  312,  313,  314,   -1,   -1,   -1,   -1,   -1,   -1,   58,
-   59,   -1,   -1,   -1,   63,  123,   -1,   -1,   -1,   -1,
+   -1,  123,   -1,   58,   59,   -1,   -1,   -1,   63,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  272,
+  273,  274,  275,   -1,   -1,   -1,   -1,   -1,  281,   -1,
+   -1,   -1,  285,  286,  287,  288,   -1,   -1,   93,   -1,
+   -1,   -1,  295,  296,   -1,   -1,  299,  300,  301,  302,
+  303,   -1,  305,  306,   -1,   -1,  309,   -1,   -1,  312,
+  313,  314,   -1,   -1,   -1,   -1,   -1,   -1,  123,   91,
    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   41,   -1,   -1,
-  272,  273,  274,  275,   93,   -1,   -1,   -1,   -1,  281,
-   -1,   -1,   -1,   -1,   58,   59,   -1,   -1,   -1,   63,
-   -1,   -1,   -1,  295,  296,   -1,   -1,  299,  300,  301,
-  302,  303,   -1,   -1,  123,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   91,   -1,   93,
+   -1,   -1,  272,  273,  274,  275,   41,   -1,   -1,   -1,
+   -1,  281,   -1,   -1,   -1,  285,  286,  287,  288,   -1,
+   -1,  123,   -1,   58,   59,  295,  296,   -1,   63,  299,
+  300,  301,  302,  303,   -1,  305,  306,   -1,   -1,  309,
+   -1,   -1,  312,  313,  314,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   91,   -1,   93,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+  272,  273,  274,  275,   41,   -1,   -1,   44,   -1,  281,
+   -1,   -1,   -1,  285,  286,  287,  288,   -1,  123,   -1,
+   -1,   58,   59,  295,  296,   -1,   63,  299,  300,  301,
+  302,  303,   -1,  305,  306,   -1,   -1,  309,   -1,   -1,
+  312,  313,  314,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   93,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,  272,  273,  274,
+  275,   41,   -1,   -1,   44,   -1,  281,   -1,   -1,   -1,
+  285,  286,  287,  288,   -1,   -1,  123,   -1,   58,   59,
+  295,  296,   -1,   63,  299,  300,  301,  302,  303,   -1,
+  305,  306,   -1,   -1,  309,   -1,   -1,  312,  313,  314,
+   -1,   -1,   -1,  285,   41,  287,  288,   44,   -1,   -1,
+   -1,   -1,   -1,   93,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   58,   59,  305,  306,   -1,   63,  309,   -1,   -1,
+  312,  313,  314,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   93,  272,  273,  274,
+  275,   41,   -1,   -1,   44,   -1,  281,   -1,   -1,   -1,
+  285,  286,  287,  288,   -1,   -1,   -1,   -1,   58,   59,
+  295,  296,   -1,   63,  299,  300,  301,  302,  303,   -1,
+  305,  306,   -1,   -1,  309,   -1,   -1,  312,  313,  314,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   93,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,  272,  273,  274,  275,   41,
+   -1,   -1,   44,   -1,  281,   -1,   -1,   -1,  285,  286,
+  287,  288,   -1,   -1,   -1,   -1,   58,   59,  295,  296,
+   -1,   63,  299,  300,  301,  302,  303,   -1,  305,  306,
+   -1,   -1,  309,   -1,   -1,  312,  313,  314,   -1,   -1,
    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   93,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
    -1,   -1,  272,  273,  274,  275,   -1,   -1,   -1,   -1,
-   -1,  281,   -1,   -1,   -1,  285,  286,  287,  288,  123,
-   -1,   -1,   91,   -1,   -1,  295,  296,   -1,   -1,  299,
-  300,  301,  302,  303,   41,  305,  306,   44,   -1,  309,
-   -1,   -1,  312,  313,  314,   -1,   -1,   -1,   -1,   -1,
-   -1,   58,   59,   -1,  123,   -1,   63,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,  272,  273,  274,  275,   -1,   -1,
-   -1,   -1,   -1,  281,   -1,   -1,   -1,  285,  286,  287,
-  288,   -1,   -1,   -1,   -1,   -1,   93,  295,  296,   -1,
-   -1,  299,  300,  301,  302,  303,   41,  305,  306,   44,
-   -1,  309,   -1,   -1,  312,  313,  314,   -1,   -1,   -1,
-   -1,   -1,   -1,   58,   59,   -1,  123,   -1,   63,   -1,
-   -1,   -1,   -1,  272,  273,  274,  275,   -1,   -1,   -1,
-   -1,   -1,  281,   -1,   -1,   -1,  285,  286,  287,  288,
-   -1,   -1,   -1,   -1,   -1,   -1,  295,  296,   93,   -1,
-  299,  300,  301,  302,  303,   -1,  305,  306,   -1,   -1,
-  309,   -1,   -1,  312,  313,  314,   -1,   -1,  272,  273,
-  274,  275,   41,   -1,   -1,   44,   -1,  281,   -1,   -1,
-   -1,  285,  286,  287,  288,   -1,   -1,   -1,   -1,   58,
-   59,  295,  296,   -1,   63,  299,  300,  301,  302,  303,
-   -1,  305,  306,   -1,   -1,  309,   -1,   -1,  312,  313,
-  314,   -1,   -1,   -1,   -1,   -1,  285,   41,  287,  288,
-   44,   -1,   -1,   -1,   93,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   58,   59,  305,  306,   -1,   63,
-  309,   -1,   -1,  312,  313,  314,   -1,   -1,   -1,   -1,
+   -1,  281,   -1,   -1,   -1,  285,  286,  287,  288,   -1,
+   -1,   -1,   -1,   -1,   -1,  295,  296,   -1,   -1,  299,
+  300,  301,  302,  303,   -1,  305,  306,   -1,   -1,  309,
+   -1,   -1,  312,  313,  314,  272,  273,  274,  275,   41,
+   -1,   -1,   44,   -1,  281,   -1,   -1,   -1,  285,  286,
+  287,  288,   -1,   -1,   -1,   -1,   58,   59,  295,  296,
+   -1,   63,  299,  300,  301,  302,  303,   -1,  305,  306,
+   -1,   -1,  309,   -1,   -1,  312,  313,  314,   -1,   -1,
    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,  272,  273,  274,  275,   93,
-   -1,   -1,   -1,   -1,  281,   -1,   -1,   -1,  285,  286,
-  287,  288,   -1,   -1,   -1,   -1,   -1,   -1,  295,  296,
-   -1,   -1,  299,  300,  301,  302,  303,   41,  305,  306,
-   44,   -1,  309,   -1,   -1,  312,  313,  314,   -1,   -1,
+   -1,   93,  272,  273,  274,  275,   -1,   -1,   -1,   -1,
+   -1,  281,   -1,   -1,   -1,  285,  286,  287,  288,   -1,
+   -1,   -1,   -1,   -1,   -1,  295,  296,   -1,   -1,  299,
+  300,  301,  302,  303,   -1,  305,  306,   41,   -1,  309,
+   44,   -1,  312,  313,  314,   -1,   -1,   -1,   -1,   -1,
    -1,   -1,   -1,   -1,   58,   59,   -1,   -1,   -1,   63,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,  272,  273,  274,
-  275,   -1,   -1,   -1,   -1,   -1,  281,   -1,   -1,   -1,
-  285,  286,  287,  288,   -1,   -1,   -1,   -1,   -1,   93,
-  295,  296,   -1,   -1,  299,  300,  301,  302,  303,   41,
-  305,  306,   44,   -1,  309,   -1,   -1,  312,  313,  314,
-   -1,   -1,   -1,   -1,   -1,   -1,   58,   59,   -1,   -1,
-   -1,   63,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,  272,  273,  274,  275,   41,   -1,   -1,
-   44,   93,  281,   -1,   -1,   -1,  285,  286,  287,  288,
-   -1,   -1,   -1,   -1,   58,   59,  295,  296,   -1,   63,
-  299,  300,  301,  302,  303,   -1,  305,  306,   -1,   -1,
-  309,   -1,   -1,  312,  313,  314,   -1,   -1,  272,  273,
-  274,  275,   41,   -1,   -1,   44,   -1,  281,   -1,   93,
-   -1,  285,  286,  287,  288,   -1,   -1,   -1,   -1,   58,
-   59,  295,  296,   -1,   63,  299,  300,  301,  302,  303,
-   -1,  305,  306,   -1,   -1,  309,   -1,   -1,  312,  313,
-  314,   -1,   -1,   41,   -1,   -1,   44,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   93,   -1,   -1,   -1,   -1,   -1,
-   58,   59,   -1,   -1,   -1,   63,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  272,  273,
-  274,  275,   41,   -1,   -1,   44,   -1,  281,   -1,   -1,
-   -1,  285,  286,  287,  288,   93,   -1,   -1,   -1,   58,
-   59,  295,  296,   -1,   63,  299,  300,  301,  302,  303,
-   -1,  305,  306,   -1,   -1,  309,   -1,   -1,  312,  313,
-  314,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   41,   -1,
-   -1,   44,   -1,   -1,   93,   -1,   -1,   -1,   -1,   -1,
+  272,  273,  274,  275,   -1,   -1,   -1,   -1,   -1,  281,
+   -1,   -1,   -1,  285,  286,  287,  288,   -1,   -1,   93,
+   -1,   -1,   -1,  295,  296,   -1,   -1,  299,  300,  301,
+  302,  303,   -1,  305,  306,   30,   -1,  309,   -1,   -1,
+  312,  313,  314,   38,   -1,   -1,   -1,   -1,   43,   -1,
+   41,   -1,   -1,   44,   -1,   -1,   51,   52,   53,   54,
+   55,   56,   -1,   -1,   59,   60,   -1,   58,   59,   -1,
+   -1,   66,   63,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   92,   41,   -1,
+   -1,   44,   93,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   272,  273,  274,  275,   -1,   58,   59,   -1,   -1,  281,
    63,   -1,   -1,  285,  286,  287,  288,   -1,   -1,   -1,
    -1,   -1,   -1,  295,  296,   -1,   -1,  299,  300,  301,
-  302,  303,   -1,  305,  306,   -1,   41,  309,   -1,   44,
-   93,   -1,   91,   -1,   -1,   -1,   -1,   -1,  272,  273,
-  274,  275,   -1,   58,   59,   -1,   -1,  281,   63,   -1,
-   -1,  285,  286,  287,  288,   -1,   -1,   -1,   -1,   -1,
-   -1,  295,  296,   -1,  123,  299,  300,  301,  302,  303,
-   -1,  305,  306,   -1,   -1,  309,   -1,   -1,   93,   -1,
-   -1,   -1,   -1,  272,  273,  274,  275,   -1,   -1,   -1,
-   -1,   -1,  281,   -1,   -1,   -1,  285,  286,  287,  288,
-   91,   -1,   -1,   -1,   -1,   -1,  295,  296,   -1,   -1,
-  299,  300,  301,  302,  303,   -1,  305,  306,   -1,   -1,
-   -1,   -1,   -1,   -1,  272,  273,  274,  275,   41,   -1,
-   -1,   44,  123,  281,   -1,   -1,   -1,  285,  286,  287,
-  288,   -1,   -1,   -1,   -1,   58,   59,  295,  296,   -1,
-   63,  299,  300,  301,  302,  303,   -1,  305,  306,   -1,
-   -1,   -1,   -1,  272,  273,  274,  275,   41,   -1,   -1,
-   44,   -1,  281,   -1,   -1,   -1,  285,  286,  287,  288,
-   93,   -1,   -1,   -1,   58,   59,  295,  296,   -1,   63,
+  302,  303,   -1,  305,  306,   -1,   -1,  309,   -1,   -1,
+   93,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  153,  154,
+  155,  156,  157,  158,  159,  160,  161,  162,  163,  164,
+  165,  166,   41,   -1,   -1,   44,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,  178,   -1,   -1,   -1,   -1,   -1,   58,
+   59,   -1,   -1,   -1,   63,   -1,   -1,   -1,  272,  273,
+  274,  275,   -1,   -1,   -1,   -1,   -1,  281,   -1,   -1,
+   -1,  285,  286,  287,  288,   -1,   41,   -1,   -1,   44,
+   -1,  295,  296,   -1,   93,  299,  300,  301,  302,  303,
+   -1,  305,  306,   58,   59,   -1,   -1,   -1,   63,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   41,   -1,   -1,   44,   -1,   -1,
+   -1,   -1,   -1,  258,   -1,   -1,   -1,   -1,   93,   -1,
+   -1,   58,   59,   -1,   -1,   -1,   63,   -1,   -1,   -1,
+   -1,  272,  273,  274,  275,   -1,   -1,   -1,   -1,   -1,
+  281,   -1,   -1,   -1,  285,  286,  287,  288,   -1,   41,
+  295,   -1,   44,   -1,  295,  296,   93,   -1,  299,  300,
+  301,  302,  303,   -1,  305,  306,   58,   59,   -1,   -1,
+   -1,   63,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  272,
+  273,  274,  275,   -1,   -1,   -1,   -1,   -1,  281,   -1,
+   -1,   -1,  285,  286,  287,  288,   -1,   41,   -1,   -1,
+   44,   93,  295,  296,   91,   -1,  299,  300,  301,  302,
+  303,   -1,  305,  306,   58,   59,   -1,   -1,   -1,   63,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,  123,   -1,   -1,   -1,
+   -1,   41,   -1,   -1,   44,   -1,   -1,   -1,   -1,   93,
+   -1,   -1,   -1,  272,  273,  274,  275,   41,   58,   59,
+   44,   -1,  281,   63,   -1,   -1,  285,  286,  287,  288,
+   -1,   -1,   -1,   -1,   58,   59,  295,  296,   -1,   63,
   299,  300,  301,  302,  303,   -1,  305,  306,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  272,
-  273,  274,  275,   41,   -1,   -1,   44,   -1,  281,   93,
-   -1,   -1,  285,  286,  287,  288,  285,  286,  287,  288,
-   58,   59,  295,  296,   -1,   63,  299,  300,  301,  302,
-  303,   -1,  305,  306,  303,   -1,  305,  306,   -1,   -1,
-  309,   -1,   -1,  312,  313,  314,   -1,  272,  273,  274,
-  275,   41,   -1,   -1,   44,   93,  281,   -1,   -1,   -1,
+   -1,   -1,   -1,   93,   -1,   -1,   -1,  272,  273,  274,
+  275,   41,   -1,   -1,   44,   -1,  281,   -1,   -1,   93,
   285,  286,  287,  288,   -1,   -1,   -1,   -1,   58,   59,
   295,  296,   -1,   63,  299,  300,  301,  302,  303,   -1,
-  305,  306,   -1,   -1,  285,  286,  287,  288,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  300,
-  301,  302,  303,   93,  305,  306,   -1,   -1,  309,   -1,
-   -1,  312,  313,  314,   41,   -1,   -1,   44,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,   58,   59,   -1,   -1,   -1,   63,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  272,
-  273,  274,  275,   41,   -1,   -1,   44,   -1,  281,   -1,
-   -1,   -1,  285,  286,  287,  288,   93,   -1,   -1,   -1,
-   58,   59,  295,  296,   -1,   63,  299,  300,  301,  302,
-  303,   -1,  305,  306,   -1,   -1,   -1,   -1,  272,  273,
+  305,  306,   -1,   -1,   -1,  272,  273,  274,  275,   -1,
+   -1,   58,   -1,   -1,  281,   -1,   63,   -1,  285,  286,
+  287,  288,   -1,   93,   -1,   -1,   -1,   -1,  295,  296,
+   -1,   -1,  299,  300,  301,  302,  303,   -1,  305,  306,
+   -1,   -1,   -1,   -1,   91,   -1,   -1,   -1,   -1,   -1,
+  272,  273,  274,  275,   -1,   -1,   63,   -1,   -1,  281,
+   -1,   -1,   -1,  285,  286,  287,  288,   -1,  285,  286,
+  287,  288,   -1,  295,  296,   -1,  123,  299,  300,  301,
+  302,  303,   -1,  305,   91,  302,  303,   -1,  305,  306,
+   -1,   -1,  309,   -1,   -1,  312,  313,  314,  272,  273,
   274,  275,   -1,   -1,   -1,   -1,   -1,  281,   -1,   -1,
-   -1,  285,  286,  287,  288,   93,   -1,   -1,   -1,   -1,
+   -1,  285,  286,   -1,  288,   91,  123,   -1,   -1,   -1,
+   -1,  295,  296,   -1,   -1,  299,  300,  301,  302,  303,
+   -1,  305,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,  272,  273,  274,  275,   -1,  123,   -1,   -1,
+   -1,  281,   -1,   -1,   -1,   -1,  286,   -1,  272,  273,
+  274,  275,   -1,   -1,   -1,  295,  296,  281,   -1,  299,
+  300,  301,  302,  303,   -1,   -1,   -1,   -1,   -1,   -1,
    -1,  295,  296,   -1,   -1,  299,  300,  301,  302,  303,
-   -1,  305,  306,   -1,   -1,   -1,   -1,   41,   -1,   -1,
-   44,   -1,   -1,   -1,  272,  273,  274,  275,   -1,   -1,
-   -1,   -1,   -1,  281,   58,   59,   -1,  285,  286,   63,
-  288,   -1,   -1,   -1,   -1,   -1,   -1,  295,  296,   -1,
-   -1,  299,  300,  301,  302,  303,   -1,  305,   -1,   -1,
-   41,   -1,   -1,   44,   -1,   -1,   -1,   -1,   -1,   93,
-   -1,   -1,  272,  273,  274,  275,   -1,   58,   59,   -1,
-   -1,  281,   63,   -1,   -1,  285,  286,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,  295,  296,   -1,   30,  299,
-  300,  301,  302,  303,   -1,  305,   38,   -1,   58,   -1,
-   -1,   43,   93,   63,   -1,   -1,   -1,   -1,   -1,   51,
-   52,   53,   54,   55,   56,   -1,   -1,   59,   60,   -1,
-   -1,   -1,   -1,   -1,   66,  272,  273,  274,  275,   -1,
-   -1,   91,   -1,   -1,  281,   -1,   -1,   -1,  285,  286,
-   63,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  295,  296,
-   92,   -1,  299,  300,  301,  302,  303,   -1,   -1,   -1,
-   -1,   -1,   -1,  123,  272,  273,  274,  275,   91,   -1,
-   63,   -1,   -1,  281,   -1,   -1,   -1,  285,  286,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,  295,  296,   -1,
-   -1,  299,  300,  301,  302,  303,   -1,   -1,   91,   -1,
-  123,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,  153,  154,  155,  156,  157,  158,  159,  160,  161,
-  162,  163,  164,  165,  166,   -1,   -1,   -1,   91,   -1,
-  123,   -1,   -1,   -1,   -1,   -1,  178,   -1,  272,  273,
-  274,  275,   -1,   -1,   -1,   -1,   -1,  281,   -1,   -1,
-   -1,  285,  286,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-  123,  295,  296,   -1,   -1,  299,  300,  301,  302,  303,
    -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,  272,  273,  274,  275,   -1,   -1,   -1,   -1,   -1,
-  281,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,  295,  296,   -1,   -1,  299,  300,
-   -1,   -1,   -1,   -1,   -1,   -1,  258,   -1,   -1,   -1,
-   -1,  281,   -1,   -1,   -1,  285,  286,  287,  288,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  299,
-  300,  301,  302,  303,   -1,  305,  306,   -1,   -1,  309,
-   -1,  293,  312,  313,  314,   -1,   -1,   -1,  281,   -1,
-   -1,   -1,  285,  286,  287,  288,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,  299,  300,  301,  302,
-  303,   -1,  305,  306,   -1,   -1,  309,   -1,  281,  312,
-  313,  314,  285,  286,  287,  288,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,  300,  301,  302,
-  303,   -1,  305,  306,   -1,   -1,  309,   -1,   -1,  312,
-  313,  314,  285,  286,  287,  288,   -1,   -1,   -1,   -1,
-   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  301,  302,
-  303,   -1,  305,  306,   -1,   -1,  309,   -1,   -1,  312,
-  313,  314,
+   -1,   -1,  272,  273,  274,  275,   -1,   -1,   -1,   -1,
+   -1,  281,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,  295,  296,   -1,   -1,  299,
+  300,  301,  302,  303,  281,   -1,   -1,   -1,  285,  286,
+  287,  288,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,  299,  300,  301,  302,  303,   -1,  305,  306,
+   -1,   -1,  309,   -1,   -1,  312,  313,  314,   -1,   -1,
+   -1,   -1,   -1,   -1,  281,   -1,   -1,   -1,  285,  286,
+  287,  288,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,  299,  300,  301,  302,  303,   -1,  305,  306,
+   -1,   -1,  309,   -1,   -1,  312,  313,  314,   -1,  285,
+  286,  287,  288,   -1,   -1,   -1,   -1,   -1,   -1,   13,
+   -1,   -1,   -1,   17,   -1,  301,  302,  303,   -1,  305,
+  306,   -1,   -1,  309,   -1,   -1,  312,  313,  314,   33,
+   34,   35,   36,   -1,   -1,   -1,   -1,   -1,   -1,   43,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   51,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   80,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   94,   -1,   -1,   97,   -1,   99,   -1,  101,   -1,  103,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+  144,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,  181,   -1,   -1,
+   -1,   -1,   -1,   -1,  188,
 };
 #define YYFINAL 1
 #ifndef YYDEBUG
@@ -1062,8 +1104,7 @@ char *yyrule[] = {
 "prog : $$1 lineseq",
 "block : '{' remember lineseq '}'",
 "remember :",
-"mblock : '{' mintro mremember lineseq '}'",
-"mintro :",
+"mblock : '{' mremember lineseq '}'",
 "mremember :",
 "lineseq :",
 "lineseq : lineseq decl",
@@ -1091,12 +1132,10 @@ char *yyrule[] = {
 "loop : label UNTIL '(' remember miexpr ')' mblock cont",
 "loop : label WHILE block block cont",
 "loop : label UNTIL block block cont",
-"loop : label FOR MY remember my_scalar '(' expr ')' mblock cont",
-"loop : label FOR scalar '(' expr ')' block cont",
-"loop : label FOR '(' remember expr ')' mblock cont",
-"$$2 :",
-"$$3 :",
-"loop : label FOR '(' remember nexpr ';' $$2 texpr ';' $$3 nexpr ')' mblock",
+"loop : label FOR MY remember my_scalar '(' mexpr ')' mblock cont",
+"loop : label FOR scalar '(' remember mexpr ')' mblock cont",
+"loop : label FOR '(' remember mexpr ')' mblock cont",
+"loop : label FOR '(' remember mnexpr ';' mtexpr ';' mnexpr ')' mblock",
 "loop : label block cont",
 "nexpr :",
 "nexpr : sideff",
@@ -1104,6 +1143,7 @@ char *yyrule[] = {
 "texpr : expr",
 "iexpr : expr",
 "mexpr : expr",
+"mnexpr : nexpr",
 "mtexpr : texpr",
 "miexpr : iexpr",
 "label :",
@@ -1252,9 +1292,9 @@ int yyerrflag;
 int yychar;
 YYSTYPE yyval;
 YYSTYPE yylval;
-#line 631 "perly.y"
+#line 616 "perly.y"
  /* PROGRAM */
-#line 1329 "perly.c"
+#line 1369 "perly.c"
 #define YYABORT goto yyabort
 #define YYACCEPT goto yyaccept
 #define YYERROR goto yyerrlab
@@ -1501,42 +1541,33 @@ case 4:
 break;
 case 5:
 #line 104 "perly.y"
-{ if (yyvsp[-3].opval)
-                           yyvsp[-1].opval = yyvsp[-1].opval ? append_list(OP_LINESEQ,
-                                         (LISTOP*)yyvsp[-3].opval, (LISTOP*)yyvsp[-1].opval) : yyvsp[-3].opval;
-                         yyval.opval = block_end(yyvsp[-4].ival, yyvsp[-2].ival, yyvsp[-1].opval); }
+{ yyval.opval = block_end(yyvsp[-3].ival,yyvsp[-2].ival,yyvsp[-1].opval); }
 break;
 case 6:
-#line 111 "perly.y"
-{ yyval.opval = min_intro_pending
-                             ? newSTATEOP(0, Nullch, newOP(OP_NULL, 0))
-                             : NULL; }
-break;
-case 7:
-#line 117 "perly.y"
+#line 108 "perly.y"
 { yyval.ival = block_start(FALSE); }
 break;
-case 8:
-#line 121 "perly.y"
+case 7:
+#line 112 "perly.y"
 { yyval.opval = Nullop; }
 break;
-case 9:
-#line 123 "perly.y"
+case 8:
+#line 114 "perly.y"
 { yyval.opval = yyvsp[-1].opval; }
 break;
-case 10:
-#line 125 "perly.y"
+case 9:
+#line 116 "perly.y"
 {   yyval.opval = append_list(OP_LINESEQ,
                                (LISTOP*)yyvsp[-1].opval, (LISTOP*)yyvsp[0].opval);
                            pad_reset_pending = TRUE;
                            if (yyvsp[-1].opval && yyvsp[0].opval) hints |= HINT_BLOCK_SCOPE; }
 break;
-case 11:
-#line 132 "perly.y"
+case 10:
+#line 123 "perly.y"
 { yyval.opval = newSTATEOP(0, yyvsp[-1].pval, yyvsp[0].opval); }
 break;
-case 13:
-#line 135 "perly.y"
+case 12:
+#line 126 "perly.y"
 { if (yyvsp[-1].pval != Nullch) {
                              yyval.opval = newSTATEOP(0, yyvsp[-1].pval, newOP(OP_NULL, 0));
                            }
@@ -1546,507 +1577,497 @@ case 13:
                            }
                            expect = XSTATE; }
 break;
-case 14:
-#line 144 "perly.y"
+case 13:
+#line 135 "perly.y"
 { yyval.opval = newSTATEOP(0, yyvsp[-2].pval, yyvsp[-1].opval);
                          expect = XSTATE; }
 break;
-case 15:
-#line 149 "perly.y"
+case 14:
+#line 140 "perly.y"
 { yyval.opval = Nullop; }
 break;
-case 16:
-#line 151 "perly.y"
+case 15:
+#line 142 "perly.y"
 { yyval.opval = yyvsp[0].opval; }
 break;
-case 17:
-#line 153 "perly.y"
+case 16:
+#line 144 "perly.y"
 { yyval.opval = newLOGOP(OP_AND, 0, yyvsp[0].opval, yyvsp[-2].opval); }
 break;
-case 18:
-#line 155 "perly.y"
+case 17:
+#line 146 "perly.y"
 { yyval.opval = newLOGOP(OP_OR, 0, yyvsp[0].opval, yyvsp[-2].opval); }
 break;
-case 19:
-#line 157 "perly.y"
+case 18:
+#line 148 "perly.y"
 { yyval.opval = newLOOPOP(OPf_PARENS, 1, scalar(yyvsp[0].opval), yyvsp[-2].opval); }
 break;
-case 20:
-#line 159 "perly.y"
+case 19:
+#line 150 "perly.y"
 { yyval.opval = newLOOPOP(OPf_PARENS, 1, yyvsp[0].opval, yyvsp[-2].opval);}
 break;
-case 21:
-#line 163 "perly.y"
+case 20:
+#line 154 "perly.y"
 { yyval.opval = Nullop; }
 break;
-case 22:
-#line 165 "perly.y"
+case 21:
+#line 156 "perly.y"
 { yyval.opval = scope(yyvsp[0].opval); }
 break;
-case 23:
-#line 167 "perly.y"
+case 22:
+#line 158 "perly.y"
 { copline = yyvsp[-5].ival;
-                           yyval.opval = newCONDOP(0, yyvsp[-3].opval, scope(yyvsp[-1].opval), yyvsp[0].opval);
+                           yyval.opval = newSTATEOP(0, Nullch,
+                                  newCONDOP(0, yyvsp[-3].opval, scope(yyvsp[-1].opval), yyvsp[0].opval));
                            hints |= HINT_BLOCK_SCOPE; }
 break;
-case 24:
-#line 173 "perly.y"
+case 23:
+#line 165 "perly.y"
 { copline = yyvsp[-6].ival;
                            yyval.opval = block_end(yyvsp[-6].ival, yyvsp[-4].ival,
-                                   newCONDOP(0, yyvsp[-3].opval, scope(yyvsp[-1].opval), yyvsp[0].opval)); }
+                                  newCONDOP(0, yyvsp[-3].opval, scope(yyvsp[-1].opval), yyvsp[0].opval)); }
 break;
-case 25:
-#line 177 "perly.y"
+case 24:
+#line 169 "perly.y"
 { copline = yyvsp[-6].ival;
                            yyval.opval = block_end(yyvsp[-6].ival, yyvsp[-4].ival,
-                                   newCONDOP(0, yyvsp[-3].opval, scope(yyvsp[-1].opval), yyvsp[0].opval)); }
+                                  newCONDOP(0, yyvsp[-3].opval, scope(yyvsp[-1].opval), yyvsp[0].opval)); }
 break;
-case 26:
-#line 181 "perly.y"
+case 25:
+#line 173 "perly.y"
 { copline = yyvsp[-3].ival;
                            deprecate("if BLOCK BLOCK");
                            yyval.opval = newCONDOP(0, scope(yyvsp[-2].opval), scope(yyvsp[-1].opval), yyvsp[0].opval); }
 break;
-case 27:
-#line 185 "perly.y"
+case 26:
+#line 177 "perly.y"
 { copline = yyvsp[-3].ival;
                            deprecate("unless BLOCK BLOCK");
                            yyval.opval = newCONDOP(0, invert(scalar(scope(yyvsp[-2].opval))),
                                                scope(yyvsp[-1].opval), yyvsp[0].opval); }
 break;
-case 28:
-#line 192 "perly.y"
+case 27:
+#line 184 "perly.y"
 { yyval.opval = Nullop; }
 break;
-case 29:
-#line 194 "perly.y"
+case 28:
+#line 186 "perly.y"
 { yyval.opval = scope(yyvsp[0].opval); }
 break;
-case 30:
-#line 198 "perly.y"
+case 29:
+#line 190 "perly.y"
 { copline = yyvsp[-6].ival;
                            yyval.opval = block_end(yyvsp[-6].ival, yyvsp[-4].ival,
                                   newSTATEOP(0, yyvsp[-7].pval,
-                                     newWHILEOP(0, 1, (LOOP*)Nullop,
-                                                yyvsp[-3].opval, yyvsp[-1].opval, yyvsp[0].opval) )); }
+                                    newWHILEOP(0, 1, (LOOP*)Nullop,
+                                               yyvsp[-3].opval, yyvsp[-1].opval, yyvsp[0].opval))); }
 break;
-case 31:
-#line 204 "perly.y"
+case 30:
+#line 196 "perly.y"
 { copline = yyvsp[-6].ival;
                            yyval.opval = block_end(yyvsp[-6].ival, yyvsp[-4].ival,
                                   newSTATEOP(0, yyvsp[-7].pval,
-                                     newWHILEOP(0, 1, (LOOP*)Nullop,
-                                                yyvsp[-3].opval, yyvsp[-1].opval, yyvsp[0].opval) )); }
+                                    newWHILEOP(0, 1, (LOOP*)Nullop,
+                                               yyvsp[-3].opval, yyvsp[-1].opval, yyvsp[0].opval))); }
+break;
+case 31:
+#line 202 "perly.y"
+{ copline = yyvsp[-3].ival;
+                           yyval.opval = newWHILEOP(0, 1, (LOOP*)Nullop,
+                                           scope(yyvsp[-2].opval), yyvsp[-1].opval, yyvsp[0].opval); }
 break;
 case 32:
-#line 210 "perly.y"
+#line 206 "perly.y"
 { copline = yyvsp[-3].ival;
-                           yyval.opval = newSTATEOP(0, yyvsp[-4].pval,
-                                   newWHILEOP(0, 1, (LOOP*)Nullop,
-                                       scope(yyvsp[-2].opval), yyvsp[-1].opval, yyvsp[0].opval) ); }
+                           yyval.opval = newWHILEOP(0, 1, (LOOP*)Nullop,
+                                           invert(scalar(scope(yyvsp[-2].opval))),
+                                           yyvsp[-1].opval, yyvsp[0].opval); }
 break;
 case 33:
-#line 215 "perly.y"
-{ copline = yyvsp[-3].ival;
-                           yyval.opval = newSTATEOP(0, yyvsp[-4].pval,
-                                   newWHILEOP(0, 1, (LOOP*)Nullop,
-                                       invert(scalar(scope(yyvsp[-2].opval))), yyvsp[-1].opval, yyvsp[0].opval)); }
+#line 211 "perly.y"
+{ yyval.opval = block_end(yyvsp[-8].ival, yyvsp[-6].ival,
+                                newFOROP(0, yyvsp[-9].pval, yyvsp[-8].ival, yyvsp[-5].opval, yyvsp[-3].opval, yyvsp[-1].opval, yyvsp[0].opval)); }
 break;
 case 34:
-#line 220 "perly.y"
-{ yyval.opval = block_end(yyvsp[-8].ival, yyvsp[-6].ival,
-                                 newFOROP(0, yyvsp[-9].pval, yyvsp[-8].ival, yyvsp[-5].opval, yyvsp[-3].opval, yyvsp[-1].opval, yyvsp[0].opval)); }
+#line 214 "perly.y"
+{ yyval.opval = block_end(yyvsp[-7].ival, yyvsp[-4].ival,
+                                newFOROP(0, yyvsp[-8].pval, yyvsp[-7].ival, mod(yyvsp[-6].opval, OP_ENTERLOOP),
+                                         yyvsp[-3].opval, yyvsp[-1].opval, yyvsp[0].opval)); }
 break;
 case 35:
-#line 223 "perly.y"
-{ yyval.opval = newFOROP(0, yyvsp[-7].pval, yyvsp[-6].ival, mod(yyvsp[-5].opval, OP_ENTERLOOP),
-                               yyvsp[-3].opval, yyvsp[-1].opval, yyvsp[0].opval); }
-break;
-case 36:
-#line 226 "perly.y"
+#line 218 "perly.y"
 { yyval.opval = block_end(yyvsp[-6].ival, yyvsp[-4].ival,
                                 newFOROP(0, yyvsp[-7].pval, yyvsp[-6].ival, Nullop, yyvsp[-3].opval, yyvsp[-1].opval, yyvsp[0].opval)); }
 break;
-case 37:
-#line 229 "perly.y"
-{ if (yyvsp[-1].opval) {
-                                   yyvsp[-1].opval = scalar(yyvsp[-1].opval);
-                                   if (min_intro_pending)
-                                     yyvsp[-1].opval = newSTATEOP(0, Nullch, yyvsp[-1].opval); } }
-break;
-case 38:
-#line 234 "perly.y"
-{ yyvsp[-1].opval = scalar(yyvsp[-1].opval);
-                                 if (min_intro_pending)
-                                   yyvsp[-1].opval = newSTATEOP(0, Nullch, yyvsp[-1].opval); }
-break;
-case 39:
-#line 239 "perly.y"
-{ copline = yyvsp[-11].ival;
-                           yyval.opval = block_end(yyvsp[-11].ival, yyvsp[-9].ival,
-                                  append_elem(OP_LINESEQ, yyvsp[-8].opval,
-                                     newSTATEOP(0, yyvsp[-12].pval,
-                                        newWHILEOP(0, 1, (LOOP*)Nullop,
-                                                   yyvsp[-5].opval, yyvsp[0].opval, scalar(yyvsp[-2].opval))))); }
+case 36:
+#line 222 "perly.y"
+{ copline = yyvsp[-9].ival;
+                           yyval.opval = block_end(yyvsp[-9].ival, yyvsp[-7].ival,
+                                  append_elem(OP_LINESEQ, scalar(yyvsp[-6].opval),
+                                    newSTATEOP(0, yyvsp[-10].pval,
+                                      newWHILEOP(0, 1, (LOOP*)Nullop,
+                                                 scalar(yyvsp[-4].opval),
+                                                 yyvsp[0].opval, scalar(yyvsp[-2].opval))))); }
 break;
-case 40:
-#line 246 "perly.y"
+case 37:
+#line 230 "perly.y"
 { yyval.opval = newSTATEOP(0,
                                yyvsp[-2].pval, newWHILEOP(0, 1, (LOOP*)Nullop,
                                        Nullop, yyvsp[-1].opval, yyvsp[0].opval)); }
 break;
-case 41:
-#line 252 "perly.y"
+case 38:
+#line 236 "perly.y"
 { yyval.opval = Nullop; }
 break;
-case 43:
-#line 257 "perly.y"
+case 40:
+#line 241 "perly.y"
 { (void)scan_num("1"); yyval.opval = yylval.opval; }
 break;
-case 45:
-#line 262 "perly.y"
+case 42:
+#line 246 "perly.y"
 { yyval.opval = invert(scalar(yyvsp[0].opval)); }
 break;
+case 43:
+#line 250 "perly.y"
+{ yyval.opval = yyvsp[0].opval; intro_my(); }
+break;
+case 44:
+#line 254 "perly.y"
+{ yyval.opval = yyvsp[0].opval; intro_my(); }
+break;
+case 45:
+#line 258 "perly.y"
+{ yyval.opval = yyvsp[0].opval; intro_my(); }
+break;
 case 46:
-#line 266 "perly.y"
-{ yyval.opval = min_intro_pending
-                               ? newSTATEOP(0, Nullch, yyvsp[0].opval) : yyvsp[0].opval; }
+#line 262 "perly.y"
+{ yyval.opval = yyvsp[0].opval; intro_my(); }
 break;
 case 47:
-#line 271 "perly.y"
-{ yyval.opval = min_intro_pending
-                               ? newSTATEOP(0, Nullch, yyvsp[0].opval) : yyvsp[0].opval; }
-break;
-case 48:
-#line 276 "perly.y"
-{ yyval.opval = min_intro_pending
-                               ? newSTATEOP(0, Nullch, yyvsp[0].opval) : yyvsp[0].opval; }
+#line 266 "perly.y"
+{ yyval.pval = Nullch; }
 break;
 case 49:
-#line 281 "perly.y"
-{ yyval.pval = Nullch; }
+#line 271 "perly.y"
+{ yyval.ival = 0; }
+break;
+case 50:
+#line 273 "perly.y"
+{ yyval.ival = 0; }
 break;
 case 51:
-#line 286 "perly.y"
+#line 275 "perly.y"
 { yyval.ival = 0; }
 break;
 case 52:
-#line 288 "perly.y"
+#line 277 "perly.y"
 { yyval.ival = 0; }
 break;
 case 53:
-#line 290 "perly.y"
-{ yyval.ival = 0; }
+#line 281 "perly.y"
+{ newFORM(yyvsp[-2].ival, yyvsp[-1].opval, yyvsp[0].opval); }
 break;
 case 54:
-#line 292 "perly.y"
-{ yyval.ival = 0; }
-break;
-case 55:
-#line 296 "perly.y"
-{ newFORM(yyvsp[-2].ival, yyvsp[-1].opval, yyvsp[0].opval); }
-break;
-case 56:
-#line 298 "perly.y"
+#line 283 "perly.y"
 { newFORM(yyvsp[-1].ival, Nullop, yyvsp[0].opval); }
 break;
-case 57:
-#line 302 "perly.y"
+case 55:
+#line 287 "perly.y"
 { newSUB(yyvsp[-3].ival, yyvsp[-2].opval, yyvsp[-1].opval, yyvsp[0].opval); }
 break;
-case 58:
-#line 304 "perly.y"
+case 56:
+#line 289 "perly.y"
 { newSUB(yyvsp[-3].ival, yyvsp[-2].opval, yyvsp[-1].opval, Nullop); expect = XSTATE; }
 break;
-case 59:
-#line 308 "perly.y"
+case 57:
+#line 293 "perly.y"
 { yyval.opval = Nullop; }
 break;
-case 61:
-#line 313 "perly.y"
+case 59:
+#line 298 "perly.y"
 { yyval.ival = start_subparse(); }
 break;
-case 62:
-#line 317 "perly.y"
+case 60:
+#line 302 "perly.y"
 { package(yyvsp[-1].opval); }
 break;
-case 63:
-#line 319 "perly.y"
+case 61:
+#line 304 "perly.y"
 { package(Nullop); }
 break;
-case 64:
-#line 323 "perly.y"
+case 62:
+#line 308 "perly.y"
 { utilize(yyvsp[-5].ival, yyvsp[-4].ival, yyvsp[-3].opval, yyvsp[-2].opval, yyvsp[-1].opval); }
 break;
-case 65:
-#line 327 "perly.y"
+case 63:
+#line 312 "perly.y"
 { yyval.opval = newLOGOP(OP_AND, 0, yyvsp[-2].opval, yyvsp[0].opval); }
 break;
-case 66:
-#line 329 "perly.y"
+case 64:
+#line 314 "perly.y"
 { yyval.opval = newLOGOP(yyvsp[-1].ival, 0, yyvsp[-2].opval, yyvsp[0].opval); }
 break;
-case 68:
-#line 334 "perly.y"
+case 66:
+#line 319 "perly.y"
 { yyval.opval = yyvsp[-1].opval; }
 break;
-case 69:
-#line 336 "perly.y"
+case 67:
+#line 321 "perly.y"
 { yyval.opval = append_elem(OP_LIST, yyvsp[-2].opval, yyvsp[0].opval); }
 break;
-case 71:
-#line 341 "perly.y"
+case 69:
+#line 326 "perly.y"
 { yyval.opval = convert(yyvsp[-2].ival, OPf_STACKED,
                                prepend_elem(OP_LIST, newGVREF(yyvsp[-2].ival,yyvsp[-1].opval), yyvsp[0].opval) ); }
 break;
-case 72:
-#line 344 "perly.y"
+case 70:
+#line 329 "perly.y"
 { yyval.opval = convert(yyvsp[-4].ival, OPf_STACKED,
                                prepend_elem(OP_LIST, newGVREF(yyvsp[-4].ival,yyvsp[-2].opval), yyvsp[-1].opval) ); }
 break;
-case 73:
-#line 347 "perly.y"
+case 71:
+#line 332 "perly.y"
 { yyval.opval = convert(OP_ENTERSUB, OPf_STACKED,
                                append_elem(OP_LIST,
                                    prepend_elem(OP_LIST, scalar(yyvsp[-5].opval), yyvsp[-1].opval),
                                    newUNOP(OP_METHOD, 0, yyvsp[-3].opval))); }
 break;
-case 74:
-#line 352 "perly.y"
+case 72:
+#line 337 "perly.y"
 { yyval.opval = convert(OP_ENTERSUB, OPf_STACKED,
                                append_elem(OP_LIST,
                                    prepend_elem(OP_LIST, yyvsp[-1].opval, yyvsp[0].opval),
                                    newUNOP(OP_METHOD, 0, yyvsp[-2].opval))); }
 break;
-case 75:
-#line 357 "perly.y"
+case 73:
+#line 342 "perly.y"
 { yyval.opval = convert(OP_ENTERSUB, OPf_STACKED,
                                append_elem(OP_LIST,
                                    prepend_elem(OP_LIST, yyvsp[-3].opval, yyvsp[-1].opval),
                                    newUNOP(OP_METHOD, 0, yyvsp[-4].opval))); }
 break;
-case 76:
-#line 362 "perly.y"
+case 74:
+#line 347 "perly.y"
 { yyval.opval = convert(yyvsp[-1].ival, 0, yyvsp[0].opval); }
 break;
-case 77:
-#line 364 "perly.y"
+case 75:
+#line 349 "perly.y"
 { yyval.opval = convert(yyvsp[-3].ival, 0, yyvsp[-1].opval); }
 break;
-case 78:
-#line 366 "perly.y"
+case 76:
+#line 351 "perly.y"
 { yyval.opval = newUNOP(OP_ENTERSUB, OPf_STACKED,
                            append_elem(OP_LIST,
                              prepend_elem(OP_LIST, newANONSUB(yyvsp[-2].ival, 0, yyvsp[-1].opval), yyvsp[0].opval),
                              yyvsp[-3].opval)); }
 break;
-case 81:
-#line 377 "perly.y"
+case 79:
+#line 362 "perly.y"
 { yyval.opval = newASSIGNOP(OPf_STACKED, yyvsp[-2].opval, yyvsp[-1].ival, yyvsp[0].opval); }
 break;
-case 82:
-#line 379 "perly.y"
+case 80:
+#line 364 "perly.y"
 { yyval.opval = newBINOP(yyvsp[-1].ival, 0, scalar(yyvsp[-2].opval), scalar(yyvsp[0].opval)); }
 break;
-case 83:
-#line 381 "perly.y"
+case 81:
+#line 366 "perly.y"
 {   if (yyvsp[-1].ival != OP_REPEAT)
                                scalar(yyvsp[-2].opval);
                            yyval.opval = newBINOP(yyvsp[-1].ival, 0, yyvsp[-2].opval, scalar(yyvsp[0].opval)); }
 break;
+case 82:
+#line 370 "perly.y"
+{ yyval.opval = newBINOP(yyvsp[-1].ival, 0, scalar(yyvsp[-2].opval), scalar(yyvsp[0].opval)); }
+break;
+case 83:
+#line 372 "perly.y"
+{ yyval.opval = newBINOP(yyvsp[-1].ival, 0, scalar(yyvsp[-2].opval), scalar(yyvsp[0].opval)); }
+break;
 case 84:
-#line 385 "perly.y"
+#line 374 "perly.y"
 { yyval.opval = newBINOP(yyvsp[-1].ival, 0, scalar(yyvsp[-2].opval), scalar(yyvsp[0].opval)); }
 break;
 case 85:
-#line 387 "perly.y"
+#line 376 "perly.y"
 { yyval.opval = newBINOP(yyvsp[-1].ival, 0, scalar(yyvsp[-2].opval), scalar(yyvsp[0].opval)); }
 break;
 case 86:
-#line 389 "perly.y"
+#line 378 "perly.y"
 { yyval.opval = newBINOP(yyvsp[-1].ival, 0, scalar(yyvsp[-2].opval), scalar(yyvsp[0].opval)); }
 break;
 case 87:
-#line 391 "perly.y"
+#line 380 "perly.y"
 { yyval.opval = newBINOP(yyvsp[-1].ival, 0, scalar(yyvsp[-2].opval), scalar(yyvsp[0].opval)); }
 break;
 case 88:
-#line 393 "perly.y"
-{ yyval.opval = newBINOP(yyvsp[-1].ival, 0, scalar(yyvsp[-2].opval), scalar(yyvsp[0].opval)); }
-break;
-case 89:
-#line 395 "perly.y"
-{ yyval.opval = newBINOP(yyvsp[-1].ival, 0, scalar(yyvsp[-2].opval), scalar(yyvsp[0].opval)); }
-break;
-case 90:
-#line 397 "perly.y"
+#line 382 "perly.y"
 { yyval.opval = newRANGE(yyvsp[-1].ival, scalar(yyvsp[-2].opval), scalar(yyvsp[0].opval));}
 break;
-case 91:
-#line 399 "perly.y"
+case 89:
+#line 384 "perly.y"
 { yyval.opval = newLOGOP(OP_AND, 0, yyvsp[-2].opval, yyvsp[0].opval); }
 break;
-case 92:
-#line 401 "perly.y"
+case 90:
+#line 386 "perly.y"
 { yyval.opval = newLOGOP(OP_OR, 0, yyvsp[-2].opval, yyvsp[0].opval); }
 break;
-case 93:
-#line 403 "perly.y"
+case 91:
+#line 388 "perly.y"
 { yyval.opval = newCONDOP(0, yyvsp[-4].opval, yyvsp[-2].opval, yyvsp[0].opval); }
 break;
-case 94:
-#line 405 "perly.y"
+case 92:
+#line 390 "perly.y"
 { yyval.opval = bind_match(yyvsp[-1].ival, yyvsp[-2].opval, yyvsp[0].opval); }
 break;
-case 95:
-#line 408 "perly.y"
+case 93:
+#line 393 "perly.y"
 { yyval.opval = newUNOP(OP_NEGATE, 0, scalar(yyvsp[0].opval)); }
 break;
-case 96:
-#line 410 "perly.y"
+case 94:
+#line 395 "perly.y"
 { yyval.opval = yyvsp[0].opval; }
 break;
-case 97:
-#line 412 "perly.y"
+case 95:
+#line 397 "perly.y"
 { yyval.opval = newUNOP(OP_NOT, 0, scalar(yyvsp[0].opval)); }
 break;
-case 98:
-#line 414 "perly.y"
+case 96:
+#line 399 "perly.y"
 { yyval.opval = newUNOP(OP_COMPLEMENT, 0, scalar(yyvsp[0].opval));}
 break;
-case 99:
-#line 416 "perly.y"
+case 97:
+#line 401 "perly.y"
 { yyval.opval = newUNOP(OP_REFGEN, 0, mod(yyvsp[0].opval,OP_REFGEN)); }
 break;
-case 100:
-#line 418 "perly.y"
+case 98:
+#line 403 "perly.y"
 { yyval.opval = newUNOP(OP_POSTINC, 0,
                                        mod(scalar(yyvsp[-1].opval), OP_POSTINC)); }
 break;
-case 101:
-#line 421 "perly.y"
+case 99:
+#line 406 "perly.y"
 { yyval.opval = newUNOP(OP_POSTDEC, 0,
                                        mod(scalar(yyvsp[-1].opval), OP_POSTDEC)); }
 break;
-case 102:
-#line 424 "perly.y"
+case 100:
+#line 409 "perly.y"
 { yyval.opval = newUNOP(OP_PREINC, 0,
                                        mod(scalar(yyvsp[0].opval), OP_PREINC)); }
 break;
-case 103:
-#line 427 "perly.y"
+case 101:
+#line 412 "perly.y"
 { yyval.opval = newUNOP(OP_PREDEC, 0,
                                        mod(scalar(yyvsp[0].opval), OP_PREDEC)); }
 break;
-case 104:
-#line 430 "perly.y"
+case 102:
+#line 415 "perly.y"
 { yyval.opval = localize(yyvsp[0].opval,yyvsp[-1].ival); }
 break;
-case 105:
-#line 432 "perly.y"
+case 103:
+#line 417 "perly.y"
 { yyval.opval = sawparens(yyvsp[-1].opval); }
 break;
-case 106:
-#line 434 "perly.y"
+case 104:
+#line 419 "perly.y"
 { yyval.opval = sawparens(newNULLLIST()); }
 break;
-case 107:
-#line 436 "perly.y"
+case 105:
+#line 421 "perly.y"
 { yyval.opval = newANONLIST(yyvsp[-1].opval); }
 break;
-case 108:
-#line 438 "perly.y"
+case 106:
+#line 423 "perly.y"
 { yyval.opval = newANONLIST(Nullop); }
 break;
-case 109:
-#line 440 "perly.y"
+case 107:
+#line 425 "perly.y"
 { yyval.opval = newANONHASH(yyvsp[-2].opval); }
 break;
-case 110:
-#line 442 "perly.y"
+case 108:
+#line 427 "perly.y"
 { yyval.opval = newANONHASH(Nullop); }
 break;
-case 111:
-#line 444 "perly.y"
+case 109:
+#line 429 "perly.y"
 { yyval.opval = newANONSUB(yyvsp[-2].ival, yyvsp[-1].opval, yyvsp[0].opval); }
 break;
-case 112:
-#line 446 "perly.y"
+case 110:
+#line 431 "perly.y"
 { yyval.opval = yyvsp[0].opval; }
 break;
-case 113:
-#line 448 "perly.y"
+case 111:
+#line 433 "perly.y"
 { yyval.opval = newBINOP(OP_GELEM, 0, newGVREF(0,yyvsp[-4].opval), yyvsp[-2].opval); }
 break;
-case 114:
-#line 450 "perly.y"
+case 112:
+#line 435 "perly.y"
 { yyval.opval = yyvsp[0].opval; }
 break;
-case 115:
-#line 452 "perly.y"
+case 113:
+#line 437 "perly.y"
 { yyval.opval = newBINOP(OP_AELEM, 0, oopsAV(yyvsp[-3].opval), scalar(yyvsp[-1].opval)); }
 break;
-case 116:
-#line 454 "perly.y"
+case 114:
+#line 439 "perly.y"
 { yyval.opval = newBINOP(OP_AELEM, 0,
                                        ref(newAVREF(yyvsp[-4].opval),OP_RV2AV),
                                        scalar(yyvsp[-1].opval));}
 break;
-case 117:
-#line 458 "perly.y"
+case 115:
+#line 443 "perly.y"
 { assertref(yyvsp[-3].opval); yyval.opval = newBINOP(OP_AELEM, 0,
                                        ref(newAVREF(yyvsp[-3].opval),OP_RV2AV),
                                        scalar(yyvsp[-1].opval));}
 break;
-case 118:
-#line 462 "perly.y"
+case 116:
+#line 447 "perly.y"
 { yyval.opval = yyvsp[0].opval; }
 break;
-case 119:
-#line 464 "perly.y"
+case 117:
+#line 449 "perly.y"
 { yyval.opval = yyvsp[0].opval; }
 break;
-case 120:
-#line 466 "perly.y"
+case 118:
+#line 451 "perly.y"
 { yyval.opval = newUNOP(OP_AV2ARYLEN, 0, ref(yyvsp[0].opval, OP_AV2ARYLEN));}
 break;
-case 121:
-#line 468 "perly.y"
+case 119:
+#line 453 "perly.y"
 { yyval.opval = newBINOP(OP_HELEM, 0, oopsHV(yyvsp[-4].opval), jmaybe(yyvsp[-2].opval));
                            expect = XOPERATOR; }
 break;
-case 122:
-#line 471 "perly.y"
+case 120:
+#line 456 "perly.y"
 { yyval.opval = newBINOP(OP_HELEM, 0,
                                        ref(newHVREF(yyvsp[-5].opval),OP_RV2HV),
                                        jmaybe(yyvsp[-2].opval));
                            expect = XOPERATOR; }
 break;
-case 123:
-#line 476 "perly.y"
+case 121:
+#line 461 "perly.y"
 { assertref(yyvsp[-4].opval); yyval.opval = newBINOP(OP_HELEM, 0,
                                        ref(newHVREF(yyvsp[-4].opval),OP_RV2HV),
                                        jmaybe(yyvsp[-2].opval));
                            expect = XOPERATOR; }
 break;
-case 124:
-#line 481 "perly.y"
+case 122:
+#line 466 "perly.y"
 { yyval.opval = newSLICEOP(0, yyvsp[-1].opval, yyvsp[-4].opval); }
 break;
-case 125:
-#line 483 "perly.y"
+case 123:
+#line 468 "perly.y"
 { yyval.opval = newSLICEOP(0, yyvsp[-1].opval, Nullop); }
 break;
-case 126:
-#line 485 "perly.y"
+case 124:
+#line 470 "perly.y"
 { yyval.opval = prepend_elem(OP_ASLICE,
                                newOP(OP_PUSHMARK, 0),
                                    newLISTOP(OP_ASLICE, 0,
                                        list(yyvsp[-1].opval),
                                        ref(yyvsp[-3].opval, OP_ASLICE))); }
 break;
-case 127:
-#line 491 "perly.y"
+case 125:
+#line 476 "perly.y"
 { yyval.opval = prepend_elem(OP_HSLICE,
                                newOP(OP_PUSHMARK, 0),
                                    newLISTOP(OP_HSLICE, 0,
@@ -2054,38 +2075,38 @@ case 127:
                                        ref(oopsHV(yyvsp[-4].opval), OP_HSLICE)));
                            expect = XOPERATOR; }
 break;
-case 128:
-#line 498 "perly.y"
+case 126:
+#line 483 "perly.y"
 { yyval.opval = yyvsp[0].opval; }
 break;
-case 129:
-#line 500 "perly.y"
+case 127:
+#line 485 "perly.y"
 { yyval.opval = newUNOP(OP_ENTERSUB, 0, scalar(yyvsp[0].opval)); }
 break;
-case 130:
-#line 502 "perly.y"
+case 128:
+#line 487 "perly.y"
 { yyval.opval = newUNOP(OP_ENTERSUB, OPf_STACKED, scalar(yyvsp[-2].opval)); }
 break;
-case 131:
-#line 504 "perly.y"
+case 129:
+#line 489 "perly.y"
 { yyval.opval = newUNOP(OP_ENTERSUB, OPf_STACKED,
                            append_elem(OP_LIST, yyvsp[-1].opval, scalar(yyvsp[-3].opval))); }
 break;
-case 132:
-#line 507 "perly.y"
+case 130:
+#line 492 "perly.y"
 { yyval.opval = newUNOP(OP_ENTERSUB, OPf_STACKED,
                            append_elem(OP_LIST, yyvsp[0].opval, scalar(yyvsp[-1].opval))); }
 break;
-case 133:
-#line 510 "perly.y"
+case 131:
+#line 495 "perly.y"
 { yyval.opval = newUNOP(OP_DOFILE, 0, scalar(yyvsp[0].opval)); }
 break;
-case 134:
-#line 512 "perly.y"
+case 132:
+#line 497 "perly.y"
 { yyval.opval = newUNOP(OP_NULL, OPf_SPECIAL, scope(yyvsp[0].opval)); }
 break;
-case 135:
-#line 514 "perly.y"
+case 133:
+#line 499 "perly.y"
 { yyval.opval = newUNOP(OP_ENTERSUB,
                            OPf_SPECIAL|OPf_STACKED,
                            prepend_elem(OP_LIST,
@@ -2094,8 +2115,8 @@ case 135:
                                    scalar(yyvsp[-2].opval)
                                )),Nullop)); dep();}
 break;
-case 136:
-#line 522 "perly.y"
+case 134:
+#line 507 "perly.y"
 { yyval.opval = newUNOP(OP_ENTERSUB,
                            OPf_SPECIAL|OPf_STACKED,
                            append_elem(OP_LIST,
@@ -2105,151 +2126,151 @@ case 136:
                                    scalar(yyvsp[-3].opval)
                                )))); dep();}
 break;
-case 137:
-#line 531 "perly.y"
+case 135:
+#line 516 "perly.y"
 { yyval.opval = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED,
                            prepend_elem(OP_LIST,
                                scalar(newCVREF(0,scalar(yyvsp[-2].opval))), Nullop)); dep();}
 break;
-case 138:
-#line 535 "perly.y"
+case 136:
+#line 520 "perly.y"
 { yyval.opval = newUNOP(OP_ENTERSUB, OPf_SPECIAL|OPf_STACKED,
                            prepend_elem(OP_LIST,
                                yyvsp[-1].opval,
                                scalar(newCVREF(0,scalar(yyvsp[-3].opval))))); dep();}
 break;
-case 139:
-#line 540 "perly.y"
+case 137:
+#line 525 "perly.y"
 { yyval.opval = newOP(yyvsp[0].ival, OPf_SPECIAL);
                            hints |= HINT_BLOCK_SCOPE; }
 break;
-case 140:
-#line 543 "perly.y"
+case 138:
+#line 528 "perly.y"
 { yyval.opval = newLOOPEX(yyvsp[-1].ival,yyvsp[0].opval); }
 break;
-case 141:
-#line 545 "perly.y"
+case 139:
+#line 530 "perly.y"
 { yyval.opval = newUNOP(OP_NOT, 0, scalar(yyvsp[0].opval)); }
 break;
-case 142:
-#line 547 "perly.y"
+case 140:
+#line 532 "perly.y"
 { yyval.opval = newOP(yyvsp[0].ival, 0); }
 break;
-case 143:
-#line 549 "perly.y"
+case 141:
+#line 534 "perly.y"
 { yyval.opval = newUNOP(yyvsp[-1].ival, 0, yyvsp[0].opval); }
 break;
-case 144:
-#line 551 "perly.y"
+case 142:
+#line 536 "perly.y"
 { yyval.opval = newUNOP(yyvsp[-1].ival, 0, yyvsp[0].opval); }
 break;
-case 145:
-#line 553 "perly.y"
+case 143:
+#line 538 "perly.y"
 { yyval.opval = newUNOP(OP_ENTERSUB, OPf_STACKED,
                            append_elem(OP_LIST, yyvsp[0].opval, scalar(yyvsp[-1].opval))); }
 break;
-case 146:
-#line 556 "perly.y"
+case 144:
+#line 541 "perly.y"
 { yyval.opval = newOP(yyvsp[0].ival, 0); }
 break;
-case 147:
-#line 558 "perly.y"
+case 145:
+#line 543 "perly.y"
 { yyval.opval = newOP(yyvsp[-2].ival, 0); }
 break;
-case 148:
-#line 560 "perly.y"
+case 146:
+#line 545 "perly.y"
 { yyval.opval = newUNOP(OP_ENTERSUB, 0,
                                scalar(yyvsp[0].opval)); }
 break;
-case 149:
-#line 563 "perly.y"
+case 147:
+#line 548 "perly.y"
 { yyval.opval = newOP(yyvsp[-2].ival, OPf_SPECIAL); }
 break;
-case 150:
-#line 565 "perly.y"
+case 148:
+#line 550 "perly.y"
 { yyval.opval = newUNOP(yyvsp[-3].ival, 0, yyvsp[-1].opval); }
 break;
-case 151:
-#line 567 "perly.y"
+case 149:
+#line 552 "perly.y"
 { yyval.opval = pmruntime(yyvsp[-3].opval, yyvsp[-1].opval, Nullop); }
 break;
-case 152:
-#line 569 "perly.y"
+case 150:
+#line 554 "perly.y"
 { yyval.opval = pmruntime(yyvsp[-5].opval, yyvsp[-3].opval, yyvsp[-1].opval); }
 break;
-case 155:
-#line 575 "perly.y"
+case 153:
+#line 560 "perly.y"
 { yyval.opval = Nullop; }
 break;
-case 156:
-#line 577 "perly.y"
+case 154:
+#line 562 "perly.y"
 { yyval.opval = yyvsp[0].opval; }
 break;
-case 157:
-#line 581 "perly.y"
+case 155:
+#line 566 "perly.y"
 { yyval.opval = Nullop; }
 break;
-case 158:
-#line 583 "perly.y"
+case 156:
+#line 568 "perly.y"
 { yyval.opval = yyvsp[0].opval; }
 break;
-case 159:
-#line 585 "perly.y"
+case 157:
+#line 570 "perly.y"
 { yyval.opval = yyvsp[-1].opval; }
 break;
-case 160:
-#line 588 "perly.y"
+case 158:
+#line 573 "perly.y"
 { yyval.ival = 0; }
 break;
-case 161:
-#line 589 "perly.y"
+case 159:
+#line 574 "perly.y"
 { yyval.ival = 1; }
 break;
-case 162:
-#line 593 "perly.y"
+case 160:
+#line 578 "perly.y"
 { in_my = 0; yyval.opval = my(yyvsp[0].opval); }
 break;
-case 163:
-#line 597 "perly.y"
+case 161:
+#line 582 "perly.y"
 { yyval.opval = newCVREF(yyvsp[-1].ival,yyvsp[0].opval); }
 break;
-case 164:
-#line 601 "perly.y"
+case 162:
+#line 586 "perly.y"
 { yyval.opval = newSVREF(yyvsp[0].opval); }
 break;
-case 165:
-#line 605 "perly.y"
+case 163:
+#line 590 "perly.y"
 { yyval.opval = newAVREF(yyvsp[0].opval); }
 break;
-case 166:
-#line 609 "perly.y"
+case 164:
+#line 594 "perly.y"
 { yyval.opval = newHVREF(yyvsp[0].opval); }
 break;
-case 167:
-#line 613 "perly.y"
+case 165:
+#line 598 "perly.y"
 { yyval.opval = newAVREF(yyvsp[0].opval); }
 break;
-case 168:
-#line 617 "perly.y"
+case 166:
+#line 602 "perly.y"
 { yyval.opval = newGVREF(0,yyvsp[0].opval); }
 break;
-case 169:
-#line 621 "perly.y"
+case 167:
+#line 606 "perly.y"
 { yyval.opval = scalar(yyvsp[0].opval); }
 break;
-case 170:
-#line 623 "perly.y"
+case 168:
+#line 608 "perly.y"
 { yyval.opval = scalar(yyvsp[0].opval);  }
 break;
-case 171:
-#line 625 "perly.y"
+case 169:
+#line 610 "perly.y"
 { yyval.opval = scope(yyvsp[0].opval); }
 break;
-case 172:
-#line 628 "perly.y"
+case 170:
+#line 613 "perly.y"
 { yyval.opval = yyvsp[0].opval; }
 break;
-#line 2240 "perly.c"
+#line 2261 "perly.c"
     }
     yyssp -= yym;
     yystate = *yyssp;
index cc55c40..3f4ab02 100644 (file)
@@ -1,7 +1,6 @@
 Index: perly.c
 ***************
-*** 12,83 ****
-      deprecate("\"do\" to call subroutines");
+*** 13,82 ****
   }
   
 - #line 29 "perly.y"
@@ -72,11 +71,9 @@ Index: perly.c
 - #define ARROW 314
   #define YYERRCODE 256
   short yylhs[] = {                                        -1,
-     40,    0,    7,    5,    8,    9,    6,   10,   10,   10,
---- 12,17 ----
+--- 13,16 ----
 ***************
-*** 1316,1342 ****
-  int yynerrs;
+*** 1357,1367 ****
   int yyerrflag;
   int yychar;
 - short *yyssp;
@@ -86,33 +83,12 @@ Index: perly.c
 - short yyss[YYSTACKSIZE];
 - YYSTYPE yyvs[YYSTACKSIZE];
 - #define yystacksize YYSTACKSIZE
-  #line 631 "perly.y"
+  #line 616 "perly.y"
    /* PROGRAM */
-  #line 1329 "y.tab.c"
-  #define YYABORT goto yyabort
-  #define YYACCEPT goto yyaccept
-  #define YYERROR goto yyerrlab
-  int
-  yyparse()
-  {
-      register int yym, yyn, yystate;
-  #if YYDEBUG
-      register char *yys;
-      extern char *getenv();
-  
-      if (yys = getenv("YYDEBUG"))
-      {
-          yyn = *yys;
---- 1250,1316 ----
-  int yynerrs;
-  int yyerrflag;
-  int yychar;
-  YYSTYPE yyval;
-  YYSTYPE yylval;
-  #line 631 "perly.y"
-   /* PROGRAM */
-  #line 1329 "y.tab.c"
-  #define YYABORT goto yyabort
+--- 1291,1296 ----
+***************
+*** 1370,1381 ****
+--- 1299,1355 ----
   #define YYACCEPT goto yyaccept
   #define YYERROR goto yyerrlab
 + 
@@ -170,11 +146,9 @@ Index: perly.c
 + #if YYDEBUG
       if (yys = getenv("YYDEBUG"))
       {
-          yyn = *yys;
 ***************
-*** 1349,1354 ****
---- 1323,1336 ----
-      yyerrflag = 0;
+*** 1390,1393 ****
+--- 1364,1375 ----
       yychar = (-1);
   
 +     /*
@@ -187,27 +161,21 @@ Index: perly.c
 + 
       yyssp = yyss;
       yyvsp = yyvs;
-      *yyssp = yystate = 0;
 ***************
-*** 1364,1370 ****
-              yys = 0;
+*** 1405,1409 ****
               if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
               if (!yys) yys = "illegal-symbol";
 !             printf("yydebug: state %d, reading %d (%s)\n", yystate,
                       yychar, yys);
           }
-  #endif
---- 1346,1352 ----
-              yys = 0;
+--- 1387,1391 ----
               if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
               if (!yys) yys = "illegal-symbol";
 !             fprintf(stderr, "yydebug: state %d, reading %d (%s)\n", yystate,
                       yychar, yys);
           }
-  #endif
 ***************
-*** 1374,1385 ****
-      {
+*** 1415,1424 ****
   #if YYDEBUG
           if (yydebug)
 !             printf("yydebug: state %d, shifting to state %d\n",
@@ -218,9 +186,7 @@ Index: perly.c
 !             goto yyoverflow;
           }
           *++yyssp = yystate = yytable[yyn];
-          *++yyvsp = yylval;
---- 1356,1381 ----
-      {
+--- 1397,1420 ----
   #if YYDEBUG
           if (yydebug)
 !             fprintf(stderr, "yydebug: state %d, shifting to state %d\n",
@@ -245,10 +211,8 @@ Index: perly.c
 !          yyvsp = yyvs + yypv_index;
           }
           *++yyssp = yystate = yytable[yyn];
-          *++yyvsp = yylval;
 ***************
-*** 1415,1426 ****
-              {
+*** 1456,1465 ****
   #if YYDEBUG
                   if (yydebug)
 !                     printf("yydebug: state %d, error recovery shifting\
@@ -259,9 +223,7 @@ Index: perly.c
 !                     goto yyoverflow;
                   }
                   *++yyssp = yystate = yytable[yyn];
-                  *++yyvsp = yylval;
---- 1411,1437 ----
-              {
+--- 1452,1476 ----
   #if YYDEBUG
                   if (yydebug)
 !                     fprintf(stderr,
@@ -287,19 +249,15 @@ Index: perly.c
 !                  yyvsp = yyvs + yypv_index;
                   }
                   *++yyssp = yystate = yytable[yyn];
-                  *++yyvsp = yylval;
 ***************
-*** 1430,1437 ****
-              {
+*** 1471,1476 ****
   #if YYDEBUG
                   if (yydebug)
 !                     printf("yydebug: error recovery discarding state %d\n",
 !                             *yyssp);
   #endif
                   if (yyssp <= yyss) goto yyabort;
-                  --yyssp;
---- 1441,1449 ----
-              {
+--- 1482,1488 ----
   #if YYDEBUG
                   if (yydebug)
 !                     fprintf(stderr,
@@ -307,19 +265,15 @@ Index: perly.c
 !                      *yyssp);
   #endif
                   if (yyssp <= yyss) goto yyabort;
-                  --yyssp;
 ***************
-*** 1448,1455 ****
-              yys = 0;
+*** 1489,1494 ****
               if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
               if (!yys) yys = "illegal-symbol";
 !             printf("yydebug: state %d, error recovery discards token %d (%s)\n",
 !                     yystate, yychar, yys);
           }
   #endif
-          yychar = (-1);
---- 1460,1468 ----
-              yys = 0;
+--- 1501,1507 ----
               if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
               if (!yys) yys = "illegal-symbol";
 !             fprintf(stderr,
@@ -327,36 +281,28 @@ Index: perly.c
 !              yystate, yychar, yys);
           }
   #endif
-          yychar = (-1);
 ***************
-*** 1458,1464 ****
-  yyreduce:
+*** 1499,1503 ****
   #if YYDEBUG
       if (yydebug)
 !         printf("yydebug: state %d, reducing by rule %d (%s)\n",
                   yystate, yyn, yyrule[yyn]);
   #endif
-      yym = yylen[yyn];
---- 1471,1477 ----
-  yyreduce:
+--- 1512,1516 ----
   #if YYDEBUG
       if (yydebug)
 !         fprintf(stderr, "yydebug: state %d, reducing by rule %d (%s)\n",
                   yystate, yyn, yyrule[yyn]);
   #endif
-      yym = yylen[yyn];
 ***************
-*** 2246,2253 ****
-      {
+*** 2268,2273 ****
   #if YYDEBUG
           if (yydebug)
 !             printf("yydebug: after reduction, shifting from state 0 to\
 !  state %d\n", YYFINAL);
   #endif
           yystate = YYFINAL;
-          *++yyssp = YYFINAL;
---- 2259,2267 ----
-      {
+--- 2281,2287 ----
   #if YYDEBUG
           if (yydebug)
 !             fprintf(stderr,
@@ -364,27 +310,21 @@ Index: perly.c
 !              YYFINAL);
   #endif
           yystate = YYFINAL;
-          *++yyssp = YYFINAL;
 ***************
-*** 2261,2267 ****
-                  yys = 0;
+*** 2283,2287 ****
                   if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
                   if (!yys) yys = "illegal-symbol";
 !                 printf("yydebug: state %d, reading %d (%s)\n",
                           YYFINAL, yychar, yys);
               }
-  #endif
---- 2275,2281 ----
-                  yys = 0;
+--- 2297,2301 ----
                   if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
                   if (!yys) yys = "illegal-symbol";
 !                 fprintf(stderr, "yydebug: state %d, reading %d (%s)\n",
                           YYFINAL, yychar, yys);
               }
-  #endif
 ***************
-*** 2276,2295 ****
-          yystate = yydgoto[yym];
+*** 2298,2307 ****
   #if YYDEBUG
       if (yydebug)
 !         printf("yydebug: after reduction, shifting from state %d \
@@ -395,17 +335,7 @@ Index: perly.c
 !         goto yyoverflow;
       }
       *++yyssp = yystate;
-      *++yyvsp = yyval;
-      goto yyloop;
-  yyoverflow:
-!     yyerror("yacc stack overflow");
-  yyabort:
-!     return (1);
-  yyaccept:
-!     return (0);
-  }
---- 2290,2324 ----
-          yystate = yydgoto[yym];
+--- 2312,2336 ----
   #if YYDEBUG
       if (yydebug)
 !         fprintf(stderr,
@@ -431,7 +361,17 @@ Index: perly.c
 !      yyvsp = yyvs + yypv_index;
       }
       *++yyssp = yystate;
-      *++yyvsp = yyval;
+***************
+*** 2309,2316 ****
+      goto yyloop;
+  yyoverflow:
+!     yyerror("yacc stack overflow");
+  yyabort:
+!     return (1);
+  yyaccept:
+!     return (0);
+  }
+--- 2338,2345 ----
       goto yyloop;
   yyoverflow:
 !     yyerror("Out of memory for yacc stack");
diff --git a/perly.y b/perly.y
index 4feb549..6d3c75c 100644 (file)
--- a/perly.y
+++ b/perly.y
@@ -47,9 +47,9 @@ dep()
 %token LOCAL MY
 
 %type <ival> prog decl local format startsub remember mremember '&'
-%type <opval> block mblock mintro lineseq line loop cond else
+%type <opval> block mblock lineseq line loop cond else
 %type <opval> expr term scalar ary hsh arylen star amper sideff
-%type <opval> argexpr nexpr texpr iexpr mexpr mtexpr miexpr
+%type <opval> argexpr nexpr texpr iexpr mexpr mnexpr mtexpr miexpr
 %type <opval> listexpr listexprcom indirob
 %type <opval> listop method proto cont my_scalar
 %type <pval> label
@@ -100,17 +100,8 @@ remember:  /* NULL */      /* start a full lexical scope */
                        { $$ = block_start(TRUE); }
        ;
 
-mblock :       '{' mintro mremember lineseq '}'
-                       { if ($2)
-                           $4 = $4 ? append_list(OP_LINESEQ,
-                                         (LISTOP*)$2, (LISTOP*)$4) : $2;
-                         $$ = block_end($1, $3, $4); }
-       ;
-
-mintro :       /* NULL */      /* introduce pending lexicals */
-                       { $$ = min_intro_pending
-                             ? newSTATEOP(0, Nullch, newOP(OP_NULL, 0))
-                             : NULL; }
+mblock :       '{' mremember lineseq '}'
+                       { $$ = block_end($1,$2,$3); }
        ;
 
 mremember:     /* NULL */      /* start a partial lexical scope */
@@ -165,18 +156,19 @@ else      :       /* NULL */
                        { $$ = scope($2); }
        |       ELSIF '(' mexpr ')' mblock else
                        { copline = $1;
-                           $$ = newCONDOP(0, $3, scope($5), $6);
+                           $$ = newSTATEOP(0, Nullch,
+                                  newCONDOP(0, $3, scope($5), $6));
                            hints |= HINT_BLOCK_SCOPE; }
        ;
 
 cond   :       IF '(' remember mexpr ')' mblock else
                        { copline = $1;
                            $$ = block_end($1, $3,
-                                   newCONDOP(0, $4, scope($6), $7)); }
+                                  newCONDOP(0, $4, scope($6), $7)); }
        |       UNLESS '(' remember miexpr ')' mblock else
                        { copline = $1;
                            $$ = block_end($1, $3,
-                                   newCONDOP(0, $4, scope($6), $7)); }
+                                  newCONDOP(0, $4, scope($6), $7)); }
        |       IF block block else
                        { copline = $1;
                            deprecate("if BLOCK BLOCK");
@@ -198,50 +190,42 @@ loop      :       label WHILE '(' remember mtexpr ')' mblock cont
                        { copline = $2;
                            $$ = block_end($2, $4,
                                   newSTATEOP(0, $1,
-                                     newWHILEOP(0, 1, (LOOP*)Nullop,
-                                                $5, $7, $8) )); }
+                                    newWHILEOP(0, 1, (LOOP*)Nullop,
+                                               $5, $7, $8))); }
        |       label UNTIL '(' remember miexpr ')' mblock cont
                        { copline = $2;
                            $$ = block_end($2, $4,
                                   newSTATEOP(0, $1,
-                                     newWHILEOP(0, 1, (LOOP*)Nullop,
-                                                $5, $7, $8) )); }
+                                    newWHILEOP(0, 1, (LOOP*)Nullop,
+                                               $5, $7, $8))); }
        |       label WHILE block block cont
                        { copline = $2;
-                           $$ = newSTATEOP(0, $1,
-                                   newWHILEOP(0, 1, (LOOP*)Nullop,
-                                       scope($3), $4, $5) ); }
+                           $$ = newWHILEOP(0, 1, (LOOP*)Nullop,
+                                           scope($3), $4, $5); }
        |       label UNTIL block block cont
                        { copline = $2;
-                           $$ = newSTATEOP(0, $1,
-                                   newWHILEOP(0, 1, (LOOP*)Nullop,
-                                       invert(scalar(scope($3))), $4, $5)); }
-       |       label FOR MY remember my_scalar '(' expr ')' mblock cont
+                           $$ = newWHILEOP(0, 1, (LOOP*)Nullop,
+                                           invert(scalar(scope($3))),
+                                           $4, $5); }
+       |       label FOR MY remember my_scalar '(' mexpr ')' mblock cont
                        { $$ = block_end($2, $4,
-                                 newFOROP(0, $1, $2, $5, $7, $9, $10)); }
-       |       label FOR scalar '(' expr ')' block cont
-                       { $$ = newFOROP(0, $1, $2, mod($3, OP_ENTERLOOP),
-                               $5, $7, $8); }
-       |       label FOR '(' remember expr ')' mblock cont
+                                newFOROP(0, $1, $2, $5, $7, $9, $10)); }
+       |       label FOR scalar '(' remember mexpr ')' mblock cont
+                       { $$ = block_end($2, $5,
+                                newFOROP(0, $1, $2, mod($3, OP_ENTERLOOP),
+                                         $6, $8, $9)); }
+       |       label FOR '(' remember mexpr ')' mblock cont
                        { $$ = block_end($2, $4,
                                 newFOROP(0, $1, $2, Nullop, $5, $7, $8)); }
-       |       label FOR '(' remember nexpr ';'
-                               { if ($5) {
-                                   $5 = scalar($5);
-                                   if (min_intro_pending)
-                                     $5 = newSTATEOP(0, Nullch, $5); } }
-                             texpr ';'
-                               { $8 = scalar($8);
-                                 if (min_intro_pending)
-                                   $8 = newSTATEOP(0, Nullch, $8); }
-                             nexpr ')' mblock
+       |       label FOR '(' remember mnexpr ';' mtexpr ';' mnexpr ')' mblock
                        /* basically fake up an initialize-while lineseq */
                        { copline = $2;
                            $$ = block_end($2, $4,
-                                  append_elem(OP_LINESEQ, $5,
-                                     newSTATEOP(0, $1,
-                                        newWHILEOP(0, 1, (LOOP*)Nullop,
-                                                   $8, $13, scalar($11))))); }
+                                  append_elem(OP_LINESEQ, scalar($5),
+                                    newSTATEOP(0, $1,
+                                      newWHILEOP(0, 1, (LOOP*)Nullop,
+                                                 scalar($7),
+                                                 $11, scalar($9))))); }
        |       label block cont  /* a block is a loop that happens once */
                        { $$ = newSTATEOP(0,
                                $1, newWHILEOP(0, 1, (LOOP*)Nullop,
@@ -263,18 +247,19 @@ iexpr     :       expr
        ;
 
 mexpr  :       expr
-                       { $$ = min_intro_pending
-                               ? newSTATEOP(0, Nullch, $1) : $1; }
+                       { $$ = $1; intro_my(); }
+       ;
+
+mnexpr :       nexpr
+                       { $$ = $1; intro_my(); }
        ;
 
 mtexpr :       texpr
-                       { $$ = min_intro_pending
-                               ? newSTATEOP(0, Nullch, $1) : $1; }
+                       { $$ = $1; intro_my(); }
        ;
 
 miexpr :       iexpr
-                       { $$ = min_intro_pending
-                               ? newSTATEOP(0, Nullch, $1) : $1; }
+                       { $$ = $1; intro_my(); }
        ;
 
 label  :       /* empty */
index 240ebcc..402761d 100644 (file)
@@ -214,6 +214,13 @@ know which context to supply to the right side.
 be garbage collected on exit.  An SV was discovered to be outside any
 of those arenas.
 
+=item Attempt to free non-existent shared string
+
+(P) Perl maintains a reference counted internal table of strings to
+optimize the storage and access of hash keys and other strings.  This
+indicates someone tried to decrement the reference count of a string
+that can no longer be found in the table.
+
 =item Attempt to free temp prematurely
 
 (W) Mortalized values are supposed to be freed by the free_tmps()
@@ -1062,6 +1069,18 @@ setgid script if C<$ENV{PATH}> is derived from data supplied (or
 potentially supplied) by the user.  The script must set the path to a
 known value, using trustworthy data.  See L<perlsec>.
 
+=item Integer overflow in hex number
+
+(S) The literal hex number you have specified is too big for your
+architecture. On a 32-bit architecture the largest hex literal is
+0xFFFFFFFF.
+
+=item Integer overflow in octal number
+
+(S) The literal octal number you have specified is too big for your
+architecture. On a 32-bit architecture the largest octal literal is
+037777777777.
+
 =item Internal inconsistency in tracking vforks
 
 (S) A warning peculiar to VMS.  Perl keeps track of the number
@@ -1425,6 +1444,13 @@ supplied it an uninitialized value.  See L<perlform>.
 (S) You specified an odd number of elements to a hash list, which is odd,
 since hash lists come in key/value pairs.
 
+=item Offset outside string
+
+(F) You tried to do a read/write/send/recv operation with an offset
+pointing outside the buffer.  This is difficult to imagine.
+The sole exception to this is that C<sysread()>ing past the buffer
+will extend the buffer and zero pad the new area.
+
 =item oops: oopsAV
 
 (S) An internal warning that the grammar is screwed up.
@@ -1655,6 +1681,30 @@ perspective, it's probably not what you intended.
 (F) Your C compiler uses POSIX getpgrp(), which takes no argument, unlike
 the BSD version, which takes a pid.
 
+=item Possible attempt to put comments in qw() list
+
+(W) You probably wrote somthing like this:
+
+    qw( a # a comment
+        b # another comment
+      ) ;
+
+when you should have written this:
+
+    qw( a 
+        b 
+      ) ;
+
+=item Possible attempt to separate words with commas
+
+(W) You probably wrote somthing like this:
+
+    qw( a, b, c );
+
+when you should have written this:
+
+    qw( a b c );
+
 =item Possible memory corruption: %s overflowed 3rd argument
 
 (F) An ioctl() or fcntl() returned more than Perl was bargaining for.
index d4998cf..df8d23f 100644 (file)
@@ -304,7 +304,10 @@ symbolic link, not the real file.)  Example:
 
 =item abs VALUE
 
+=item abs 
+
 Returns the absolute value of its argument.
+If VALUE is omitted, uses $_.
 
 =item accept NEWSOCKET,GENERICSOCKET
 
@@ -314,8 +317,11 @@ See example in L<perlipc/"Sockets: Client/Server Communication">.
 
 =item alarm SECONDS
 
+=item alarm 
+
 Arranges to have a SIGALRM delivered to this process after the
-specified number of seconds have elapsed.  (On some machines,
+specified number of seconds have elapsed.  If SECONDS is not specified,
+the value stored in $_ is used. (On some machines,
 unfortunately, the elapsed time may be up to one second less than you
 specified because of how seconds are counted.)  Only one timer may be
 counting at once.  Each call disables the previous timer, and an
@@ -488,11 +494,17 @@ restrictions may be relaxed, but this is not a portable assumption.
 
 =item chr NUMBER
 
+=item chr 
+
 Returns the character represented by that NUMBER in the character set.
 For example, C<chr(65)> is "A" in ASCII.
 
+If NUMBER is omitted, uses $_.
+
 =item chroot FILENAME
 
+=item chroot 
+
 This function works as the system call by the same name: it makes the
 named directory the new root directory for all further pathnames that
 begin with a "/" by your process and all of its children.  (It doesn't
@@ -618,10 +630,13 @@ rich implementation.
 
 =item defined EXPR
 
+=item defined 
+
 Returns a boolean value saying whether EXPR has a real value
-or not.  Many operations return the undefined value under exceptional
-conditions, such as end of file, uninitialized variable, system error
-and such.  This function allows you to distinguish between an undefined
+or not. If EXPR is not present, $_ will be checked. Many operations
+return the undefined value under exceptional conditions, such as end of
+file, uninitialized variable, system error and such.  This function
+allows you to distinguish between an undefined
 null scalar and a defined null scalar with operations that might return
 a real null string, such as referencing elements of an array.  You may
 also check to see if arrays or subroutines exist.  Use of defined on
@@ -962,6 +977,8 @@ See also die().  If EXPR is omitted, exits with 0 status.
 
 =item exp EXPR
 
+=item exp 
+
 Returns I<e> (the natural logarithm base) to the power of EXPR.  
 If EXPR is omitted, gives C<exp($_)>.
 
@@ -1343,6 +1360,8 @@ array.
 
 =item hex EXPR
 
+=item hex 
+
 Interprets EXPR as a hex string and returns the corresponding decimal
 value.  (To convert strings that might start with 0 or 0x see
 oct().)  If EXPR is omitted, uses $_.
@@ -1366,6 +1385,8 @@ one less than the base, ordinarily -1.
 
 =item int EXPR
 
+=item int 
+
 Returns the integer portion of EXPR.  If EXPR is omitted, uses $_.
 
 =item ioctl FILEHANDLE,FUNCTION,SCALAR
@@ -1497,18 +1518,28 @@ C<continue> block, if any, is not executed:
 
 =item lc EXPR
 
+=item lc 
+
 Returns an lowercased version of EXPR.  This is the internal function
 implementing the \L escape in double-quoted strings.  
 Should respect any POSIX setlocale() settings.
 
+If EXPR is omitted, uses $_.
+
 =item lcfirst EXPR
 
+=item lcfirst 
+
 Returns the value of EXPR with the first character lowercased.  This is
 the internal function implementing the \l escape in double-quoted strings.
 Should respect any POSIX setlocale() settings.
 
+If EXPR is omitted, uses $_.
+
 =item length EXPR
 
+=item length 
+
 Returns the length in characters of the value of EXPR.  If EXPR is
 omitted, returns length of $_.
 
@@ -1555,6 +1586,8 @@ via the POSIX module.
 
 =item log EXPR
 
+=item log 
+
 Returns logarithm (base I<e>) of EXPR.  If EXPR is omitted, returns log
 of $_.
 
@@ -1562,10 +1595,14 @@ of $_.
 
 =item lstat EXPR
 
+=item lstat 
+
 Does the same thing as the stat() function, but stats a symbolic link
 instead of the file the symbolic link points to.  If symbolic links are
 unimplemented on your system, a normal stat() is done.
 
+If EXPR is omitted, stats $_.
+
 =item m//
 
 The match operator.  See L<perlop>.
@@ -1655,6 +1692,8 @@ See the "use" function, which "no" is the opposite of.
 
 =item oct EXPR
 
+=item oct 
+
 Interprets EXPR as an octal string and returns the corresponding
 decimal value.  (If EXPR happens to start off with 0x, interprets it as
 a hex string instead.)  The following will handle decimal, octal, and
@@ -1852,6 +1891,8 @@ DIRHANDLEs have their own namespace separate from FILEHANDLEs.
 
 =item ord EXPR
 
+=item ord 
+
 Returns the numeric ascii value of the first character of EXPR.  If
 EXPR is omitted, uses $_.
 
@@ -1996,8 +2037,11 @@ like shift().
 
 =item pos SCALAR
 
+=item pos 
+
 Returns the offset of where the last C<m//g> search left off for the variable
-in question.  May be modified to change that offset.
+is in question ($_ is used when the variable is not specified). May be
+modified to change that offset.
 
 =item print FILEHANDLE LIST
 
@@ -2065,10 +2109,14 @@ Generalized quotes.  See L<perlop>.
 
 =item quotemeta EXPR
 
+=item quotemeta 
+
 Returns the value of EXPR with with all regular expression
 metacharacters backslashed.  This is the internal function implementing
 the \Q escape in double-quoted strings.
 
+If EXPR is omitted, uses $_.
+
 =item rand EXPR
 
 =item rand
@@ -2114,6 +2162,8 @@ chdir() there, it would have been testing the wrong file.
 
 =item readlink EXPR
 
+=item readlink 
+
 Returns the value of a symbolic link, if symbolic links are
 implemented.  If not, gives a fatal error.  If there is some system
 error, returns the undefined value and sets C<$!> (errno).  If EXPR is
@@ -2158,8 +2208,11 @@ themselves about what was just input:
 
 =item ref EXPR
 
-Returns a TRUE value if EXPR is a reference, FALSE otherwise.  The value
-returned depends on the type of thing the reference is a reference to.
+=item ref 
+
+Returns a TRUE value if EXPR is a reference, FALSE otherwise. If EXPR
+is not specified, $_ will be used. The value returned depends on the
+type of thing the reference is a reference to.
 Builtin types include:
 
     REF
@@ -2289,6 +2342,8 @@ last occurrence at or before that position.
 
 =item rmdir FILENAME
 
+=item rmdir 
+
 Deletes the directory specified by FILENAME if it is empty.  If it
 succeeds it returns 1, otherwise it returns 0 and sets C<$!> (errno).  If
 FILENAME is omitted, uses $_.
@@ -2527,6 +2582,8 @@ has the same interpretation as in the system call of the same name.
 
 =item sin EXPR
 
+=item sin 
+
 Returns the sine of EXPR (expressed in radians).  If EXPR is omitted,
 returns sine of $_.
 
@@ -2804,6 +2861,8 @@ dump core when fed ludicrous arguments.
 
 =item sqrt EXPR
 
+=item sqrt 
+
 Return the square root of EXPR.  If EXPR is omitted, returns square
 root of $_.
 
@@ -2821,9 +2880,13 @@ the comp.security.unix newsgroup.
 
 =item stat EXPR
 
+=item stat 
+
 Returns a 13-element array giving the status info for a file, either the
-file opened via FILEHANDLE, or named by EXPR.  Returns a null list if
-the stat fails.  Typically used as follows:
+file opened via FILEHANDLE, or named by EXPR. If EXPR is omitted, it
+stats $_.  Returns a null list if the stat fails.  Typically used as
+follows:
+
 
     ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
        $atime,$mtime,$ctime,$blksize,$blocks)
@@ -3003,9 +3066,12 @@ Attempts to read LENGTH bytes of data into variable SCALAR from the
 specified FILEHANDLE, using the system call read(2).  It bypasses
 stdio, so mixing this with other kinds of reads may cause confusion.
 Returns the number of bytes actually read, or undef if there was an
-error.  SCALAR will be grown or shrunk to the length actually read.  An
-OFFSET may be specified to place the read data at some other place than
-the beginning of the string.
+error.  SCALAR will be grown or shrunk to the length actually read.
+In the case of growing the new data area will be padded with "\0" bytes.
+An OFFSET may be specified to place the read data at some other
+place than the beginning of the string. A negative OFFSET means
+placing the read data at that many bytes counting backwards from the end
+of the string.
 
 =item system LIST
 
@@ -3025,9 +3091,12 @@ described in L<perlop/"`STRING`">.
 Attempts to write LENGTH bytes of data from variable SCALAR to the
 specified FILEHANDLE, using the system call write(2).  It bypasses
 stdio, so mixing this with prints may cause confusion.  Returns the
-number of bytes actually written, or undef if there was an error.  An
-OFFSET may be specified to get the write data from some other place than
-the beginning of the string.
+number of bytes actually written, or undef if there was an error.
+If the length is greater than the available data, only as much data as
+is available will be written.  An OFFSET may be specified to write the
+data from some other place than the beginning of the string.
+A negative OFFSET means starting the writing from that many bytes
+counting backwards from the end of the string.
 
 =item tell FILEHANDLE
 
@@ -3134,16 +3203,24 @@ on your system.
 
 =item uc EXPR
 
+=item uc 
+
 Returns an uppercased version of EXPR.  This is the internal function
 implementing the \U escape in double-quoted strings.
 Should respect any POSIX setlocale() settings.
 
+If EXPR is omitted, uses $_.
+
 =item ucfirst EXPR
 
+=item ucfirst 
+
 Returns the value of EXPR with the first character uppercased.  This is
 the internal function implementing the \u escape in double-quoted strings.
 Should respect any POSIX setlocale() settings.
 
+If EXPR is omitted, uses $_.
+
 =item umask EXPR
 
 =item umask
@@ -3172,6 +3249,8 @@ subroutine.  Examples:
 
 =item unlink LIST
 
+=item unlink 
+
 Deletes a list of files.  Returns the number of files successfully
 deleted.
 
@@ -3184,6 +3263,8 @@ the B<-U> flag is supplied to Perl.  Even if these conditions are
 met, be warned that unlinking a directory can inflict damage on your
 filesystem.  Use rmdir instead.
 
+If LIST is omitted, uses $_.
+
 =item unpack TEMPLATE,EXPR
 
 Unpack does the reverse of pack: it takes a string representing a
index 3f36396..c397142 100644 (file)
@@ -655,7 +655,8 @@ To create a mortal variable, use the functions:
     SV*  sv_mortalcopy(SV*)
 
 The first call creates a mortal SV, the second converts an existing SV to
-a mortal SV, the third creates a mortal copy of an existing SV.
+a mortal SV, the third creates a mortal copy of an existing SV (possibly
+destroying it in the process).
 
 The mortal routines are not just for SVs -- AVs and HVs can be made mortal
 by passing their address (and casting them to C<SV*>) to the C<sv_2mortal> or
@@ -848,6 +849,7 @@ The current kinds of Magic Virtual Tables are:
     i        vtbl_isaelem        @ISA array element
     L        0 (but sets RMAGICAL)     Perl Module/Debugger???
     l        vtbl_dbline         Debugger?
+    o        vtbl_collxfrm       Locale Collation
     P        vtbl_pack           Tied Array or Hash
     p        vtbl_packelem       Tied Array or Hash element
     q        vtbl_packelem       Tied Scalar or Handle
@@ -2051,7 +2053,7 @@ Adds magic to an SV.
 =item sv_mortalcopy
 
 Creates a new SV which is a copy of the original SV.  The new SV is marked
-as mortal.
+as mortal.  The old SV may become invalid if it was marked as a temporary.
 
        SV*     sv_mortalcopy _((SV* oldsv));
 
@@ -2310,10 +2312,14 @@ Note that C<sv_setref_pv> copies the pointer while this copies the string.
 =item sv_setsv
 
 Copies the contents of the source SV C<ssv> into the destination SV C<dsv>.
-The source SV may be destroyed if it is mortal.
+The source SV may be destroyed if it is mortal or temporary.
 
        void    sv_setsv _((SV* dsv, SV* ssv));
 
+=item SvSetSV
+
+A wrapper around C<sv_setsv>. Safe even if C<dst==ssv>.
+
 =item SvSTASH
 
 Returns the stash of the SV.
diff --git a/pp.c b/pp.c
index 525e7af..4f04eb6 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -313,6 +313,7 @@ PP(pp_refgen)
        MARK[1] = *SP;
        SP = MARK + 1;
     }
+    EXTEND_MORTAL(SP - MARK);
     while (MARK < SP) {
        sv = *++MARK;
        rv = sv_newmortal();
@@ -421,13 +422,6 @@ PP(pp_study)
        else
            snext[pos] = -pos;
        sfirst[ch] = pos;
-
-       /* If there were any case insensitive searches, we must assume they
-        * all are.  This speeds up insensitive searches much more than
-        * it slows down sensitive ones.
-        */
-       if (sawi)
-           sfirst[fold[ch]] = pos;
     }
 
     SvSCREAM_on(sv);
@@ -859,7 +853,10 @@ PP(pp_slt)
     dSP; tryAMAGICbinSET(slt,0); 
     {
       dPOPTOPssrl;
-      SETs( sv_cmp(left, right) < 0 ? &sv_yes : &sv_no );
+      int cmp = ((op->op_private & OPpLOCALE)
+                ? sv_cmp_locale(left, right)
+                : sv_cmp(left, right));
+      SETs( cmp < 0 ? &sv_yes : &sv_no );
       RETURN;
     }
 }
@@ -869,7 +866,10 @@ PP(pp_sgt)
     dSP; tryAMAGICbinSET(sgt,0); 
     {
       dPOPTOPssrl;
-      SETs( sv_cmp(left, right) > 0 ? &sv_yes : &sv_no );
+      int cmp = ((op->op_private & OPpLOCALE)
+                ? sv_cmp_locale(left, right)
+                : sv_cmp(left, right));
+      SETs( cmp > 0 ? &sv_yes : &sv_no );
       RETURN;
     }
 }
@@ -879,7 +879,10 @@ PP(pp_sle)
     dSP; tryAMAGICbinSET(sle,0); 
     {
       dPOPTOPssrl;
-      SETs( sv_cmp(left, right) <= 0 ? &sv_yes : &sv_no );
+      int cmp = ((op->op_private & OPpLOCALE)
+                ? sv_cmp_locale(left, right)
+                : sv_cmp(left, right));
+      SETs( cmp <= 0 ? &sv_yes : &sv_no );
       RETURN;
     }
 }
@@ -889,7 +892,10 @@ PP(pp_sge)
     dSP; tryAMAGICbinSET(sge,0); 
     {
       dPOPTOPssrl;
-      SETs( sv_cmp(left, right) >= 0 ? &sv_yes : &sv_no );
+      int cmp = ((op->op_private & OPpLOCALE)
+                ? sv_cmp_locale(left, right)
+                : sv_cmp(left, right));
+      SETs( cmp >= 0 ? &sv_yes : &sv_no );
       RETURN;
     }
 }
@@ -899,7 +905,10 @@ PP(pp_sne)
     dSP; tryAMAGICbinSET(sne,0); 
     {
       dPOPTOPssrl;
-      SETs( !sv_eq(left, right) ? &sv_yes : &sv_no );
+      bool ne = ((op->op_private & OPpLOCALE)
+                ? (sv_cmp_locale(left, right) != 0)
+                : !sv_eq(left, right));
+      SETs( ne ? &sv_yes : &sv_no );
       RETURN;
     }
 }
@@ -909,7 +918,10 @@ PP(pp_scmp)
     dSP; dTARGET;  tryAMAGICbin(scmp,0);
     {
       dPOPTOPssrl;
-      SETi( sv_cmp(left, right) );
+      int cmp = ((op->op_private & OPpLOCALE)
+                ? sv_cmp_locale(left, right)
+                : sv_cmp(left, right));
+      SETi( cmp );
       RETURN;
     }
 }
@@ -988,7 +1000,7 @@ PP(pp_negate)
        else if (SvPOKp(sv)) {
            STRLEN len;
            char *s = SvPV(sv, len);
-           if (isALPHA(*s) || *s == '_') {
+           if (isIDFIRST(*s)) {
                sv_setpvn(TARG, "-", 1);
                sv_catsv(TARG, sv);
            }
@@ -1311,8 +1323,10 @@ PP(pp_log)
     {
       double value;
       value = POPn;
-      if (value <= 0.0)
+      if (value <= 0.0) {
+       NUMERIC_STANDARD();
        DIE("Can't take log of %g", value);
+      }
       value = log(value);
       XPUSHn(value);
       RETURN;
@@ -1325,8 +1339,10 @@ PP(pp_sqrt)
     {
       double value;
       value = POPn;
-      if (value < 0.0)
+      if (value < 0.0) {
+       NUMERIC_STANDARD();
        DIE("Can't take sqrt of %g", value);
+      }
       value = sqrt(value);
       XPUSHn(value);
       RETURN;
@@ -1613,7 +1629,14 @@ PP(pp_rindex)
 PP(pp_sprintf)
 {
     dSP; dMARK; dORIGMARK; dTARGET;
+#ifdef LC_NUMERIC
+    if (op->op_private & OPpLOCALE)
+       NUMERIC_LOCAL();
+    else
+       NUMERIC_STANDARD();
+#endif /* LC_NUMERIC */
     do_sprintf(TARG, SP-MARK, MARK+1);
+    TAINT_IF(SvTAINTED(TARG));
     SP = ORIGMARK;
     PUSHTARG;
     RETURN;
@@ -1685,8 +1708,15 @@ PP(pp_ucfirst)
        SETs(sv);
     }
     s = SvPV_force(sv, na);
-    if (isLOWER(*s))
-       *s = toUPPER(*s);
+    if (*s) {
+       if (op->op_private & OPpLOCALE) {
+           TAINT;
+           SvTAINTED_on(sv);
+           *s = toUPPER_LC(*s);
+       }
+       else
+           *s = toUPPER(*s);
+    }
 
     RETURN;
 }
@@ -1704,8 +1734,15 @@ PP(pp_lcfirst)
        SETs(sv);
     }
     s = SvPV_force(sv, na);
-    if (isUPPER(*s))
-       *s = toLOWER(*s);
+    if (*s) {
+       if (op->op_private & OPpLOCALE) {
+           TAINT;
+           SvTAINTED_on(sv);
+           *s = toLOWER_LC(*s);
+       }
+       else
+           *s = toLOWER(*s);
+    }
 
     SETs(sv);
     RETURN;
@@ -1716,7 +1753,6 @@ PP(pp_uc)
     dSP;
     SV *sv = TOPs;
     register char *s;
-    register char *send;
     STRLEN len;
 
     if (!SvPADTMP(sv)) {
@@ -1725,12 +1761,21 @@ PP(pp_uc)
        sv = TARG;
        SETs(sv);
     }
+
     s = SvPV_force(sv, len);
-    send = s + len;
-    while (s < send) {
-       if (isLOWER(*s))
-           *s = toUPPER(*s);
-       s++;
+    if (len) {
+       register char *send = s + len;
+
+       if (op->op_private & OPpLOCALE) {
+           TAINT;
+           SvTAINTED_on(sv);
+           for (; s < send; s++)
+               *s = toUPPER_LC(*s);
+       }
+       else {
+           for (; s < send; s++)
+               *s = toUPPER(*s);
+       }
     }
     RETURN;
 }
@@ -1740,7 +1785,6 @@ PP(pp_lc)
     dSP;
     SV *sv = TOPs;
     register char *s;
-    register char *send;
     STRLEN len;
 
     if (!SvPADTMP(sv)) {
@@ -1749,12 +1793,21 @@ PP(pp_lc)
        sv = TARG;
        SETs(sv);
     }
+
     s = SvPV_force(sv, len);
-    send = s + len;
-    while (s < send) {
-       if (isUPPER(*s))
-           *s = toLOWER(*s);
-       s++;
+    if (len) {
+       register char *send = s + len;
+
+       if (op->op_private & OPpLOCALE) {
+           TAINT;
+           SvTAINTED_on(sv);
+           for (; s < send; s++)
+               *s = toLOWER_LC(*s);
+       }
+       else {
+           for (; s < send; s++)
+               *s = toLOWER(*s);
+       }
     }
     RETURN;
 }
@@ -2098,6 +2151,7 @@ PP(pp_splice)
            MEXTEND(MARK, length);
            Copy(AvARRAY(ary)+offset, MARK, length, SV*);
            if (AvREAL(ary)) {
+               EXTEND_MORTAL(length);
                for (i = length, dst = MARK; i; i--)
                    sv_2mortal(*dst++); /* free them eventualy */
            }
@@ -2192,6 +2246,7 @@ PP(pp_splice)
            if (length) {
                Copy(tmparyval, MARK, length, SV*);
                if (AvREAL(ary)) {
+                   EXTEND_MORTAL(length);
                    for (i = length, dst = MARK; i; i--)
                        sv_2mortal(*dst++);     /* free them eventualy */
                }
@@ -2574,6 +2629,7 @@ PP(pp_unpack)
            }
            else {
                EXTEND(SP, len);
+               EXTEND_MORTAL(len);
                while (len-- > 0) {
                    aint = *s++;
                    if (aint >= 128)    /* fake up signed chars */
@@ -2596,6 +2652,7 @@ PP(pp_unpack)
            }
            else {
                EXTEND(SP, len);
+               EXTEND_MORTAL(len);
                while (len-- > 0) {
                    auint = *s++ & 255;
                    sv = NEWSV(37, 0);
@@ -2617,6 +2674,7 @@ PP(pp_unpack)
            }
            else {
                EXTEND(SP, len);
+               EXTEND_MORTAL(len);
                while (len-- > 0) {
                    Copy(s, &ashort, 1, I16);
                    s += sizeof(I16);
@@ -2649,6 +2707,7 @@ PP(pp_unpack)
            }
            else {
                EXTEND(SP, len);
+               EXTEND_MORTAL(len);
                while (len-- > 0) {
                    Copy(s, &aushort, 1, U16);
                    s += sizeof(U16);
@@ -2682,6 +2741,7 @@ PP(pp_unpack)
            }
            else {
                EXTEND(SP, len);
+               EXTEND_MORTAL(len);
                while (len-- > 0) {
                    Copy(s, &aint, 1, int);
                    s += sizeof(int);
@@ -2707,6 +2767,7 @@ PP(pp_unpack)
            }
            else {
                EXTEND(SP, len);
+               EXTEND_MORTAL(len);
                while (len-- > 0) {
                    Copy(s, &auint, 1, unsigned int);
                    s += sizeof(unsigned int);
@@ -2735,6 +2796,7 @@ PP(pp_unpack)
            }
            else {
                EXTEND(SP, len);
+               EXTEND_MORTAL(len);
                while (len-- > 0) {
                    Copy(s, &along, 1, I32);
                    s += sizeof(I32);
@@ -2770,6 +2832,7 @@ PP(pp_unpack)
            }
            else {
                EXTEND(SP, len);
+               EXTEND_MORTAL(len);
                while (len-- > 0) {
                    Copy(s, &aulong, 1, U32);
                    s += sizeof(U32);
@@ -2792,6 +2855,7 @@ PP(pp_unpack)
            if (len > along)
                len = along;
            EXTEND(SP, len);
+           EXTEND_MORTAL(len);
            while (len-- > 0) {
                if (sizeof(char*) > strend - s)
                    break;
@@ -2806,61 +2870,47 @@ PP(pp_unpack)
            }
            break;
        case 'w':
-           along = (strend - s) / sizeof(char);
-           if (len > along)
-               len = along;
            EXTEND(SP, len);
-            { 
-              I8  bytes = 0;
-
-              auint = 0;
-              while  (len > 0) {
-                if (s >= strend) {
-                  if (auint) {
-                    croak("Unterminated compressed integer");
-                  } else {
-                    break;
-                  }
-                }
-                auint = (auint << 7) | (*s & 0x7f);
-                if (!(*s & 0x80)) {
-                  sv = NEWSV(40, 0);
-                  sv_setiv(sv, (I32) auint);
-                  PUSHs(sv_2mortal(sv));
-                  len--;
-                  auint = 0;
-                  bytes = 0;
-                } else if (++bytes >= sizeof(auint)) { /* promote to string */
-                  char            zero[10];
-
-                  (void) sprintf(zero, "%010ld", auint);
-                  sv = newSVpv(zero, 10);
-            
-                  while (*s &  0x80) {
-                    sv = mul128(sv, (U8) (*(++s) & 0x7f));
-                    if (s >= strend) {
-                      croak("Unterminated compressed integer");
-                    }
-                  }
-                  /* remove leading '0's */
-                  {
-                    char           *s = SvPV(sv, na);
-            
-                    while (*s == '0') {
-                      s++;
-                      na--;
-                    }
-                    /* overlapping copy !! */
-                    sv_setpvn(sv, s, na);
-                  }
-                  PUSHs(sv_2mortal(sv));
-                  len--;
-                  auint = 0;
-                  bytes = 0;
-                }
-                s++;
-              }
-            }
+           EXTEND_MORTAL(len);
+           { 
+               UV auv = 0;
+               U32 bytes = 0;
+               
+               while ((len > 0) && (s < strend)) {
+                   auv = (auv << 7) | (*s & 0x7f);
+                   if (!(*s++ & 0x80)) {
+                       bytes = 0;
+                       sv = NEWSV(40, 0);
+                       sv_setuv(sv, auv);
+                       PUSHs(sv_2mortal(sv));
+                       len--;
+                       auv = 0;
+                   }
+                   else if (++bytes >= sizeof(UV)) {   /* promote to string */
+                       char decn[sizeof(UV) * 3 + 1];
+                       char *t;
+
+                       (void) sprintf(decn, "%0*ld", sizeof(decn) - 1, auv);
+                       sv = newSVpv(decn, 0);
+                       while (s < strend) {
+                           sv = mul128(sv, *s & 0x7f);
+                           if (!(*s++ & 0x80)) {
+                               bytes = 0;
+                               break;
+                           }
+                       }
+                       t = SvPV(sv, na);
+                       while (*t == '0')
+                           t++;
+                       sv_chop(sv, t);
+                       PUSHs(sv_2mortal(sv));
+                       len--;
+                       auv = 0;
+                   }
+               }
+               if ((s >= strend) && bytes)
+                   croak("Unterminated compressed integer");
+           }
            break;
        case 'P':
            EXTEND(SP, 1);
@@ -2878,6 +2928,7 @@ PP(pp_unpack)
 #ifdef HAS_QUAD
        case 'q':
            EXTEND(SP, len);
+           EXTEND_MORTAL(len);
            while (len-- > 0) {
                if (s + sizeof(Quad_t) > strend)
                    aquad = 0;
@@ -2892,6 +2943,7 @@ PP(pp_unpack)
            break;
        case 'Q':
            EXTEND(SP, len);
+           EXTEND_MORTAL(len);
            while (len-- > 0) {
                if (s + sizeof(unsigned Quad_t) > strend)
                    auquad = 0;
@@ -2920,6 +2972,7 @@ PP(pp_unpack)
            }
            else {
                EXTEND(SP, len);
+               EXTEND_MORTAL(len);
                while (len-- > 0) {
                    Copy(s, &afloat, 1, float);
                    s += sizeof(float);
@@ -2943,6 +2996,7 @@ PP(pp_unpack)
            }
            else {
                EXTEND(SP, len);
+               EXTEND_MORTAL(len);
                while (len-- > 0) {
                    Copy(s, &adouble, 1, double);
                    s += sizeof(double);
@@ -3418,69 +3472,61 @@ PP(pp_pack)
            break;
        case 'w':
             while (len-- > 0) {
-              fromstr = NEXTFROM;
-              adouble = floor((double)SvNV(fromstr));
-
-              if (adouble <= PERL_ULONG_MAX) { /* we can use integers */
-                unsigned char   buf[5];         /* buffer for compressed int */
-                unsigned char  *in = buf + 4;
-            
-                auint = U_I(adouble);
-
-                do {
-                  *(in--) = (unsigned char) ((auint & 0x7f) |  0x80); 
-                  auint >>= 7;
-                } while (auint);
-                buf[4] &= 0x7f;                /* clear continue bit */
-                sv_catpvn(cat, (char *) in + 1, buf + 4 - in);
-              } else if (SvPOKp(fromstr)) {     /* decimal string arithmetics */
-                char           *from;
-                SV             *norm;
-                STRLEN          len;
-            
-                /* Copy string and check for compliance */
-                from = SvPV(fromstr, len);
-                if ((norm = is_an_int(from, len)) == NULL) {
-                  croak("can compress only unsigned integer");
-              } else {
-                  bool            done = 0;
-                  char           *result, *in;
-            
-                  New('w', result, len, char);
-                  in = result + len;
-                  while (!done) {
-                    U8              digit = div128(norm, &done);
-            
-                    *(--in) = digit | 0x80;
-                  }
-                  result[len - 1] &= 0x7F;
-                  sv_catpvn(cat, in, result + len - in);
-                  SvREFCNT_dec(norm);  /* free norm */
-                }
-              } else if (SvNOKp(fromstr)) {
-                I8              msize = sizeof(double) * 2; /* 8/7 <= 2 */
-                unsigned char   buf[sizeof(double) * 2];
-                unsigned char *in = buf + msize -1;
+               fromstr = NEXTFROM;
+               adouble = floor(SvNV(fromstr));
+
+               if (adouble < 0)
+                   croak("Cannot compress negative numbers");
+
+               if (adouble <= UV_MAX) {
+                   char   buf[1 + sizeof(UV)];
+                   char  *in = buf + sizeof(buf);
+                   UV     auv = U_V(adouble);;
+
+                   do {
+                       *--in = (auv & 0x7f) | 0x80;
+                       auv >>= 7;
+                   } while (auv);
+                   buf[sizeof(buf) - 1] &= 0x7f; /* clear continue bit */
+                   sv_catpvn(cat, in, (buf + sizeof(buf)) - in);
+               }
+               else if (SvPOKp(fromstr)) {  /* decimal string arithmetics */
+                   char           *from, *result, *in;
+                   SV             *norm;
+                   STRLEN          len;
+                   bool            done;
             
-                if (adouble<0) {
-                  croak("Cannot compress negative numbers");
+                   /* Copy string and check for compliance */
+                   from = SvPV(fromstr, len);
+                   if ((norm = is_an_int(from, len)) == NULL)
+                       croak("can compress only unsigned integer");
+
+                   New('w', result, len, char);
+                   in = result + len;
+                   done = FALSE;
+                   while (!done)
+                       *--in = div128(norm, &done) | 0x80;
+                   result[len - 1] &= 0x7F; /* clear continue bit */
+                   sv_catpvn(cat, in, (result + len) - in);
+                   SvREFCNT_dec(norm); /* free norm */
                 }
-                do  {
-                  double next = adouble/128;
-            
-                  *in = (unsigned char) (adouble - floor(next)*128);
-                  *in |= 0x80;                     /* set continue bit */
-                  if (--in < buf) {                /* this cannot happen ;-) */
-                    croak ("Cannot compress integer");
-                  }
-                  adouble = next;
-                } while (floor(adouble));      /* floor() not necessary? */
-                buf[msize-1] &= 0x7f;              /* clear continue bit */
-                sv_catpvn(cat, (char*) in+1, buf+msize-in-1);
-              } else {
-                croak("Cannot compress non integer");
-              }
-            }
+               else if (SvNOKp(fromstr)) {
+                   char   buf[sizeof(double) * 2];     /* 8/7 <= 2 */
+                   char  *in = buf + sizeof(buf);
+
+                   do {
+                       double next = floor(adouble / 128);
+                       *--in = (unsigned char)(adouble - (next * 128)) | 0x80;
+                       if (--in < buf)  /* this cannot happen ;-) */
+                           croak ("Cannot compress integer");
+                       adouble = next;
+                   } while (adouble > 0);
+                   buf[sizeof(buf) - 1] &= 0x7f; /* clear continue bit */
+                   sv_catpvn(cat, in, (buf + sizeof(buf)) - in);
+               }
+               else
+                   croak("Cannot compress non integer");
+           }
             break;
        case 'i':
            while (len-- > 0) {
@@ -3604,6 +3650,10 @@ PP(pp_split)
 
     if (!pm || !s)
        DIE("panic: do_split");
+
+    TAINT_IF((pm->op_pmflags & PMf_LOCALE) &&
+            (pm->op_pmflags & (PMf_WHITE | PMf_SKIPWHITE)));
+
     if (pm->op_pmreplroot)
        ary = GvAVn((GV*)pm->op_pmreplroot);
     else if (gimme != G_ARRAY)
@@ -3625,8 +3675,14 @@ PP(pp_split)
     base = SP - stack_base;
     orig = s;
     if (pm->op_pmflags & PMf_SKIPWHITE) {
-       while (isSPACE(*s))
-           s++;
+       if (pm->op_pmflags & PMf_LOCALE) {
+           while (isSPACE_LC(*s))
+               s++;
+       }
+       else {
+           while (isSPACE(*s))
+               s++;
+       }
     }
     if (pm->op_pmflags & (PMf_MULTILINE|PMf_SINGLELINE)) {
        SAVEINT(multiline);
@@ -3637,17 +3693,25 @@ PP(pp_split)
        limit = maxiters + 2;
     if (pm->op_pmflags & PMf_WHITE) {
        while (--limit) {
-           /*SUPPRESS 530*/
-           for (m = s; m < strend && !isSPACE(*m); m++) ;
+           m = s;
+           while (m < strend &&
+                  !((pm->op_pmflags & PMf_LOCALE)
+                    ? isSPACE_LC(*m) : isSPACE(*m)))
+               ++m;
            if (m >= strend)
                break;
+
            dstr = NEWSV(30, m-s);
            sv_setpvn(dstr, s, m-s);
            if (!realarray)
                sv_2mortal(dstr);
            XPUSHs(dstr);
-           /*SUPPRESS 530*/
-           for (s = m + 1; s < strend && isSPACE(*s); s++) ;
+
+           s = m + 1;
+           while (s < strend &&
+                  ((pm->op_pmflags & PMf_LOCALE)
+                   ? isSPACE_LC(*s) : isSPACE(*s)))
+               ++s;
        }
     }
     else if (strEQ("^", rx->precomp)) {
@@ -3668,20 +3732,10 @@ PP(pp_split)
     else if (pm->op_pmshort) {
        i = SvCUR(pm->op_pmshort);
        if (i == 1) {
-           I32 fold = (pm->op_pmflags & PMf_FOLD);
            i = *SvPVX(pm->op_pmshort);
-           if (fold && isUPPER(i))
-               i = toLOWER(i);
            while (--limit) {
-               if (fold) {
-                   for ( m = s;
-                         m < strend && *m != i &&
-                           (!isUPPER(*m) || toLOWER(*m) != i);
-                         m++)                  /*SUPPRESS 530*/
-                       ;
-               }
-               else                            /*SUPPRESS 530*/
-                   for (m = s; m < strend && *m != i; m++) ;
+               /*SUPPRESS 530*/
+               for (m = s; m < strend && *m != i; m++) ;
                if (m >= strend)
                    break;
                dstr = NEWSV(30, m-s);
@@ -3711,7 +3765,9 @@ PP(pp_split)
     else {
        maxiters += (strend - s) * rx->nparens;
        while (s < strend && --limit &&
-           pregexec(rx, s, strend, orig, 1, Nullsv, TRUE) ) {
+              pregexec(rx, s, strend, orig, 1, Nullsv, TRUE))
+       {
+           TAINT_IF(rx->exec_tainted);
            if (rx->subbase
              && rx->subbase != orig) {
                m = s;
diff --git a/pp.h b/pp.h
index 0448152..a3b9ac9 100644 (file)
--- a/pp.h
+++ b/pp.h
 #define TOPl           ((long)SvIV(TOPs))
 
 /* Go to some pains in the rare event that we must extend the stack. */
-#define EXTEND(p,n)    STMT_START { if (stack_max - p < (n)) {                     \
-                           sp = stack_grow(sp,p, (int) (n));               \
+#define EXTEND(p,n)    STMT_START { if (stack_max - p < (n)) {         \
+                           sp = stack_grow(sp,p, (int) (n));           \
                        } } STMT_END
 
 /* Same thing, but update mark register too. */
-#define MEXTEND(p,n)   STMT_START {if (stack_max - p < (n)) {                      \
-                           int markoff = mark - stack_base;                \
-                           sp = stack_grow(sp,p,(int) (n));                \
-                           mark = stack_base + markoff;                    \
+#define MEXTEND(p,n)   STMT_START {if (stack_max - p < (n)) {          \
+                           int markoff = mark - stack_base;            \
+                           sp = stack_grow(sp,p,(int) (n));            \
+                           mark = stack_base + markoff;                \
                        } } STMT_END
 
 #define PUSHs(s)       (*++sp = (s))
                                sp = stack_sp = stack_base + AvFILL(t); \
                                curstack = t;
 
+#define EXTEND_MORTAL(n) \
+       STMT_START { \
+           if (tmps_ix + (n) >= tmps_max) \
+               Renew(tmps_stack, tmps_max = tmps_ix + (n) + 1, SV*); \
+       } STMT_END
+
 #ifdef OVERLOAD
 
 #define AMGf_noright   1
index 6d6b469..999b2cc 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -31,8 +31,9 @@ static I32 dopoptolabel _((char *label));
 static I32 dopoptoloop _((I32 startingblock));
 static I32 dopoptosub _((I32 startingblock));
 static void save_lines _((AV *array, SV *sv));
-static int sortcmp _((const void *, const void *));
 static int sortcv _((const void *, const void *));
+static int sortcmp _((const void *, const void *));
+static int sortcmp_locale _((const void *, const void *));
 
 static I32 sortcxix;
 
@@ -376,6 +377,8 @@ PP(pp_formline)
            }
            gotsome = TRUE;
            value = SvNV(sv);
+           /* Formats aren't yet marked for locales, so assume "yes". */
+           NUMERIC_LOCAL();
            if (arg & 256) {
                sprintf(t, "%#*.*f", (int) fieldsize, (int) arg & 255, value);
            } else {
@@ -649,7 +652,8 @@ PP(pp_sort)
     else {
        if (max > 1) {
            MEXTEND(SP, 20);    /* Can't afford stack realloc on signal. */
-           qsort((char*)(ORIGMARK+1), max, sizeof(SV*), sortcmp);
+           qsort((char*)(ORIGMARK+1), max, sizeof(SV*),
+                 (op->op_private & OPpLOCALE) ? sortcmp_locale : sortcmp);
        }
     }
     stack_sp = ORIGMARK + max;
@@ -707,18 +711,16 @@ PP(pp_flop)
        I32 max;
 
        if (SvNIOKp(left) || !SvPOKp(left) ||
-         (looks_like_number(left) && *SvPVX(left) != '0') ) {
-           SV *sv_iv;
-
+         (looks_like_number(left) && *SvPVX(left) != '0') )
+       {
            i = SvIV(left);
            max = SvIV(right);
-           if (max > i)
+           if (max >= i) {
+               EXTEND_MORTAL(max - i + 1);
                EXTEND(SP, max - i + 1);
-           sv_iv = sv_2mortal(newSViv(i));
-           if (i++ <= max) PUSHs(sv_iv);
+           }
            while (i <= max) {
-               sv = sv_mortalcopy(sv_iv);
-               sv_setiv(sv,i++);
+               sv = sv_2mortal(newSViv(i++));
                PUSHs(sv);
            }
        }
@@ -945,6 +947,7 @@ die(pat, va_alist)
        PUSHs(sv_2mortal(newSVpv(message,0)));
        PUTBACK;
        perl_call_sv((SV*)cv, G_DISCARD);
+       message = mess(pat, &args);     /* Static buffer could be reused. */
     }
     restartop = die_where(message);
     if ((!restartop && was_in_eval) || oldrunlevel > 1)
@@ -1193,63 +1196,15 @@ sortcmp(a, b)
 const void *a;
 const void *b;
 {
-    register SV *str1 = *(SV **) a;
-    register SV *str2 = *(SV **) b;
-    I32 retval;
-
-    if (!SvPOKp(str1)) {
-       if (!SvPOKp(str2))
-           return 0;
-       else
-           return -1;
-    }
-    if (!SvPOKp(str2))
-       return 1;
-
-    if (lc_collate_active) {   /* NOTE: this is the LC_COLLATE branch */
-      register char * pv1, * pv2, * pvx;
-      STRLEN cur1, cur2, curx;
-
-      pv1 = SvPV(str1, cur1);
-      pvx = mem_collxfrm(pv1, cur1, &curx);
-      pv1 = pvx;
-      cur1 = curx;
-
-      pv2 = SvPV(str2, cur2);
-      pvx = mem_collxfrm(pv2, cur2, &curx);
-      pv2 = pvx;
-      cur2 = curx;
-
-      retval = memcmp((void *)pv1, (void *)pv2, cur1 < cur2 ? cur1 : cur2);
-
-      Safefree(pv1);
-      Safefree(pv2);
-
-      if (retval)
-       return retval < 0 ? -1 : 1;
-
-      if (cur1 == cur2)
-       return 0;
-      else
-       return cur1 < cur2 ? -1 : 1;
-    }
-
-    /* NOTE: this is the non-LC_COLLATE area */
+    return sv_cmp(*(SV **)a, *(SV **)b);
+}
 
-    if (SvCUR(str1) < SvCUR(str2)) {
-       /*SUPPRESS 560*/
-       if (retval = memcmp(SvPVX(str1), SvPVX(str2), SvCUR(str1)))
-           return retval;
-       else
-           return -1;
-    }
-    /*SUPPRESS 560*/
-    else if (retval = memcmp(SvPVX(str1), SvPVX(str2), SvCUR(str2)))
-       return retval;
-    else if (SvCUR(str1) == SvCUR(str2))
-       return 0;
-    else
-       return 1;
+static int
+sortcmp_locale(a, b)
+const void *a;
+const void *b;
+{
+    return sv_cmp_locale(*(SV **)a, *(SV **)b);
 }
 
 PP(pp_reset)
@@ -2117,6 +2072,7 @@ PP(pp_require)
 
     sv = POPs;
     if (SvNIOKp(sv) && !SvPOKp(sv)) {
+       NUMERIC_STANDARD();
        if (atof(patchlevel) + 0.00000999 < SvNV(sv))
            DIE("Perl %s required--this is only version %s, stopped",
                SvPV(sv,na),patchlevel);
@@ -2142,8 +2098,8 @@ PP(pp_require)
       || (tmpname[0] && tmpname[1] == ':')
 #endif
 #ifdef VMS
-       || (strchr(tmpname,':') || ((*tmpname == '[' || *tmpname == '<') &&
-           (tmpname[1] == '-' || tmpname[1] == ']' || tmpname[1] == '>')))
+       || (strchr(tmpname,':')  || ((*tmpname == '[' || *tmpname == '<') &&
+           (isALNUM(tmpname[1]) || strchr("$-_]>",tmpname[1]))))
 #endif
     )
     {
@@ -2152,13 +2108,15 @@ PP(pp_require)
     else {
        AV *ar = GvAVn(incgv);
        I32 i;
-
-       for (i = 0; i <= AvFILL(ar); i++) {
 #ifdef VMS
+       char unixified[256];
+       if (tounixspec_ts(tmpname,unixified) != NULL)
+         for (i = 0; i <= AvFILL(ar); i++) {
            if (tounixpath_ts(SvPVx(*av_fetch(ar, i, TRUE), na),buf) == NULL)
                continue;
-           strcat(buf,name);
+           strcat(buf,unixified);
 #else
+       for (i = 0; i <= AvFILL(ar); i++) {
            (void)sprintf(buf, "%s/%s",
                SvPVx(*av_fetch(ar, i, TRUE), na), name);
 #endif
@@ -2418,7 +2376,7 @@ SV *sv;
     bool ischop;
 
     if (len == 0)
-       die("Null picture in formline");
+       croak("Null picture in formline");
     
     New(804, fops, (send - s)*3+10, U16);    /* Almost certainly too long... */
     fpc = fops;
index d8b2bfc..6fd0441 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -154,11 +154,8 @@ PP(pp_sassign)
        SV *temp;
        temp = left; left = right; right = temp;
     }
-    if (tainting && tainted && (!SvGMAGICAL(left) || !SvSMAGICAL(left) ||
-                               !((mg = mg_find(left, 't')) && mg->mg_len & 1)))
-    {
+    if (tainting && tainted && !SvTAINTED(left))
        TAINT_NOT;
-    }
     SvSetSV(right, left);
     SvSETMAGIC(right);
     SETs(right);
@@ -190,7 +187,10 @@ PP(pp_seq)
     dSP; tryAMAGICbinSET(seq,0); 
     {
       dPOPTOPssrl;
-      SETs( sv_eq(left, right) ? &sv_yes : &sv_no );
+      bool eq = ((op->op_private & OPpLOCALE)
+                ? (sv_cmp_locale(left, right) == 0)
+                : sv_eq(left, right));
+      SETs( eq ? &sv_yes : &sv_no );
       RETURN;
     }
 }
@@ -599,7 +599,7 @@ PP(pp_aassign)
     ary = Null(AV*);
     hash = Null(HV*);
     while (lelem <= lastlelem) {
-       tainted = 0;            /* Each item stands on its own, taintwise. */
+       TAINT_NOT;              /* Each item stands on its own, taintwise. */
        sv = *lelem++;
        switch (SvTYPE(sv)) {
        case SVt_PVAV:
@@ -616,7 +616,7 @@ PP(pp_aassign)
                (void)av_store(ary,i++,sv);
                if (magic)
                    mg_set(sv);
-               tainted = 0;
+               TAINT_NOT;
            }
            break;
        case SVt_PVHV: {
@@ -639,7 +639,7 @@ PP(pp_aassign)
                    (void)hv_store_ent(hash,sv,tmpstr,0);
                    if (magic)
                        mg_set(tmpstr);
-                   tainted = 0;
+                   TAINT_NOT;
                }
                if (relem == lastrelem)
                    warn("Odd number of elements in hash list");
@@ -833,15 +833,10 @@ play_it_again:
                s = t;
        }
        else if (!multiline) {
-           if (*SvPVX(pm->op_pmshort) != *s ||
-             memcmp(SvPVX(pm->op_pmshort), s, pm->op_pmslen) ) {
-               if (pm->op_pmflags & PMf_FOLD) {
-                   if (ibcmp((U8*)SvPVX(pm->op_pmshort), (U8*)s, pm->op_pmslen) )
-                       goto nope;
-               }
-               else
-                   goto nope;
-           }
+           if (*SvPVX(pm->op_pmshort) != *s
+               || (pm->op_pmslen > 1
+                   && memcmp(SvPVX(pm->op_pmshort), s, pm->op_pmslen)))
+               goto nope;
        }
        if (!rx->naughty && --BmUSEFUL(pm->op_pmshort) < 0) {
            SvREFCNT_dec(pm->op_pmshort);
@@ -849,8 +844,8 @@ play_it_again:
        }
     }
     if (pregexec(rx, s, strend, truebase, minmatch,
-      SvSCREAM(TARG) ? TARG : Nullsv,
-      safebase)) {
+                SvSCREAM(TARG) ? TARG : Nullsv, safebase))
+    {
        curpm = pm;
        if (pm->op_pmflags & PMf_ONCE)
            pm->op_pmflags |= PMf_USED;
@@ -864,12 +859,14 @@ play_it_again:
     if (gimme == G_ARRAY) {
        I32 iters, i, len;
 
+       TAINT_IF(rx->exec_tainted);
        iters = rx->nparens;
        if (global && !iters)
            i = 1;
        else
            i = 0;
        EXTEND(SP, iters + i);
+       EXTEND_MORTAL(iters + i);
        for (i = !i; i <= iters; i++) {
            PUSHs(sv_newmortal());
            /*SUPPRESS 560*/
@@ -1160,14 +1157,13 @@ do_readline()
            }
            RETURN;
        }
+       /* This should not be marked tainted if the fp is marked clean */
+       if (!(IoFLAGS(io) & IOf_UNTAINT)) {
+           TAINT;
+           SvTAINTED_on(sv);
+       }
        IoLINES(io)++;
        XPUSHs(sv);
-       if (tainting) {
-           /* This should not be marked tainted if the fp is marked clean */
-           if (!(IoFLAGS(io) & IOf_UNTAINT))
-               tainted = TRUE;
-           SvTAINT(sv); /* Anything from the outside world...*/
-       }
        if (type == OP_GLOB) {
            char *tmps;
 
@@ -1410,15 +1406,10 @@ PP(pp_subst)
                s = m;
        }
        else if (!multiline) {
-           if (*SvPVX(pm->op_pmshort) != *s ||
-             memcmp(SvPVX(pm->op_pmshort), s, pm->op_pmslen) ) {
-               if (pm->op_pmflags & PMf_FOLD) {
-                   if (ibcmp((U8*)SvPVX(pm->op_pmshort), (U8*)s, pm->op_pmslen) )
-                       goto nope;
-               }
-               else
-                   goto nope;
-           }
+           if (*SvPVX(pm->op_pmshort) != *s
+               || (pm->op_pmslen > 1
+                   && memcmp(SvPVX(pm->op_pmshort), s, pm->op_pmslen)))
+               goto nope;
        }
        if (!rx->naughty && --BmUSEFUL(pm->op_pmshort) < 0) {
            SvREFCNT_dec(pm->op_pmshort);
@@ -1750,8 +1741,7 @@ PP(pp_entersub)
            if (ngv && ngv != gv && (cv = GvCV(ngv))) { /* One more chance... */
                gv = ngv;
                sv_setsv(GvSV(CvGV(cv)), tmpstr);       /* Set CV's $AUTOLOAD */
-               if (tainting)
-                   sv_unmagic(GvSV(CvGV(cv)), 't');
+               SvTAINTED_off(GvSV(CvGV(cv)));
                goto retry;
            }
            else
index 40a0d35..d580fba 100644 (file)
--- a/pp_sys.c
+++ b/pp_sys.c
@@ -787,7 +787,7 @@ PP(pp_getc)
        gv = argvgv;
     if (!gv || do_eof(gv)) /* make sure we have fp with something */
        RETPUSHUNDEF;
-    TAINT_IF(1);
+    TAINT;
     sv_setpv(TARG, " ");
     *SvPVX(TARG) = PerlIO_getc(IoIFP(GvIOp(gv))); /* should never be EOF */
     PUSHTARG;
@@ -1007,6 +1007,12 @@ PP(pp_prtf)
        goto just_say_no;
     }
     else {
+#ifdef LC_NUMERIC
+       if (op->op_private & OPpLOCALE)
+           NUMERIC_LOCAL();
+       else
+           NUMERIC_STANDARD();
+#endif /* LC_NUMERIC */
        do_sprintf(sv, SP - MARK, MARK + 1);
        if (!do_print(sv, fp))
            goto just_say_no;
@@ -1087,6 +1093,7 @@ PP(pp_sysread)
     if (op->op_type == OP_RECV) {
        bufsize = sizeof buf;
        buffer = SvGROW(bufsv, length+1);
+       /* 'offset' means 'flags' here */
        length = recvfrom(PerlIO_fileno(IoIFP(io)), buffer, length, offset,
            (struct sockaddr *)buf, &bufsize);
        if (length < 0)
@@ -1096,8 +1103,8 @@ PP(pp_sysread)
        (void)SvPOK_only(bufsv);
        SvSETMAGIC(bufsv);
        /* This should not be marked tainted if the fp is marked clean */
-       if (tainting && !(IoFLAGS(io) & IOf_UNTAINT))
-           sv_magic(bufsv, Nullsv, 't', Nullch, 0);
+       if (!(IoFLAGS(io) & IOf_UNTAINT))
+           SvTAINTED_on(bufsv);
        SP = ORIGMARK;
        sv_setpvn(TARG, buf, bufsize);
        PUSHs(TARG);
@@ -1107,6 +1114,11 @@ PP(pp_sysread)
     if (op->op_type == OP_RECV)
        DIE(no_sock_func, "recv");
 #endif
+    if (offset < 0) {
+       if (-offset > blen)
+           DIE("Offset outside string");
+       offset += blen;
+    }
     bufsize = SvCUR(bufsv);
     buffer = SvGROW(bufsv, length+offset+1);
     if (offset > bufsize) { /* Zero any newly allocated space */
@@ -1132,8 +1144,8 @@ PP(pp_sysread)
     (void)SvPOK_only(bufsv);
     SvSETMAGIC(bufsv);
     /* This should not be marked tainted if the fp is marked clean */
-    if (tainting && !(IoFLAGS(io) & IOf_UNTAINT))
-       sv_magic(bufsv, Nullsv, 't', Nullch, 0);
+    if (!(IoFLAGS(io) & IOf_UNTAINT))
+       SvTAINTED_on(bufsv);
     SP = ORIGMARK;
     PUSHi(length);
     RETURN;
@@ -1179,9 +1191,15 @@ PP(pp_send)
        }
     }
     else if (op->op_type == OP_SYSWRITE) {
-       if (MARK < SP)
+       if (MARK < SP) {
            offset = SvIVx(*++MARK);
-       else
+           if (offset < 0) {
+               if (-offset > blen)
+                   DIE("Offset outside string");
+               offset += blen;
+           } else if (offset >= blen)
+               DIE("Offset outside string");
+       } else
            offset = 0;
        if (length > blen - offset)
            length = blen - offset;
@@ -1293,7 +1311,7 @@ PP(pp_truncate)
            int tmpfd;
 
            if ((tmpfd = open(SvPV (sv, na), O_RDWR)) < 0)
-               result = 0;
+               result = 0;
            else {
                if (my_chsize(tmpfd, len) < 0)
                    result = 0;
@@ -1873,6 +1891,7 @@ PP(pp_stat)
     }
 
     EXTEND(SP, 13);
+    EXTEND_MORTAL(13);
     if (GIMME != G_ARRAY) {
        if (max)
            RETPUSHYES;
@@ -3134,6 +3153,7 @@ PP(pp_gmtime)
        tmbuf = gmtime(&when);
 
     EXTEND(SP, 9);
+    EXTEND_MORTAL(9);
     if (GIMME != G_ARRAY) {
        dTARGET;
        char mybuf[30];
@@ -3974,9 +3994,10 @@ PP(pp_syscall)
 
     if (tainting) {
        while (++MARK <= SP) {
-           if (SvGMAGICAL(*MARK) && SvSMAGICAL(*MARK) &&
-             (mg = mg_find(*MARK, 't')) && mg->mg_len & 1)
-               tainted = TRUE;
+           if (SvTAINTED(*MARK)) {
+               TAINT;
+               break;
+           }
        }
        MARK = ORIGMARK;
        TAINT_PROPER("syscall");
diff --git a/proto.h b/proto.h
index 851567b..3b89d99 100644 (file)
--- a/proto.h
+++ b/proto.h
@@ -113,7 +113,7 @@ void        dump_op _((OP* arg));
 void   dump_pm _((PMOP* pm));
 void   dump_packsubs _((HV* stash));
 void   dump_sub _((GV* gv));
-void   fbm_compile _((SV* sv, I32 iflag));
+void   fbm_compile _((SV* sv));
 char*  fbm_instr _((unsigned char* big, unsigned char* bigend, SV* littlesv));
 OP*    force_list _((OP* arg));
 OP*    fold_constants _((OP * arg));
@@ -158,8 +158,10 @@ void       hv_magic _((HV* hv, GV* gv, int how));
 SV**   hv_store _((HV* tb, char* key, U32 klen, SV* val, U32 hash));
 HE*    hv_store_ent _((HV* tb, SV* key, SV* val, U32 hash));
 void   hv_undef _((HV* tb));
-I32    ibcmp _((U8* a, U8* b, I32 len));
+I32    ibcmp _((char* a, char* b, I32 len));
+I32    ibcmp_locale _((char* a, char* b, I32 len));
 I32    ingroup _((I32 testgid, I32 effective));
+U32    intro_my _((void));
 char*  instr _((char* big, char* little));
 bool   io_close _((IO* io));
 OP*    invert _((OP* cmd));
@@ -194,6 +196,7 @@ int magic_setamagic _((SV* sv, MAGIC* mg));
 int    magic_setarylen _((SV* sv, MAGIC* mg));
 int    magic_setbm     _((SV* sv, MAGIC* mg));
 int    magic_setdbline _((SV* sv, MAGIC* mg));
+int    magic_setcollxfrm _((SV* sv, MAGIC* mg));
 int    magic_setenv    _((SV* sv, MAGIC* mg));
 int    magic_setfm     _((SV* sv, MAGIC* mg));
 int    magic_setisa    _((SV* sv, MAGIC* mg));
@@ -211,7 +214,7 @@ int magic_wipepack  _((SV* sv, MAGIC* mg));
 void   magicname _((char* sym, char* name, I32 namlen));
 int    main _((int argc, char** argv, char** env));
 void   markstack_grow _((void));
-char*  mem_collxfrm _((const char *m, const Size_t n, Size_t * nx));
+char*  mem_collxfrm _((const char *s, STRLEN len, STRLEN *xlen));
 char*  mess _((char* pat, va_list* args));
 int    mg_clear _((SV* sv));
 int    mg_copy _((SV *, SV *, char *, I32));
@@ -321,8 +324,13 @@ SV*        perl_get_sv _((char* name, I32 create));
 AV*    perl_get_av _((char* name, I32 create));
 HV*    perl_get_hv _((char* name, I32 create));
 CV*    perl_get_cv _((char* name, I32 create));
-void   perl_init_fold _(());
 int    perl_init_i18nl10n _((int printwarn));
+int    perl_init_i18nl14n _((int printwarn));
+void   perl_new_collate _((char *newcoll));
+void   perl_new_ctype _((char *newctype));
+void   perl_new_numeric _((char *newcoll));
+void   perl_numeric_local _((void));
+void   perl_numeric_standard _((void));
 int    perl_parse _((PerlInterpreter* sv_interp, void(*xsinit)(void), int argc, char** argv, char** env));
 void   perl_require_pv _((char* pv));
 #define perl_requirepv perl_require_pv
@@ -355,6 +363,8 @@ char*       savepv _((char* sv));
 char*  savepvn _((char* sv, I32 len));
 char*  sharepvn _((char* sv, I32 len, U32 hash));
 void   unsharepvn _((char* sv, I32 len, U32 hash));
+HEK*   share_hek _((char* sv, I32 len, U32 hash));
+void   unshare_hek _((HEK* hek));
 void   savestack_grow _((void));
 void   save_aptr _((AV** aptr));
 AV*    save_ary _((GV* gv));
@@ -415,6 +425,8 @@ void        sv_clean_all _((void));
 void   sv_clean_objs _((void));
 void   sv_clear _((SV* sv));
 I32    sv_cmp _((SV* sv1, SV* sv2));
+I32    sv_cmp_locale _((SV* sv1, SV* sv2));
+char*  sv_collxfrm _((SV* sv, STRLEN* nxp));
 void   sv_dec _((SV* sv));
 void   sv_dump _((SV* sv));
 bool   sv_derived_from _((SV* sv, char* name));
@@ -452,12 +464,14 @@ SV*       sv_setref_pvn _((SV *rv, char *classname, char* pv, I32 n));
 void   sv_setpv _((SV* sv, char* ptr));
 void   sv_setpvn _((SV* sv, char* ptr, STRLEN len));
 void   sv_setsv _((SV* dsv, SV* ssv));
+void   sv_taint _((SV* sv));
+bool   sv_tainted _((SV* sv));
 int    sv_unmagic _((SV* sv, int type));
 void   sv_unref _((SV* sv));
+void   sv_untaint _((SV* sv));
 bool   sv_upgrade _((SV* sv, U32 mt));
 void   sv_usepvn _((SV* sv, char* ptr, STRLEN len));
 void   taint_env _((void));
-void   taint_not _((char *s));
 void   taint_proper _((char* f, char* s));
 #ifdef UNLINK_ALL_VERSIONS
 I32    unlnk _((char* f));
@@ -479,6 +493,13 @@ Malloc_t realloc _((Malloc_t where, MEM_SIZE nbytes));
 Free_t   free _((Malloc_t where));
 #endif
 
+#ifndef MYMALLOC
+Malloc_t safemalloc _((MEM_SIZE nbytes));
+Malloc_t safecalloc _((MEM_SIZE elements, MEM_SIZE size));
+Malloc_t saferealloc _((Malloc_t where, MEM_SIZE nbytes));
+Free_t   safefree _((Malloc_t where));
+#endif
+
 #ifdef LEAKTEST
 Malloc_t safexmalloc _((I32 x, MEM_SIZE size));
 Malloc_t safexcalloc _((I32 x, MEM_SIZE elements, MEM_SIZE size));
index 6befee8..bbb7c8e 100644 (file)
--- a/regcomp.c
+++ b/regcomp.c
@@ -107,7 +107,7 @@ static char *regnode _((char));
 static char *regpiece _((I32 *));
 static void reginsert _((char, char *));
 static void regoptail _((char *, char *));
-static void regset _((char *, I32, I32));
+static void regset _((char *, I32));
 static void regtail _((char *, char *));
 static char* nextchar _((void));
 
@@ -132,7 +132,6 @@ char* exp;
 char* xend;
 PMOP* pm;
 {
-    I32 fold = pm->op_pmflags & PMf_FOLD;
     register regexp *r;
     register char *scan;
     register SV *longish;
@@ -150,13 +149,14 @@ PMOP* pm;
     if (exp == NULL)
        croak("NULL regexp argument");
 
-    /* First pass: determine size, legality. */
+    regprecomp = savepvn(exp, xend - exp);
     regflags = pm->op_pmflags;
+    regsawback = 0;
+
+    /* First pass: determine size, legality. */
     regparse = exp;
     regxend = xend;
-    regprecomp = savepvn(exp,xend-exp);
     regnaughty = 0;
-    regsawback = 0;
     regnpar = 1;
     regsize = 0L;
     regcode = &regdummy;
@@ -171,17 +171,18 @@ PMOP* pm;
     if (regsize >= 32767L)             /* Probably could be 65535L. */
        FAIL("regexp too big");
 
-    /* Allocate space. */
+    /* Allocate space and initialize. */
     Newc(1001, r, sizeof(regexp) + (unsigned)regsize, char, regexp);
     if (r == NULL)
        FAIL("regexp out of space");
-
-    /* Second pass: emit code. */
-    r->prelen = xend-exp;
+    r->prelen = xend - exp;
     r->precomp = regprecomp;
     r->subbeg = r->subbase = NULL;
-    regnaughty = 0;
+
+    /* Second pass: emit code. */
     regparse = exp;
+    regxend = xend;
+    regnaughty = 0;
     regnpar = 1;
     regcode = r->program;
     regc((char)MAGIC);
@@ -190,7 +191,6 @@ PMOP* pm;
 
     /* Dig out information for optimizations. */
     pm->op_pmflags = regflags;
-    fold = pm->op_pmflags & PMf_FOLD;
     r->regstart = Nullsv;      /* Worst-case defaults. */
     r->reganch = 0;
     r->regmust = Nullsv;
@@ -216,16 +216,16 @@ PMOP* pm;
 
        /* Starting-point info. */
       again:
-       if (OP(first) == EXACTLY) {
+       if (OP(first) == EXACT) {
            r->regstart = newSVpv(OPERAND(first)+1,*OPERAND(first));
-           if (SvCUR(r->regstart) > !(sawstudy|fold))
-               fbm_compile(r->regstart,fold);
-           else
-               sv_upgrade(r->regstart, SVt_PVBM);
+           if (SvCUR(r->regstart) > !sawstudy)
+               fbm_compile(r->regstart);
+           (void)SvUPGRADE(r->regstart, SVt_PVBM);
        }
        else if (strchr(simple+2,OP(first)))
            r->regstclass = first;
-       else if (OP(first) == BOUND || OP(first) == NBOUND)
+       else if (regkind[(U8)OP(first)] == BOUND ||
+                regkind[(U8)OP(first)] == NBOUND)
            r->regstclass = first;
        else if (regkind[(U8)OP(first)] == BOL) {
            r->reganch = ROPT_ANCH;
@@ -280,7 +280,7 @@ PMOP* pm;
                scan = regnext(scan);
                continue;
            }
-           if (OP(scan) == EXACTLY) {
+           if (OP(scan) == EXACT) {
                char *t;
 
                first = scan;
@@ -333,8 +333,8 @@ PMOP* pm;
 
        /* Prefer earlier on tie, unless we can tail match latter */
 
-       if (SvCUR(longish) + (regkind[(U8)OP(first)] == EOL) >
-               SvCUR(longest))
+       if (SvCUR(longish) + (regkind[(U8)OP(first)] == EOL)
+               > SvCUR(longest))
        {
            sv_setsv(longest,longish);
            backest = backish;
@@ -342,23 +342,18 @@ PMOP* pm;
        else
            sv_setpvn(longish,"",0);
        if (SvCUR(longest)
-           &&
-           (!r->regstart
-            ||
-            !fbm_instr((unsigned char*) SvPVX(r->regstart),
-                 (unsigned char *) SvPVX(r->regstart)
-                   + SvCUR(r->regstart),
-                 longest)
-           )
-          )
+           && (!r->regstart
+               || !fbm_instr((unsigned char*) SvPVX(r->regstart),
+                             (unsigned char *) (SvPVX(r->regstart)
+                                                + SvCUR(r->regstart)),
+                             longest)))
        {
            r->regmust = longest;
            if (backest < 0)
                backest = -1;
            r->regback = backest;
-           if (SvCUR(longest) > !(sawstudy || fold ||
-                       regkind[(U8)OP(first)]==EOL))
-               fbm_compile(r->regmust,fold);
+           if (SvCUR(longest) > !(sawstudy || regkind[(U8)OP(first)] == EOL))
+               fbm_compile(r->regmust);
            (void)SvUPGRADE(r->regmust, SVt_PVBM);
            BmUSEFUL(r->regmust) = 100;
            if (regkind[(U8)OP(first)] == EOL && SvCUR(longish))
@@ -371,7 +366,6 @@ PMOP* pm;
        SvREFCNT_dec(longish);
     }
 
-    r->do_folding = fold;
     r->nparens = regnpar - 1;
     r->minlen = minlen;
     Newz(1002, r->startp, regnpar, char*);
@@ -793,32 +787,32 @@ tryagain:
            nextchar();
            break;
        case 'w':
-           ret = regnode(ALNUM);
+           ret = regnode((regflags & PMf_LOCALE) ? ALNUML : ALNUM);
            *flagp |= HASWIDTH|SIMPLE;
            nextchar();
            break;
        case 'W':
-           ret = regnode(NALNUM);
+           ret = regnode((regflags & PMf_LOCALE) ? NALNUML : NALNUM);
            *flagp |= HASWIDTH|SIMPLE;
            nextchar();
            break;
        case 'b':
-           ret = regnode(BOUND);
+           ret = regnode((regflags & PMf_LOCALE) ? BOUNDL : BOUND);
            *flagp |= SIMPLE;
            nextchar();
            break;
        case 'B':
-           ret = regnode(NBOUND);
+           ret = regnode((regflags & PMf_LOCALE) ? NBOUNDL : NBOUND);
            *flagp |= SIMPLE;
            nextchar();
            break;
        case 's':
-           ret = regnode(SPACE);
+           ret = regnode((regflags & PMf_LOCALE) ? SPACEL : SPACE);
            *flagp |= HASWIDTH|SIMPLE;
            nextchar();
            break;
        case 'S':
-           ret = regnode(NSPACE);
+           ret = regnode((regflags & PMf_LOCALE) ? NSPACEL : NSPACE);
            *flagp |= HASWIDTH|SIMPLE;
            nextchar();
            break;
@@ -887,7 +881,9 @@ tryagain:
            regparse++;
 
        defchar:
-           ret = regnode(EXACTLY);
+           ret = regnode((regflags & PMf_FOLD)
+                         ? ((regflags & PMf_LOCALE) ? EXACTFL : EXACTF)
+                         : EXACT);
            regc(0);            /* save spot for len */
            for (len = 0, p = regparse - 1;
              len < 127 && p < regxend;
@@ -948,10 +944,8 @@ tryagain:
                        break;
                    case 'c':
                        p++;
-                       ender = *p++;
-                       if (isLOWER(ender))
-                           ender = toUPPER(ender);
-                       ender ^= 64;
+                       ender = UCHARAT(p++);
+                       ender = toCTRL(ender);
                        break;
                    case '0': case '1': case '2': case '3':case '4':
                    case '5': case '6': case '7': case '8':case '9':
@@ -990,8 +984,6 @@ tryagain:
                    ender = *p++;
                    break;
                }
-               if (regflags & PMf_FOLD && isUPPER(ender))
-                   ender = toLOWER(ender);
                if (ISMULT2(p)) { /* Back off on ?+*. */
                    if (len)
                        p = oldp;
@@ -1023,24 +1015,20 @@ tryagain:
 }
 
 static void
-regset(bits,def,c)
-char *bits;
-I32 def;
+regset(opnd, c)
+char *opnd;
 register I32 c;
 {
-    if (regcode == &regdummy)
-      return;
-    c &= 255;
-    if (def)
-       bits[c >> 3] &= ~(1 << (c & 7));
-    else
-       bits[c >> 3] |=  (1 << (c & 7));
+    if (opnd == &regdummy)
+       return;
+    c &= 0xFF;
+    opnd[1 + (c >> 3)] |= (1 << (c & 7));
 }
 
 static char *
 regclass()
 {
-    register char *bits;
+    register char *opnd;
     register I32 class;
     register I32 lastclass = 1234;
     register I32 range = 0;
@@ -1049,16 +1037,21 @@ regclass()
     I32 numlen;
 
     ret = regnode(ANYOF);
+    opnd = regcode;
+    for (class = 0; class < 33; class++)
+       regc(0);
     if (*regparse == '^') {    /* Complement of range. */
        regnaughty++;
        regparse++;
-       def = 0;
-    } else {
-       def = 255;
+       if (opnd != &regdummy)
+           *opnd |= ANYOF_INVERT;
+    }
+    if (opnd != &regdummy) {
+       if (regflags & PMf_FOLD)
+           *opnd |= ANYOF_FOLD;
+       if (regflags & PMf_LOCALE)
+           *opnd |= ANYOF_LOCALE;
     }
-    bits = regcode;
-    for (class = 0; class < 32; class++)
-      regc(def);
     if (*regparse == ']' || *regparse == '-')
        goto skipcond;          /* allow 1st char to be ] or - */
     while (regparse < regxend && *regparse != ']') {
@@ -1068,39 +1061,63 @@ regclass()
            class = UCHARAT(regparse++);
            switch (class) {
            case 'w':
-               for (class = 0; class < 256; class++)
-                 if (isALNUM(class))
-                   regset(bits,def,class);
+               if (regflags & PMf_LOCALE) {
+                   if (opnd != &regdummy)
+                       *opnd |= ANYOF_ALNUML;
+               }
+               else {
+                   for (class = 0; class < 256; class++)
+                       if (isALNUM(class))
+                           regset(opnd, class);
+               }
                lastclass = 1234;
                continue;
            case 'W':
-               for (class = 0; class < 256; class++)
-                 if (!isALNUM(class))
-                   regset(bits,def,class);
+               if (regflags & PMf_LOCALE) {
+                   if (opnd != &regdummy)
+                       *opnd |= ANYOF_NALNUML;
+               }
+               else {
+                   for (class = 0; class < 256; class++)
+                       if (!isALNUM(class))
+                           regset(opnd, class);
+               }
                lastclass = 1234;
                continue;
            case 's':
-               for (class = 0; class < 256; class++)
-                 if (isSPACE(class))
-                   regset(bits,def,class);
+               if (regflags & PMf_LOCALE) {
+                   if (opnd != &regdummy)
+                       *opnd |= ANYOF_SPACEL;
+               }
+               else {
+                   for (class = 0; class < 256; class++)
+                       if (isSPACE(class))
+                           regset(opnd, class);
+               }
                lastclass = 1234;
                continue;
            case 'S':
-               for (class = 0; class < 256; class++)
-                 if (!isSPACE(class))
-                   regset(bits,def,class);
+               if (regflags & PMf_LOCALE) {
+                   if (opnd != &regdummy)
+                       *opnd |= ANYOF_NSPACEL;
+               }
+               else {
+                   for (class = 0; class < 256; class++)
+                       if (!isSPACE(class))
+                           regset(opnd, class);
+               }
                lastclass = 1234;
                continue;
            case 'd':
                for (class = '0'; class <= '9'; class++)
-                   regset(bits,def,class);
+                   regset(opnd, class);
                lastclass = 1234;
                continue;
            case 'D':
                for (class = 0; class < '0'; class++)
-                   regset(bits,def,class);
+                   regset(opnd, class);
                for (class = '9' + 1; class < 256; class++)
-                   regset(bits,def,class);
+                   regset(opnd, class);
                lastclass = 1234;
                continue;
            case 'n':
@@ -1129,10 +1146,8 @@ regclass()
                regparse += numlen;
                break;
            case 'c':
-               class = *regparse++;
-               if (isLOWER(class))
-                 class = toUPPER(class);
-               class ^= 64;
+               class = UCHARAT(regparse++);
+               class = toCTRL(class);
                break;
            case '0': case '1': case '2': case '3': case '4':
            case '5': case '6': case '7': case '8': case '9':
@@ -1155,11 +1170,8 @@ regclass()
                continue;       /* do it next time */
            }
        }
-       for ( ; lastclass <= class; lastclass++) {
-           regset(bits,def,lastclass);
-           if (regflags & PMf_FOLD && isUPPER(lastclass))
-               regset(bits,def,toLOWER(lastclass));
-       }
+       for ( ; lastclass <= class; lastclass++)
+           regset(opnd, lastclass);
        lastclass = class;
     }
     if (*regparse != ']')
@@ -1439,7 +1451,7 @@ regdump(r)
 regexp *r;
 {
     register char *s;
-    register char op = EXACTLY;        /* Arbitrary non-END op. */
+    register char op = EXACT;  /* Arbitrary non-END op. */
     register char *next;
 
 
@@ -1459,9 +1471,9 @@ regexp *r;
            PerlIO_printf(Perl_debug_log, "(%d)", (s-r->program)+(next-s));
        s += 3;
        if (op == ANYOF) {
-           s += 32;
+           s += 33;
        }
-       if (op == EXACTLY) {
+       if (regkind[(U8)op] == EXACT) {
            /* Literal string, where present. */
            s++;
            (void)PerlIO_putc(Perl_debug_log, ' ');
@@ -1536,8 +1548,14 @@ char *op;
     case BRANCH:
        p = "BRANCH";
        break;
-    case EXACTLY:
-       p = "EXACTLY";
+    case EXACT:
+       p = "EXACT";
+       break;
+    case EXACTF:
+       p = "EXACTF";
+       break;
+    case EXACTFL:
+       p = "EXACTFL";
        break;
     case NOTHING:
        p = "NOTHING";
@@ -1548,29 +1566,17 @@ char *op;
     case END:
        p = "END";
        break;
-    case ALNUM:
-       p = "ALNUM";
-       break;
-    case NALNUM:
-       p = "NALNUM";
-       break;
     case BOUND:
        p = "BOUND";
        break;
+    case BOUNDL:
+       p = "BOUNDL";
+       break;
     case NBOUND:
        p = "NBOUND";
        break;
-    case SPACE:
-       p = "SPACE";
-       break;
-    case NSPACE:
-       p = "NSPACE";
-       break;
-    case DIGIT:
-       p = "DIGIT";
-       break;
-    case NDIGIT:
-       p = "NDIGIT";
+    case NBOUNDL:
+       p = "NBOUNDL";
        break;
     case CURLY:
        (void)sprintf(buf+strlen(buf), "CURLY {%d,%d}", ARG1(op),ARG2(op));
@@ -1616,6 +1622,36 @@ char *op;
     case WHILEM:
        p = "WHILEM";
        break;
+    case DIGIT:
+       p = "DIGIT";
+       break;
+    case NDIGIT:
+       p = "NDIGIT";
+       break;
+    case ALNUM:
+       p = "ALNUM";
+       break;
+    case NALNUM:
+       p = "NALNUM";
+       break;
+    case SPACE:
+       p = "SPACE";
+       break;
+    case NSPACE:
+       p = "NSPACE";
+       break;
+    case ALNUML:
+       p = "ALNUML";
+       break;
+    case NALNUML:
+       p = "NALNUML";
+       break;
+    case SPACEL:
+       p = "SPACEL";
+       break;
+    case NSPACEL:
+       p = "NSPACEL";
+       break;
     default:
        FAIL("corrupted regexp opcode");
     }
index b2d9b84..9d07ff9 100644 (file)
--- a/regcomp.h
+++ b/regcomp.h
  */
 
 /* definition  number  opnd?   meaning */
-#define        END     0       /* no   End of program. */
-#define        BOL     1       /* no   Match "" at beginning of line. */
-#define MBOL   2       /* no   Same, assuming multiline. */
-#define SBOL   3       /* no   Same, assuming singleline. */
-#define        EOL     4       /* no   Match "" at end of line. */
-#define MEOL   5       /* no   Same, assuming multiline. */
-#define SEOL   6       /* no   Same, assuming singleline. */
-#define        ANY     7       /* no   Match any one character (except newline). */
-#define        SANY    8       /* no   Match any one character. */
-#define        ANYOF   9       /* sv   Match character in (or not in) this class. */
+#define        END      0      /* no   End of program. */
+#define        BOL      1      /* no   Match "" at beginning of line. */
+#define MBOL    2      /* no   Same, assuming multiline. */
+#define SBOL    3      /* no   Same, assuming singleline. */
+#define        EOL      4      /* no   Match "" at end of line. */
+#define MEOL    5      /* no   Same, assuming multiline. */
+#define SEOL    6      /* no   Same, assuming singleline. */
+#define        ANY      7      /* no   Match any one character (except newline). */
+#define        SANY     8      /* no   Match any one character. */
+#define        ANYOF    9      /* sv   Match character in (or not in) this class. */
 #define        CURLY   10      /* sv   Match this simple thing {n,m} times. */
 #define        CURLYX  11      /* sv   Match this complex thing {n,m} times. */
 #define        BRANCH  12      /* node Match this alternative, or the next... */
 #define        BACK    13      /* no   Match "", "next" ptr points backward. */
-#define        EXACTLY 14      /* sv   Match this string (preceded by length). */
-#define        NOTHING 15      /* no   Match empty string. */
-#define        STAR    16      /* node Match this (simple) thing 0 or more times. */
-#define        PLUS    17      /* node Match this (simple) thing 1 or more times. */
-#define ALNUM  18      /* no   Match any alphanumeric character */
-#define NALNUM 19      /* no   Match any non-alphanumeric character */
+#define        EXACT   14      /* sv   Match this string (preceded by length). */
+#define        EXACTF  15      /* sv   Match this string, folded (prec. by length). */
+#define        EXACTFL 16      /* sv   Match this string, folded in locale (w/len). */
+#define        NOTHING 17      /* no   Match empty string. */
+#define        STAR    18      /* node Match this (simple) thing 0 or more times. */
+#define        PLUS    19      /* node Match this (simple) thing 1 or more times. */
 #define BOUND  20      /* no   Match "" at any word boundary */
-#define NBOUND 21      /* no   Match "" at any word non-boundary */
-#define SPACE  22      /* no   Match any whitespace character */
-#define NSPACE 23      /* no   Match any non-whitespace character */
-#define DIGIT  24      /* no   Match any numeric character */
-#define NDIGIT 25      /* no   Match any non-numeric character */
-#define REF    26      /* num  Match some already matched string */
-#define        OPEN    27      /* num  Mark this point in input as start of #n. */
-#define        CLOSE   28      /* num  Analogous to OPEN. */
-#define MINMOD 29      /* no   Next operator is not greedy. */
-#define GBOL   30      /* no   Matches where last m//g left off. */
-#define IFMATCH        31      /* no   Succeeds if the following matches. */
-#define UNLESSM        32      /* no   Fails if the following matches. */
-#define SUCCEED        33      /* no   Return from a subroutine, basically. */
-#define WHILEM 34      /* no   Do curly processing and see if rest matches. */
+#define BOUNDL 21      /* no   Match "" at any word boundary */
+#define NBOUND 22      /* no   Match "" at any word non-boundary */
+#define NBOUNDL        23      /* no   Match "" at any word non-boundary */
+#define REF    24      /* num  Match some already matched string */
+#define        OPEN    25      /* num  Mark this point in input as start of #n. */
+#define        CLOSE   26      /* num  Analogous to OPEN. */
+#define MINMOD 27      /* no   Next operator is not greedy. */
+#define GBOL   28      /* no   Matches where last m//g left off. */
+#define IFMATCH        29      /* no   Succeeds if the following matches. */
+#define UNLESSM        30      /* no   Fails if the following matches. */
+#define SUCCEED        31      /* no   Return from a subroutine, basically. */
+#define WHILEM 32      /* no   Do curly processing and see if rest matches. */
+#define ALNUM  33      /* no   Match any alphanumeric character */
+#define ALNUML 34      /* no   Match any alphanumeric char in locale */
+#define NALNUM 35      /* no   Match any non-alphanumeric character */
+#define NALNUML        36      /* no   Match any non-alphanumeric char in locale */
+#define SPACE  37      /* no   Match any whitespace character */
+#define SPACEL 38      /* no   Match any whitespace char in locale */
+#define NSPACE 39      /* no   Match any non-whitespace character */
+#define NSPACEL        40      /* no   Match any non-whitespace char in locale */
+#define DIGIT  41      /* no   Match any numeric character */
+#define NDIGIT 42      /* no   Match any non-numeric character */
 
 /*
  * Opcode notes:
 #ifndef DOINIT
 EXT char regarglen[];
 #else
-EXT char regarglen[] = {0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0};
+EXT char regarglen[] = {
+    0,0,0,0,0,0,0,0,0,0,
+    /*CURLY*/ 4, /*CURLYX*/ 4,
+    0,0,0,0,0,0,0,0,0,0,0,0,
+    /*REF*/ 2, /*OPEN*/ 2, /*CLOSE*/ 2,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+};
 #endif
 
 #ifndef DOINIT
@@ -130,18 +144,16 @@ EXT char regkind[] = {
        CURLY,
        BRANCH,
        BACK,
-       EXACTLY,
+       EXACT,
+       EXACT,
+       EXACT,
        NOTHING,
        STAR,
        PLUS,
-       ALNUM,
-       NALNUM,
+       BOUND,
        BOUND,
        NBOUND,
-       SPACE,
-       NSPACE,
-       DIGIT,
-       NDIGIT,
+       NBOUND,
        REF,
        OPEN,
        CLOSE,
@@ -150,7 +162,17 @@ EXT char regkind[] = {
        BRANCH,
        BRANCH,
        END,
-       WHILEM
+       WHILEM,
+       ALNUM,
+       ALNUM,
+       NALNUM,
+       NALNUM,
+       SPACE,
+       SPACE,
+       NSPACE,
+       NSPACE,
+       DIGIT,
+       NDIGIT,
 };
 #endif
 
@@ -158,14 +180,21 @@ EXT char regkind[] = {
 #ifndef DOINIT
 EXT char varies[];
 #else
-EXT char varies[] = {BRANCH,BACK,STAR,PLUS,CURLY,CURLYX,REF,WHILEM,0};
+EXT char varies[] = {
+    BRANCH, BACK, STAR, PLUS, CURLY, CURLYX, REF, WHILEM, 0
+};
 #endif
 
 /* The following always have a length of 1. */
 #ifndef DOINIT
 EXT char simple[];
 #else
-EXT char simple[] = {ANY,SANY,ANYOF,ALNUM,NALNUM,SPACE,NSPACE,DIGIT,NDIGIT,0};
+EXT char simple[] = {
+    ANY, SANY, ANYOF,
+    ALNUM, ALNUML, NALNUM, NALNUML,
+    SPACE, SPACEL, NSPACE, NSPACEL,
+    DIGIT, NDIGIT, 0
+};
 #endif
 
 EXT char regdummy;
@@ -222,6 +251,16 @@ EXT char regdummy;
 
 #define MAGIC 0234
 
+/* Flags for first parameter byte of ANYOF */
+#define ANYOF_INVERT   0x40
+#define ANYOF_FOLD     0x20
+#define ANYOF_LOCALE   0x10
+#define ANYOF_ISA      0x0F
+#define ANYOF_ALNUML    0x08
+#define ANYOF_NALNUML   0x04
+#define ANYOF_SPACEL    0x02
+#define ANYOF_NSPACEL   0x01
+
 /*
  * Utility definitions.
  */
index 6e79d6b..d9a893e 100644 (file)
--- a/regexec.c
+++ b/regexec.c
@@ -147,6 +147,9 @@ regcppop()
 static I32 regmatch _((char *prog));
 static I32 regrepeat _((char *p, I32 max));
 static I32 regtry _((regexp *prog, char *startpos));
+static bool reginclass _((char *p, I32 c));
+
+static bool regtainted;                /* tainted information used? */
 
 /*
  - pregexec - match a regexp against a string
@@ -162,7 +165,6 @@ SV *screamer;
 I32 safebase;  /* no need to remember string in subbase */
 {
     register char *s;
-    register I32 i;
     register char *c;
     register char *startpos = stringarg;
     register I32 tmp;
@@ -192,23 +194,15 @@ I32 safebase;     /* no need to remember string in subbase */
        if (!multiline && regprev == '\n')
            regprev = '\0';             /* force ^ to NOT match */
     }
+
     regprecomp = prog->precomp;
-    regnpar = prog->nparens;
     /* Check validity of program. */
     if (UCHARAT(prog->program) != MAGIC) {
        FAIL("corrupted regexp program");
     }
 
-    if (prog->do_folding) {
-       i = strend - startpos;
-       New(1101,c,i+1,char);
-       Copy(startpos, c, i+1, char);
-       startpos = c;
-       strend = startpos + i;
-       for (s = startpos; s < strend; s++)
-           if (isUPPER(*s))
-               *s = toLOWER(*s);
-    }
+    regnpar = prog->nparens;
+    regtainted = FALSE;
 
     /* If there is a "must appear" string, look for it. */
     s = startpos;
@@ -281,13 +275,13 @@ I32 safebase;     /* no need to remember string in subbase */
     if (prog->regstart) {
        if (prog->reganch & ROPT_SKIP) {  /* we have /x+whatever/ */
            /* it must be a one character string */
-           i = SvPVX(prog->regstart)[0];
+           char ch = SvPVX(prog->regstart)[0];
            while (s < strend) {
-               if (*s == i) {
+               if (*s == ch) {
                    if (regtry(prog, s))
                        goto got_it;
                    s++;
-                   while (s < strend && *s == i)
+                   while (s < strend && *s == ch)
                        s++;
                }
                s++;
@@ -327,8 +321,7 @@ I32 safebase;       /* no need to remember string in subbase */
        case ANYOF:
            c = OPERAND(c);
            while (s < strend) {
-               i = UCHARAT(s);
-               if (!(c[i >> 3] & (1 << (i&7)))) {
+               if (reginclass(c, *s)) {
                    if (tmp && regtry(prog, s))
                        goto got_it;
                    else
@@ -339,18 +332,16 @@ I32 safebase;     /* no need to remember string in subbase */
                s++;
            }
            break;
+       case BOUNDL:
+           regtainted = TRUE;
+           /* FALL THROUGH */
        case BOUND:
            if (minlen)
                dontbother++,strend--;
-           if (s != startpos) {
-               i = s[-1];
-               tmp = isALNUM(i);
-           }
-           else
-               tmp = isALNUM(regprev); /* assume not alphanumeric */
+           tmp = (s != startpos) ? UCHARAT(s - 1) : regprev;
+           tmp = (OP(c) == BOUND ? isALNUM(tmp) : isALNUM_LC(tmp));
            while (s < strend) {
-               i = *s;
-               if (tmp != isALNUM(i)) {
+               if (tmp != (OP(c) == BOUND ? isALNUM(*s) : isALNUM_LC(*s))) {
                    tmp = !tmp;
                    if (regtry(prog, s))
                        goto got_it;
@@ -360,18 +351,16 @@ I32 safebase;     /* no need to remember string in subbase */
            if ((minlen || tmp) && regtry(prog,s))
                goto got_it;
            break;
+       case NBOUNDL:
+           regtainted = TRUE;
+           /* FALL THROUGH */
        case NBOUND:
            if (minlen)
                dontbother++,strend--;
-           if (s != startpos) {
-               i = s[-1];
-               tmp = isALNUM(i);
-           }
-           else
-               tmp = isALNUM(regprev); /* assume not alphanumeric */
+           tmp = (s != startpos) ? UCHARAT(s - 1) : regprev;
+           tmp = (OP(c) == NBOUND ? isALNUM(tmp) : isALNUM_LC(tmp));
            while (s < strend) {
-               i = *s;
-               if (tmp != isALNUM(i))
+               if (tmp != (OP(c) == NBOUND ? isALNUM(*s) : isALNUM_LC(*s)))
                    tmp = !tmp;
                else if (regtry(prog, s))
                    goto got_it;
@@ -382,8 +371,21 @@ I32 safebase;      /* no need to remember string in subbase */
            break;
        case ALNUM:
            while (s < strend) {
-               i = *s;
-               if (isALNUM(i)) {
+               if (isALNUM(*s)) {
+                   if (tmp && regtry(prog, s))
+                       goto got_it;
+                   else
+                       tmp = doevery;
+               }
+               else
+                   tmp = 1;
+               s++;
+           }
+           break;
+       case ALNUML:
+           regtainted = TRUE;
+           while (s < strend) {
+               if (isALNUM_LC(*s)) {
                    if (tmp && regtry(prog, s))
                        goto got_it;
                    else
@@ -396,8 +398,21 @@ I32 safebase;      /* no need to remember string in subbase */
            break;
        case NALNUM:
            while (s < strend) {
-               i = *s;
-               if (!isALNUM(i)) {
+               if (!isALNUM(*s)) {
+                   if (tmp && regtry(prog, s))
+                       goto got_it;
+                   else
+                       tmp = doevery;
+               }
+               else
+                   tmp = 1;
+               s++;
+           }
+           break;
+       case NALNUML:
+           regtainted = TRUE;
+           while (s < strend) {
+               if (!isALNUM_LC(*s)) {
                    if (tmp && regtry(prog, s))
                        goto got_it;
                    else
@@ -421,6 +436,20 @@ I32 safebase;      /* no need to remember string in subbase */
                s++;
            }
            break;
+       case SPACEL:
+           regtainted = TRUE;
+           while (s < strend) {
+               if (isSPACE_LC(*s)) {
+                   if (tmp && regtry(prog, s))
+                       goto got_it;
+                   else
+                       tmp = doevery;
+               }
+               else
+                   tmp = 1;
+               s++;
+           }
+           break;
        case NSPACE:
            while (s < strend) {
                if (!isSPACE(*s)) {
@@ -434,6 +463,20 @@ I32 safebase;      /* no need to remember string in subbase */
                s++;
            }
            break;
+       case NSPACEL:
+           regtainted = TRUE;
+           while (s < strend) {
+               if (!isSPACE_LC(*s)) {
+                   if (tmp && regtry(prog, s))
+                       goto got_it;
+                   else
+                       tmp = doevery;
+               }
+               else
+                   tmp = 1;
+               s++;
+           }
+           break;
        case DIGIT:
            while (s < strend) {
                if (isDIGIT(*s)) {
@@ -480,8 +523,9 @@ got_it:
     strend += dontbother;      /* uncheat */
     prog->subbeg = strbeg;
     prog->subend = strend;
-    if ((!safebase && (prog->nparens || sawampersand)) || prog->do_folding) {
-       i = strend - startpos + (stringarg - strbeg);
+    prog->exec_tainted = regtainted;
+    if (!safebase && (prog->nparens || sawampersand)) {
+       I32 i = strend - startpos + (stringarg - strbeg);
        if (safebase) {                 /* no need for $digit later */
            s = strbeg;
            prog->subend = s+i;
@@ -504,14 +548,10 @@ got_it:
                prog->endp[i] = s + (prog->endp[i] - startpos);
            }
        }
-       if (prog->do_folding)
-           Safefree(startpos);
     }
     return 1;
 
 phooey:
-    if (prog->do_folding)
-       Safefree(startpos);
     return 0;
 }
 
@@ -576,13 +616,14 @@ char *prog;
     register I32 ln;           /* len or last */
     register char *s;          /* operand or save */
     register char *locinput = reginput;
+    register I32 c1, c2;       /* case fold search */
     int minmod = 0;
 #ifdef DEBUGGING
     static int regindent = 0;
     regindent++;
 #endif
 
-    nextchar = *locinput;
+    nextchar = UCHARAT(locinput);
     scan = prog;
     while (scan != NULL) {
 #ifdef DEBUGGING
@@ -653,14 +694,14 @@ char *prog;
        case SANY:
            if (!nextchar && locinput >= regeol)
                sayNO;
-           nextchar = *++locinput;
+           nextchar = UCHARAT(++locinput);
            break;
        case ANY:
            if (!nextchar && locinput >= regeol || nextchar == '\n')
                sayNO;
-           nextchar = *++locinput;
+           nextchar = UCHARAT(++locinput);
            break;
-       case EXACTLY:
+       case EXACT:
            s = OPERAND(scan);
            ln = *s++;
            /* Inline the first character, for speed. */
@@ -671,67 +712,111 @@ char *prog;
            if (ln > 1 && memcmp(s, locinput, ln) != 0)
                sayNO;
            locinput += ln;
-           nextchar = *locinput;
+           nextchar = UCHARAT(locinput);
+           break;
+       case EXACTFL:
+           regtainted = TRUE;
+           /* FALL THROUGH */
+       case EXACTF:
+           s = OPERAND(scan);
+           ln = *s++;
+           /* Inline the first character, for speed. */
+           if (UCHARAT(s) != nextchar &&
+               UCHARAT(s) != ((OP(scan) == EXACTF)
+                              ? fold : fold_locale)[nextchar])
+               sayNO;
+           if (regeol - locinput < ln)
+               sayNO;
+           if (ln > 1 && ((OP(scan) == EXACTF)
+                          ? ibcmp : ibcmp_locale)(s, locinput, ln) != 0)
+               sayNO;
+           locinput += ln;
+           nextchar = UCHARAT(locinput);
            break;
        case ANYOF:
            s = OPERAND(scan);
            if (nextchar < 0)
                nextchar = UCHARAT(locinput);
-           if (s[nextchar >> 3] & (1 << (nextchar&7)))
+           if (!reginclass(s, nextchar))
                sayNO;
            if (!nextchar && locinput >= regeol)
                sayNO;
-           nextchar = *++locinput;
+           nextchar = UCHARAT(++locinput);
            break;
+       case ALNUML:
+           regtainted = TRUE;
+           /* FALL THROUGH */
        case ALNUM:
            if (!nextchar)
                sayNO;
-           if (!isALNUM(nextchar))
+           if (!(OP(scan) == ALNUM
+                 ? isALNUM(nextchar) : isALNUM_LC(nextchar)))
                sayNO;
-           nextchar = *++locinput;
+           nextchar = UCHARAT(++locinput);
            break;
+       case NALNUML:
+           regtainted = TRUE;
+           /* FALL THROUGH */
        case NALNUM:
            if (!nextchar && locinput >= regeol)
                sayNO;
-           if (isALNUM(nextchar))
+           if (OP(scan) == NALNUM
+               ? isALNUM(nextchar) : isALNUM_LC(nextchar))
                sayNO;
-           nextchar = *++locinput;
+           nextchar = UCHARAT(++locinput);
            break;
-       case NBOUND:
+       case BOUNDL:
+       case NBOUNDL:
+           regtainted = TRUE;
+           /* FALL THROUGH */
        case BOUND:
-           if (locinput == regbol)     /* was last char in word? */
-               ln = isALNUM(regprev);
-           else 
-               ln = isALNUM(locinput[-1]);
-           n = isALNUM(nextchar); /* is next char in word? */
-           if ((ln == n) == (OP(scan) == BOUND))
+       case NBOUND:
+           /* was last char in word? */
+           ln = (locinput != regbol) ? UCHARAT(locinput - 1) : regprev;
+           if (OP(scan) == BOUND || OP(scan) == NBOUND) {
+               ln = isALNUM(ln);
+               n = isALNUM(nextchar);
+           }
+           else {
+               ln = isALNUM_LC(ln);
+               n = isALNUM_LC(nextchar);
+           }
+           if ((ln == n) == (OP(scan) == BOUND || OP(scan) == BOUNDL))
                sayNO;
            break;
+       case SPACEL:
+           regtainted = TRUE;
+           /* FALL THROUGH */
        case SPACE:
            if (!nextchar && locinput >= regeol)
                sayNO;
-           if (!isSPACE(nextchar))
+           if (!(OP(scan) == SPACE
+                 ? isSPACE(nextchar) : isSPACE_LC(nextchar)))
                sayNO;
-           nextchar = *++locinput;
+           nextchar = UCHARAT(++locinput);
            break;
+       case NSPACEL:
+           regtainted = TRUE;
+           /* FALL THROUGH */
        case NSPACE:
            if (!nextchar)
                sayNO;
-           if (isSPACE(nextchar))
+           if (OP(scan) == SPACE
+               ? isSPACE(nextchar) : isSPACE_LC(nextchar))
                sayNO;
-           nextchar = *++locinput;
+           nextchar = UCHARAT(++locinput);
            break;
        case DIGIT:
            if (!isDIGIT(nextchar))
                sayNO;
-           nextchar = *++locinput;
+           nextchar = UCHARAT(++locinput);
            break;
        case NDIGIT:
            if (!nextchar && locinput >= regeol)
                sayNO;
            if (isDIGIT(nextchar))
                sayNO;
-           nextchar = *++locinput;
+           nextchar = UCHARAT(++locinput);
            break;
        case REF:
            n = ARG1(scan);  /* which paren pair */
@@ -751,7 +836,7 @@ char *prog;
            if (ln > 1 && memcmp(s, locinput, ln) != 0)
                sayNO;
            locinput += ln;
-           nextchar = *locinput;
+           nextchar = UCHARAT(locinput);
            break;
 
        case NOTHING:
@@ -929,10 +1014,17 @@ char *prog;
            n = 32767;
            scan = NEXTOPER(scan);
          repeat:
-           if (OP(next) == EXACTLY)
-               nextchar = *(OPERAND(next)+1);
+           if (regkind[(U8)OP(next)] == EXACT) {
+               c1 = UCHARAT(OPERAND(next) + 1);
+               if (OP(next) == EXACTF)
+                   c2 = fold[c1];
+               else if (OP(next) == EXACTFL)
+                   c2 = fold_locale[c1];
+               else
+                   c2 = c1;
+           }
            else
-               nextchar = -1000;
+               c1 = c2 = -1000;
            reginput = locinput;
            if (minmod) {
                minmod = 0;
@@ -940,9 +1032,13 @@ char *prog;
                    sayNO;
                while (n >= ln || (n == 32767 && ln > 0)) { /* ln overflow ? */
                    /* If it could work, try it. */
-                   if (nextchar == -1000 || *reginput == nextchar)
+                   if (c1 == -1000 ||
+                       UCHARAT(reginput) == c1 ||
+                       UCHARAT(reginput) == c2)
+                   {
                        if (regmatch(next))
                            sayYES;
+                   }
                    /* Couldn't or didn't -- back up. */
                    reginput = locinput + ln;
                    if (regrepeat(scan, 1)) {
@@ -960,9 +1056,13 @@ char *prog;
                    ln = n;                     /* why back off? */
                while (n >= ln) {
                    /* If it could work, try it. */
-                   if (nextchar == -1000 || *reginput == nextchar)
+                   if (c1 == -1000 ||
+                       UCHARAT(reginput) == c1 ||
+                       UCHARAT(reginput) == c2)
+                   {
                        if (regmatch(next))
                            sayYES;
+                   }
                    /* Couldn't or didn't -- back up. */
                    n--;
                    reginput = locinput + n;
@@ -1043,34 +1143,64 @@ I32 max;
     case SANY:
        scan = loceol;
        break;
-    case EXACTLY:              /* length of string is 1 */
-       opnd++;
-       while (scan < loceol && *opnd == *scan)
+    case EXACT:                /* length of string is 1 */
+       c = UCHARAT(++opnd);
+       while (scan < loceol && UCHARAT(scan) == c)
+           scan++;
+       break;
+    case EXACTF:       /* length of string is 1 */
+       c = UCHARAT(++opnd);
+       while (scan < loceol &&
+              (UCHARAT(scan) == c || UCHARAT(scan) == fold[c]))
+           scan++;
+       break;
+    case EXACTFL:      /* length of string is 1 */
+       regtainted = TRUE;
+       c = UCHARAT(++opnd);
+       while (scan < loceol &&
+              (UCHARAT(scan) == c || UCHARAT(scan) == fold_locale[c]))
            scan++;
        break;
     case ANYOF:
-       c = UCHARAT(scan);
-       while (scan < loceol && !(opnd[c >> 3] & (1 << (c & 7)))) {
+       while (scan < loceol && reginclass(opnd, *scan))
            scan++;
-           c = UCHARAT(scan);
-       }
        break;
     case ALNUM:
        while (scan < loceol && isALNUM(*scan))
            scan++;
        break;
+    case ALNUML:
+       regtainted = TRUE;
+       while (scan < loceol && isALNUM_LC(*scan))
+           scan++;
+       break;
     case NALNUM:
        while (scan < loceol && !isALNUM(*scan))
            scan++;
        break;
+    case NALNUML:
+       regtainted = TRUE;
+       while (scan < loceol && !isALNUM_LC(*scan))
+           scan++;
+       break;
     case SPACE:
        while (scan < loceol && isSPACE(*scan))
            scan++;
        break;
+    case SPACEL:
+       regtainted = TRUE;
+       while (scan < loceol && isSPACE_LC(*scan))
+           scan++;
+       break;
     case NSPACE:
        while (scan < loceol && !isSPACE(*scan))
            scan++;
        break;
+    case NSPACEL:
+       regtainted = TRUE;
+       while (scan < loceol && !isSPACE_LC(*scan))
+           scan++;
+       break;
     case DIGIT:
        while (scan < loceol && isDIGIT(*scan))
            scan++;
@@ -1090,6 +1220,48 @@ I32 max;
 }
 
 /*
+ - regclass - determine if a character falls into a character class
+ */
+
+static bool
+reginclass(p, c)
+register char *p;
+register I32 c;
+{
+    char flags = *p;
+    bool match = FALSE;
+
+    c &= 0xFF;
+    if (p[1 + (c >> 3)] & (1 << (c & 7)))
+       match = TRUE;
+    else if (flags & ANYOF_FOLD) {
+       I32 cf;
+       if (flags & ANYOF_LOCALE) {
+           regtainted = TRUE;
+           cf = fold_locale[c];
+       }
+       else
+           cf = fold[c];
+       if (p[1 + (cf >> 3)] & (1 << (cf & 7)))
+           match = TRUE;
+    }
+
+    if (!match && (flags & ANYOF_ISA)) {
+       regtainted = TRUE;
+
+       if (((flags & ANYOF_ALNUML)  && isALNUM_LC(c))  ||
+           ((flags & ANYOF_NALNUML) && !isALNUM_LC(c)) ||
+           ((flags & ANYOF_SPACEL)  && isSPACE_LC(c))  ||
+           ((flags & ANYOF_NSPACEL) && !isSPACE_LC(c)))
+       {
+           match = TRUE;
+       }
+    }
+
+    return match ^ ((flags & ANYOF_INVERT) != 0);
+}
+
+/*
  - regnext - dig the "next" pointer out of a node
  *
  * [Note, when REGALIGN is defined there are two places in regmatch()
index 018312e..ebd30ad 100644 (file)
--- a/regexp.h
+++ b/regexp.h
@@ -26,7 +26,7 @@ typedef struct regexp {
        char *subend;           /* end of subbase */
        U16 naughty;            /* how exponential is this pattern? */
        char reganch;           /* Internal use only. */
-       char do_folding;        /* do case-insensitive match? */
+       char exec_tainted;      /* Tainted information used by regexec? */
        char program[1];        /* Unwarranted chumminess with compiler. */
 } regexp;
 
diff --git a/sv.c b/sv.c
index 60d41b1..e9580c2 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -1000,8 +1000,10 @@ register SV *sv;
        else
            sprintf(t,"(\"%.127s\")",SvPVX(sv));
     }
-    else if (SvNOKp(sv))
+    else if (SvNOKp(sv)) {
+       NUMERIC_STANDARD();
        sprintf(t,"(%g)",SvNVX(sv));
+    }
     else if (SvIOKp(sv))
        sprintf(t,"(%ld)",(long)SvIVX(sv));
     else
@@ -1187,17 +1189,33 @@ SV *sv;
     int i;
 
     for (s = SvPVX(sv), i = 50; *s && i; s++,i--) {
-       int ch = *s;
-       if (ch & 128 && !isprint(ch)) {
+       int ch = *s & 0xFF;
+       if (ch & 128 && !isPRINT_LC(ch)) {
            *d++ = 'M';
            *d++ = '-';
            ch &= 127;
        }
-       if (isprint(ch))
+       if (ch == '\n') {
+           *d++ = '\\';
+           *d++ = 'n';
+       }
+       else if (ch == '\r') {
+           *d++ = '\\';
+           *d++ = 'r';
+       }
+       else if (ch == '\f') {
+           *d++ = '\\';
+           *d++ = 'f';
+       }
+       else if (ch == '\\') {
+           *d++ = '\\';
+           *d++ = '\\';
+       }
+       else if (isPRINT_LC(ch))
            *d++ = ch;
        else {
            *d++ = '^';
-           *d++ = ch ^ 64;
+           *d++ = toCTRL(ch);
        }
     }
     if (*s) {
@@ -1312,6 +1330,7 @@ register SV *sv;
        if (SvPOKp(sv) && SvLEN(sv)) {
            if (dowarn && !SvIOKp(sv) && !looks_like_number(sv))
                not_a_number(sv);
+           NUMERIC_STANDARD();
            return atof(SvPVX(sv));
        }
        if (SvIOKp(sv))
@@ -1333,6 +1352,7 @@ register SV *sv;
            if (SvPOKp(sv) && SvLEN(sv)) {
                if (dowarn && !SvIOKp(sv) && !looks_like_number(sv))
                    not_a_number(sv);
+               NUMERIC_STANDARD();
                return atof(SvPVX(sv));
            }
            if (SvIOKp(sv))
@@ -1347,7 +1367,9 @@ register SV *sv;
            sv_upgrade(sv, SVt_PVNV);
        else
            sv_upgrade(sv, SVt_NV);
-       DEBUG_c(PerlIO_printf(Perl_debug_log, "0x%lx num(%g)\n",(unsigned long)sv,SvNVX(sv)));
+       DEBUG_c(NUMERIC_STANDARD());
+       DEBUG_c(PerlIO_printf(Perl_debug_log,
+                             "0x%lx num(%g)\n",(unsigned long)sv,SvNVX(sv)));
     }
     else if (SvTYPE(sv) < SVt_PVNV)
        sv_upgrade(sv, SVt_PVNV);
@@ -1359,6 +1381,7 @@ register SV *sv;
     else if (SvPOKp(sv) && SvLEN(sv)) {
        if (dowarn && !SvIOKp(sv) && !looks_like_number(sv))
            not_a_number(sv);
+       NUMERIC_STANDARD();
        SvNVX(sv) = atof(SvPVX(sv));
     }
     else  {
@@ -1367,7 +1390,9 @@ register SV *sv;
        return 0.0;
     }
     SvNOK_on(sv);
-    DEBUG_c(PerlIO_printf(Perl_debug_log, "0x%lx 2nv(%g)\n",(unsigned long)sv,SvNVX(sv)));
+    DEBUG_c(NUMERIC_STANDARD());
+    DEBUG_c(PerlIO_printf(Perl_debug_log,
+                         "0x%lx 2nv(%g)\n",(unsigned long)sv,SvNVX(sv)));
     return SvNVX(sv);
 }
 
@@ -1394,6 +1419,7 @@ STRLEN *lp;
            goto tokensave;
        }
        if (SvNOKp(sv)) {
+           NUMERIC_STANDARD();
            Gconvert(SvNVX(sv), DBL_DIG, 0, tokenbuf);
            goto tokensave;
        }
@@ -1444,6 +1470,7 @@ STRLEN *lp;
        }
        if (SvREADONLY(sv)) {
            if (SvNOKp(sv)) {
+               NUMERIC_STANDARD();
                Gconvert(SvNVX(sv), DBL_DIG, 0, tokenbuf);
                goto tokensave;
            }
@@ -1470,7 +1497,10 @@ STRLEN *lp;
            (void)strcpy(s,"0");
        else
 #endif /*apollo*/
+       {
+           NUMERIC_STANDARD();
            Gconvert(SvNVX(sv), DBL_DIG, 0, s);
+       }
        errno = olderrno;
 #ifdef FIXNEGATIVEZERO
         if (*s == '-' && s[1] == '0' && !s[2])
@@ -1830,7 +1860,7 @@ register SV *sstr;
         * has to be allocated and SvPVX(sstr) has to be freed.
         */
 
-       if (SvTEMP(sstr) &&             /* slated for free anyway? */
+       if ((SvTEMP(sstr) || SvPADTMP(sstr)) && /* slated for free anyway? */
            !(sflags & SVf_OOK))        /* and not involved in OOK hack? */
        {
            if (SvPVX(dstr)) {          /* we know that dtype >= SVt_PV */
@@ -2177,6 +2207,11 @@ I32 namlen;
     case 'l':
        mg->mg_virtual = &vtbl_dbline;
        break;
+#ifdef HAS_STRXFRM
+    case 'o':
+        mg->mg_virtual = &vtbl_collxfrm;
+        break;
+#endif
     case 'P':
        mg->mg_virtual = &vtbl_pack;
        break;
@@ -2617,103 +2652,129 @@ register SV *str2;
 }
 
 I32
-sv_cmp(str1,str2)
+sv_cmp(str1, str2)
 register SV *str1;
 register SV *str2;
 {
+    STRLEN cur1 = 0;
+    char *pv1 = str1 ? SvPV(str1, cur1) : NULL;
+    STRLEN cur2 = 0;
+    char *pv2 = str2 ? SvPV(str2, cur2) : NULL;
     I32 retval;
-    char *pv1;
-    STRLEN cur1;
-    char *pv2;
-    STRLEN cur2;
 
-    if (lc_collate_active) {   /* NOTE: this is the LC_COLLATE branch */
+    if (!cur1)
+       return cur2 ? -1 : 0;
 
-    if (!str1) {
-       pv1 = "";
-       cur1 = 0;
-      } else {
-       pv1 = SvPV(str1, cur1);
+    if (!cur2)
+       return 1;
 
-       {
-         STRLEN cur1x;
-         char * pv1x = mem_collxfrm(pv1, cur1, &cur1x);
+    retval = memcmp((void*)pv1, (void*)pv2, cur1 < cur2 ? cur1 : cur2);
 
-         pv1 = pv1x;
-         cur1 = cur1x;
-       }
-      }
+    if (retval)
+       return retval < 0 ? -1 : 1;
 
-    if (!str2) {
-       pv2 = "";
-       cur2 = 0;
-      } else {
-       pv2 = SvPV(str2, cur2);
+    if (cur1 == cur2)
+       return 0;
+    else
+       return cur1 < cur2 ? -1 : 1;
+}
 
-        {
-         STRLEN cur2x;
-         char * pv2x = mem_collxfrm(pv2, cur2, &cur2x);
+I32
+sv_cmp_locale(sv1, sv2)
+register SV *sv1;
+register SV *sv2;
+{
+#ifdef LC_COLLATE
 
-         pv2 = pv2x;
-         cur2 = cur2x;
-       }
-    }
+    char *pv1, *pv2;
+    STRLEN len1, len2;
+    I32 retval;
 
-      if (!cur1) {
-       Safefree(pv2);
-       return cur2 ? -1 : 0;
-      }
+    if (collation_standard)
+       goto raw_compare;
 
-      if (!cur2) {
-       Safefree(pv1);
-       return 1;
-      }
+    len1 = 0;
+    pv1 = sv1 ? sv_collxfrm(sv1, &len1) : NULL;
+    len2 = 0;
+    pv2 = sv2 ? sv_collxfrm(sv2, &len2) : NULL;
 
-      retval = memcmp((void*)pv1, (void*)pv2, cur1 < cur2 ? cur1 : cur2);
+    if (!pv1 || !len1) {
+       if (pv2 && len2)
+           return -1;
+       else
+           goto raw_compare;
+    }
+    else {
+       if (!pv2 || !len2)
+           return 1;
+    }
 
-      Safefree(pv1);
-      Safefree(pv2);
+    retval = memcmp((void*)pv1, (void*)pv2, len1 < len2 ? len1 : len2);
 
-      if (retval)
+    if (retval)
        return retval < 0 ? -1 : 1;
 
-      if (cur1 == cur2)
-       return 0;
-    else
-       return cur1 < cur2 ? -1 : 1;
+    /*
+     * When the result of collation is equality, that doesn't mean
+     * that there are no differences -- some locales exclude some
+     * characters from consideration.  So to avoid false equalities,
+     * we use the raw string as a tiebreaker.
+     */
 
-    } else {                   /* NOTE: this is the non-LC_COLLATE branch */
+  raw_compare:
+    /* FALL THROUGH */
 
-      if (!str1) {
-       pv1 = "";
-       cur1 = 0;
-      } else
-       pv1 = SvPV(str1, cur1);
+#endif /* LC_COLLATE */
 
-      if (!str2) {
-       pv2 = "";
-       cur2 = 0;
-      } else
-       pv2 = SvPV(str2, cur2);
+    return sv_cmp(sv1, sv2);
+}
 
-    if (!cur1)
-       return cur2 ? -1 : 0;
+#ifdef LC_COLLATE
 
-    if (!cur2)
-       return 1;
+char *
+sv_collxfrm(sv, nxp)
+     SV *sv;
+     STRLEN *nxp;
+{
+    /* Any scalar variable may carry an 'o' magic that contains the
+     * scalar data of the variable transformed to such a format that
+     * a normal memcmp() can be used to compare the data according
+     * to the locale settings. */
 
-      retval = memcmp((void*)pv1, (void*)pv2, cur1 < cur2 ? cur1 : cur2);
+    MAGIC *mg = NULL;
 
-      if (retval)
-       return retval < 0 ? -1 : 1;
+    if (SvMAGICAL(sv)) {
+       mg = mg_find(sv, 'o');
+       if (mg && *(U32*)mg->mg_ptr != collation_ix)
+           mg = NULL;
+    }
 
-      if (cur1 == cur2)
-       return 0;
-    else
-       return cur1 < cur2 ? -1 : 1;
+    if (! mg) {
+       char *s, *xf;
+       STRLEN len, xlen;
+
+       s = SvPV(sv, len);
+       if ((xf = mem_collxfrm(s, len, &xlen))) {
+           sv_magic(sv, 0, 'o', 0, 0);
+           if ((mg = mg_find(sv, 'o'))) {
+               mg->mg_ptr = xf;
+               mg->mg_len = xlen;
+           }
+       }
+    }
+
+    if (mg) {
+       *nxp = mg->mg_len;
+       return mg->mg_ptr + sizeof(collation_ix);
+    }
+    else {
+       *nxp = 0;
+       return NULL;
     }
 }
 
+#endif /* LC_COLLATE */
+
 char *
 sv_gets(sv,fp,append)
 register SV *sv;
@@ -2801,7 +2862,8 @@ I32 append;
        }
        else {
            shortbuffered = 0;
-           SvGROW(sv, append+cnt+2);/* (remembering cnt can be -1) */
+           /* remember that cnt can be negative */
+           SvGROW(sv, append + (cnt <= 0 ? 2 : (cnt + 1)));
        }
     }
     else
@@ -2812,7 +2874,8 @@ I32 append;
        "Screamer: entering, ptr=%d, cnt=%d\n",ptr,cnt));
     DEBUG_P(PerlIO_printf(Perl_debug_log,
        "Screamer: entering: FILE * thinks ptr=%d, cnt=%d, base=%d\n",
-              PerlIO_get_ptr(fp), PerlIO_get_cnt(fp), PerlIO_get_base(fp)));
+              PerlIO_get_ptr(fp), PerlIO_get_cnt(fp), 
+              PerlIO_has_base(fp) ? PerlIO_get_base(fp) : 0));
     for (;;) {
       screamer:
        if (cnt > 0) {
@@ -2846,7 +2909,8 @@ I32 append;
        PerlIO_set_ptrcnt(fp, ptr, cnt); /* deregisterize cnt and ptr */
        DEBUG_P(PerlIO_printf(Perl_debug_log,
            "Screamer: pre: FILE * thinks ptr=%d, cnt=%d, base=%d\n",
-           PerlIO_get_ptr(fp), PerlIO_get_cnt(fp), PerlIO_get_base(fp)));
+           PerlIO_get_ptr(fp), PerlIO_get_cnt(fp), 
+           PerlIO_has_base (fp) ? PerlIO_get_base(fp) : 0));
        /* This used to call 'filbuf' in stdio form, but as that behaves like 
           getc when cnt <= 0 we use PerlIO_getc here to avoid another 
           abstraction.  This may also avoid issues with different named 
@@ -2856,7 +2920,8 @@ I32 append;
        i   = PerlIO_getc(fp);          /* get more characters */
        DEBUG_P(PerlIO_printf(Perl_debug_log,
            "Screamer: post: FILE * thinks ptr=%d, cnt=%d, base=%d\n",
-           PerlIO_get_ptr(fp), PerlIO_get_cnt(fp), PerlIO_get_base(fp)));
+           PerlIO_get_ptr(fp), PerlIO_get_cnt(fp), 
+           PerlIO_has_base (fp) ? PerlIO_get_base(fp) : 0));
        cnt = PerlIO_get_cnt(fp);
        ptr = (STDCHAR*)PerlIO_get_ptr(fp);     /* reregisterize cnt and ptr */
        DEBUG_P(PerlIO_printf(Perl_debug_log,
@@ -2888,7 +2953,8 @@ thats_really_all_folks:
     PerlIO_set_ptrcnt(fp, ptr, cnt);   /* put these back or we're in trouble */
     DEBUG_P(PerlIO_printf(Perl_debug_log,
        "Screamer: end: FILE * thinks ptr=%d, cnt=%d, base=%d\n",
-       PerlIO_get_ptr(fp), PerlIO_get_cnt(fp), PerlIO_get_base(fp)));
+       PerlIO_get_ptr(fp), PerlIO_get_cnt(fp), 
+       PerlIO_has_base (fp) ? PerlIO_get_base(fp) : 0));
     *bp = '\0';
     SvCUR_set(sv, bp - (STDCHAR*)SvPVX(sv));   /* set length */
     DEBUG_P(PerlIO_printf(Perl_debug_log,
@@ -2992,7 +3058,8 @@ register SV *sv;
     while (isALPHA(*d)) d++;
     while (isDIGIT(*d)) d++;
     if (*d) {
-        sv_setnv(sv,atof(SvPVX(sv)) + 1.0);  /* punt */
+       NUMERIC_STANDARD();
+       sv_setnv(sv,atof(SvPVX(sv)) + 1.0);  /* punt */
        return;
     }
     d--;
@@ -3062,7 +3129,8 @@ register SV *sv;
        (void)SvNOK_only(sv);
        return;
     }
-    sv_setnv(sv,atof(SvPVX(sv)) - 1.0);
+    NUMERIC_STANDARD();
+    sv_setnv(sv,atof(SvPVX(sv)) - 1.0);        /* punt */
 }
 
 /* Make a string that will exist for the duration of the expression
@@ -3196,6 +3264,7 @@ newSVsv(old)
 register SV *old;
 {
     register SV *sv;
+    U32 oflags;
 
     if (!old)
        return Nullsv;
@@ -3207,10 +3276,11 @@ register SV *old;
     SvANY(sv) = 0;
     SvREFCNT(sv) = 1;
     SvFLAGS(sv) = 0;
-    if (SvTEMP(old)) {
-       SvTEMP_off(old);
+    oflags = SvFLAGS(old) & (SVs_TEMP|SVs_PADTMP);
+    if (oflags) {
+       SvFLAGS(old) &= ~(SVs_TEMP|SVs_PADTMP);
        sv_setsv(sv,old);
-       SvTEMP_on(old);
+       SvFLAGS(old) |= oflags;
     }
     else
        sv_setsv(sv,old);
@@ -3648,6 +3718,65 @@ SV* sv;
        sv_2mortal(rv);         /* Schedule for freeing later */
 }
 
+IO*
+sv_2io(sv)
+SV *sv;
+{
+    IO* io;
+    GV* gv;
+
+    switch (SvTYPE(sv)) {
+    case SVt_PVIO:
+       io = (IO*)sv;
+       break;
+    case SVt_PVGV:
+       gv = (GV*)sv;
+       io = GvIO(gv);
+       if (!io)
+           croak("Bad filehandle: %s", GvNAME(gv));
+       break;
+    default:
+       if (!SvOK(sv))
+           croak(no_usym, "filehandle");
+       if (SvROK(sv))
+           return sv_2io(SvRV(sv));
+       gv = gv_fetchpv(SvPV(sv,na), FALSE, SVt_PVIO);
+       if (gv)
+           io = GvIO(gv);
+       else
+           io = 0;
+       if (!io)
+           croak("Bad filehandle: %s", SvPV(sv,na));
+       break;
+    }
+    return io;
+}
+
+void
+sv_taint(sv)
+SV *sv;
+{
+    sv_magic((sv), Nullsv, 't', Nullch, 0);
+}
+
+void
+sv_untaint(sv)
+SV *sv;
+{
+    MAGIC *mg = mg_find(sv, 't');
+    if (mg)
+       mg->mg_len &= ~1;
+}
+
+bool
+sv_tainted(sv)
+SV *sv;
+{
+    MAGIC *mg = mg_find(sv, 't');
+    return (mg && ((mg->mg_len & 1)
+                  || (mg->mg_len & 2) && mg->mg_obj == sv));
+}
+
 #ifdef DEBUGGING
 void
 sv_dump(sv)
@@ -3790,8 +3919,10 @@ SV* sv;
     }
     if (type >= SVt_PVIV || type == SVt_IV)
        PerlIO_printf(Perl_debug_log, "  IV = %ld\n", (long)SvIVX(sv));
-    if (type >= SVt_PVNV || type == SVt_NV)
+    if (type >= SVt_PVNV || type == SVt_NV) {
+       NUMERIC_STANDARD();
        PerlIO_printf(Perl_debug_log, "  NV = %.*g\n", DBL_DIG, SvNVX(sv));
+    }
     if (SvROK(sv)) {
        PerlIO_printf(Perl_debug_log, "  RV = 0x%lx\n", (long)SvRV(sv));
        sv_dump(SvRV(sv));
@@ -3916,38 +4047,3 @@ SV* sv;
 {
 }
 #endif
-
-IO*
-sv_2io(sv)
-SV *sv;
-{
-    IO* io;
-    GV* gv;
-
-    switch (SvTYPE(sv)) {
-    case SVt_PVIO:
-       io = (IO*)sv;
-       break;
-    case SVt_PVGV:
-       gv = (GV*)sv;
-       io = GvIO(gv);
-       if (!io)
-           croak("Bad filehandle: %s", GvNAME(gv));
-       break;
-    default:
-       if (!SvOK(sv))
-           croak(no_usym, "filehandle");
-       if (SvROK(sv))
-           return sv_2io(SvRV(sv));
-       gv = gv_fetchpv(SvPV(sv,na), FALSE, SVt_PVIO);
-       if (gv)
-           io = GvIO(gv);
-       else
-           io = 0;
-       if (!io)
-           croak("Bad filehandle: %s", SvPV(sv,na));
-       break;
-    }
-    return io;
-}
-
diff --git a/sv.h b/sv.h
index 1b86ed9..3fb7127 100644 (file)
--- a/sv.h
+++ b/sv.h
@@ -128,8 +128,7 @@ struct io {
 #define SVpfm_COMPILED 0x80000000
 
 #define SVpbm_VALID    0x80000000
-#define SVpbm_CASEFOLD 0x40000000
-#define SVpbm_TAIL     0x20000000
+#define SVpbm_TAIL     0x40000000
 
 #define SVphv_SHAREKEYS 0x20000000     /* keys live on shared string table */
 #define SVphv_LAZYDEL  0x40000000      /* entry in xhv_eiter must be deleted */
@@ -404,10 +403,6 @@ struct xpvio {
 #define SvTAIL_on(sv)          (SvFLAGS(sv) |= SVpbm_TAIL)
 #define SvTAIL_off(sv)         (SvFLAGS(sv) &= ~SVpbm_TAIL)
 
-#define SvCASEFOLD(sv)         (SvFLAGS(sv) & SVpbm_CASEFOLD)
-#define SvCASEFOLD_on(sv)      (SvFLAGS(sv) |= SVpbm_CASEFOLD)
-#define SvCASEFOLD_off(sv)     (SvFLAGS(sv) &= ~SVpbm_CASEFOLD)
-
 #define SvVALID(sv)            (SvFLAGS(sv) & SVpbm_VALID)
 #define SvVALID_on(sv)         (SvFLAGS(sv) |= SVpbm_VALID)
 #define SvVALID_off(sv)                (SvFLAGS(sv) &= ~SVpbm_VALID)
@@ -476,7 +471,11 @@ struct xpvio {
 #define IoTYPE(sv)     ((XPVIO*)  SvANY(sv))->xio_type
 #define IoFLAGS(sv)    ((XPVIO*)  SvANY(sv))->xio_flags
 
-#define SvTAINT(sv) if (tainting && tainted) sv_magic(sv, Nullsv, 't', Nullch, 0)
+#define SvTAINTED(sv)    (SvMAGICAL(sv) && sv_tainted(sv))
+#define SvTAINTED_on(sv)  STMT_START{ if(tainting){sv_taint(sv);}   }STMT_END
+#define SvTAINTED_off(sv) STMT_START{ if(tainting){sv_untaint(sv);} }STMT_END
+
+#define SvTAINT(sv)      STMT_START{ if(tainted){SvTAINTED_on(sv);} }STMT_END
 
 #ifdef CRIPPLED_CC
 
index f8c4c6e..c20fb89 100644 (file)
@@ -53,6 +53,42 @@ a[^-b]c      adc     y       $&      adc
 a[^-b]c        a-c     n       -       -
 a[^]b]c        a]c     n       -       -
 a[^]b]c        adc     y       $&      adc
+\ba\b  a-      y       -       -
+\ba\b  -a      y       -       -
+\ba\b  -a-     y       -       -
+\by\b  xy      n       -       -
+\by\b  yz      n       -       -
+\by\b  xyz     n       -       -
+\Ba\B  a-      n       -       -
+\Ba\B  -a      n       -       -
+\Ba\B  -a-     n       -       -
+\By\b  xy      y       -       -
+\by\B  yz      y       -       -
+\By\B  xyz     y       -       -
+\w     a       y       -       -
+\w     -       n       -       -
+\W     a       n       -       -
+\W     -       y       -       -
+a\sb   a b     y       -       -
+a\sb   a-b     n       -       -
+a\Sb   a b     n       -       -
+a\Sb   a-b     y       -       -
+\d     1       y       -       -
+\d     -       n       -       -
+\D     1       n       -       -
+\D     -       y       -       -
+[\w]   a       y       -       -
+[\w]   -       n       -       -
+[\W]   a       n       -       -
+[\W]   -       y       -       -
+a[\s]b a b     y       -       -
+a[\s]b a-b     n       -       -
+a[\S]b a b     n       -       -
+a[\S]b a-b     y       -       -
+[\d]   1       y       -       -
+[\d]   -       n       -       -
+[\D]   1       n       -       -
+[\D]   -       y       -       -
 ab|cd  abc     y       $&      ab
 ab|cd  abcd    y       $&      ab
 ()ef   def     y       $&-$1   ef-
index e69de29..94a29c1 100755 (executable)
@@ -0,0 +1,156 @@
+#!./perl
+
+print "1..30\n";
+
+chdir('op') || die "sysio.t: cannot look for myself: $!";
+
+open(I, 'sysio.t') || die "sysio.t: cannot find myself: $!";
+
+$x = 'abc';
+
+# should not be able to do negative lengths
+eval { sysread(I, $x, -1) };
+print 'not ' unless ($@ =~ /^Negative length /);
+print "ok 1\n";
+
+# $x should be intact
+print 'not ' unless ($x eq 'abc');
+print "ok 2\n";
+
+# should not be able to read before the buffer
+eval { sysread(I, $x, 1, -4) };
+print 'not ' unless ($x eq 'abc');
+print "ok 3\n";
+
+# $x should be intact
+print 'not ' unless ($x eq 'abc');
+print "ok 4\n";
+
+$a ='0123456789';
+
+# default offset 0
+print 'not ' unless(sysread(I, $a, 3) == 3);
+print "ok 5\n";
+
+# $a should be as follows
+print 'not ' unless ($a eq '#!.');
+print "ok 6\n";
+
+# reading past the buffer should zero pad
+print 'not ' unless(sysread(I, $a, 2, 5) == 2);
+print "ok 7\n";
+
+# the zero pad should be seen now
+print 'not ' unless ($a eq "#!.\0\0/p");
+print "ok 8\n";
+
+# try changing the last two characters of $a
+print 'not ' unless(sysread(I, $a, 3, -2) == 3);
+print "ok 9\n";
+
+# the last two characters of $a should have changed (into three)
+print 'not ' unless ($a eq "#!.\0\0erl");
+print "ok 10\n";
+
+$outfile = 'sysio.out';
+
+open(O, ">$outfile") || die "sysio.t: cannot write $outfile: $!";
+
+select(O); $|=1; select(STDOUT);
+
+# cannot write negative lengths
+eval { syswrite(O, $x, -1) };
+print 'not ' unless ($@ =~ /^Negative length /);
+print "ok 11\n";
+
+# $x still intact
+print 'not ' unless ($x eq 'abc');
+print "ok 12\n";
+
+# $outfile still intact
+print 'not ' if (-s $outfile);
+print "ok 13\n";
+
+# should not be able to write from after the buffer
+eval { syswrite(O, $x, 1, 3) };
+print 'not ' unless ($@ =~ /^Offset outside string /);
+print "ok 14\n";
+
+# $x still intact
+print 'not ' unless ($x eq 'abc');
+print "ok 15\n";
+
+# $outfile still intact
+print 'not ' if (-s $outfile);
+print "ok 16\n";
+
+# should not be able to write from before the buffer
+
+eval { syswrite(O, $x, 1, -4) };
+print 'not ' unless ($@ =~ /^Offset outside string /);
+print "ok 17\n";
+
+# $x still intact
+print 'not ' unless ($x eq 'abc');
+print "ok 18\n";
+
+# $outfile still intact
+print 'not ' if (-s $outfile);
+print "ok 19\n";
+
+# default offset 0
+print 'not ' unless (syswrite(O, $a, 2) == 2);
+print "ok 20\n";
+
+# $a still intact
+print 'not ' unless ($a eq "#!.\0\0erl");
+print "ok 21\n";
+
+# $outfile should have grown now
+print 'not ' unless (-s $outfile == 2);
+print "ok 22\n";
+
+# with offset
+print 'not ' unless (syswrite(O, $a, 2, 5) == 2);
+print "ok 23\n";
+
+# $a still intact
+print 'not ' unless ($a eq "#!.\0\0erl");
+print "ok 24\n";
+
+# $outfile should have grown now
+print 'not ' unless (-s $outfile == 4);
+print "ok 25\n";
+
+# with negative offset and a bit too much length
+print 'not ' unless (syswrite(O, $a, 5, -3) == 3);
+print "ok 26\n";
+
+# $a still intact
+print 'not ' unless ($a eq "#!.\0\0erl");
+print "ok 27\n";
+
+# $outfile should have grown now
+print 'not ' unless (-s $outfile == 7);
+print "ok 28\n";
+
+close(O);
+
+open(I, $outfile) || die "sysio.t: cannot read $outfile: $!";
+
+$b = 'xyz';
+
+# reading too much only return as much as available
+print 'not ' unless (sysread(I, $b, 100) == 7);
+print "ok 29\n";
+# this we should have
+print 'not ' unless ($b eq '#!ererl');
+print "ok 30\n";
+
+close(I);
+
+unlink $outfile;
+
+1;
+
+# eof
diff --git a/taint.c b/taint.c
index be69c0e..d9fac77 100644 (file)
--- a/taint.c
+++ b/taint.c
@@ -8,37 +8,25 @@
 #include "perl.h"
 
 void
-taint_not(s)
-char *s;
-{
-    if (euid != uid)
-        croak("No %s allowed while running setuid", s);
-    if (egid != gid)
-        croak("No %s allowed while running setgid", s);
-}
-
-void
 taint_proper(f, s)
 char *f;
 char *s;
 {
-    if (tainting) {
-       DEBUG_u(PerlIO_printf(PerlIO_stderr(), "%s %d %d %d\n",s,tainted,uid, euid));
-       if (tainted) {
-           char *ug = 0;
-           if (euid != uid)
-               ug = " while running setuid";
-           else if (egid != gid)
-               ug = " while running setgid";
-           else if (tainting)
-               ug = " while running with -T switch";
-           if (ug) {
-               if (!unsafe)
-                   croak(f, s, ug);
-               else if (dowarn)
-                   warn(f, s, ug);
-           }
-       }
+    char *ug;
+
+    if (tainted) {
+       DEBUG_u(PerlIO_printf(PerlIO_stderr(),
+                             "%s %d %d %d\n", s, tainted, uid, euid));
+       if (euid != uid)
+           ug = " while running setuid";
+       else if (egid != gid)
+           ug = " while running setgid";
+       else
+           ug = " while running with -T switch";
+       if (!unsafe)
+           croak(f, s, ug);
+       else if (dowarn)
+           warn(f, s, ug);
     }
 }
 
@@ -46,26 +34,24 @@ void
 taint_env()
 {
     SV** svp;
+    MAGIC *mg = 0;
 
-    if (tainting) {
-       MAGIC *mg = 0;
-       svp = hv_fetch(GvHVn(envgv),"PATH",4,FALSE);
-       if (!svp || *svp == &sv_undef ||
-         ((mg = mg_find(*svp, 't')) && mg->mg_len & 1))
-       {
-           tainted = TRUE;
-           if (mg && MgTAINTEDDIR(mg))
-               taint_proper("Insecure directory in %s%s", "$ENV{PATH}");
-           else
-               taint_proper("Insecure %s%s", "$ENV{PATH}");
-       }
-       svp = hv_fetch(GvHVn(envgv),"IFS",3,FALSE);
-       if (svp && *svp != &sv_undef &&
-         (mg = mg_find(*svp, 't')) && mg->mg_len & 1)
-       {
-           tainted = TRUE;
-           taint_proper("Insecure %s%s", "$ENV{IFS}");
-       }
+    svp = hv_fetch(GvHVn(envgv),"PATH",4,FALSE);
+    if (!svp || *svp == &sv_undef ||
+       ((mg = mg_find(*svp, 't')) && mg->mg_len & 1))
+    {
+       TAINT;
+       if (mg && MgTAINTEDDIR(mg))
+           taint_proper("Insecure directory in %s%s", "$ENV{PATH}");
+       else
+           taint_proper("Insecure %s%s", "$ENV{PATH}");
     }
-}
 
+    svp = hv_fetch(GvHVn(envgv),"IFS",3,FALSE);
+    if (svp && *svp != &sv_undef &&
+       (mg = mg_find(*svp, 't')) && mg->mg_len & 1)
+    {
+       TAINT;
+       taint_proper("Insecure %s%s", "$ENV{IFS}");
+    }
+}
diff --git a/toke.c b/toke.c
index 0ce1749..b4c4d9e 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -50,6 +50,8 @@ static void restore_rsfp _((void *f));
 
 static char *linestart;                /* beg. of most recently read line */
 
+static char pending_ident;     /* pending identifier lookup */
+
 static struct {
     I32 super_state;   /* lexer state to save */
     I32 sub_inwhat;    /* "lex_inwhat" to use */
@@ -189,7 +191,7 @@ char *s;
     }
     else if (multi_close < 32 || multi_close == 127) {
        *tmpbuf = '^';
-       tmpbuf[1] = multi_close ^ 64;
+       tmpbuf[1] = toCTRL(multi_close);
        s = "\\n";
        tmpbuf[2] = '\0';
        s = tmpbuf;
@@ -822,10 +824,8 @@ char *start;
                continue;
            case 'c':
                s++;
-               *d = *s++;
-               if (isLOWER(*d))
-                   *d = toUPPER(*d);
-               *d++ ^= 64;
+               len = *s++;
+               *d++ = toCTRL(len);
                continue;
            case 'b':
                *d++ = '\b';
@@ -1218,6 +1218,59 @@ yylex()
     register I32 tmp;
     STRLEN len;
 
+    if (pending_ident) {
+       char pit = pending_ident;
+       pending_ident = 0;
+
+       if (in_my) {
+           if (strchr(tokenbuf,':'))
+               croak(no_myglob,tokenbuf);
+           yylval.opval = newOP(OP_PADANY, 0);
+           yylval.opval->op_targ = pad_allocmy(tokenbuf);
+           return PRIVATEREF;
+       }
+
+       if (!strchr(tokenbuf,':') && (tmp = pad_findmy(tokenbuf))) {
+           if (last_lop_op == OP_SORT &&
+               tokenbuf[0] == '$' &&
+               (tokenbuf[1] == 'a' || tokenbuf[1] == 'b')
+               && !tokenbuf[2])
+           {
+               for (d = in_eval ? oldoldbufptr : linestart;
+                    d < bufend && *d != '\n';
+                    d++)
+               {
+                   if (strnEQ(d,"<=>",3) || strnEQ(d,"cmp",3)) {
+                       croak("Can't use \"my %s\" in sort comparison",
+                             tokenbuf);
+                   }
+               }
+           }
+
+           yylval.opval = newOP(OP_PADANY, 0);
+           yylval.opval->op_targ = tmp;
+           return PRIVATEREF;
+       }
+
+       /* Force them to make up their mind on "@foo". */
+       if (pit == '@' && lex_state != LEX_NORMAL && !lex_brackets) {
+           GV *gv = gv_fetchpv(tokenbuf+1, FALSE, SVt_PVAV);
+           if (!gv || (tokenbuf[0] == '@') ? !GvAV(gv) : !GvHV(gv)) {
+               char tmpbuf[1024];
+               sprintf(tmpbuf, "Literal %s now requires backslash", tokenbuf);
+               yyerror(tmpbuf);
+           }
+       }
+
+       yylval.opval = (OP*)newSVOP(OP_CONST, 0, newSVpv(tokenbuf+1, 0));
+       yylval.opval->op_private = OPpCONST_ENTERED;
+       gv_fetchpv(tokenbuf+1, in_eval ? GV_ADDMULTI : TRUE,
+                  ((tokenbuf[0] == '$') ? SVt_PV
+                   : (tokenbuf[0] == '@') ? SVt_PVAV
+                   : SVt_PVHV));
+       return WORD;
+    }
+
     switch (lex_state) {
 #ifdef COMMENTARY
     case LEX_NORMAL:           /* Some compilers will produce faster */
@@ -1716,35 +1769,19 @@ yylex()
        Mop(OP_MULTIPLY);
 
     case '%':
-       if (expect != XOPERATOR) {
-           s = scan_ident(s, bufend, tokenbuf + 1, TRUE);
-           if (tokenbuf[1]) {
-               expect = XOPERATOR;
-               tokenbuf[0] = '%';
-               if (in_my) {
-                   if (strchr(tokenbuf,':'))
-                       croak(no_myglob,tokenbuf);
-                   nextval[nexttoke].opval = newOP(OP_PADANY, 0);
-                   nextval[nexttoke].opval->op_targ = pad_allocmy(tokenbuf);
-                   force_next(PRIVATEREF);
-                   TERM('%');
-               }
-               if (!strchr(tokenbuf,':')) {
-                   if (tmp = pad_findmy(tokenbuf)) {
-                       nextval[nexttoke].opval = newOP(OP_PADANY, 0);
-                       nextval[nexttoke].opval->op_targ = tmp;
-                       force_next(PRIVATEREF);
-                       TERM('%');
-                   }
-               }
-               force_ident(tokenbuf + 1, *tokenbuf);
-           }
-           else
-               PREREF('%');
-           TERM('%');
+       if (expect == XOPERATOR) {
+           ++s;
+           Mop(OP_MODULO);
        }
-       ++s;
-       Mop(OP_MODULO);
+       tokenbuf[0] = '%';
+       s = scan_ident(s, bufend, tokenbuf+1, TRUE);
+       if (!tokenbuf[1]) {
+           if (s == bufend)
+               yyerror("Final % should be \\% or %name");
+           PREREF('%');
+       }
+       pending_ident = '%';
+       TERM('%');
 
     case '^':
        s++;
@@ -2027,67 +2064,68 @@ yylex()
        Rop(OP_GT);
 
     case '$':
-       if (s[1] == '#'  && (isALPHA(s[2]) || strchr("_{$:", s[2]))) {
-           s = scan_ident(s+1, bufend, tokenbuf+1, FALSE);
-           if (expect == XOPERATOR) {
-               if (lex_formbrack && lex_brackets == lex_formbrack) {
-                   expect = XTERM;
-                   depcom();
-                   return ','; /* grandfather non-comma-format format */
-               }
-               else
-                   no_op("Array length",s);
+       CLINE;
+
+       if (expect == XOPERATOR) {
+           if (lex_formbrack && lex_brackets == lex_formbrack) {
+               expect = XTERM;
+               depcom();
+               return ','; /* grandfather non-comma-format format */
            }
-           else if (!tokenbuf[1])
+       }
+
+       if (s[1] == '#' && (isALPHA(s[2]) || strchr("_{$:", s[2]))) {
+           if (expect == XOPERATOR)
+               no_op("Array length", bufptr);
+           tokenbuf[0] = '@';
+           s = scan_ident(s+1, bufend, tokenbuf+1, FALSE);
+           if (!tokenbuf[1])
                PREREF(DOLSHARP);
-           if (!strchr(tokenbuf+1,':')) {
-               tokenbuf[0] = '@';
-               if (tmp = pad_findmy(tokenbuf)) {
-                   nextval[nexttoke].opval = newOP(OP_PADANY, 0);
-                   nextval[nexttoke].opval->op_targ = tmp;
-                   expect = XOPERATOR;
-                   force_next(PRIVATEREF);
-                   TOKEN(DOLSHARP);
-               }
-           }
            expect = XOPERATOR;
-           force_ident(tokenbuf+1, *tokenbuf);
+           pending_ident = '#';
            TOKEN(DOLSHARP);
        }
+
+       if (expect == XOPERATOR)
+           no_op("Scalar", bufptr);
+       tokenbuf[0] = '$';
        s = scan_ident(s, bufend, tokenbuf+1, FALSE);
-       if (expect == XOPERATOR) {
-           if (lex_formbrack && lex_brackets == lex_formbrack) {
-               expect = XTERM;
-               depcom();
-               return ',';     /* grandfather non-comma-format format */
-           }
-           else
-               no_op("Scalar",s);
+       if (!tokenbuf[1]) {
+           if (s == bufend)
+               yyerror("Final $ should be \\$ or $name");
+           PREREF('$');
        }
-       if (tokenbuf[1]) {
-           expectation oldexpect = expect;
 
-           /* This kludge not intended to be bulletproof. */
-           if (tokenbuf[1] == '[' && !tokenbuf[2]) {
-               yylval.opval = newSVOP(OP_CONST, 0,
-                                       newSViv((IV)compiling.cop_arybase));
-               yylval.opval->op_private = OPpCONST_ARYBASE;
-               TERM(THING);
-           }
-           tokenbuf[0] = '$';
-           if (dowarn) {
-               char *t;
-               if (*s == '[' && oldexpect != XREF) {
-                   for (t = s+1; isSPACE(*t) || isALNUM(*t) || *t == '$'; t++) ;
+       /* This kludge not intended to be bulletproof. */
+       if (tokenbuf[1] == '[' && !tokenbuf[2]) {
+           yylval.opval = newSVOP(OP_CONST, 0,
+                                  newSViv((IV)compiling.cop_arybase));
+           yylval.opval->op_private = OPpCONST_ARYBASE;
+           TERM(THING);
+       }
+
+       if ((expect != XREF || oldoldbufptr == last_lop) && intuit_more(s)) {
+           char *t;
+           if (*s == '[') {
+               tokenbuf[0] = '@';
+               if (dowarn) {
+                   for(t = s + 1;
+                       isSPACE(*t) || isALNUM(*t) || *t == '$';
+                       t++) ;
                    if (*t++ == ',') {
                        bufptr = skipspace(bufptr);
-                       while (t < bufend && *t != ']') t++;
+                       while (t < bufend && *t != ']')
+                           t++;
                        warn("Multidimensional syntax %.*s not supported",
-                           t-bufptr+1, bufptr);
+                            (t - bufptr) + 1, bufptr);
                    }
                }
-               if (*s == '{' && strEQ(tokenbuf, "$SIG") &&
-                 (t = strchr(s,'}')) && (t = strchr(t,'='))) {
+           }
+           else if (*s == '{') {
+               tokenbuf[0] = '%';
+               if (dowarn && strEQ(tokenbuf+1, "SIG") &&
+                   (t = strchr(s, '}')) && (t = strchr(t, '=')))
+               {
                    char tmpbuf[1024];
                    STRLEN len;
                    for (t++; isSPACE(*t); t++) ;
@@ -2098,114 +2136,43 @@ yylex()
                    }
                }
            }
-           expect = XOPERATOR;
-           if (lex_state == LEX_NORMAL && isSPACE(*s)) {
-               bool islop = (last_lop == oldoldbufptr);
-               s = skipspace(s);
-               if (!islop || last_lop_op == OP_GREPSTART)
-                   expect = XOPERATOR;
-               else if (strchr("$@\"'`q", *s))
-                   expect = XTERM;             /* e.g. print $fh "foo" */
-               else if (strchr("&*<%", *s) && isIDFIRST(s[1]))
-                   expect = XTERM;             /* e.g. print $fh &sub */
-               else if (isDIGIT(*s))
-                   expect = XTERM;             /* e.g. print $fh 3 */
-               else if (*s == '.' && isDIGIT(s[1]))
-                   expect = XTERM;             /* e.g. print $fh .3 */
-               else if (strchr("/?-+", *s) && !isSPACE(s[1]))
-                   expect = XTERM;             /* e.g. print $fh -1 */
-               else if (*s == '<' && s[1] == '<' && !isSPACE(s[2]))
-                   expect = XTERM;             /* print $fh <<"EOF" */
-           }
-           if (in_my) {
-               if (strchr(tokenbuf,':'))
-                   croak(no_myglob,tokenbuf);
-               nextval[nexttoke].opval = newOP(OP_PADANY, 0);
-               nextval[nexttoke].opval->op_targ = pad_allocmy(tokenbuf);
-               force_next(PRIVATEREF);
-           }
-           else if (!strchr(tokenbuf,':')) {
-               if (oldexpect != XREF || oldoldbufptr == last_lop) {
-                   if (intuit_more(s)) {
-                       if (*s == '[')
-                           tokenbuf[0] = '@';
-                       else if (*s == '{')
-                           tokenbuf[0] = '%';
-                   }
-               }
-               if (tmp = pad_findmy(tokenbuf)) {
-                   if (last_lop_op == OP_SORT &&
-                       !tokenbuf[2] && *tokenbuf =='$' &&
-                       tokenbuf[1] <= 'b' && tokenbuf[1] >= 'a')
-                   {
-                       for (d = in_eval ? oldoldbufptr : linestart;
-                           d < bufend && *d != '\n';
-                           d++)
-                       {
-                           if (strnEQ(d,"<=>",3) || strnEQ(d,"cmp",3)) {
-                               croak("Can't use \"my %s\" in sort comparison",
-                                   tokenbuf);
-                           }
-                       }
-                   }
-                   nextval[nexttoke].opval = newOP(OP_PADANY, 0);
-                   nextval[nexttoke].opval->op_targ = tmp;
-                   force_next(PRIVATEREF);
-               }
-               else
-                   force_ident(tokenbuf+1, *tokenbuf);
-           }
-           else
-               force_ident(tokenbuf+1, *tokenbuf);
-       }
-       else {
-           if (s == bufend)
-               yyerror("Final $ should be \\$ or $name");
-           PREREF('$');
        }
+
+       expect = XOPERATOR;
+       if (lex_state == LEX_NORMAL && isSPACE(*s)) {
+           bool islop = (last_lop == oldoldbufptr);
+           s = skipspace(s);
+           if (!islop || last_lop_op == OP_GREPSTART)
+               expect = XOPERATOR;
+           else if (strchr("$@\"'`q", *s))
+               expect = XTERM;         /* e.g. print $fh "foo" */
+           else if (strchr("&*<%", *s) && isIDFIRST(s[1]))
+               expect = XTERM;         /* e.g. print $fh &sub */
+           else if (isDIGIT(*s))
+               expect = XTERM;         /* e.g. print $fh 3 */
+           else if (*s == '.' && isDIGIT(s[1]))
+               expect = XTERM;         /* e.g. print $fh .3 */
+           else if (strchr("/?-+", *s) && !isSPACE(s[1]))
+               expect = XTERM;         /* e.g. print $fh -1 */
+           else if (*s == '<' && s[1] == '<' && !isSPACE(s[2]))
+               expect = XTERM;         /* print $fh <<"EOF" */
+       }
+       pending_ident = '$';
        TOKEN('$');
 
     case '@':
-       s = scan_ident(s, bufend, tokenbuf+1, FALSE);
        if (expect == XOPERATOR)
-           no_op("Array",s);
-       if (tokenbuf[1]) {
-           GV* gv;
-
-           tokenbuf[0] = '@';
-           expect = XOPERATOR;
-           if (in_my) {
-               if (strchr(tokenbuf,':'))
-                   croak(no_myglob,tokenbuf);
-               nextval[nexttoke].opval = newOP(OP_PADANY, 0);
-               nextval[nexttoke].opval->op_targ = pad_allocmy(tokenbuf);
-               force_next(PRIVATEREF);
-               TERM('@');
-           }
-           else if (!strchr(tokenbuf,':')) {
-               if (intuit_more(s)) {
-                   if (*s == '{')
-                       tokenbuf[0] = '%';
-               }
-               if (tmp = pad_findmy(tokenbuf)) {
-                   nextval[nexttoke].opval = newOP(OP_PADANY, 0);
-                   nextval[nexttoke].opval->op_targ = tmp;
-                   force_next(PRIVATEREF);
-                   TERM('@');
-               }
-           }
-
-           /* Force them to make up their mind on "@foo". */
-           if (lex_state != LEX_NORMAL && !lex_brackets &&
-                   ( !(gv = gv_fetchpv(tokenbuf+1, FALSE, SVt_PVAV)) ||
-                     (*tokenbuf == '@'
-                       ? !GvAV(gv)
-                       : !GvHV(gv) )))
-           {
-               char tmpbuf[1024];
-               sprintf(tmpbuf, "Literal @%s now requires backslash",tokenbuf+1);
-               yyerror(tmpbuf);
-           }
+           no_op("Array", s);
+       tokenbuf[0] = '@';
+       s = scan_ident(s, bufend, tokenbuf+1, FALSE);
+       if (!tokenbuf[1]) {
+           if (s == bufend)
+               yyerror("Final @ should be \\@ or @name");
+           PREREF('@');
+       }
+       if ((expect != XREF || oldoldbufptr == last_lop) && intuit_more(s)) {
+           if (*s == '{')
+               tokenbuf[0] = '%';
 
            /* Warn about @ where they meant $. */
            if (dowarn) {
@@ -2221,13 +2188,8 @@ yylex()
                    }
                }
            }
-           force_ident(tokenbuf+1, *tokenbuf);
-       }
-       else {
-           if (s == bufend)
-               yyerror("Final @ should be \\@ or @name");
-           PREREF('@');
        }
+       pending_ident = '@';
        TERM('@');
 
     case '/':                  /* may either be division or pattern */
@@ -4291,7 +4253,8 @@ I32 ck_uni;
        *d = *s++;
     d[1] = '\0';
     if (*d == '^' && *s && (isUPPER(*s) || strchr("[\\]^_?", *s))) {
-       *d = *s++ ^ 64;
+       *d = toCTRL(*s);
+       s++;
     }
     if (bracket) {
        if (isSPACE(s[-1])) {
@@ -4341,10 +4304,8 @@ void pmflag(pmfl,ch)
 U16* pmfl;
 int ch;
 {
-    if (ch == 'i') {
-       sawi = TRUE;
+    if (ch == 'i')
        *pmfl |= PMf_FOLD;
-    }
     else if (ch == 'g')
        *pmfl |= PMf_GLOBAL;
     else if (ch == 'o')
@@ -4371,14 +4332,16 @@ char *start;
        lex_stuff = Nullsv;
        croak("Search pattern not terminated");
     }
+
     pm = (PMOP*)newPMOP(OP_MATCH, 0);
     if (multi_open == '?')
        pm->op_pmflags |= PMf_ONCE;
-
+    if (hints & HINT_LOCALE)
+       pm->op_pmflags |= PMf_LOCALE;
     while (*s && strchr("iogmsx", *s))
        pmflag(&pm->op_pmflags,*s++);
-
     pm->op_pmpermflags = pm->op_pmflags;
+
     lex_op = (OP*)pm;
     yylval.ival = OP_MATCH;
     return s;
@@ -4456,8 +4419,6 @@ register PMOP *pm;
        ) {
        if (!(pm->op_pmregexp->reganch & ROPT_ANCH))
            pm->op_pmflags |= PMf_SCANFIRST;
-       else if (pm->op_pmflags & PMf_FOLD)
-           return;
        pm->op_pmshort = SvREFCNT_inc(pm->op_pmregexp->regstart);
        pm->op_pmslen = SvCUR(pm->op_pmshort);
     }
@@ -4916,6 +4877,7 @@ char *start;
        }
        *d = '\0';
        sv = NEWSV(92,0);
+       NUMERIC_STANDARD();
        value = atof(tokenbuf);
        tryi32 = I_32(value);
        if (!floatit && (double)tryi32 == value)
@@ -5100,7 +5062,7 @@ char *s;
            (void)strcpy(tname,"within string");
     }
     else if (yychar < 32)
-       (void)sprintf(tname,"next char ^%c",yychar+64);
+       (void)sprintf(tname,"next char ^%c",toCTRL(yychar));
     else
        (void)sprintf(tname,"next char %c",yychar);
     (void)sprintf(buf, "%s at %s line %d, %s\n",
diff --git a/util.c b/util.c
index 82e6d0f..22bda3f 100644 (file)
--- a/util.c
+++ b/util.c
@@ -396,20 +396,128 @@ char *lend;
     return Nullch;
 }
 
-/* Initialize the fold[] array. */
+#ifdef LC_CTYPE
+
+/*
+ * Set up for a new ctype locale.
+ */
+void
+perl_new_ctype(newctype)
+    char *newctype;
+{
+    int i;
+
+    for (i = 0; i < 256; i++) {
+       if (isUPPER_LC(i))
+           fold_locale[i] = toLOWER_LC(i);
+       else if (isLOWER_LC(i))
+           fold_locale[i] = toUPPER_LC(i);
+       else
+           fold_locale[i] = i;
+    }
+}
+
+#endif /* LC_CTYPE */
+
+#ifdef LC_COLLATE
+
+/*
+ * Set up for a new collation locale.
+ */
+void
+perl_new_collate(newcoll)
+    char *newcoll;
+{
+    if (! newcoll) {
+       if (collation_name) {
+           ++collation_ix;
+           Safefree(collation_name);
+           collation_name = NULL;
+           collation_standard = TRUE;
+#ifdef HAS_STRXFRM
+           collxfrm_base = 0;
+           collxfrm_mult = 2;
+#endif /* HAS_STRXFRM */
+       }
+       return;
+    }
+
+    if (! collation_name || strNE(collation_name, newcoll)) {
+       ++collation_ix;
+       Safefree(collation_name);
+       collation_name = savepv(newcoll);
+       collation_standard = strEQ(newcoll, "C");
+
+#ifdef HAS_STRXFRM
+       {
+         /*  2: at most so many chars ('a', 'b'). */
+         /* 50: surely no system expands a char more. */
+#define XFRMBUFSIZE  (2 * 50)
+         char xbuf[XFRMBUFSIZE];
+         Size_t fa = strxfrm(xbuf, "a",  XFRMBUFSIZE);
+         Size_t fb = strxfrm(xbuf, "ab", XFRMBUFSIZE);
+         SSize_t mult = fb - fa;
+         if (mult < 1)
+             croak("strxfrm() gets absurd");
+         collxfrm_base = (fa > mult) ? (fa - mult) : 0;
+         collxfrm_mult = mult;
+       }
+#endif /* HAS_STRXFRM */
+    }
+}
+
+#endif /* LC_COLLATE */
+
+#ifdef LC_NUMERIC
+
+/*
+ * Set up for a new numeric locale.
+ */
+void
+perl_new_numeric(newnum)
+    char *newnum;
+{
+    if (! newnum) {
+       if (numeric_name) {
+           Safefree(numeric_name);
+           numeric_name = NULL;
+           numeric_standard = TRUE;
+           numeric_local = TRUE;
+       }
+       return;
+    }
+
+    if (! numeric_name || strNE(numeric_name, newnum)) {
+       Safefree(numeric_name);
+       numeric_name = savepv(newnum);
+       numeric_standard = strEQ(newnum, "C");
+       numeric_local = TRUE;
+    }
+}
+
 void
-perl_init_fold()
+perl_numeric_standard()
 {
-  int i;
+    if (! numeric_standard) {
+       setlocale(LC_NUMERIC, "C");
+       numeric_standard = TRUE;
+       numeric_local = FALSE;
+    }
+}
 
-  for (i = 0; i < 256; i++) {
-    if (isUPPER(i)) fold[i] = toLOWER(i);
-    else if (isLOWER(i)) fold[i] = toUPPER(i);
-    else fold[i] = i;
-  }
+void
+perl_numeric_local()
+{
+    if (! numeric_local) {
+       setlocale(LC_NUMERIC, numeric_name);
+       numeric_standard = FALSE;
+       numeric_local = TRUE;
+    }
 }
 
-/* Initialize locale (and the fold[] array).*/
+#endif /* LC_NUMERIC */
+
+/* Initialize locale awareness */
 int
 perl_init_i18nl10n(printwarn)  
     int printwarn;
@@ -420,28 +528,47 @@ perl_init_i18nl10n(printwarn)
      *    0 = fallback to C locale,
      *   -1 = fallback to C locale failed
      */
-#if defined(HAS_SETLOCALE)
-    char * lc_all   = getenv("LC_ALL");
-    char * lc_ctype = getenv("LC_CTYPE");
-    char * lc_collate = getenv("LC_COLLATE");
-    char * lang       = getenv("LANG");
-    int setlocale_failure = 0;
-
-#define SETLOCALE_LC_CTYPE   0x01
-#define SETLOCALE_LC_COLLATE 0x02
-    
+
+#ifdef HAS_SETLOCALE
+
+    char *lc_all     = getenv("LC_ALL");
+    char *lang       = getenv("LANG");
 #ifdef LC_CTYPE
-    if (setlocale(LC_CTYPE, "")   == 0)
-      setlocale_failure |= SETLOCALE_LC_CTYPE;
-#endif
+    char *lc_ctype   = getenv("LC_CTYPE");
+    char *curctype   = NULL;
+#endif /* LC_CTYPE */
+#ifdef LC_COLLATE
+    char *lc_collate = getenv("LC_COLLATE");
+    char *curcoll    = NULL;
+#endif /* LC_COLLATE */
+#ifdef LC_NUMERIC
+    char *lc_numeric = getenv("LC_NUMERIC");
+    char *curnum     = NULL;
+#endif /* LC_NUMERIC */
+    bool setlocale_failure = FALSE;
+    char *subloc;
+
+#ifdef LC_ALL
+    subloc = NULL;
+    if (! setlocale(LC_ALL, ""))
+       setlocale_failure = TRUE;
+#else
+    subloc = "";
+#endif /* LC_ALL */
 
+#ifdef LC_CTYPE
+    if (! (curctype = setlocale(LC_CTYPE, subloc)))
+       setlocale_failure = TRUE;
+#endif /* LC_CTYPE */
 #ifdef LC_COLLATE
-    if (setlocale(LC_COLLATE, "") == 0)
-      setlocale_failure |= SETLOCALE_LC_COLLATE;
-    else
-      lc_collate_active = 1;
-#endif
-    
+    if (! (curcoll = setlocale(LC_COLLATE, subloc)))
+       setlocale_failure = TRUE;
+#endif /* LC_COLLATE */
+#ifdef LC_NUMERIC
+    if (! (curnum = setlocale(LC_NUMERIC, subloc)))
+       setlocale_failure = TRUE;
+#endif /* LC_NUMERIC */
+
     if (setlocale_failure && (lc_all || lang)) {
        char *perl_badlang;
 
@@ -449,146 +576,183 @@ perl_init_i18nl10n(printwarn)
            printwarn &&
            (!(perl_badlang = getenv("PERL_BADLANG")) || atoi(perl_badlang))) {
          
-         PerlIO_printf(PerlIO_stderr(),
-                       "perl: warning: Setting locale failed for the categories:\n\t");
-#ifdef LC_CTYPE
-         if (setlocale_failure & SETLOCALE_LC_CTYPE)
            PerlIO_printf(PerlIO_stderr(),
-                         "LC_CTYPE ");
-#endif
+              "perl: warning: Setting locale failed for the categories:\n\t");
+#ifdef LC_CTYPE
+           if (! curctype)
+               PerlIO_printf(PerlIO_stderr(), "LC_CTYPE ");
+#endif /* LC_CTYPE */
 #ifdef LC_COLLATE
-         if (setlocale_failure & SETLOCALE_LC_COLLATE)
+           if (! curcoll)
+               PerlIO_printf(PerlIO_stderr(), "LC_COLLATE ");
+#endif /* LC_COLLATE */
+#ifdef LC_NUMERIC
+           if (! curnum)
+               PerlIO_printf(PerlIO_stderr(), "LC_NUMERIC ");
+#endif /* LC_NUMERIC */
+           PerlIO_printf(PerlIO_stderr(), "\n");
+
            PerlIO_printf(PerlIO_stderr(),
-                         "LC_COLLATE ");
-#endif
-         PerlIO_printf(PerlIO_stderr(),
-                       "\n");
+               "perl: warning: Please check that your locale settings:\n");
 
            PerlIO_printf(PerlIO_stderr(),
-                       "perl: warning: Please check that your locale settings:\n");
-
-         PerlIO_printf(PerlIO_stderr(),
-                       "\tLC_ALL = %c%s%c,\n",
-                       lc_all ? '"' : '(',
-                       lc_all ? lc_all : "unset",
-                         lc_all ? '"' : ')'
-             );
+                         "\tLC_ALL = %c%s%c,\n",
+                         lc_all ? '"' : '(',
+                         lc_all ? lc_all : "unset",
+                         lc_all ? '"' : ')');
 #ifdef LC_CTYPE
-         if (setlocale_failure & SETLOCALE_LC_CTYPE)
-           PerlIO_printf(PerlIO_stderr(),
-                         "\tLC_CTYPE = %c%s%c,\n",
-                         lc_ctype ? '"' : '(',
-                         lc_ctype ? lc_ctype : "unset",
-                         lc_ctype ? '"' : ')'
-                         );
-#endif
+           if (! curctype)
+               PerlIO_printf(PerlIO_stderr(),
+                             "\tLC_CTYPE = %c%s%c,\n",
+                             lc_ctype ? '"' : '(',
+                             lc_ctype ? lc_ctype : "unset",
+                             lc_ctype ? '"' : ')');
+#endif /* LC_CTYPE */
 #ifdef LC_COLLATE
-         if (setlocale_failure & SETLOCALE_LC_COLLATE)
+           if (! curcoll)
+               PerlIO_printf(PerlIO_stderr(),
+                             "\tLC_COLLATE = %c%s%c,\n",
+                             lc_collate ? '"' : '(',
+                             lc_collate ? lc_collate : "unset",
+                             lc_collate ? '"' : ')');
+#endif /* LC_COLLATE */
+#ifdef LC_NUMERIC
+           if (! curcoll)
+               PerlIO_printf(PerlIO_stderr(),
+                             "\tLC_NUMERIC = %c%s%c,\n",
+                             lc_numeric ? '"' : '(',
+                             lc_numeric ? lc_numeric : "unset",
+                             lc_numeric ? '"' : ')');
+#endif /* LC_NUMERIC */
            PerlIO_printf(PerlIO_stderr(),
-                         "\tLC_COLLATE = %c%s%c,\n",
-                         lc_collate ? '"' : '(',
-                         lc_collate ? lc_collate : "unset",
-                         lc_collate ? '"' : ')'
-                         );
-#endif
-         PerlIO_printf(PerlIO_stderr(),
-                       "\tLANG = %c%s%c\n",
-                       lang ? '"' : ')',
-                       lang ? lang : "unset",
-                       lang ? '"' : ')'
-                       );
+                         "\tLANG = %c%s%c\n",
+                         lang ? '"' : ')',
+                         lang ? lang : "unset",
+                         lang ? '"' : ')');
 
-         PerlIO_printf(PerlIO_stderr(),
-                       "    are supported and installed on your system.\n");
+           PerlIO_printf(PerlIO_stderr(),
+                         "    are supported and installed on your system.\n");
 
-       ok = 0;
-         
+           ok = 0;
        }
+
 #ifdef LC_ALL
        if (setlocale_failure) {
-         PerlIO_printf(PerlIO_stderr(),
-                       "perl: warning: Falling back to the \"C\" locale.\n");
-         if (setlocale(LC_ALL, "C") == NULL) {
-           ok = -1;
            PerlIO_printf(PerlIO_stderr(),
-                         "perl: warning: Failed to fall back to the \"C\" locale.\n");
-    }
-    }
-#else
+                       "perl: warning: Falling back to the \"C\" locale.\n");
+           if (setlocale(LC_ALL, "C")) {
+#ifdef LC_CTYPE
+               curctype = "C";
+#endif /* LC_CTYPE */
+#ifdef LC_COLLATE
+               curcoll = "C";
+#endif /* LC_COLLATE */
+#ifdef LC_NUMERIC
+               curnum = "C";
+#endif /* LC_NUMERIC */
+           }
+           else {
+               PerlIO_printf(PerlIO_stderr(),
+                 "perl: warning: Failed to fall back to the \"C\" locale.\n");
+               ok = -1;
+           }
+       }
+#else /* ! LC_ALL */
        PerlIO_printf(PerlIO_stderr(),
-                     "perl: warning: Cannot fall back to the \"C\" locale.\n");
-#endif
+                  "perl: warning: Cannot fall back to the \"C\" locale.\n");
+#endif /* ! LC_ALL */
     }
 
-    if (setlocale_failure & SETLOCALE_LC_CTYPE == 0)
-      perl_init_fold();
+#ifdef LC_CTYPE
+    perl_new_ctype(curctype);
+#endif /* LC_NUMERIC */
+
+#ifdef LC_COLLATE
+    perl_new_collate(curcoll);
+#endif /* LC_NUMERIC */
+
+#ifdef LC_NUMERIC
+    perl_new_numeric(curnum);
+#endif /* LC_NUMERIC */
 
 #endif /* #if defined(HAS_SETLOCALE) */
 
     return ok;
 }
 
-char *
-mem_collxfrm(m, n, nx) /* mem_collxfrm() does strxfrm() for (data,size) */
-     const char *m;    /* "strings", that is, transforms normal eight-bit */
-     const Size_t n;   /* data into a format that can be memcmp()ed to get */
-     Size_t * nx;      /* 'the right' result for each locale. */
-{                      /* Uses strxfrm() but handles embedded NULs. */
-  char * mx = 0;
+/* Backwards compatibility. */
+int
+perl_init_i18nl14n(printwarn)  
+    int printwarn;
+{
+    perl_init_i18nl10n(printwarn);
+}
 
 #ifdef HAS_STRXFRM
-  Size_t ma;
-
-  /* the expansion factor of 16 has been seen with strxfrm() */
-  ma = (lc_collate_active ? 16 : 1) * n + 1;
-
-#define RENEW_mx()                     \
-  do {                                 \
-       ma = 2 * ma + 1;                \
-       Renew(mx, ma, char);            \
-       if (mx == 0)                    \
-         goto out;                     \
-  } while (0)
-
-  New(171, mx, ma, char);
-
-  if (mx) {
-    Size_t xc, dx;
-    int xok;
-
-    for (*nx = 0, xc = 0; xc < n; ) {
-      if (m[xc] == 0)
-       do {
-         if (*nx == ma)
-           RENEW_mx();
-         mx[*nx++] = m[xc++];
-       } while (xc < n && m[xc] == 0);
-      else {
-       do {
-         dx = strxfrm(mx + *nx, m + xc, ma - *nx);
-         if (dx + *nx > ma) {
-           RENEW_mx();
-           xok = 0;
-         } else
-           xok = 1;
-       } while (!xok);
-       xc += strlen(mx + *nx);
-       *nx += dx;
-      }
-    }
-  }
-
-out:
 
-#endif /* HAS_STRXFRM */
+/*
+ * mem_collxfrm() is a bit like strxfrm() but with two important
+ * differences. First, it handles embedded NULs. Second, it allocates
+ * a bit more memory than needed for the transformed data itself.
+ * The real transformed data begins at offset sizeof(collationix).
+ * Please see sv_collxfrm() to see how this is used.
+ */
+char *
+mem_collxfrm(s, len, xlen)
+     const char *s;
+     STRLEN len;
+     STRLEN *xlen;
+{
+    char *xbuf;
+    STRLEN xalloc, xin, xout;
+
+    /* the first sizeof(collationix) bytes are used by sv_collxfrm(). */
+    /* the +1 is for the terminating NUL. */
+
+    xalloc = sizeof(collation_ix) + collxfrm_base + (collxfrm_mult * len) + 1;
+    New(171, xbuf, xalloc, char);
+    if (! xbuf)
+       goto bad;
+
+    *(U32*)xbuf = collation_ix;
+    xout = sizeof(collation_ix);
+    for (xin = 0; xin < len; ) {
+       SSize_t xused;
+
+       for (;;) {
+           xused = strxfrm(xbuf + xout, s + xin, xalloc - xout);
+           if (xused == -1)
+               goto bad;
+           if (xused < xalloc - xout)
+               break;
+           xalloc = (2 * xalloc) + 1;
+           Renew(xbuf, xalloc, char);
+           if (! xbuf)
+               goto bad;
+       }
+
+       xin += strlen(s + xin) + 1;
+       xout += xused;
 
-  return mx;
+       /* Embedded NULs are understood but silently skipped
+        * because they make no sense in locale collation. */
+    }
+
+    xbuf[xout] = '\0';
+    *xlen = xout - sizeof(collation_ix);
+    return xbuf;
+
+  bad:
+    Safefree(xbuf);
+    *xlen = 0;
+    return NULL;
 }
 
+#endif /* HAS_STRXFRM */
+
 void
-fbm_compile(sv, iflag)
+fbm_compile(sv)
 SV *sv;
-I32 iflag;
 {
     register unsigned char *s;
     register unsigned char *table;
@@ -608,47 +772,19 @@ I32 iflag;
     i = 0;
     while (s >= (unsigned char*)(SvPVX(sv)))
     {
-       if (table[*s] == len) {
-#ifndef pdp11
-           if (iflag)
-               table[*s] = table[fold[*s]] = i;
-#else
-           if (iflag) {
-               I32 j;
-               j = fold[*s];
-               table[j] = i;
-               table[*s] = i;
-           }
-#endif /* pdp11 */
-           else
-               table[*s] = i;
-       }
+       if (table[*s] == len)
+           table[*s] = i;
        s--,i++;
     }
     sv_upgrade(sv, SVt_PVBM);
-    sv_magic(sv, Nullsv, 'B', Nullch, 0);                      /* deep magic */
+    sv_magic(sv, Nullsv, 'B', Nullch, 0);      /* deep magic */
     SvVALID_on(sv);
 
     s = (unsigned char*)(SvPVX(sv));           /* deeper magic */
-    if (iflag) {
-       register U32 tmp, foldtmp;
-       SvCASEFOLD_on(sv);
-       for (i = 0; i < len; i++) {
-           tmp=freq[s[i]];
-           foldtmp=freq[fold[s[i]]];
-           if (tmp < frequency && foldtmp < frequency) {
-               rarest = i;
-               /* choose most frequent among the two */
-               frequency = (tmp > foldtmp) ? tmp : foldtmp;
-           }
-       }
-    }
-    else {
-       for (i = 0; i < len; i++) {
-           if (freq[s[i]] < frequency) {
-               rarest = i;
-               frequency = freq[s[i]];
-           }
+    for (i = 0; i < len; i++) {
+       if (freq[s[i]] < frequency) {
+           rarest = i;
+           frequency = freq[s[i]];
        }
     }
     BmRARE(sv) = s[rarest];
@@ -683,91 +819,50 @@ SV *littlestr;
        if (littlelen > bigend - big)
            return Nullch;
        little = (unsigned char*)SvPVX(littlestr);
-       if (SvCASEFOLD(littlestr)) {    /* oops, fake it */
-           big = bigend - littlelen;           /* just start near end */
-           if (bigend[-1] == '\n' && little[littlelen-1] != '\n')
-               big--;
-       }
-       else {
-           s = bigend - littlelen;
+       s = bigend - littlelen;
+       if (*s == *little && memcmp((char*)s,(char*)little,littlelen)==0)
+           return (char*)s;            /* how sweet it is */
+       else if (bigend[-1] == '\n' && little[littlelen-1] != '\n'
+                && s > big) {
+           s--;
            if (*s == *little && memcmp((char*)s,(char*)little,littlelen)==0)
-               return (char*)s;                /* how sweet it is */
-           else if (bigend[-1] == '\n' && little[littlelen-1] != '\n'
-             && s > big) {
-                   s--;
-               if (*s == *little && memcmp((char*)s,(char*)little,littlelen)==0)
-                   return (char*)s;
-           }
-           return Nullch;
+               return (char*)s;
        }
+       return Nullch;
     }
     table = (unsigned char*)(SvPVX(littlestr) + littlelen + 1);
     if (--littlelen >= bigend - big)
        return Nullch;
     s = big + littlelen;
     oldlittle = little = table - 2;
-    if (SvCASEFOLD(littlestr)) {       /* case insensitive? */
-       if (s < bigend) {
-         top1:
-           /*SUPPRESS 560*/
-           if (tmp = table[*s]) {
+    if (s < bigend) {
+      top2:
+       /*SUPPRESS 560*/
+       if (tmp = table[*s]) {
 #ifdef POINTERRIGOR
-               if (bigend - s > tmp) {
-                   s += tmp;
-                   goto top1;
-               }
+           if (bigend - s > tmp) {
+               s += tmp;
+               goto top2;
+           }
 #else
-               if ((s += tmp) < bigend)
-                   goto top1;
+           if ((s += tmp) < bigend)
+               goto top2;
 #endif
-               return Nullch;
-           }
-           else {
-               tmp = littlelen;        /* less expensive than calling strncmp() */
-               olds = s;
-               while (tmp--) {
-                   if (*--s == *--little || fold[*s] == *little)
-                       continue;
-                   s = olds + 1;       /* here we pay the price for failure */
-                   little = oldlittle;
-                   if (s < bigend)     /* fake up continue to outer loop */
-                       goto top1;
-                   return Nullch;
-               }
-               return (char *)s;
-           }
+           return Nullch;
        }
-    }
-    else {
-       if (s < bigend) {
-         top2:
-           /*SUPPRESS 560*/
-           if (tmp = table[*s]) {
-#ifdef POINTERRIGOR
-               if (bigend - s > tmp) {
-                   s += tmp;
-                   goto top2;
-               }
-#else
-               if ((s += tmp) < bigend)
+       else {
+           tmp = littlelen;    /* less expensive than calling strncmp() */
+           olds = s;
+           while (tmp--) {
+               if (*--s == *--little)
+                   continue;
+               s = olds + 1;   /* here we pay the price for failure */
+               little = oldlittle;
+               if (s < bigend) /* fake up continue to outer loop */
                    goto top2;
-#endif
                return Nullch;
            }
-           else {
-               tmp = littlelen;        /* less expensive than calling strncmp() */
-               olds = s;
-               while (tmp--) {
-                   if (*--s == *--little)
-                       continue;
-                   s = olds + 1;       /* here we pay the price for failure */
-                   little = oldlittle;
-                   if (s < bigend)     /* fake up continue to outer loop */
-                       goto top2;
-                   return Nullch;
-               }
-               return (char *)s;
-           }
+           return (char *)s;
        }
     }
     return Nullch;
@@ -800,96 +895,66 @@ SV *littlestr;
            return Nullch;
     }
 #ifdef POINTERRIGOR
-    if (SvCASEFOLD(littlestr)) {       /* case insignificant? */
-       do {
-           if (big[pos-previous] != first && big[pos-previous] != fold[first])
-               continue;
-           for (x=big+pos+1-previous,s=little; s < littleend; /**/ ) {
-               if (x >= bigend)
-                   return Nullch;
-               if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
-                   s--;
-                   break;
-               }
-           }
-           if (s == littleend)
-               return (char *)(big+pos-previous);
-       } while (
-               pos += screamnext[pos]  /* does this goof up anywhere? */
-           );
-    }
-    else {
-       do {
-           if (big[pos-previous] != first)
-               continue;
-           for (x=big+pos+1-previous,s=little; s < littleend; /**/ ) {
-               if (x >= bigend)
-                   return Nullch;
-               if (*s++ != *x++) {
-                   s--;
-                   break;
-               }
+    do {
+       if (big[pos-previous] != first)
+           continue;
+       for (x=big+pos+1-previous,s=little; s < littleend; /**/ ) {
+           if (x >= bigend)
+               return Nullch;
+           if (*s++ != *x++) {
+               s--;
+               break;
            }
-           if (s == littleend)
-               return (char *)(big+pos-previous);
-       } while ( pos += screamnext[pos] );
-    }
+       }
+       if (s == littleend)
+           return (char *)(big+pos-previous);
+    } while ( pos += screamnext[pos] );
 #else /* !POINTERRIGOR */
     big -= previous;
-    if (SvCASEFOLD(littlestr)) {       /* case insignificant? */
-       do {
-           if (big[pos] != first && big[pos] != fold[first])
-               continue;
-           for (x=big+pos+1,s=little; s < littleend; /**/ ) {
-               if (x >= bigend)
-                   return Nullch;
-               if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
-                   s--;
-                   break;
-               }
-           }
-           if (s == littleend)
-               return (char *)(big+pos);
-       } while (
-               pos += screamnext[pos]  /* does this goof up anywhere? */
-           );
-    }
-    else {
-       do {
-           if (big[pos] != first)
-               continue;
-           for (x=big+pos+1,s=little; s < littleend; /**/ ) {
-               if (x >= bigend)
-                   return Nullch;
-               if (*s++ != *x++) {
-                   s--;
-                   break;
-               }
+    do {
+       if (big[pos] != first)
+           continue;
+       for (x=big+pos+1,s=little; s < littleend; /**/ ) {
+           if (x >= bigend)
+               return Nullch;
+           if (*s++ != *x++) {
+               s--;
+               break;
            }
-           if (s == littleend)
-               return (char *)(big+pos);
-       } while (
-               pos += screamnext[pos]
-           );
-    }
+       }
+       if (s == littleend)
+           return (char *)(big+pos);
+    } while ( pos += screamnext[pos] );
 #endif /* POINTERRIGOR */
     return Nullch;
 }
 
 I32
-ibcmp(a,b,len)
-register U8 *a;
-register U8 *b;
+ibcmp(s1, s2, len)
+char *s1, *s2;
 register I32 len;
 {
+    register U8 *a = (U8 *)s1;
+    register U8 *b = (U8 *)s2;
     while (len--) {
-       if (*a == *b) {
-           a++,b++;
-           continue;
-       }
-       if (fold[*a++] == *b++)
-           continue;
-       return 1;
+       if (*a != *b && *a != fold[*b])
+           return 1;
+       a++,b++;
+    }
+    return 0;
+}
+
+I32
+ibcmp_locale(s1, s2, len)
+char *s1, *s2;
+register I32 len;
+{
+    register U8 *a = (U8 *)s1;
+    register U8 *b = (U8 *)s2;
+    while (len--) {
+       if (*a != *b && *a != fold_locale[*b])
+           return 1;
+       a++,b++;
     }
     return 0;
 }
@@ -1595,11 +1660,9 @@ char     *mode;
        return Nullfp;
     this = (*mode == 'w');
     that = !this;
-    if (tainting) {
-       if (doexec) {
-           taint_env();
-           taint_proper("Insecure %s%s", "EXEC");
-       }
+    if (doexec && tainting) {
+       taint_env();
+       taint_proper("Insecure %s%s", "EXEC");
     }
     while ((pid = (doexec?vfork():fork())) < 0) {
        if (errno != EAGAIN) {
index 81e27c9..7e54d49 100644 (file)
@@ -880,7 +880,7 @@ if ($^O eq 'VMS') {
     # Fix up for case-sensitive file systems
     s/$modfname/$modfname/i && next;
     $_ = "\U$_" if $_ eq 'manifest' or $_ eq 'changes';
-    $_ = 'Makefile.PL' if $_ = 'makefile.pl';
+    $_ = 'Makefile.PL' if $_ eq 'makefile.pl';
   }
 }
 print MANI join("\n",@files);
index 792c893..b8132ad 100644 (file)
@@ -8,10 +8,10 @@
  * GenConfig.pl when producing Config.pm.
  *
  * config.h for VMS
- * Version: 5.003_07
+ * Version: 5.003_08
  */                 
 
-/* Configuration time: 22-Mar-1996 14:45
+/* Configuration time: 19-Nov-1996 23:34
  * Configured by: Charles Bailey  bailey@genetics.upenn.edu
  * Target system: VMS
  */
@@ -76,7 +76,7 @@
  * when Perl is built.  Please do not change it by hand; make
  * any changes to FndVers.Com instead.
  */
-#define ARCHLIB_EXP "/perl_root/lib/VMS_VAX/5_00307"  /**/
+#define ARCHLIB_EXP "/perl_root/lib/VMS_VAX/5_00308"  /**/
 #define ARCHLIB ARCHLIB_EXP    /*config-skip*/
 
 /* CPPSTDIN:
  */
 #undef HAS_STRCOLL     /**/
 
+/* HAS_STRTOD:
+ *     This symbol, if defined, indicates that the strtod routine is
+ *     available to translate strings to doubles.
+ */
+#define HAS_STRTOD     /**/
+
+/* HAS_STRTOL:
+ *     This symbol, if defined, indicates that the strtol routine is
+ *     available to translate strings to integers.
+ */
+#define HAS_STRTOL     /**/
+
+/* HAS_STRTOUL:
+ *     This symbol, if defined, indicates that the strtoul routine is
+ *     available to translate strings to integers.
+ */
+#define HAS_STRTOUL    /**/
+
 /* HAS_STRXFRM:
  *     This symbol, if defined, indicates that the strxfrm() routine is
  *     available to compare strings using collating information.
index a162ad0..35e59ee 100644 (file)
@@ -65,7 +65,7 @@ OBJVAL = $(MMS$TARGET_NAME)$(O)
 .endif
 
 # Updated by fndvers.com -- do not edit by hand
-PERL_VERSION = 5_00307#
+PERL_VERSION = 5_00308#
 
 
 ARCHDIR =  [.lib.$(ARCH).$(PERL_VERSION)]
@@ -1565,9 +1565,9 @@ cleanlis :
        - If F$Search("*.Map").nes."" Then Delete/NoConfirm/Log *.Map;*
 
 tidy : cleanlis
-       - If F$Search("*.Opt;-1").nes."" Then Purge/NoConfirm/Log *.Opt
-       - If F$Search("*$(O);-1").nes."" Then Purge/NoConfirm/Log *$(O)
-       - If F$Search("*$(E);-1").nes."" Then Purge/NoConfirm/Log *$(E)
+       - If F$Search("[...]*.Opt;-1").nes."" Then Purge/NoConfirm/Log [...]*.Opt
+       - If F$Search("[...]*$(O);-1").nes."" Then Purge/NoConfirm/Log [...]*$(O)
+       - If F$Search("[...]*$(E);-1").nes."" Then Purge/NoConfirm/Log [...]*$(E)
        - If F$Search("Config.H;-1").nes."" Then Purge/NoConfirm/Log Config.H
        - If F$Search("Config.SH;-1").nes."" Then Purge/NoConfirm/Log Config.SH
        - If F$Search("perly.c;-1").nes."" Then Purge/NoConfirm/Log perly.c
@@ -1592,6 +1592,7 @@ tidy : cleanlis
        - If F$Search("[.Lib.Pod]*.Pod;-1").nes."" Then Purge/NoConfirm/Log [.Lib.Pod]*.Pod
        - If F$Search("$(ARCHCORE)*.*").nes."" Then Purge/NoConfirm/Log $(ARCHCORE)*.*
        - If F$Search("[.utils]*.;-1").nes."" Then Purge/NoConfirm/Log [.utils]*.
+       - If F$Search("[.lib]perlbug.;-1").nes."" Then Purge/NoConfirm/Log [.lib]perlbug.
        - If F$Search("[.lib.pod]*.;-1").nes."" Then Purge/NoConfirm/Log [.lib.pod]*.
 
 clean : tidy
index 8753893..c9f51ab 100644 (file)
@@ -330,7 +330,7 @@ if ($isvax) {
   print DRVR "\$ Set Verify\n";
   print DRVR "\$ If F\$Search(\"$libperl\").eqs.\"\" Then Library/Object/Create $libperl\n";
   do {
-    $incstr .= ",perlshr_gbl$marord";
+    push(@symfiles,"perlshr_gbl$marord");
     print DRVR "\$ Macro/NoDebug/Object=PerlShr_Gbl${marord}$objsuffix PerlShr_Gbl$marord.Mar\n";
     print DRVR "\$ Library/Object/Replace/Log $libperl PerlShr_Gbl${marord}$objsuffix\n";
   } while (--$marord); 
@@ -345,6 +345,17 @@ if ($isvax) {
   close DRVR;
 }
 
+# Initial hack to permit building of compatible shareable images for a
+# given version of Perl.
+if ($ENV{PERLSHR_USE_GSMATCH}) {
+  my $major = int($] * 1000)                        & 0xFF;  # range 0..255
+  my $minor = int(($] * 1000 - $major) * 100 + 0.5) & 0xFF;  # range 0..255
+  print OPTBLD "GSMATCH=LEQUAL,$major,$minor\n";
+  foreach (@symfiles) {
+    print OPTBLD "CLUSTER=\$\$TRANSFER_VECTOR,,,$_.$objsuffix\n";
+  }
+}
+else { $incstr .= ',' . join(',',@symfiles); }
 # Include object modules and RTLs in options file
 # Linker wants /Include and /Library on different lines
 print OPTBLD "$libperl/Include=($incstr)\n";
index d2ab577..924fa08 100644 (file)
@@ -324,7 +324,7 @@ if (open(PL,"${outdir}patchlevel.h")) {
 else { warn "Can't read ${outdir}patchlevel.h - skipping 'PATCHLEVEL'"; }
 
 # simple pager support for perldoc                                             
-if    (`most` =~ /IVVERB/) {
+if    (`most not..file` =~ /IVVERB/) {
   $pager = 'more';
   if (`more nl:` =~ /IVVERB/) { $pager = 'type/page'; }
 }
index b56d202..e065b08 100644 (file)
@@ -140,13 +140,16 @@ be added to the linker options file F<PGPLOT.Opt> produced
 during the build process for the Perl extension.
 
 By default, the shareable image for an extension is placed
-in the F<[.Lib.Auto.>I<Arch>.I<Extname>F<]> directory of the
+F<[.lib.site_perl.auto>I<Arch>.I<Extname>F<]> directory of the
 installed Perl directory tree (where I<Arch> is F<VMS_VAX> or
-F<VMS_AXP>, followed by the Perl version number, and I<Extname>
-is the name of the extension, with each C<::> translated to C<.>).
+F<VMS_AXP>, and I<Extname> is the name of the extension, with
+each C<::> translated to C<.>).  (See the MakeMaker documentation
+for more details on installation options for extensions.)
 However, it can be manually placed in any of several locations:
-   - the F<[.Lib.Auto.>I<Extname>F<]> subdirectory of one of
-     the directories in C<@INC>, or
+   - the F<[.Lib.Auto.>I<Arch>I<$PVers>I<Extname>F<]> subdirectory
+     of one of the directories in C<@INC> (where I<PVers>
+     is the version of Perl you're using, as supplied in C<$]>,
+     with '.' converted to '_'), or
    - one of the directories in C<@INC>, or
    - a directory which the extensions Perl library module
      passes to the DynaLoader when asking it to map
index 9a4b55e..b6f163f 100644 (file)
--- a/vms/vms.c
+++ b/vms/vms.c
@@ -322,6 +322,7 @@ my_crypt(const char *textpasswd, const char *usrname)
 /*}}}*/
 
 
+static char *do_rmsexpand(char *, char *, int, char *, unsigned);
 static char *do_fileify_dirspec(char *, char *, int);
 static char *do_tovmsspec(char *, char *, int);
 
@@ -353,7 +354,7 @@ do_rmdir(char *name)
 int
 kill_file(char *name)
 {
-    char vmsname[NAM$C_MAXRSS+1];
+    char vmsname[NAM$C_MAXRSS+1], rspec[NAM$C_MAXRSS+1];
     unsigned long int jpicode = JPI$_UIC, type = ACL$C_FILE;
     unsigned long int cxt = 0, aclsts, fndsts, rmsts = -1;
     struct dsc$descriptor_s fildsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
@@ -374,7 +375,12 @@ kill_file(char *name)
        lcklst[2] = {{sizeof newace, ACL$C_WLOCK_ACL, &newace, 0},{0,0,0,0}},
        ulklst[2] = {{sizeof newace, ACL$C_UNLOCK_ACL, &newace, 0},{0,0,0,0}};
       
-    if (!remove(name)) return 0;   /* Can we just get rid of it? */
+    /* Expand the input spec using RMS, since the CRTL remove() and
+     * system services won't do this by themselves, so we may miss
+     * a file "hiding" behind a logical name or search list. */
+    if (do_tovmsspec(name,vmsname,0) == NULL) return -1;
+    if (do_rmsexpand(vmsname,rspec,1,NULL,0) == NULL) return -1;
+    if (!remove(rspec)) return 0;   /* Can we just get rid of it? */
     /* If not, can changing protections help? */
     if (vaxc$errno != RMS$_PRV) return -1;
 
@@ -383,9 +389,8 @@ kill_file(char *name)
      * to delete the file.
      */
     _ckvmssts(lib$getjpi(&jpicode,0,0,&(oldace.myace$l_ident),0,0));
-    if (do_tovmsspec(name,vmsname,0) == NULL) return -1;
-    fildsc.dsc$w_length = strlen(vmsname);
-    fildsc.dsc$a_pointer = vmsname;
+    fildsc.dsc$w_length = strlen(rspec);
+    fildsc.dsc$a_pointer = rspec;
     cxt = 0;
     newace.myace$l_ident = oldace.myace$l_ident;
     if (!((aclsts = sys$change_acl(0,&type,&fildsc,lcklst,0,0,0)) & 1)) {
@@ -758,6 +763,28 @@ I32 my_pclose(FILE *fp)
       /* get here => no such pipe open */
       croak("No such pipe open");
 
+    /* If we were writing to a subprocess, insure that someone reading from
+     * the mailbox gets an EOF.  It looks like a simple fclose() doesn't
+     * produce an EOF record in the mailbox.  */
+    if (info->mode != 'r') {
+      char devnam[NAM$C_MAXRSS+1], *cp;
+      unsigned long int chan, iosb[2], retsts, retsts2;
+      struct dsc$descriptor devdsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, devnam};
+
+      if (fgetname(info->fp,devnam)) {
+        /* It oughta be a mailbox, so fgetname should give just the device
+         * name, but just in case . . . */
+        if ((cp = strrchr(devnam,':')) != NULL) *(cp+1) = '\0';
+        devdsc.dsc$w_length = strlen(devnam);
+        _ckvmssts(sys$assign(&devdsc,&chan,0,0));
+        retsts = sys$qiow(0,chan,IO$_WRITEOF,iosb,0,0,0,0,0,0,0,0);
+        if (retsts & 1) retsts = iosb[0];
+        retsts2 = sys$dassgn(chan);  /* Be sure to deassign the channel */
+        if (retsts & 1) retsts = retsts2;
+        _ckvmssts(retsts);
+      }
+      else _ckvmssts(vaxc$errno);  /* Should never happen */
+    }
     PerlIO_close(info->fp);
 
     if (info->done) retsts = info->completion;
@@ -844,6 +871,108 @@ my_gconvert(double val, int ndig, int trail, char *buf)
 }
 /*}}}*/
 
+
+/*{{{char *do_rmsexpand(char *fspec, char *out, int ts, char *def, unsigned opts)*/
+/* Shortcut for common case of simple calls to $PARSE and $SEARCH
+ * to expand file specification.  Allows for a single default file
+ * specification and a simple mask of options.  If outbuf is non-NULL,
+ * it must point to a buffer at least NAM$C_MAXRSS bytes long, into which
+ * the resultant file specification is placed.  If outbuf is NULL, the
+ * resultant file specification is placed into a static buffer.
+ * The third argument, if non-NULL, is taken to be a default file
+ * specification string.  The fourth argument is unused at present.
+ * rmesexpand() returns the address of the resultant string if
+ * successful, and NULL on error.
+ */
+static char *
+do_rmsexpand(char *filespec, char *outbuf, int ts, char *defspec, unsigned opts)
+{
+  static char __rmsexpand_retbuf[NAM$C_MAXRSS+1];
+  char esa[NAM$C_MAXRSS], *cp, *out = NULL;
+  struct FAB myfab = cc$rms_fab;
+  struct NAM mynam = cc$rms_nam;
+  STRLEN speclen;
+  unsigned long int retsts, haslower = 0;
+
+  if (!filespec || !*filespec) {
+    set_vaxc_errno(LIB$_INVARG); set_errno(EINVAL);
+    return NULL;
+  }
+  if (!outbuf) {
+    if (ts) out = New(7019,outbuf,NAM$C_MAXRSS+1,char);
+    else    outbuf = __rmsexpand_retbuf;
+  }
+
+  myfab.fab$l_fna = filespec;
+  myfab.fab$b_fns = strlen(filespec);
+  myfab.fab$l_nam = &mynam;
+
+  if (defspec && *defspec) {
+    myfab.fab$l_dna = defspec;
+    myfab.fab$b_dns = strlen(defspec);
+  }
+
+  mynam.nam$l_esa = esa;
+  mynam.nam$b_ess = sizeof esa;
+  mynam.nam$l_rsa = outbuf;
+  mynam.nam$b_rss = NAM$C_MAXRSS;
+
+  retsts = sys$parse(&myfab,0,0);
+  if (!(retsts & 1)) {
+    if (retsts == RMS$_DNF || retsts == RMS$_DIR ||
+        retsts == RMS$_DEV || retsts == RMS$_DEV) {
+      mynam.nam$b_nop |= NAM$M_SYNCHK;
+      retsts = sys$parse(&myfab,0,0);
+      if (retsts & 1) goto expanded;
+    }  
+    if (out) Safefree(out);
+    set_vaxc_errno(retsts);
+    if      (retsts == RMS$_PRV) set_errno(EACCES);
+    else if (retsts == RMS$_DEV) set_errno(ENODEV);
+    else if (retsts == RMS$_DIR) set_errno(ENOTDIR);
+    else                         set_errno(EVMSERR);
+    return NULL;
+  }
+  retsts = sys$search(&myfab,0,0);
+  if (!(retsts & 1) && retsts != RMS$_FNF) {
+    if (out) Safefree(out);
+    set_vaxc_errno(retsts);
+    if      (retsts == RMS$_PRV) set_errno(EACCES);
+    else                         set_errno(EVMSERR);
+    return NULL;
+  }
+
+  /* If the input filespec contained any lowercase characters,
+   * downcase the result for compatibility with Unix-minded code. */
+  expanded:
+  for (out = myfab.fab$l_fna; *out; out++)
+    if (islower(*out)) { haslower = 1; break; }
+  if (mynam.nam$b_rsl) { out = outbuf; speclen = mynam.nam$b_rsl; }
+  else                 { out = esa;    speclen = mynam.nam$b_esl; }
+  if (!(mynam.nam$l_fnb & NAM$M_EXP_VER) &&
+      (!defspec || !*defspec || !strchr(myfab.fab$l_dna,';')))
+    speclen = mynam.nam$l_ver - out;
+  /* If we just had a directory spec on input, $PARSE "helpfully"
+   * adds an empty name and type for us */
+  if (mynam.nam$l_name == mynam.nam$l_type &&
+      mynam.nam$l_ver  == mynam.nam$l_type + 1 &&
+      !(mynam.nam$l_fnb & NAM$M_EXP_NAME))
+    speclen = mynam.nam$l_name - out;
+  out[speclen] = '\0';
+  if (haslower) __mystrtolower(out);
+
+  /* Have we been working with an expanded, but not resultant, spec? */
+  if (!mynam.nam$b_rsl) strcpy(outbuf,esa);
+  return outbuf;
+}
+/*}}}*/
+/* External entry points */
+char *rmsexpand(char *spec, char *buf, char *def, unsigned opt)
+{ return do_rmsexpand(spec,buf,0,def,opt); }
+char *rmsexpand_ts(char *spec, char *buf, char *def, unsigned opt)
+{ return do_rmsexpand(spec,buf,1,def,opt); }
+
+
 /*
 ** The following routines are provided to make life easier when
 ** converting among VMS-style and Unix-style directory specifications.
@@ -3258,10 +3387,13 @@ cando_by_name(I32 bit, I32 effective, char *fname)
   }
 
   retsts = sys$check_access(&objtyp,&namdsc,&usrdsc,armlst);
-  if (retsts == SS$_NOPRIV || retsts == SS$_NOSUCHOBJECT ||
-      retsts == RMS$_FNF   || retsts == RMS$_DIR         ||
-      retsts == RMS$_DEV) {
-    set_errno(retsts == SS$_NOPRIV ? EACCES : ENOENT); set_vaxc_errno(retsts);
+  if (retsts == SS$_NOPRIV      || retsts == SS$_NOSUCHOBJECT ||
+      retsts == SS$_INVFILFOROP || retsts == RMS$_FNF    ||
+      retsts == RMS$_DIR        || retsts == RMS$_DEV) {
+    set_vaxc_errno(retsts);
+    if (retsts == SS$_NOPRIV) set_errno(EACCES);
+    else if (retsts == SS$_INVFILFOROP) set_errno(EINVAL);
+    else set_errno(ENOENT);
     return FALSE;
   }
   if (retsts == SS$_NORMAL) {
@@ -3309,10 +3441,8 @@ int
 flex_stat(char *fspec, struct mystat *statbufp)
 {
     char fileified[NAM$C_MAXRSS+1];
-    int retval,myretval;
-    struct mystat tmpbuf;
+    int retval = -1;
 
-    
     if (statbufp == &statcache) do_tovmsspec(fspec,namecache,0);
     if (is_null_device(fspec)) { /* Fake a stat() for the null device */
       memset(statbufp,0,sizeof *statbufp);
@@ -3325,22 +3455,19 @@ flex_stat(char *fspec, struct mystat *statbufp)
       return 0;
     }
 
-    if (do_fileify_dirspec(fspec,fileified,0) == NULL) myretval = -1;
-    else {
-      myretval = stat(fileified,(stat_t *) &tmpbuf);
-    }
-    retval = stat(fspec,(stat_t *) statbufp);
-    if (!myretval) {
-      if (retval == -1) {
-        *statbufp = tmpbuf;
-        retval = 0;
-      }
-      else if (!retval) { /* Dir with same name.  Substitute it. */
-        statbufp->st_mode &= ~S_IFDIR;
-        statbufp->st_mode |= tmpbuf.st_mode & S_IFDIR;
-        strcpy(namecache,fileified);
-      }
+    /* Try for a directory name first.  If fspec contains a filename without
+     * a type (e.g. sea:[dark.dark]water), and both sea:[wine.dark]water.dir
+     * and sea:[wine.dark]water. exist, we prefer the directory here.
+     * Similarly, sea:[wine.dark] returns the result for sea:[wine]dark.dir,
+     * not sea:[wine.dark]., if the latter exists.  If the intended target is
+     * the file with null type, specify this by calling flex_stat() with
+     * a '.' at the end of fspec.
+     */
+    if (do_fileify_dirspec(fspec,fileified,0) != NULL) {
+      retval = stat(fileified,(stat_t *) statbufp);
+      if (!retval && statbufp == &statcache) strcpy(namecache,fileified);
     }
+    if (retval) retval = stat(fspec,(stat_t *) statbufp);
     if (!retval) statbufp->st_dev = encode_dev(statbufp->st_devnam);
     return retval;
 
@@ -3583,71 +3710,17 @@ void
 rmsexpand_fromperl(CV *cv)
 {
   dXSARGS;
-  char esa[NAM$C_MAXRSS], rsa[NAM$C_MAXRSS], *cp, *out;
-  struct FAB myfab = cc$rms_fab;
-  struct NAM mynam = cc$rms_nam;
-  STRLEN speclen;
-  unsigned long int retsts, haslower = 0;
+  char *fspec, *defspec = NULL, *rslt;
 
-  if (items > 2) croak("Usage: VMS::Filespec::rmsexpand(spec[,defspec])");
+  if (!items || items > 2)
+    croak("Usage: VMS::Filespec::rmsexpand(spec[,defspec])");
+  fspec = SvPV(ST(0),na);
+  if (!fspec || !*fspec) XSRETURN_UNDEF;
+  if (items == 2) defspec = SvPV(ST(1),na);
 
-  myfab.fab$l_fna = SvPV(ST(0),speclen);
-  myfab.fab$b_fns = speclen;
-  myfab.fab$l_nam = &mynam;
-
-  if (items == 2) {
-    myfab.fab$l_dna = SvPV(ST(1),speclen);
-    myfab.fab$b_dns = speclen;
-  }
-
-  mynam.nam$l_esa = esa;
-  mynam.nam$b_ess = sizeof esa;
-  mynam.nam$l_rsa = rsa;
-  mynam.nam$b_rss = sizeof rsa;
-
-  retsts = sys$parse(&myfab,0,0);
-  if (!(retsts & 1)) {
-    if (retsts == RMS$_DNF || retsts == RMS$_DIR ||
-        retsts == RMS$_DEV || retsts == RMS$_DEV) {
-      mynam.nam$b_nop |= NAM$M_SYNCHK;
-      retsts = sys$parse(&myfab,0,0);
-      if (retsts & 1) goto expanded;
-    }  
-    set_vaxc_errno(retsts);
-    if      (retsts == RMS$_PRV) set_errno(EACCES);
-    else if (retsts == RMS$_DEV) set_errno(ENODEV);
-    else if (retsts == RMS$_DIR) set_errno(ENOTDIR);
-    else                         set_errno(EVMSERR);
-    XSRETURN_UNDEF;
-  }
-  retsts = sys$search(&myfab,0,0);
-  if (!(retsts & 1) && retsts != RMS$_FNF) {
-    set_vaxc_errno(retsts);
-    if      (retsts == RMS$_PRV) set_errno(EACCES);
-    else                         set_errno(EVMSERR);
-    XSRETURN_UNDEF;
-  }
-
-  /* If the input filespec contained any lowercase characters,
-   * downcase the result for compatibility with Unix-minded code. */
-  expanded:
-  for (out = myfab.fab$l_fna; *out; out++)
-    if (islower(*out)) { haslower = 1; break; }
-  if (mynam.nam$b_rsl) { out = rsa; speclen = mynam.nam$b_rsl; }
-  else                 { out = esa; speclen = mynam.nam$b_esl; }
-  if (!(mynam.nam$l_fnb & NAM$M_EXP_VER) &&
-      (items == 1 || !strchr(myfab.fab$l_dna,';')))
-    speclen = mynam.nam$l_ver - out;
-  /* If we just had a directory spec on input, $PARSE "helpfully"
-   * adds an empty name and type for us */
-  if (mynam.nam$l_name == mynam.nam$l_type &&
-      mynam.nam$l_ver  == mynam.nam$l_type + 1 &&
-      !(mynam.nam$l_fnb & NAM$M_EXP_NAME))
-    speclen = mynam.nam$l_name - out;
-  out[speclen] = '\0';
-  if (haslower) __mystrtolower(out);
-
-  ST(0) = sv_2mortal(newSVpv(out, speclen));
+  rslt = do_rmsexpand(fspec,NULL,1,defspec,0);
+  ST(0) = sv_newmortal();
+  if (rslt != NULL) sv_usepvn(ST(0),rslt,strlen(rslt));
   XSRETURN(1);
 }
 
index a362374..a7f4e89 100644 (file)
@@ -51,6 +51,9 @@
 #include <unixio.h>
 #include <unixlib.h>
 #include <file.h>  /* it's not <sys/file.h>, so don't use I_SYS_FILE */
+#ifdef __DECC
+#  include <unistd.h> /* DECC has this; VAXC and gcc don't */
+#endif
 
 /* Our own contribution to PerlShr's global symbols . . . */
 #ifdef EMBED
@@ -64,6 +67,8 @@
 #  define do_rmdir             Perl_do_rmdir
 #  define kill_file            Perl_kill_file
 #  define my_utime             Perl_my_utime
+#  define rmsexpand    Perl_rmsexpand
+#  define rmsexpand_ts Perl_rmsexpand_ts
 #  define fileify_dirspec      Perl_fileify_dirspec
 #  define fileify_dirspec_ts   Perl_fileify_dirspec_ts
 #  define pathify_dirspec      Perl_pathify_dirspec
@@ -413,6 +418,8 @@ char *      my_gconvert _((double, int, int, char *));
 int    do_rmdir _((char *));
 int    kill_file _((char *));
 int    my_utime _((char *, struct utimbuf *));
+char * rmsexpand _((char *, char *, char *, unsigned));
+char * rmsexpand_ts _((char *, char *, char *, unsigned));
 char * fileify_dirspec _((char *, char *));
 char * fileify_dirspec_ts _((char *, char *));
 char * pathify_dirspec _((char *, char *));