# endif
#endif
+#ifdef PERL_OBJECT
+# define VTBL this->*vtbl
+#else
+# define VTBL *vtbl
+static void restore_magic _((void *p));
+#endif
+
/*
* Use the "DESTRUCTOR" scope cleanup to reinstate magic.
*/
-#ifdef PERL_OBJECT
-
-#define VTBL this->*vtbl
-
-#else
struct magic_state {
SV* mgs_sv;
U32 mgs_flags;
+ I32 mgs_ss_ix;
};
-typedef struct magic_state MGS;
-
-static void restore_magic _((void *p));
-#define VTBL *vtbl
-
-#endif
+/* MGS is typedef'ed to struct magic_state in perl.h */
STATIC void
-save_magic(MGS *mgs, SV *sv)
+save_magic(I32 mgs_ix, SV *sv)
{
+ dTHR;
+ MGS* mgs;
assert(SvMAGICAL(sv));
+ SAVEDESTRUCTOR(restore_magic, (void*)mgs_ix);
+
+ mgs = SSPTR(mgs_ix, MGS*);
mgs->mgs_sv = sv;
mgs->mgs_flags = SvMAGICAL(sv) | SvREADONLY(sv);
- SAVEDESTRUCTOR(restore_magic, mgs);
+ mgs->mgs_ss_ix = PL_savestack_ix; /* points after the saved destructor */
SvMAGICAL_off(sv);
SvREADONLY_off(sv);
STATIC void
restore_magic(void *p)
{
- MGS* mgs = (MGS*)p;
+ dTHR;
+ MGS* mgs = SSPTR((I32)p, MGS*);
SV* sv = mgs->mgs_sv;
+ if (!sv)
+ return;
+
if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv))
{
if (mgs->mgs_flags)
if (SvGMAGICAL(sv))
SvFLAGS(sv) &= ~(SVf_IOK|SVf_NOK|SVf_POK);
}
+
+ mgs->mgs_sv = NULL; /* mark the MGS structure as restored */
+
+ /* If we're still on top of the stack, pop us off. (That condition
+ * will be satisfied if restore_magic was called explicitly, but *not*
+ * if it's being called via leave_scope.)
+ * The reason for doing this is that otherwise, things like sv_2cv()
+ * may leave alloc gunk on the savestack, and some code
+ * (e.g. sighandler) doesn't expect that...
+ */
+ if (PL_savestack_ix == mgs->mgs_ss_ix)
+ {
+ I32 popval = SSPOPINT;
+ assert(popval == SAVEt_DESTRUCTOR);
+ PL_savestack_ix -= 2;
+ popval = SSPOPINT;
+ assert(popval == SAVEt_ALLOC);
+ popval = SSPOPINT;
+ PL_savestack_ix -= popval;
+ }
+
}
void
int
mg_get(SV *sv)
{
- MGS mgs;
+ dTHR;
+ I32 mgs_ix;
MAGIC* mg;
MAGIC** mgp;
int mgp_valid = 0;
- ENTER;
- save_magic(&mgs, sv);
+ mgs_ix = SSNEW(sizeof(MGS));
+ save_magic(mgs_ix, sv);
mgp = &SvMAGIC(sv);
while ((mg = *mgp) != 0) {
/* Ignore this magic if it's been deleted */
if ((mg == (mgp_valid ? *mgp : SvMAGIC(sv))) &&
(mg->mg_flags & MGf_GSKIP))
- mgs.mgs_flags = 0;
+ (SSPTR(mgs_ix, MGS*))->mgs_flags = 0;
}
/* Advance to next magic (complicated by possible deletion) */
if (mg == (mgp_valid ? *mgp : SvMAGIC(sv))) {
mgp = &SvMAGIC(sv); /* Re-establish pointer after sv_upgrade */
}
- LEAVE;
+ restore_magic((void*)mgs_ix);
return 0;
}
int
mg_set(SV *sv)
{
- MGS mgs;
+ dTHR;
+ I32 mgs_ix;
MAGIC* mg;
MAGIC* nextmg;
- ENTER;
- save_magic(&mgs, sv);
+ mgs_ix = SSNEW(sizeof(MGS));
+ save_magic(mgs_ix, sv);
for (mg = SvMAGIC(sv); mg; mg = nextmg) {
MGVTBL* vtbl = mg->mg_virtual;
nextmg = mg->mg_moremagic; /* it may delete itself */
if (mg->mg_flags & MGf_GSKIP) {
mg->mg_flags &= ~MGf_GSKIP; /* setting requires another read */
- mgs.mgs_flags = 0;
+ (SSPTR(mgs_ix, MGS*))->mgs_flags = 0;
}
if (vtbl && (vtbl->svt_set != NULL))
(VTBL->svt_set)(sv, mg);
}
- LEAVE;
+ restore_magic((void*)mgs_ix);
return 0;
}
for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
MGVTBL* vtbl = mg->mg_virtual;
if (vtbl && (vtbl->svt_len != NULL)) {
- MGS mgs;
+ I32 mgs_ix;
- ENTER;
- save_magic(&mgs, sv);
+ mgs_ix = SSNEW(sizeof(MGS));
+ save_magic(mgs_ix, sv);
/* omit MGf_GSKIP -- not changed here */
len = (VTBL->svt_len)(sv, mg);
- LEAVE;
+ restore_magic((void*)mgs_ix);
return len;
}
}
for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
MGVTBL* vtbl = mg->mg_virtual;
if (vtbl && (vtbl->svt_len != NULL)) {
- MGS mgs;
- ENTER;
+ I32 mgs_ix;
+
+ mgs_ix = SSNEW(sizeof(MGS));
+ save_magic(mgs_ix, sv);
/* omit MGf_GSKIP -- not changed here */
len = (VTBL->svt_len)(sv, mg);
- LEAVE;
+ restore_magic((void*)mgs_ix);
return len;
}
}
int
mg_clear(SV *sv)
{
- MGS mgs;
+ I32 mgs_ix;
MAGIC* mg;
- ENTER;
- save_magic(&mgs, sv);
+ mgs_ix = SSNEW(sizeof(MGS));
+ save_magic(mgs_ix, sv);
for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
MGVTBL* vtbl = mg->mg_virtual;
(VTBL->svt_clear)(sv, mg);
}
- LEAVE;
+ restore_magic((void*)mgs_ix);
return 0;
}
MAGIC* mg;
for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
if (isUPPER(mg->mg_type)) {
- sv_magic(nsv, mg->mg_obj, toLOWER(mg->mg_type), key, klen);
+ sv_magic(nsv,
+ mg->mg_type == 'P' ? SvTIED_obj(sv, mg) : mg->mg_obj,
+ toLOWER(mg->mg_type), key, klen);
count++;
}
}
#endif
U32
+magic_regdata_cnt(SV *sv, MAGIC *mg)
+{
+ dTHR;
+ register char *s;
+ register I32 i;
+ register REGEXP *rx;
+ char *t;
+
+ if (PL_curpm && (rx = PL_curpm->op_pmregexp))
+ return rx->lastparen;
+ return (U32)-1;
+}
+
+int
+magic_regdatum_get(SV *sv, MAGIC *mg)
+{
+ dTHR;
+ register I32 paren;
+ register char *s;
+ register I32 i;
+ register REGEXP *rx;
+ char *t;
+
+ if (PL_curpm && (rx = PL_curpm->op_pmregexp)) {
+ paren = mg->mg_len;
+ if (paren < 0)
+ return 0;
+ if (paren <= rx->nparens &&
+ (s = rx->startp[paren]) &&
+ (t = rx->endp[paren]))
+ {
+ if (mg->mg_obj) /* @+ */
+ i = t - rx->subbase;
+ else /* @- */
+ i = s - rx->subbase;
+ sv_setiv(sv,i);
+ }
+ }
+ return 0;
+}
+
+U32
magic_len(SV *sv, MAGIC *mg)
{
dTHR;
return 0;
}
+#if 0
+static char *
+printW(sv)
+SV * sv ;
+{
+#if 1
+ return "" ;
+
+#else
+ int i ;
+ static char buffer[50] ;
+ char buf1[20] ;
+ char * p ;
+
+
+ sprintf(buffer, "Buffer %d, Length = %d - ", sv, SvCUR(sv)) ;
+ p = SvPVX(sv) ;
+ for (i = 0; i < SvCUR(sv) ; ++ i) {
+ sprintf (buf1, " %x [%x]", (p+i), *(p+i)) ;
+ strcat(buffer, buf1) ;
+ }
+
+ return buffer ;
+
+#endif
+}
+#endif
+
int
magic_get(SV *sv, MAGIC *mg)
{
case '\001': /* ^A */
sv_setsv(sv, PL_bodytarget);
break;
+ case '\002': /* ^B */
+ /* printf("magic_get $^B: ") ; */
+ if (PL_curcop->cop_warnings == WARN_NONE)
+ /* printf("WARN_NONE\n"), */
+ sv_setpvn(sv, WARN_NONEstring, WARNsize) ;
+ else if (PL_curcop->cop_warnings == WARN_ALL)
+ /* printf("WARN_ALL\n"), */
+ sv_setpvn(sv, WARN_ALLstring, WARNsize) ;
+ else
+ /* printf("some %s\n", printW(PL_curcop->cop_warnings)), */
+ sv_setsv(sv, PL_curcop->cop_warnings);
+ break;
case '\004': /* ^D */
sv_setiv(sv, (IV)(PL_debug & 32767));
break;
sv_setnv(sv, (double)errno);
sv_setpv(sv, errno ? Strerror(errno) : "");
} else {
- if (errno != errno_isOS2)
- Perl_rc = _syserrno();
+ if (errno != errno_isOS2) {
+ int tmp = _syserrno();
+ if (tmp) /* 2nd call to _syserrno() makes it 0 */
+ Perl_rc = tmp;
+ }
sv_setnv(sv, (double)Perl_rc);
sv_setpv(sv, os2error(Perl_rc));
}
case '\010': /* ^H */
sv_setiv(sv, (IV)PL_hints);
break;
- case '\t': /* ^I */
+ case '\011': /* ^I */ /* NOT \t in EBCDIC */
if (PL_inplace)
sv_setpv(sv, PL_inplace);
else
break;
case '\024': /* ^T */
#ifdef BIG_TIME
- sv_setnv(sv, basetime);
+ sv_setnv(sv, PL_basetime);
#else
sv_setiv(sv, (IV)PL_basetime);
#endif
break;
case '\027': /* ^W */
- sv_setiv(sv, (IV)PL_dowarn);
+ sv_setiv(sv, (IV)((PL_dowarn & G_WARN_ON) == G_WARN_ON));
break;
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': case '&':
break;
case '?':
{
- dTHR;
sv_setiv(sv, (IV)STATUS_CURRENT);
#ifdef COMPLEX_STATUS
- LvTARGOFF(sv) = statusvalue;
- LvTARGLEN(sv) = statusvalue_vms;
+ LvTARGOFF(sv) = PL_statusvalue;
+ LvTARGLEN(sv) = PL_statusvalue_vms;
#endif
}
break;
/* waiting in the wings? */
if (!len) {
SV **valp;
- if ((valp = hv_fetch(GvHVn(envgv), ptr, klen, FALSE)))
+ if ((valp = hv_fetch(GvHVn(PL_envgv), ptr, klen, FALSE)))
s = SvPV(*valp, len);
}
#endif
else {
i = whichsig(s); /* ...no, a brick */
if (!i) {
- if (PL_dowarn || strEQ(s,"ALARM"))
- warn("No such signal: SIG%s", s);
+ if (ckWARN(WARN_SIGNAL) || strEQ(s,"ALARM"))
+ warner(WARN_SIGNAL, "No such signal: SIG%s", s);
return 0;
}
SvREFCNT_dec(psig_name[i]);
if (hv) {
(void) hv_iterinit(hv);
- if (!SvRMAGICAL(hv) || !mg_find((SV*)hv,'P'))
+ if (! SvTIED_mg((SV*)hv, 'P'))
i = HvKEYS(hv);
else {
/*SUPPRESS 560*/
/* caller is responsible for stack switching/cleanup */
STATIC int
-magic_methcall(MAGIC *mg, char *meth, I32 flags, int n, SV *val)
+magic_methcall(SV *sv, MAGIC *mg, char *meth, I32 flags, int n, SV *val)
{
dSP;
PUSHMARK(SP);
EXTEND(SP, n);
- PUSHs(mg->mg_obj);
+ PUSHs(SvTIED_obj(sv, mg));
if (n > 1) {
if (mg->mg_ptr) {
if (mg->mg_len >= 0)
SAVETMPS;
PUSHSTACKi(PERLSI_MAGIC);
- if (magic_methcall(mg, meth, G_SCALAR, 2, NULL)) {
+ if (magic_methcall(sv, mg, meth, G_SCALAR, 2, NULL)) {
sv_setsv(sv, *PL_stack_sp--);
}
dSP;
ENTER;
PUSHSTACKi(PERLSI_MAGIC);
- magic_methcall(mg, "STORE", G_SCALAR|G_DISCARD, 3, sv);
+ magic_methcall(sv, mg, "STORE", G_SCALAR|G_DISCARD, 3, sv);
POPSTACK;
LEAVE;
return 0;
ENTER;
SAVETMPS;
PUSHSTACKi(PERLSI_MAGIC);
- if (magic_methcall(mg, "FETCHSIZE", G_SCALAR, 2, NULL)) {
+ if (magic_methcall(sv, mg, "FETCHSIZE", G_SCALAR, 2, NULL)) {
sv = *PL_stack_sp--;
retval = (U32) SvIV(sv)-1;
}
ENTER;
PUSHSTACKi(PERLSI_MAGIC);
PUSHMARK(SP);
- XPUSHs(mg->mg_obj);
+ XPUSHs(SvTIED_obj(sv, mg));
PUTBACK;
perl_call_method("CLEAR", G_SCALAR|G_DISCARD);
POPSTACK;
PUSHSTACKi(PERLSI_MAGIC);
PUSHMARK(SP);
EXTEND(SP, 2);
- PUSHs(mg->mg_obj);
+ PUSHs(SvTIED_obj(sv, mg));
if (SvOK(key))
PUSHs(key);
PUTBACK;
mg = mg_find(lsv, 'g');
if (mg && mg->mg_len >= 0) {
dTHR;
- sv_setiv(sv, mg->mg_len + PL_curcop->cop_arybase);
+ I32 i = mg->mg_len;
+ if (IN_UTF8)
+ sv_pos_b2u(lsv, &i);
+ sv_setiv(sv, i + PL_curcop->cop_arybase);
return 0;
}
}
SV* lsv = LvTARG(sv);
SSize_t pos;
STRLEN len;
+ STRLEN ulen;
+ dTHR;
mg = 0;
}
len = SvPOK(lsv) ? SvCUR(lsv) : sv_len(lsv);
- WITH_THR(pos = SvIV(sv) - PL_curcop->cop_arybase);
+ pos = SvIV(sv) - PL_curcop->cop_arybase;
+
+ if (IN_UTF8) {
+ ulen = sv_len_utf8(lsv);
+ if (ulen)
+ len = ulen;
+ else
+ ulen = 0;
+ }
+
if (pos < 0) {
pos += len;
if (pos < 0)
}
else if (pos > len)
pos = len;
+
+ if (ulen) {
+ I32 p = pos;
+ sv_pos_u2b(lsv, &p, 0);
+ pos = p;
+ }
+
mg->mg_len = pos;
mg->mg_flags &= ~MGf_MINMATCH;
if (mg->mg_obj) {
SV *ahv = LvTARG(sv);
if (SvTYPE(ahv) == SVt_PVHV) {
- HE *he = hv_fetch_ent((HV*)ahv, mg->mg_obj, FALSE, 0);
+ HE *he = hv_fetch_ent((HV*)ahv, mg->mg_obj, TRUE, 0);
if (he)
value = HeVAL(he);
}
else {
- SV **svp = avhv_fetch_ent((AV*)ahv, mg->mg_obj, FALSE, 0);
+ SV **svp = avhv_fetch_ent((AV*)ahv, mg->mg_obj, TRUE, 0);
if (svp)
value = *svp;
}
magic_setcollxfrm(SV *sv, MAGIC *mg)
{
/*
- * René Descartes said "I think not."
+ * RenE<eacute> Descartes said "I think not."
* and vanished with a faint plop.
*/
if (mg->mg_ptr) {
case '\001': /* ^A */
sv_setsv(PL_bodytarget, sv);
break;
+ case '\002': /* ^B */
+ if ( ! (PL_dowarn & G_WARN_ALL_MASK)) {
+ if (memEQ(SvPVX(sv), WARN_ALLstring, WARNsize))
+ PL_compiling.cop_warnings = WARN_ALL;
+ else if (memEQ(SvPVX(sv), WARN_NONEstring, WARNsize))
+ PL_compiling.cop_warnings = WARN_NONE;
+ else {
+ if (PL_compiling.cop_warnings != WARN_NONE &&
+ PL_compiling.cop_warnings != WARN_ALL)
+ sv_setsv(PL_compiling.cop_warnings, sv);
+ else
+ PL_compiling.cop_warnings = newSVsv(sv) ;
+ }
+ }
+ break;
case '\004': /* ^D */
PL_debug = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) | 0x80000000;
DEBUG_x(dump_all());
case '\010': /* ^H */
PL_hints = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
break;
- case '\t': /* ^I */
+ case '\011': /* ^I */ /* NOT \t in EBCDIC */
if (PL_inplace)
Safefree(PL_inplace);
if (SvOK(sv))
break;
case '\024': /* ^T */
#ifdef BIG_TIME
- basetime = (Time_t)(SvNOK(sv) ? SvNVX(sv) : sv_2nv(sv));
+ PL_basetime = (Time_t)(SvNOK(sv) ? SvNVX(sv) : sv_2nv(sv));
#else
PL_basetime = (Time_t)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
#endif
break;
case '\027': /* ^W */
- PL_dowarn = (bool)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
+ if ( ! (PL_dowarn & G_WARN_ALL_MASK)) {
+ i = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
+ PL_dowarn = (i ? G_WARN_ON : G_WARN_OFF) ;
+ }
break;
case '.':
if (PL_localizing) {
break;
case '?':
#ifdef COMPLEX_STATUS
- if (localizing == 2) {
- statusvalue = LvTARGOFF(sv);
- statusvalue_vms = LvTARGLEN(sv);
+ if (PL_localizing == 2) {
+ PL_statusvalue = LvTARGOFF(sv);
+ PL_statusvalue_vms = LvTARGLEN(sv);
}
else
#endif
break; /* don't do magic till later */
}
#ifdef HAS_SETRUID
- (void)setruid((Uid_t)uid);
+ (void)setruid((Uid_t)PL_uid);
#else
#ifdef HAS_SETREUID
(void)setreuid((Uid_t)PL_uid, (Uid_t)-1);
#else
#ifdef HAS_SETRESUID
- (void)setresuid((Uid_t)uid, (Uid_t)-1, (Uid_t)-1);
+ (void)setresuid((Uid_t)PL_uid, (Uid_t)-1, (Uid_t)-1);
#else
- if (uid == euid) /* special case $< = $> */
- (void)PerlProc_setuid(uid);
+ if (PL_uid == PL_euid) /* special case $< = $> */
+ (void)PerlProc_setuid(PL_uid);
else {
- uid = (I32)PerlProc_getuid();
+ PL_uid = (I32)PerlProc_getuid();
croak("setruid() not implemented");
}
#endif
(void)seteuid((Uid_t)PL_euid);
#else
#ifdef HAS_SETREUID
- (void)setreuid((Uid_t)-1, (Uid_t)euid);
+ (void)setreuid((Uid_t)-1, (Uid_t)PL_euid);
#else
#ifdef HAS_SETRESUID
- (void)setresuid((Uid_t)-1, (Uid_t)euid, (Uid_t)-1);
+ (void)setresuid((Uid_t)-1, (Uid_t)PL_euid, (Uid_t)-1);
#else
- if (euid == uid) /* special case $> = $< */
- PerlProc_setuid(euid);
+ if (PL_euid == PL_uid) /* special case $> = $< */
+ PerlProc_setuid(PL_euid);
else {
- euid = (I32)PerlProc_geteuid();
+ PL_euid = (I32)PerlProc_geteuid();
croak("seteuid() not implemented");
}
#endif
break; /* don't do magic till later */
}
#ifdef HAS_SETRGID
- (void)setrgid((Gid_t)gid);
+ (void)setrgid((Gid_t)PL_gid);
#else
#ifdef HAS_SETREGID
(void)setregid((Gid_t)PL_gid, (Gid_t)-1);
#else
#ifdef HAS_SETRESGID
- (void)setresgid((Gid_t)gid, (Gid_t)-1, (Gid_t) 1);
+ (void)setresgid((Gid_t)PL_gid, (Gid_t)-1, (Gid_t) 1);
#else
- if (gid == egid) /* special case $( = $) */
- (void)PerlProc_setgid(gid);
+ if (PL_gid == PL_egid) /* special case $( = $) */
+ (void)PerlProc_setgid(PL_gid);
else {
- gid = (I32)PerlProc_getgid();
+ PL_gid = (I32)PerlProc_getgid();
croak("setrgid() not implemented");
}
#endif
(void)setgroups(i, gary);
}
#else /* HAS_SETGROUPS */
- egid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
+ PL_egid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
#endif /* HAS_SETGROUPS */
if (PL_delaymagic) {
PL_delaymagic |= DM_EGID;
(void)setegid((Gid_t)PL_egid);
#else
#ifdef HAS_SETREGID
- (void)setregid((Gid_t)-1, (Gid_t)egid);
+ (void)setregid((Gid_t)-1, (Gid_t)PL_egid);
#else
#ifdef HAS_SETRESGID
- (void)setresgid((Gid_t)-1, (Gid_t)egid, (Gid_t)-1);
+ (void)setresgid((Gid_t)-1, (Gid_t)PL_egid, (Gid_t)-1);
#else
- if (egid == gid) /* special case $) = $( */
- (void)PerlProc_setgid(egid);
+ if (PL_egid == PL_gid) /* special case $) = $( */
+ (void)PerlProc_setgid(PL_egid);
else {
- egid = (I32)PerlProc_getegid();
+ PL_egid = (I32)PerlProc_getegid();
croak("setegid() not implemented");
}
#endif
for (i = 1; i < PL_origargc; i++) {
if (PL_origargv[i] == s + 1
#ifdef OS2
- || origargv[i] == s + 2
+ || PL_origargv[i] == s + 2
#endif
)
s += strlen(++s); /* this one is ok too */
/* can grab env area too? */
if (PL_origenviron && (PL_origenviron[0] == s + 1
#ifdef OS2
- || (origenviron[0] == s + 9 && (s += 8))
+ || (PL_origenviron[0] == s + 9 && (s += 8))
#endif
)) {
my_setenv("NoNe SuCh", Nullch);
magic_mutexfree(SV *sv, MAGIC *mg)
{
dTHR;
- DEBUG_L(PerlIO_printf(PerlIO_stderr(), "0x%lx: magic_mutexfree 0x%lx\n",
+ DEBUG_S(PerlIO_printf(PerlIO_stderr(), "0x%lx: magic_mutexfree 0x%lx\n",
(unsigned long)thr, (unsigned long)sv);)
if (MgOWNER(mg))
croak("panic: magic_mutexfree");
MUTEX_DESTROY(MgMUTEXP(mg));
COND_DESTROY(MgCONDP(mg));
- SvREFCNT_dec(sv);
return 0;
}
#endif /* USE_THREADS */
cv = sv_2cv(psig_ptr[sig],&st,&gv,TRUE);
if (!cv || !CvROOT(cv)) {
- if (PL_dowarn)
- warn("SIG%s handler \"%s\" not defined.\n",
+ if (ckWARN(WARN_SIGNAL))
+ warner(WARN_SIGNAL, "SIG%s handler \"%s\" not defined.\n",
sig_name[sig], (gv ? GvENAME(gv)
: ((cv && CvGV(cv))
? GvENAME(CvGV(cv))