GLvoid * EL(SV * sv, int needlen) { STRLEN skip = 0; SV * svref; if (SvREADONLY(sv)) croak("Readonly value for buffer"); if(SvROK(sv)) { svref = SvRV(sv); sv = svref; } else { #ifdef USE_STRICT_UNGLOB if (SvFAKE(sv) && SvTYPE(sv) == SVt_PVGV) sv_unglob(sv); #endif SvUPGRADE(sv, SVt_PV); SvGROW(sv, (unsigned int)(needlen + 1)); SvPOK_on(sv); SvCUR_set(sv, needlen); *SvEND(sv) = '\0'; /* Why is this here? -chm */ } return SvPV_force(sv, skip); }
SSize_t PerlIOScalar_write(pTHX_ PerlIO * f, const void *vbuf, Size_t count) { if (PerlIOBase(f)->flags & PERLIO_F_CANWRITE) { Off_t offset; PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar); SV *sv = s->var; char *dst; if ((PerlIOBase(f)->flags) & PERLIO_F_APPEND) { dst = SvGROW(sv, SvCUR(sv) + count); offset = SvCUR(sv); s->posn = offset + count; } else { if ((s->posn + count) > SvCUR(sv)) dst = SvGROW(sv, (STRLEN)s->posn + count); else dst = SvPV_nolen(sv); offset = s->posn; s->posn += count; } Move(vbuf, dst + offset, count, char); if ((STRLEN) s->posn > SvCUR(sv)) SvCUR_set(sv, (STRLEN)s->posn); SvPOK_on(s->var); return count; }
static HV* S_thaw_fields(lucy_InStream *instream) { // Read frozen data into an SV buffer. size_t len = (size_t)LUCY_InStream_Read_C64(instream); SV *buf_sv = newSV(len + 1); SvPOK_on(buf_sv); SvCUR_set(buf_sv, len); char *buf = SvPVX(buf_sv); LUCY_InStream_Read_Bytes(instream, buf, len); // Call back to Storable to thaw the frozen hash. dSP; ENTER; SAVETMPS; EXTEND(SP, 1); PUSHMARK(SP); mPUSHs(buf_sv); PUTBACK; call_pv("Storable::thaw", G_SCALAR); SPAGAIN; SV *frozen = POPs; if (frozen && !SvROK(frozen)) { CFISH_THROW(CFISH_ERR, "thaw failed"); } HV *fields = (HV*)SvRV(frozen); (void)SvREFCNT_inc((SV*)fields); PUTBACK; FREETMPS; LEAVE; return fields; }
static void pe_tracevar(pe_watcher *wa, SV *sv, int got) { /* Adapted from tkGlue.c We are a "magic" set processor. So we are (I think) supposed to look at "private" flags and set the public ones if appropriate. e.g. "chop" sets SvPOKp as a hint but not SvPOK presumably other operators set other private bits. Question are successive "magics" called in correct order? i.e. if we are tracing a tied variable should we call some magic list or be careful how we insert ourselves in the list? */ pe_ioevent *ev; if (SvPOKp(sv)) SvPOK_on(sv); if (SvNOKp(sv)) SvNOK_on(sv); if (SvIOKp(sv)) SvIOK_on(sv); ev = (pe_ioevent*) (*wa->vtbl->new_event)(wa); ++ev->base.hits; ev->got |= got; queueEvent((pe_event*) ev); }
SV* P_newSVqv2(pTHX_ int i, const char* (*func)(int i,int* len)){ int len; const char* s=(*func)(i,&len); SV* m=newSVpv(s,len); sv_setiv(m,i); SvPOK_on(m); return m; }
SSize_t PerlIOScalar_unread(pTHX_ PerlIO * f, const void *vbuf, Size_t count) { PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar); char *dst = SvGROW(s->var, (STRLEN)s->posn + count); Move(vbuf, dst + s->posn, count, char); s->posn += count; SvCUR_set(s->var, (STRLEN)s->posn); SvPOK_on(s->var); return count; }
static XS(epoc_getcwd) /* more or less stolen from win32.c */ { dXSARGS; /* Make the host for current directory */ char *buffer; int buflen = 256; char *ptr; buffer = (char *) malloc( buflen); if (buffer == NULL) { XSRETURN_UNDEF; } while ((NULL == ( ptr = getcwd( buffer, buflen))) && (errno == ERANGE)) { buflen *= 2; if (NULL == realloc( buffer, buflen)) { XSRETURN_UNDEF; } } /* * If ptr != Nullch * then it worked, set PV valid, * else return 'undef' */ if (ptr) { SV *sv = sv_newmortal(); char *tptr; for (tptr = ptr; *tptr != '\0'; tptr++) { if (*tptr == '\\') { *tptr = '/'; } } sv_setpv(sv, ptr); free( buffer); EXTEND(SP,1); SvPOK_on(sv); ST(0) = sv; #ifndef INCOMPLETE_TAINTS SvTAINTED_on(ST(0)); #endif XSRETURN(1); } free( buffer); XSRETURN_UNDEF; }
static void tn_encode_hash(SV *data, struct tn_buffer *buf) { HV *hash = (HV *)data; HE *entry; SV *key; hv_iterinit(hash); while(entry = hv_iternext(hash)) { key = hv_iterkeysv(entry); SvPOK_on(key); tn_encode(hv_iterval(hash, entry), buf); tn_encode(key, buf); } }
MP_INLINE SV *modperl_slurp_filename(pTHX_ request_rec *r, int tainted) { SV *sv; apr_status_t rc; apr_size_t size; apr_file_t *file; size = r->finfo.size; sv = newSV(size); /* XXX: could have checked whether r->finfo.filehand is valid and * save the apr_file_open call, but apache gives us no API to * check whether filehand is valid. we can't test whether it's * NULL or not, as it may contain garbagea */ rc = apr_file_open(&file, r->filename, APR_READ|APR_BINARY, APR_OS_DEFAULT, r->pool); SLURP_SUCCESS("opening"); rc = apr_file_read(file, SvPVX(sv), &size); SLURP_SUCCESS("reading"); MP_TRACE_o(MP_FUNC, "read %d bytes from '%s'", size, r->filename); if (r->finfo.size != size) { SvREFCNT_dec(sv); Perl_croak(aTHX_ "Error: read %d bytes, expected %d ('%s')", size, (apr_size_t)r->finfo.size, r->filename); } rc = apr_file_close(file); SLURP_SUCCESS("closing"); SvPVX(sv)[size] = '\0'; SvCUR_set(sv, size); SvPOK_on(sv); if (tainted) { SvTAINTED_on(sv); } else { SvTAINTED_off(sv); } return newRV_noinc(sv); }
lucy_HitDoc* lucy_DefDocReader_fetch_doc(lucy_DefaultDocReader *self, int32_t doc_id) { lucy_Schema *const schema = self->schema; lucy_InStream *const dat_in = self->dat_in; lucy_InStream *const ix_in = self->ix_in; HV *fields = newHV(); int64_t start; uint32_t num_fields; SV *field_name_sv = newSV(1); // Get data file pointer from index, read number of fields. Lucy_InStream_Seek(ix_in, (int64_t)doc_id * 8); start = Lucy_InStream_Read_U64(ix_in); Lucy_InStream_Seek(dat_in, start); num_fields = Lucy_InStream_Read_C32(dat_in); // Decode stored data and build up the doc field by field. while (num_fields--) { STRLEN field_name_len; char *field_name_ptr; SV *value_sv; lucy_FieldType *type; // Read field name. field_name_len = Lucy_InStream_Read_C32(dat_in); field_name_ptr = SvGROW(field_name_sv, field_name_len + 1); Lucy_InStream_Read_Bytes(dat_in, field_name_ptr, field_name_len); SvPOK_on(field_name_sv); SvCUR_set(field_name_sv, field_name_len); SvUTF8_on(field_name_sv); *SvEND(field_name_sv) = '\0'; // Find the Field's FieldType. lucy_ZombieCharBuf *field_name_zcb = CFISH_ZCB_WRAP_STR(field_name_ptr, field_name_len); Lucy_ZCB_Assign_Str(field_name_zcb, field_name_ptr, field_name_len); type = Lucy_Schema_Fetch_Type(schema, (lucy_CharBuf*)field_name_zcb); // Read the field value. switch (Lucy_FType_Primitive_ID(type) & lucy_FType_PRIMITIVE_ID_MASK) { case lucy_FType_TEXT: { STRLEN value_len = Lucy_InStream_Read_C32(dat_in); value_sv = newSV((value_len ? value_len : 1)); Lucy_InStream_Read_Bytes(dat_in, SvPVX(value_sv), value_len); SvCUR_set(value_sv, value_len); *SvEND(value_sv) = '\0'; SvPOK_on(value_sv); SvUTF8_on(value_sv); break; } case lucy_FType_BLOB: { STRLEN value_len = Lucy_InStream_Read_C32(dat_in); value_sv = newSV((value_len ? value_len : 1)); Lucy_InStream_Read_Bytes(dat_in, SvPVX(value_sv), value_len); SvCUR_set(value_sv, value_len); *SvEND(value_sv) = '\0'; SvPOK_on(value_sv); break; } case lucy_FType_FLOAT32: value_sv = newSVnv(Lucy_InStream_Read_F32(dat_in)); break; case lucy_FType_FLOAT64: value_sv = newSVnv(Lucy_InStream_Read_F64(dat_in)); break; case lucy_FType_INT32: value_sv = newSViv((int32_t)Lucy_InStream_Read_C32(dat_in)); break; case lucy_FType_INT64: if (sizeof(IV) == 8) { int64_t val = (int64_t)Lucy_InStream_Read_C64(dat_in); value_sv = newSViv((IV)val); } else { // (lossy) int64_t val = (int64_t)Lucy_InStream_Read_C64(dat_in); value_sv = newSVnv((double)val); } break; default: value_sv = NULL; CFISH_THROW(LUCY_ERR, "Unrecognized type: %o", type); } // Store the value. (void)hv_store_ent(fields, field_name_sv, value_sv, 0); } SvREFCNT_dec(field_name_sv); lucy_HitDoc *retval = lucy_HitDoc_new(fields, doc_id, 0.0); SvREFCNT_dec((SV*)fields); return retval; }
void LUCY_RegexTokenizer_Tokenize_Utf8_IMP(lucy_RegexTokenizer *self, const char *string, size_t string_len, lucy_Inversion *inversion) { dTHX; lucy_RegexTokenizerIVARS *const ivars = lucy_RegexTokenizer_IVARS(self); uint32_t num_code_points = 0; SV *wrapper = sv_newmortal(); #if (PERL_VERSION > 10) REGEXP *rx = (REGEXP*)ivars->token_re; regexp *rx_struct = (regexp*)SvANY(rx); #else REGEXP *rx = (REGEXP*)ivars->token_re; regexp *rx_struct = rx; #endif char *string_beg = (char*)string; char *string_end = string_beg + string_len; char *string_arg = string_beg; // Fake up an SV wrapper to feed to the regex engine. sv_upgrade(wrapper, SVt_PV); SvREADONLY_on(wrapper); SvLEN(wrapper) = 0; SvUTF8_on(wrapper); // Wrap the string in an SV to please the regex engine. SvPVX(wrapper) = string_beg; SvCUR_set(wrapper, string_len); SvPOK_on(wrapper); while (pregexec(rx, string_arg, string_end, string_arg, 1, wrapper, 1)) { #if ((PERL_VERSION >= 10) || (PERL_VERSION == 9 && PERL_SUBVERSION >= 5)) char *const start_ptr = string_arg + rx_struct->offs[0].start; char *const end_ptr = string_arg + rx_struct->offs[0].end; #else char *const start_ptr = string_arg + rx_struct->startp[0]; char *const end_ptr = string_arg + rx_struct->endp[0]; #endif uint32_t start, end; // Get start and end offsets in Unicode code points. for (; string_arg < start_ptr; num_code_points++) { string_arg += cfish_StrHelp_UTF8_COUNT[(uint8_t)(*string_arg)]; if (string_arg > string_end) { THROW(CFISH_ERR, "scanned past end of '%s'", string_beg); } } start = num_code_points; for (; string_arg < end_ptr; num_code_points++) { string_arg += cfish_StrHelp_UTF8_COUNT[(uint8_t)(*string_arg)]; if (string_arg > string_end) { THROW(CFISH_ERR, "scanned past end of '%s'", string_beg); } } end = num_code_points; // Add a token to the new inversion. LUCY_Inversion_Append(inversion, lucy_Token_new( start_ptr, (end_ptr - start_ptr), start, end, 1.0f, // boost always 1 for now 1 // position increment ) ); } }
/* =for apidoc mro_get_linear_isa_dfs Returns the Depth-First Search linearization of @ISA the given stash. The return value is a read-only AV*. C<level> should be 0 (it is used internally in this function's recursion). You are responsible for C<SvREFCNT_inc()> on the return value if you plan to store it anywhere semi-permanently (otherwise it might be deleted out from under you the next time the cache is invalidated). =cut */ static AV* S_mro_get_linear_isa_dfs(pTHX_ HV *stash, U32 level) { AV* retval; GV** gvp; GV* gv; AV* av; const HEK* stashhek; struct mro_meta* meta; SV *our_name; HV *stored; PERL_ARGS_ASSERT_MRO_GET_LINEAR_ISA_DFS; assert(HvAUX(stash)); stashhek = HvNAME_HEK(stash); if (!stashhek) Perl_croak(aTHX_ "Can't linearize anonymous symbol table"); if (level > 100) Perl_croak(aTHX_ "Recursive inheritance detected in package '%s'", HEK_KEY(stashhek)); meta = HvMROMETA(stash); /* return cache if valid */ if((retval = MUTABLE_AV(MRO_GET_PRIVATE_DATA(meta, &dfs_alg)))) { return retval; } /* not in cache, make a new one */ retval = MUTABLE_AV(sv_2mortal(MUTABLE_SV(newAV()))); /* We use this later in this function, but don't need a reference to it beyond the end of this function, so reference count is fine. */ our_name = newSVhek(stashhek); av_push(retval, our_name); /* add ourselves at the top */ /* fetch our @ISA */ gvp = (GV**)hv_fetchs(stash, "ISA", FALSE); av = (gvp && (gv = *gvp) && isGV_with_GP(gv)) ? GvAV(gv) : NULL; /* "stored" is used to keep track of all of the classnames we have added to the MRO so far, so we can do a quick exists check and avoid adding duplicate classnames to the MRO as we go. It's then retained to be re-used as a fast lookup for ->isa(), by adding our own name and "UNIVERSAL" to it. */ stored = MUTABLE_HV(sv_2mortal(MUTABLE_SV(newHV()))); if(av && AvFILLp(av) >= 0) { SV **svp = AvARRAY(av); I32 items = AvFILLp(av) + 1; /* foreach(@ISA) */ while (items--) { SV* const sv = *svp++; HV* const basestash = gv_stashsv(sv, 0); SV *const *subrv_p; I32 subrv_items; if (!basestash) { /* if no stash exists for this @ISA member, simply add it to the MRO and move on */ subrv_p = &sv; subrv_items = 1; } else { /* otherwise, recurse into ourselves for the MRO of this @ISA member, and append their MRO to ours. The recursive call could throw an exception, which has memory management implications here, hence the use of the mortal. */ const AV *const subrv = mro_get_linear_isa_dfs(basestash, level + 1); subrv_p = AvARRAY(subrv); subrv_items = AvFILLp(subrv) + 1; } while(subrv_items--) { SV *const subsv = *subrv_p++; /* LVALUE fetch will create a new undefined SV if necessary */ HE *const he = hv_fetch_ent(stored, subsv, 1, 0); assert(he); if(HeVAL(he) != &PL_sv_undef) { /* It was newly created. Steal it for our new SV, and replace it in the hash with the "real" thing. */ SV *const val = HeVAL(he); HEK *const key = HeKEY_hek(he); HeVAL(he) = &PL_sv_undef; /* Save copying by making a shared hash key scalar. We inline this here rather than calling Perl_newSVpvn_share because we already have the scalar, and we already have the hash key. */ assert(SvTYPE(val) == SVt_NULL); sv_upgrade(val, SVt_PV); SvPV_set(val, HEK_KEY(share_hek_hek(key))); SvCUR_set(val, HEK_LEN(key)); SvREADONLY_on(val); SvFAKE_on(val); SvPOK_on(val); if (HEK_UTF8(key)) SvUTF8_on(val); av_push(retval, val); } } } } (void) hv_store_ent(stored, our_name, &PL_sv_undef, 0); (void) hv_store(stored, "UNIVERSAL", 9, &PL_sv_undef, 0); SvREFCNT_inc_simple_void_NN(stored); SvTEMP_off(stored); SvREADONLY_on(stored); meta->isa = stored; /* now that we're past the exception dangers, grab our own reference to the AV we're about to use for the result. The reference owned by the mortals' stack will be released soon, so everything will balance. */ SvREFCNT_inc_simple_void_NN(retval); SvTEMP_off(retval); /* we don't want anyone modifying the cache entry but us, and we do so by replacing it completely */ SvREADONLY_on(retval); return MUTABLE_AV(Perl_mro_set_private_data(aTHX_ meta, &dfs_alg, MUTABLE_SV(retval))); }
SV* P_newSVqv(pTHX_ const char* s, int i){ SV* m=newSVpv(s,strlen(s)); sv_setiv(m,i); SvPOK_on(m); return m; }
SV* P_newSVqvn(pTHX_ const char* s, STRLEN len, int i){ SV* m=newSVpv(s,len); sv_setiv(m,i); SvPOK_on(m); return m; }
void P_sv_setqvn(pTHX_ SV* m, int i, const char* s, STRLEN len){ sv_setpvn(m,s,len); SvIV_set(m,i); SvPOK_on(m); }