From: Perl 5 Porters Date: Tue, 26 Nov 1996 08:48:00 +0000 (+1200) Subject: [inseparable changes from patch from perl5.003_08 to perl5.003_09] X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=bbce6d69784bf43b0e69e8d312042d65f258af23;p=p5sagit%2Fp5-mst-13.2.git [inseparable changes from patch from perl5.003_08 to perl5.003_09] CORE LANGUAGE CHANGES Subject: Lexical locales From: Chip Salzenberg Files: too many to list make effectiveness of locales depend on C Subject: Lexical scoping cleanup From: Chip Salzenberg 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 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 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 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 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 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 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 Files: pp_ctl.c private-msgid: <199611212111.QAA17070@aatma.engin.umich.edu> Subject: Cleanup of {,un}pack('w'). From: Chip Salzenberg Files: pp.c Subject: Cleanups from Ilya. From: Chip Salzenberg Files: gv.c malloc.c pod/perlguts.pod pp_ctl.c Subject: Fix for unpack('w') on 64-bit systems. From: Chip Salzenberg Files: pp.c Subject: Re: LC_NUMERIC support is ready + performance Date: Mon, 25 Nov 1996 22:08:27 -0500 (EST) From: Ilya Zakharevich 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 Files: hv.c hv.h proto.h Subject: Mortal stack pre-allocation from Ilya. From: Chip Salzenberg 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 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> --- diff --git a/MANIFEST b/MANIFEST index c2c8609..80a439b 100644 --- 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 --- 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 --- 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 --- 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 --- a/embed.h +++ b/embed.h @@ -41,6 +41,11 @@ #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 @@ -157,6 +162,9 @@ #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 @@ -189,7 +197,6 @@ #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 @@ -261,6 +268,7 @@ #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 @@ -338,9 +346,9 @@ #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 @@ -355,6 +363,7 @@ #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 @@ -475,8 +484,10 @@ #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 @@ -507,6 +518,7 @@ #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 @@ -1062,6 +1074,8 @@ #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 @@ -1097,12 +1111,14 @@ #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 @@ -1247,7 +1263,6 @@ #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) @@ -1400,7 +1415,6 @@ #define Irs rs #define Irunlevel runlevel #define Isawampersand sawampersand -#define Isawi sawi #define Isawstudy sawstudy #define Isawvec sawvec #define Iscreamfirst screamfirst @@ -1434,6 +1448,8 @@ #define Iunsafe unsafe #define Iwarnhook warnhook +#ifdef EMBED + #define Argv Perl_Argv #define Cmd Perl_Cmd #define DBgv Perl_DBgv @@ -1551,7 +1567,6 @@ #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 @@ -1585,4 +1600,6 @@ #define unsafe Perl_unsafe #define warnhook Perl_warnhook +#endif /* EMBED */ + #endif /* MULTIPLICITY */ diff --git a/ext/POSIX/POSIX.xs b/ext/POSIX/POSIX.xs index 808ef8e..a94c942 100644 --- a/ext/POSIX/POSIX.xs +++ b/ext/POSIX/POSIX.xs @@ -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 --- 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 --- 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 --- 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 --- 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 diff --git a/interp.sym b/interp.sym index 33fb2c7..55b5338 100644 --- a/interp.sym +++ b/interp.sym @@ -115,7 +115,6 @@ rightgv rs runlevel sawampersand -sawi sawstudy sawvec screamfirst diff --git a/lib/ExtUtils/MM_Unix.pm b/lib/ExtUtils/MM_Unix.pm index 5d97956..ea4741f 100644 --- a/lib/ExtUtils/MM_Unix.pm +++ b/lib/ExtUtils/MM_Unix.pm @@ -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; } diff --git a/lib/ExtUtils/MM_VMS.pm b/lib/ExtUtils/MM_VMS.pm index 1a63f21..13383e9 100644 --- a/lib/ExtUtils/MM_VMS.pm +++ b/lib/ExtUtils/MM_VMS.pm @@ -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 for an +for DCL procedure. If this fails, checks F 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[ diff --git a/lib/ExtUtils/MakeMaker.pm b/lib/ExtUtils/MakeMaker.pm index 027c1fe..f6da518 100644 --- a/lib/ExtUtils/MakeMaker.pm +++ b/lib/ExtUtils/MakeMaker.pm @@ -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 diff --git a/lib/File/Path.pm b/lib/File/Path.pm index 8d775d5..62f3b50 100644 --- a/lib/File/Path.pm +++ b/lib/File/Path.pm @@ -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 index 0000000..48213ab --- /dev/null +++ b/lib/locale.pm @@ -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; diff --git a/malloc.c b/malloc.c index 042c233..170ae3e 100644 --- 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 --- a/mg.c +++ b/mg.c @@ -26,6 +26,12 @@ # 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 --- 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 --- 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 { diff --git a/opcode.h b/opcode.h index c4902ef..97b3034 100644 --- 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 */ diff --git a/opcode.pl b/opcode.pl index 93fcbd7..d679d8a 100755 --- 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. diff --git a/patchlevel.h b/patchlevel.h index e1a4da8..8dc52bc 100644 --- a/patchlevel.h +++ b/patchlevel.h @@ -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 --- 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 --- a/perl.h +++ b/perl.h @@ -100,10 +100,11 @@ # 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) /* diff --git a/perl_exp.SH b/perl_exp.SH index 821c4d5..1c1848b 100755 --- a/perl_exp.SH +++ b/perl_exp.SH @@ -26,9 +26,10 @@ sed -n '/^[A-Za-z]/ p' interp.sym >> perl.exp # extra globals not included above. cat <> 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 --- 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; diff --git a/perly.c.diff b/perly.c.diff index cc55c40..3f4ab02 100644 --- a/perly.c.diff +++ b/perly.c.diff @@ -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 --- a/perly.y +++ b/perly.y @@ -47,9 +47,9 @@ dep() %token LOCAL MY %type prog decl local format startsub remember mremember '&' -%type block mblock mintro lineseq line loop cond else +%type block mblock lineseq line loop cond else %type expr term scalar ary hsh arylen star amper sideff -%type argexpr nexpr texpr iexpr mexpr mtexpr miexpr +%type argexpr nexpr texpr iexpr mexpr mnexpr mtexpr miexpr %type listexpr listexprcom indirob %type listop method proto cont my_scalar %type 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 */ diff --git a/pod/perldiag.pod b/pod/perldiag.pod index 240ebcc..402761d 100644 --- a/pod/perldiag.pod +++ b/pod/perldiag.pod @@ -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. +=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. (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 Cing 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. diff --git a/pod/perlfunc.pod b/pod/perlfunc.pod index d4998cf..df8d23f 100644 --- a/pod/perlfunc.pod +++ b/pod/perlfunc.pod @@ -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. =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 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 (the natural logarithm base) to the power of EXPR. If EXPR is omitted, gives C. @@ -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 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) 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. @@ -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 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. =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. 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 diff --git a/pod/perlguts.pod b/pod/perlguts.pod index 3f36396..c397142 100644 --- a/pod/perlguts.pod +++ b/pod/perlguts.pod @@ -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) to the C 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 copies the pointer while this copies the string. =item sv_setsv Copies the contents of the source SV C into the destination SV C. -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. Safe even if C. + =item SvSTASH Returns the stash of the SV. diff --git a/pp.c b/pp.c index 525e7af..4f04eb6 100644 --- 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 --- a/pp.h +++ b/pp.h @@ -66,15 +66,15 @@ #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)) @@ -134,6 +134,12 @@ 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 diff --git a/pp_ctl.c b/pp_ctl.c index 6d6b469..999b2cc 100644 --- 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; diff --git a/pp_hot.c b/pp_hot.c index d8b2bfc..6fd0441 100644 --- 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 diff --git a/pp_sys.c b/pp_sys.c index 40a0d35..d580fba 100644 --- 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 --- 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)); diff --git a/regcomp.c b/regcomp.c index 6befee8..bbb7c8e 100644 --- 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 = ®dummy; @@ -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 == ®dummy) - return; - c &= 255; - if (def) - bits[c >> 3] &= ~(1 << (c & 7)); - else - bits[c >> 3] |= (1 << (c & 7)); + if (opnd == ®dummy) + 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 != ®dummy) + *opnd |= ANYOF_INVERT; + } + if (opnd != ®dummy) { + 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 != ®dummy) + *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 != ®dummy) + *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 != ®dummy) + *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 != ®dummy) + *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"); } diff --git a/regcomp.h b/regcomp.h index b2d9b84..9d07ff9 100644 --- a/regcomp.h +++ b/regcomp.h @@ -48,41 +48,49 @@ */ /* 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: @@ -109,7 +117,13 @@ #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. */ diff --git a/regexec.c b/regexec.c index 6e79d6b..d9a893e 100644 --- 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() diff --git a/regexp.h b/regexp.h index 018312e..ebd30ad 100644 --- 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 --- 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 --- 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 diff --git a/t/op/re_tests b/t/op/re_tests index f8c4c6e..c20fb89 100644 --- a/t/op/re_tests +++ b/t/op/re_tests @@ -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- diff --git a/t/op/sysio.t b/t/op/sysio.t index e69de29..94a29c1 100755 --- a/t/op/sysio.t +++ b/t/op/sysio.t @@ -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 --- 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 --- 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 --- 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) { diff --git a/utils/h2xs.PL b/utils/h2xs.PL index 81e27c9..7e54d49 100644 --- a/utils/h2xs.PL +++ b/utils/h2xs.PL @@ -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); diff --git a/vms/config.vms b/vms/config.vms index 792c893..b8132ad 100644 --- a/vms/config.vms +++ b/vms/config.vms @@ -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: @@ -1117,6 +1117,24 @@ */ #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. diff --git a/vms/descrip.mms b/vms/descrip.mms index a162ad0..35e59ee 100644 --- a/vms/descrip.mms +++ b/vms/descrip.mms @@ -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 diff --git a/vms/gen_shrfls.pl b/vms/gen_shrfls.pl index 8753893..c9f51ab 100644 --- a/vms/gen_shrfls.pl +++ b/vms/gen_shrfls.pl @@ -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"; diff --git a/vms/genconfig.pl b/vms/genconfig.pl index d2ab577..924fa08 100644 --- a/vms/genconfig.pl +++ b/vms/genconfig.pl @@ -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'; } } diff --git a/vms/perlvms.pod b/vms/perlvms.pod index b56d202..e065b08 100644 --- a/vms/perlvms.pod +++ b/vms/perlvms.pod @@ -140,13 +140,16 @@ be added to the linker options file F 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.IF<]> directory of the +F<[.lib.site_perl.auto>I.IF<]> directory of the installed Perl directory tree (where I is F or -F, followed by the Perl version number, and I -is the name of the extension, with each C<::> translated to C<.>). +F, and I 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.>IF<]> subdirectory of one of - the directories in C<@INC>, or + - the F<[.Lib.Auto.>II<$PVers>IF<]> subdirectory + of one of the directories in C<@INC> (where I + 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 diff --git a/vms/vms.c b/vms/vms.c index 9a4b55e..b6f163f 100644 --- 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); } diff --git a/vms/vmsish.h b/vms/vmsish.h index a362374..a7f4e89 100644 --- a/vms/vmsish.h +++ b/vms/vmsish.h @@ -51,6 +51,9 @@ #include #include #include /* it's not , so don't use I_SYS_FILE */ +#ifdef __DECC +# include /* 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 *));