This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
VAX: catch vax floats beyond VMS or Ultrix
[perl5.git] / universal.c
CommitLineData
d6376244
JH
1/* universal.c
2 *
b5f8cc5c 3 * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
1129b882 4 * 2005, 2006, 2007, 2008 by Larry Wall and others
d6376244
JH
5 *
6 * You may distribute under the terms of either the GNU General Public
7 * License or the Artistic License, as specified in the README file.
8 *
9 */
10
d31a8517 11/*
4ac71550
TC
12 * '"The roots of those mountains must be roots indeed; there must be
13 * great secrets buried there which have not been discovered since the
14 * beginning."' --Gandalf, relating Gollum's history
15 *
16 * [p.54 of _The Lord of the Rings_, I/ii: "The Shadow of the Past"]
d31a8517
AT
17 */
18
166f8a29
DM
19/* This file contains the code that implements the functions in Perl's
20 * UNIVERSAL package, such as UNIVERSAL->can().
192b9cd1
AB
21 *
22 * It is also used to store XS functions that need to be present in
23 * miniperl for a lack of a better place to put them. It might be
486ec47a 24 * clever to move them to separate XS files which would then be pulled
192b9cd1 25 * in by some to-be-written build process.
166f8a29
DM
26 */
27
6d4a7be2 28#include "EXTERN.h"
864dbfa3 29#define PERL_IN_UNIVERSAL_C
6d4a7be2 30#include "perl.h"
6d4a7be2 31
97cb92d6 32#if defined(USE_PERLIO)
39f7a870
JH
33#include "perliol.h" /* For the PERLIO_F_XXX */
34#endif
35
6d4a7be2 36/*
37 * Contributed by Graham Barr <Graham.Barr@tiuk.ti.com>
38 * The main guts of traverse_isa was actually copied from gv_fetchmeth
39 */
40
a9ec700e 41STATIC bool
c7abbf64 42S_isa_lookup(pTHX_ HV *stash, const char * const name, STRLEN len, U32 flags)
6d4a7be2 43{
a49ba3fc 44 const struct mro_meta *const meta = HvMROMETA(stash);
4340b386 45 HV *isa = meta->isa;
a49ba3fc 46 const HV *our_stash;
6d4a7be2 47
7918f24d
NC
48 PERL_ARGS_ASSERT_ISA_LOOKUP;
49
4340b386
FC
50 if (!isa) {
51 (void)mro_get_linear_isa(stash);
52 isa = meta->isa;
53 }
54
c7abbf64 55 if (hv_common(isa, NULL, name, len, ( flags & SVf_UTF8 ? HVhek_UTF8 : 0),
a49ba3fc
NC
56 HV_FETCH_ISEXISTS, NULL, 0)) {
57 /* Direct name lookup worked. */
a9ec700e 58 return TRUE;
a49ba3fc 59 }
6d4a7be2 60
a49ba3fc 61 /* A stash/class can go by many names (ie. User == main::User), so
81a5123c
FC
62 we use the HvENAME in the stash itself, which is canonical, falling
63 back to HvNAME if necessary. */
c7abbf64 64 our_stash = gv_stashpvn(name, len, flags);
a49ba3fc
NC
65
66 if (our_stash) {
81a5123c
FC
67 HEK *canon_name = HvENAME_HEK(our_stash);
68 if (!canon_name) canon_name = HvNAME_HEK(our_stash);
316ebaf2 69 assert(canon_name);
a49ba3fc
NC
70 if (hv_common(isa, NULL, HEK_KEY(canon_name), HEK_LEN(canon_name),
71 HEK_FLAGS(canon_name),
72 HV_FETCH_ISEXISTS, NULL, HEK_HASH(canon_name))) {
e1a479c5 73 return TRUE;
a49ba3fc 74 }
6d4a7be2 75 }
76
a9ec700e 77 return FALSE;
6d4a7be2 78}
79
954c1994 80/*
ccfc67b7
JH
81=head1 SV Manipulation Functions
82
c7abbf64 83=for apidoc sv_derived_from_pvn
954c1994 84
6885da0e 85Returns a boolean indicating whether the SV is derived from the specified class
86I<at the C level>. To check derivation at the Perl level, call C<isa()> as a
87normal Perl method.
954c1994 88
c7abbf64
BF
89Currently, the only significant value for C<flags> is SVf_UTF8.
90
91=cut
92
93=for apidoc sv_derived_from_sv
94
95Exactly like L</sv_derived_from_pvn>, but takes the name string in the form
96of an SV instead of a string/length pair.
97
98=cut
99
100*/
101
102bool
103Perl_sv_derived_from_sv(pTHX_ SV *sv, SV *namesv, U32 flags)
104{
105 char *namepv;
106 STRLEN namelen;
107 PERL_ARGS_ASSERT_SV_DERIVED_FROM_SV;
108 namepv = SvPV(namesv, namelen);
109 if (SvUTF8(namesv))
110 flags |= SVf_UTF8;
111 return sv_derived_from_pvn(sv, namepv, namelen, flags);
112}
113
114/*
115=for apidoc sv_derived_from
116
117Exactly like L</sv_derived_from_pv>, but doesn't take a C<flags> parameter.
118
954c1994
GS
119=cut
120*/
121
55497cff 122bool
15f169a1 123Perl_sv_derived_from(pTHX_ SV *sv, const char *const name)
55497cff 124{
c7abbf64
BF
125 PERL_ARGS_ASSERT_SV_DERIVED_FROM;
126 return sv_derived_from_pvn(sv, name, strlen(name), 0);
127}
128
129/*
130=for apidoc sv_derived_from_pv
131
132Exactly like L</sv_derived_from_pvn>, but takes a nul-terminated string
133instead of a string/length pair.
134
135=cut
136*/
137
138
139bool
140Perl_sv_derived_from_pv(pTHX_ SV *sv, const char *const name, U32 flags)
141{
142 PERL_ARGS_ASSERT_SV_DERIVED_FROM_PV;
143 return sv_derived_from_pvn(sv, name, strlen(name), flags);
144}
145
146bool
147Perl_sv_derived_from_pvn(pTHX_ SV *sv, const char *const name, const STRLEN len, U32 flags)
148{
0b6f4f5c 149 HV *stash;
46e4b22b 150
c7abbf64 151 PERL_ARGS_ASSERT_SV_DERIVED_FROM_PVN;
7918f24d 152
5b295bef 153 SvGETMAGIC(sv);
55497cff 154
bff39573 155 if (SvROK(sv)) {
0b6f4f5c 156 const char *type;
55497cff 157 sv = SvRV(sv);
158 type = sv_reftype(sv,0);
0b6f4f5c
AL
159 if (type && strEQ(type,name))
160 return TRUE;
d70bfb04
JL
161 if (!SvOBJECT(sv))
162 return FALSE;
163 stash = SvSTASH(sv);
55497cff 164 }
165 else {
da51bb9b 166 stash = gv_stashsv(sv, 0);
55497cff 167 }
46e4b22b 168
d70bfb04
JL
169 if (stash && isa_lookup(stash, name, len, flags))
170 return TRUE;
171
172 stash = gv_stashpvs("UNIVERSAL", 0);
173 return stash && isa_lookup(stash, name, len, flags);
55497cff 174}
175
cbc021f9 176/*
d20c2c29 177=for apidoc sv_does_sv
cbc021f9 178
179Returns a boolean indicating whether the SV performs a specific, named role.
180The SV can be a Perl object or the name of a Perl class.
181
182=cut
183*/
184
1b026014
NIS
185#include "XSUB.h"
186
cbc021f9 187bool
f778bcfd 188Perl_sv_does_sv(pTHX_ SV *sv, SV *namesv, U32 flags)
cbc021f9 189{
f778bcfd 190 SV *classname;
cbc021f9 191 bool does_it;
59e7186f 192 SV *methodname;
cbc021f9 193 dSP;
7918f24d 194
f778bcfd
BF
195 PERL_ARGS_ASSERT_SV_DOES_SV;
196 PERL_UNUSED_ARG(flags);
7918f24d 197
cbc021f9 198 ENTER;
199 SAVETMPS;
200
201 SvGETMAGIC(sv);
202
d96ab1b5 203 if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv)))) {
7ce46f2a 204 LEAVE;
cbc021f9 205 return FALSE;
7ce46f2a 206 }
cbc021f9 207
4b523e79 208 if (SvROK(sv) && SvOBJECT(SvRV(sv))) {
f778bcfd 209 classname = sv_ref(NULL,SvRV(sv),TRUE);
cbc021f9 210 } else {
f778bcfd 211 classname = sv;
cbc021f9 212 }
213
f778bcfd 214 if (sv_eq(classname, namesv)) {
7ce46f2a 215 LEAVE;
cbc021f9 216 return TRUE;
7ce46f2a 217 }
cbc021f9 218
219 PUSHMARK(SP);
f778bcfd
BF
220 EXTEND(SP, 2);
221 PUSHs(sv);
222 PUSHs(namesv);
cbc021f9 223 PUTBACK;
224
84bafc02 225 methodname = newSVpvs_flags("isa", SVs_TEMP);
59e7186f
RGS
226 /* ugly hack: use the SvSCREAM flag so S_method_common
227 * can figure out we're calling DOES() and not isa(),
228 * and report eventual errors correctly. --rgs */
229 SvSCREAM_on(methodname);
230 call_sv(methodname, G_SCALAR | G_METHOD);
cbc021f9 231 SPAGAIN;
232
233 does_it = SvTRUE( TOPs );
234 FREETMPS;
235 LEAVE;
236
237 return does_it;
238}
239
afa74d42 240/*
f778bcfd
BF
241=for apidoc sv_does
242
d20c2c29 243Like L</sv_does_pv>, but doesn't take a C<flags> parameter.
f778bcfd
BF
244
245=cut
246*/
247
248bool
249Perl_sv_does(pTHX_ SV *sv, const char *const name)
250{
251 PERL_ARGS_ASSERT_SV_DOES;
252 return sv_does_sv(sv, newSVpvn_flags(name, strlen(name), SVs_TEMP), 0);
253}
254
255/*
256=for apidoc sv_does_pv
257
7d892b8c 258Like L</sv_does_sv>, but takes a nul-terminated string instead of an SV.
f778bcfd
BF
259
260=cut
261*/
262
263
264bool
265Perl_sv_does_pv(pTHX_ SV *sv, const char *const name, U32 flags)
266{
267 PERL_ARGS_ASSERT_SV_DOES_PV;
268 return sv_does_sv(sv, newSVpvn_flags(name, strlen(name), SVs_TEMP | flags), flags);
269}
270
7d892b8c
FC
271/*
272=for apidoc sv_does_pvn
273
274Like L</sv_does_sv>, but takes a string/length pair instead of an SV.
275
276=cut
277*/
278
f778bcfd
BF
279bool
280Perl_sv_does_pvn(pTHX_ SV *sv, const char *const name, const STRLEN len, U32 flags)
281{
282 PERL_ARGS_ASSERT_SV_DOES_PVN;
283
284 return sv_does_sv(sv, newSVpvn_flags(name, len, flags | SVs_TEMP), flags);
285}
286
287/*
afa74d42
NC
288=for apidoc croak_xs_usage
289
290A specialised variant of C<croak()> for emitting the usage message for xsubs
291
292 croak_xs_usage(cv, "eee_yow");
293
294works out the package name and subroutine name from C<cv>, and then calls
72d33970 295C<croak()>. Hence if C<cv> is C<&ouch::awk>, it would call C<croak> as:
afa74d42 296
8560fbdd
KW
297 Perl_croak(aTHX_ "Usage: %"SVf"::%"SVf"(%s)", "ouch" "awk",
298 "eee_yow");
afa74d42
NC
299
300=cut
301*/
302
303void
cb077ed2 304Perl_croak_xs_usage(const CV *const cv, const char *const params)
afa74d42 305{
ae77754a 306 /* Avoid CvGV as it requires aTHX. */
2eaf799e 307 const GV *gv = CvNAMED(cv) ? NULL : cv->sv_any->xcv_gv_u.xcv_gv;
afa74d42
NC
308
309 PERL_ARGS_ASSERT_CROAK_XS_USAGE;
310
2eaf799e 311 if (gv) got_gv: {
afa74d42 312 const HV *const stash = GvSTASH(gv);
afa74d42 313
58cb15b3 314 if (HvNAME_get(stash))
d3ee9aa5 315 /* diag_listed_as: SKIPME */
cb077ed2 316 Perl_croak_nocontext("Usage: %"HEKf"::%"HEKf"(%s)",
d0c0e7dd
FC
317 HEKfARG(HvNAME_HEK(stash)),
318 HEKfARG(GvNAME_HEK(gv)),
58cb15b3 319 params);
afa74d42 320 else
d3ee9aa5 321 /* diag_listed_as: SKIPME */
cb077ed2 322 Perl_croak_nocontext("Usage: %"HEKf"(%s)",
d0c0e7dd 323 HEKfARG(GvNAME_HEK(gv)), params);
afa74d42 324 } else {
2eaf799e
FC
325 dTHX;
326 if ((gv = CvGV(cv))) goto got_gv;
327
afa74d42 328 /* Pants. I don't think that it should be possible to get here. */
d3ee9aa5 329 /* diag_listed_as: SKIPME */
6e9fdf66 330 Perl_croak(aTHX_ "Usage: CODE(0x%"UVxf")(%s)", PTR2UV(cv), params);
afa74d42
NC
331 }
332}
55497cff 333
15eb3045 334XS(XS_UNIVERSAL_isa); /* prototype to pass -Wmissing-prototypes */
6d4a7be2 335XS(XS_UNIVERSAL_isa)
336{
337 dXSARGS;
6d4a7be2 338
339 if (items != 2)
afa74d42 340 croak_xs_usage(cv, "reference, kind");
c4420975
AL
341 else {
342 SV * const sv = ST(0);
6d4a7be2 343
c4420975 344 SvGETMAGIC(sv);
d3f7f2b2 345
d96ab1b5 346 if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))))
c4420975 347 XSRETURN_UNDEF;
f8f70380 348
c7abbf64 349 ST(0) = boolSV(sv_derived_from_sv(sv, ST(1), 0));
c4420975
AL
350 XSRETURN(1);
351 }
6d4a7be2 352}
353
15eb3045 354XS(XS_UNIVERSAL_can); /* prototype to pass -Wmissing-prototypes */
6d4a7be2 355XS(XS_UNIVERSAL_can)
356{
357 dXSARGS;
358 SV *sv;
6d4a7be2 359 SV *rv;
6f08146e 360 HV *pkg = NULL;
2bde9ae6 361 GV *iogv;
6d4a7be2 362
363 if (items != 2)
afa74d42 364 croak_xs_usage(cv, "object-ref, method");
6d4a7be2 365
366 sv = ST(0);
f8f70380 367
5b295bef 368 SvGETMAGIC(sv);
d3f7f2b2 369
4178f891
FC
370 /* Reject undef and empty string. Note that the string form takes
371 precedence here over the numeric form, as (!1)->foo treats the
372 invocant as the empty string, though it is a dualvar. */
373 if (!SvOK(sv) || (SvPOK(sv) && !SvCUR(sv)))
f8f70380
GS
374 XSRETURN_UNDEF;
375
3280af22 376 rv = &PL_sv_undef;
6d4a7be2 377
46e4b22b 378 if (SvROK(sv)) {
daba3364 379 sv = MUTABLE_SV(SvRV(sv));
46e4b22b 380 if (SvOBJECT(sv))
6f08146e 381 pkg = SvSTASH(sv);
4178f891
FC
382 else if (isGV_with_GP(sv) && GvIO(sv))
383 pkg = SvSTASH(GvIO(sv));
6f08146e 384 }
4178f891
FC
385 else if (isGV_with_GP(sv) && GvIO(sv))
386 pkg = SvSTASH(GvIO(sv));
2bde9ae6
FC
387 else if ((iogv = gv_fetchsv_nomg(sv, 0, SVt_PVIO)) && GvIO(iogv))
388 pkg = SvSTASH(GvIO(iogv));
6f08146e 389 else {
da51bb9b 390 pkg = gv_stashsv(sv, 0);
68b40612 391 if (!pkg)
7d59d161 392 pkg = gv_stashpvs("UNIVERSAL", 0);
6f08146e
NIS
393 }
394
395 if (pkg) {
a00b390b 396 GV * const gv = gv_fetchmethod_sv_flags(pkg, ST(1), 0);
dc848c6f 397 if (gv && isGV(gv))
daba3364 398 rv = sv_2mortal(newRV(MUTABLE_SV(GvCV(gv))));
6d4a7be2 399 }
400
401 ST(0) = rv;
402 XSRETURN(1);
403}
404
15eb3045 405XS(XS_UNIVERSAL_DOES); /* prototype to pass -Wmissing-prototypes */
cbc021f9 406XS(XS_UNIVERSAL_DOES)
407{
cbc021f9 408 dXSARGS;
58c0efa5 409 PERL_UNUSED_ARG(cv);
cbc021f9 410
411 if (items != 2)
46404226 412 Perl_croak(aTHX_ "Usage: invocant->DOES(kind)");
cbc021f9 413 else {
414 SV * const sv = ST(0);
f778bcfd 415 if (sv_does_sv( sv, ST(1), 0 ))
cbc021f9 416 XSRETURN_YES;
417
418 XSRETURN_NO;
419 }
420}
421
15eb3045 422XS(XS_utf8_is_utf8); /* prototype to pass -Wmissing-prototypes */
8800c35a
JH
423XS(XS_utf8_is_utf8)
424{
41be1fbd
JH
425 dXSARGS;
426 if (items != 1)
afa74d42 427 croak_xs_usage(cv, "sv");
c4420975 428 else {
76f73021
GF
429 SV * const sv = ST(0);
430 SvGETMAGIC(sv);
c4420975
AL
431 if (SvUTF8(sv))
432 XSRETURN_YES;
433 else
434 XSRETURN_NO;
41be1fbd
JH
435 }
436 XSRETURN_EMPTY;
8800c35a
JH
437}
438
15eb3045 439XS(XS_utf8_valid); /* prototype to pass -Wmissing-prototypes */
1b026014
NIS
440XS(XS_utf8_valid)
441{
41be1fbd
JH
442 dXSARGS;
443 if (items != 1)
afa74d42 444 croak_xs_usage(cv, "sv");
c4420975
AL
445 else {
446 SV * const sv = ST(0);
447 STRLEN len;
448 const char * const s = SvPV_const(sv,len);
449 if (!SvUTF8(sv) || is_utf8_string((const U8*)s,len))
450 XSRETURN_YES;
451 else
452 XSRETURN_NO;
453 }
41be1fbd 454 XSRETURN_EMPTY;
1b026014
NIS
455}
456
15eb3045 457XS(XS_utf8_encode); /* prototype to pass -Wmissing-prototypes */
1b026014
NIS
458XS(XS_utf8_encode)
459{
460 dXSARGS;
461 if (items != 1)
afa74d42 462 croak_xs_usage(cv, "sv");
c4420975 463 sv_utf8_encode(ST(0));
892f9127 464 SvSETMAGIC(ST(0));
1b026014
NIS
465 XSRETURN_EMPTY;
466}
467
15eb3045 468XS(XS_utf8_decode); /* prototype to pass -Wmissing-prototypes */
1b026014
NIS
469XS(XS_utf8_decode)
470{
471 dXSARGS;
472 if (items != 1)
afa74d42 473 croak_xs_usage(cv, "sv");
c4420975
AL
474 else {
475 SV * const sv = ST(0);
b2b7346b 476 bool RETVAL;
c7102404 477 SvPV_force_nolen(sv);
b2b7346b 478 RETVAL = sv_utf8_decode(sv);
77fc86ef 479 SvSETMAGIC(sv);
1b026014 480 ST(0) = boolSV(RETVAL);
1b026014
NIS
481 }
482 XSRETURN(1);
483}
484
15eb3045 485XS(XS_utf8_upgrade); /* prototype to pass -Wmissing-prototypes */
1b026014
NIS
486XS(XS_utf8_upgrade)
487{
488 dXSARGS;
489 if (items != 1)
afa74d42 490 croak_xs_usage(cv, "sv");
c4420975
AL
491 else {
492 SV * const sv = ST(0);
1b026014
NIS
493 STRLEN RETVAL;
494 dXSTARG;
495
496 RETVAL = sv_utf8_upgrade(sv);
497 XSprePUSH; PUSHi((IV)RETVAL);
498 }
499 XSRETURN(1);
500}
501
15eb3045 502XS(XS_utf8_downgrade); /* prototype to pass -Wmissing-prototypes */
1b026014
NIS
503XS(XS_utf8_downgrade)
504{
505 dXSARGS;
506 if (items < 1 || items > 2)
afa74d42 507 croak_xs_usage(cv, "sv, failok=0");
c4420975
AL
508 else {
509 SV * const sv = ST(0);
3ca75eca 510 const bool failok = (items < 2) ? 0 : SvTRUE(ST(1)) ? 1 : 0;
6867be6d 511 const bool RETVAL = sv_utf8_downgrade(sv, failok);
1b026014 512
1b026014 513 ST(0) = boolSV(RETVAL);
1b026014
NIS
514 }
515 XSRETURN(1);
516}
517
15eb3045 518XS(XS_utf8_native_to_unicode); /* prototype to pass -Wmissing-prototypes */
1b026014
NIS
519XS(XS_utf8_native_to_unicode)
520{
521 dXSARGS;
6867be6d 522 const UV uv = SvUV(ST(0));
b7953727
JH
523
524 if (items > 1)
afa74d42 525 croak_xs_usage(cv, "sv");
b7953727 526
b5804ad6 527 ST(0) = sv_2mortal(newSVuv(NATIVE_TO_UNI(uv)));
1b026014
NIS
528 XSRETURN(1);
529}
530
15eb3045 531XS(XS_utf8_unicode_to_native); /* prototype to pass -Wmissing-prototypes */
1b026014
NIS
532XS(XS_utf8_unicode_to_native)
533{
534 dXSARGS;
6867be6d 535 const UV uv = SvUV(ST(0));
b7953727
JH
536
537 if (items > 1)
afa74d42 538 croak_xs_usage(cv, "sv");
b7953727 539
b5804ad6 540 ST(0) = sv_2mortal(newSVuv(UNI_TO_NATIVE(uv)));
1b026014
NIS
541 XSRETURN(1);
542}
543
15eb3045 544XS(XS_Internals_SvREADONLY); /* prototype to pass -Wmissing-prototypes */
14a976d6 545XS(XS_Internals_SvREADONLY) /* This is dangerous stuff. */
29569577
JH
546{
547 dXSARGS;
80b6a949
AB
548 SV * const svz = ST(0);
549 SV * sv;
58c0efa5 550 PERL_UNUSED_ARG(cv);
6867be6d 551
80b6a949
AB
552 /* [perl #77776] - called as &foo() not foo() */
553 if (!SvROK(svz))
554 croak_xs_usage(cv, "SCALAR[, ON]");
555
556 sv = SvRV(svz);
557
29569577 558 if (items == 1) {
1620522e 559 if (SvREADONLY(sv))
29569577
JH
560 XSRETURN_YES;
561 else
562 XSRETURN_NO;
563 }
564 else if (items == 2) {
565 if (SvTRUE(ST(1))) {
a623f893 566 SvFLAGS(sv) |= SVf_READONLY;
29569577
JH
567 XSRETURN_YES;
568 }
569 else {
14a976d6 570 /* I hope you really know what you are doing. */
a623f893 571 SvFLAGS(sv) &=~ SVf_READONLY;
29569577
JH
572 XSRETURN_NO;
573 }
574 }
14a976d6 575 XSRETURN_UNDEF; /* Can't happen. */
29569577 576}
2c6c1df5 577
15eb3045 578XS(XS_constant__make_const); /* prototype to pass -Wmissing-prototypes */
2c6c1df5
FC
579XS(XS_constant__make_const) /* This is dangerous stuff. */
580{
2c6c1df5
FC
581 dXSARGS;
582 SV * const svz = ST(0);
583 SV * sv;
584 PERL_UNUSED_ARG(cv);
585
586 /* [perl #77776] - called as &foo() not foo() */
587 if (!SvROK(svz) || items != 1)
588 croak_xs_usage(cv, "SCALAR");
589
590 sv = SvRV(svz);
591
2c6c1df5
FC
592 SvREADONLY_on(sv);
593 if (SvTYPE(sv) == SVt_PVAV && AvFILLp(sv) != -1) {
594 /* for constant.pm; nobody else should be calling this
595 on arrays anyway. */
596 SV **svp;
597 for (svp = AvARRAY(sv) + AvFILLp(sv)
598 ; svp >= AvARRAY(sv)
599 ; --svp)
600 if (*svp) SvPADTMP_on(*svp);
601 }
602 XSRETURN(0);
603}
604
15eb3045 605XS(XS_Internals_SvREFCNT); /* prototype to pass -Wmissing-prototypes */
14a976d6 606XS(XS_Internals_SvREFCNT) /* This is dangerous stuff. */
29569577
JH
607{
608 dXSARGS;
80b6a949
AB
609 SV * const svz = ST(0);
610 SV * sv;
fa3febb6 611 U32 refcnt;
58c0efa5 612 PERL_UNUSED_ARG(cv);
6867be6d 613
80b6a949 614 /* [perl #77776] - called as &foo() not foo() */
fa3febb6 615 if ((items != 1 && items != 2) || !SvROK(svz))
80b6a949
AB
616 croak_xs_usage(cv, "SCALAR[, REFCOUNT]");
617
618 sv = SvRV(svz);
619
14a976d6 620 /* I hope you really know what you are doing. */
fa3febb6
DD
621 /* idea is for SvREFCNT(sv) to be accessed only once */
622 refcnt = items == 2 ?
623 /* we free one ref on exit */
624 (SvREFCNT(sv) = SvUV(ST(1)) + 1)
625 : SvREFCNT(sv);
626 XSRETURN_UV(refcnt - 1); /* Minus the ref created for us. */
627
29569577
JH
628}
629
15eb3045 630XS(XS_Internals_hv_clear_placehold); /* prototype to pass -Wmissing-prototypes */
f044d0d1 631XS(XS_Internals_hv_clear_placehold)
dfd4ef2f
NC
632{
633 dXSARGS;
6867be6d 634
80b6a949 635 if (items != 1 || !SvROK(ST(0)))
afa74d42 636 croak_xs_usage(cv, "hv");
c4420975 637 else {
ef8f7699 638 HV * const hv = MUTABLE_HV(SvRV(ST(0)));
c4420975
AL
639 hv_clear_placeholders(hv);
640 XSRETURN(0);
641 }
dfd4ef2f 642}
39f7a870 643
15eb3045 644XS(XS_PerlIO_get_layers); /* prototype to pass -Wmissing-prototypes */
39f7a870
JH
645XS(XS_PerlIO_get_layers)
646{
647 dXSARGS;
648 if (items < 1 || items % 2 == 0)
afa74d42 649 croak_xs_usage(cv, "filehandle[,args]");
97cb92d6 650#if defined(USE_PERLIO)
39f7a870
JH
651 {
652 SV * sv;
653 GV * gv;
654 IO * io;
655 bool input = TRUE;
656 bool details = FALSE;
657
658 if (items > 1) {
c4420975 659 SV * const *svp;
39f7a870 660 for (svp = MARK + 2; svp <= SP; svp += 2) {
c4420975
AL
661 SV * const * const varp = svp;
662 SV * const * const valp = svp + 1;
39f7a870 663 STRLEN klen;
c4420975 664 const char * const key = SvPV_const(*varp, klen);
39f7a870
JH
665
666 switch (*key) {
667 case 'i':
668 if (klen == 5 && memEQ(key, "input", 5)) {
669 input = SvTRUE(*valp);
670 break;
671 }
672 goto fail;
673 case 'o':
674 if (klen == 6 && memEQ(key, "output", 6)) {
675 input = !SvTRUE(*valp);
676 break;
677 }
678 goto fail;
679 case 'd':
680 if (klen == 7 && memEQ(key, "details", 7)) {
681 details = SvTRUE(*valp);
682 break;
683 }
684 goto fail;
685 default:
686 fail:
687 Perl_croak(aTHX_
688 "get_layers: unknown argument '%s'",
689 key);
690 }
691 }
692
693 SP -= (items - 1);
694 }
695
696 sv = POPs;
7f9aa7d3 697 gv = MAYBE_DEREF_GV(sv);
39f7a870 698
3825652d 699 if (!gv && !SvROK(sv))
7f9aa7d3 700 gv = gv_fetchsv_nomg(sv, 0, SVt_PVIO);
39f7a870
JH
701
702 if (gv && (io = GvIO(gv))) {
c4420975 703 AV* const av = PerlIO_get_layers(aTHX_ input ?
39f7a870 704 IoIFP(io) : IoOFP(io));
c70927a6 705 SSize_t i;
b9f2b683 706 const SSize_t last = av_tindex(av);
c70927a6 707 SSize_t nitem = 0;
39f7a870
JH
708
709 for (i = last; i >= 0; i -= 3) {
c4420975
AL
710 SV * const * const namsvp = av_fetch(av, i - 2, FALSE);
711 SV * const * const argsvp = av_fetch(av, i - 1, FALSE);
712 SV * const * const flgsvp = av_fetch(av, i, FALSE);
39f7a870 713
c4420975
AL
714 const bool namok = namsvp && *namsvp && SvPOK(*namsvp);
715 const bool argok = argsvp && *argsvp && SvPOK(*argsvp);
716 const bool flgok = flgsvp && *flgsvp && SvIOK(*flgsvp);
39f7a870 717
2102d7a2 718 EXTEND(SP, 3); /* Three is the max in all branches: better check just once */
39f7a870 719 if (details) {
92e45a3e
NC
720 /* Indents of 5? Yuck. */
721 /* We know that PerlIO_get_layers creates a new SV for
722 the name and flags, so we can just take a reference
723 and "steal" it when we free the AV below. */
2102d7a2 724 PUSHs(namok
92e45a3e 725 ? sv_2mortal(SvREFCNT_inc_simple_NN(*namsvp))
ec3bab8e 726 : &PL_sv_undef);
2102d7a2 727 PUSHs(argok
92e45a3e
NC
728 ? newSVpvn_flags(SvPVX_const(*argsvp),
729 SvCUR(*argsvp),
730 (SvUTF8(*argsvp) ? SVf_UTF8 : 0)
731 | SVs_TEMP)
732 : &PL_sv_undef);
2102d7a2 733 PUSHs(flgok
92e45a3e 734 ? sv_2mortal(SvREFCNT_inc_simple_NN(*flgsvp))
ec3bab8e 735 : &PL_sv_undef);
39f7a870
JH
736 nitem += 3;
737 }
738 else {
739 if (namok && argok)
2102d7a2 740 PUSHs(sv_2mortal(Perl_newSVpvf(aTHX_ "%"SVf"(%"SVf")",
be2597df 741 SVfARG(*namsvp),
1eb9e81d 742 SVfARG(*argsvp))));
39f7a870 743 else if (namok)
2102d7a2 744 PUSHs(sv_2mortal(SvREFCNT_inc_simple_NN(*namsvp)));
39f7a870 745 else
2102d7a2 746 PUSHs(&PL_sv_undef);
39f7a870
JH
747 nitem++;
748 if (flgok) {
c4420975 749 const IV flags = SvIVX(*flgsvp);
39f7a870
JH
750
751 if (flags & PERLIO_F_UTF8) {
2102d7a2 752 PUSHs(newSVpvs_flags("utf8", SVs_TEMP));
39f7a870
JH
753 nitem++;
754 }
755 }
756 }
757 }
758
759 SvREFCNT_dec(av);
760
761 XSRETURN(nitem);
762 }
763 }
5fef3b4a 764#endif
39f7a870
JH
765
766 XSRETURN(0);
767}
768
8bf4c401
YO
769XS(XS_hash_util_bucket_ratio); /* prototype to pass -Wmissing-prototypes */
770XS(XS_hash_util_bucket_ratio)
771{
772 dXSARGS;
773 SV *rhv;
774 PERL_UNUSED_VAR(cv);
775
776 if (items != 1)
777 croak_xs_usage(cv, "hv");
778
779 rhv= ST(0);
780 if (SvROK(rhv)) {
781 rhv= SvRV(rhv);
782 if ( SvTYPE(rhv)==SVt_PVHV ) {
783 SV *ret= Perl_hv_bucket_ratio(aTHX_ (HV*)rhv);
784 ST(0)= ret;
785 XSRETURN(1);
786 }
787 }
788 XSRETURN_UNDEF;
789}
790
791XS(XS_hash_util_num_buckets); /* prototype to pass -Wmissing-prototypes */
792XS(XS_hash_util_num_buckets)
793{
794 dXSARGS;
795 SV *rhv;
796 PERL_UNUSED_VAR(cv);
797
798 if (items != 1)
799 croak_xs_usage(cv, "hv");
800
801 rhv= ST(0);
802 if (SvROK(rhv)) {
803 rhv= SvRV(rhv);
804 if ( SvTYPE(rhv)==SVt_PVHV ) {
805 XSRETURN_UV(HvMAX((HV*)rhv)+1);
806 }
807 }
808 XSRETURN_UNDEF;
809}
810
811XS(XS_hash_util_used_buckets); /* prototype to pass -Wmissing-prototypes */
812XS(XS_hash_util_used_buckets)
813{
814 dXSARGS;
815 SV *rhv;
816 PERL_UNUSED_VAR(cv);
817
818 if (items != 1)
819 croak_xs_usage(cv, "hv");
820
821 rhv= ST(0);
822 if (SvROK(rhv)) {
823 rhv= SvRV(rhv);
824 if ( SvTYPE(rhv)==SVt_PVHV ) {
825 XSRETURN_UV(HvFILL((HV*)rhv));
826 }
827 }
828 XSRETURN_UNDEF;
829}
241d1a3b 830
15eb3045 831XS(XS_re_is_regexp); /* prototype to pass -Wmissing-prototypes */
80305961
YO
832XS(XS_re_is_regexp)
833{
80305961 834 dXSARGS;
f7e71195
AB
835 PERL_UNUSED_VAR(cv);
836
80305961 837 if (items != 1)
afa74d42 838 croak_xs_usage(cv, "sv");
f7e71195 839
f7e71195
AB
840 if (SvRXOK(ST(0))) {
841 XSRETURN_YES;
842 } else {
843 XSRETURN_NO;
80305961
YO
844 }
845}
846
15eb3045 847XS(XS_re_regnames_count); /* prototype to pass -Wmissing-prototypes */
192b9cd1 848XS(XS_re_regnames_count)
80305961 849{
192b9cd1
AB
850 REGEXP *rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
851 SV * ret;
80305961 852 dXSARGS;
192b9cd1
AB
853
854 if (items != 0)
afa74d42 855 croak_xs_usage(cv, "");
192b9cd1
AB
856
857 SP -= items;
fdae9473 858 PUTBACK;
192b9cd1
AB
859
860 if (!rx)
861 XSRETURN_UNDEF;
862
863 ret = CALLREG_NAMED_BUFF_COUNT(rx);
864
865 SPAGAIN;
fdae9473
NC
866 PUSHs(ret ? sv_2mortal(ret) : &PL_sv_undef);
867 XSRETURN(1);
192b9cd1
AB
868}
869
15eb3045 870XS(XS_re_regname); /* prototype to pass -Wmissing-prototypes */
192b9cd1
AB
871XS(XS_re_regname)
872{
192b9cd1
AB
873 dXSARGS;
874 REGEXP * rx;
875 U32 flags;
876 SV * ret;
877
28d8d7f4 878 if (items < 1 || items > 2)
afa74d42 879 croak_xs_usage(cv, "name[, all ]");
192b9cd1 880
80305961 881 SP -= items;
fdae9473 882 PUTBACK;
80305961 883
192b9cd1
AB
884 rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
885
886 if (!rx)
887 XSRETURN_UNDEF;
888
889 if (items == 2 && SvTRUE(ST(1))) {
f1b875a0 890 flags = RXapif_ALL;
192b9cd1 891 } else {
f1b875a0 892 flags = RXapif_ONE;
80305961 893 }
f1b875a0 894 ret = CALLREG_NAMED_BUFF_FETCH(rx, ST(0), (flags | RXapif_REGNAME));
192b9cd1 895
fdae9473
NC
896 SPAGAIN;
897 PUSHs(ret ? sv_2mortal(ret) : &PL_sv_undef);
898 XSRETURN(1);
80305961
YO
899}
900
192b9cd1 901
15eb3045 902XS(XS_re_regnames); /* prototype to pass -Wmissing-prototypes */
80305961
YO
903XS(XS_re_regnames)
904{
80305961 905 dXSARGS;
192b9cd1
AB
906 REGEXP * rx;
907 U32 flags;
908 SV *ret;
909 AV *av;
c70927a6
FC
910 SSize_t length;
911 SSize_t i;
192b9cd1
AB
912 SV **entry;
913
914 if (items > 1)
afa74d42 915 croak_xs_usage(cv, "[all]");
192b9cd1
AB
916
917 rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
918
919 if (!rx)
920 XSRETURN_UNDEF;
921
922 if (items == 1 && SvTRUE(ST(0))) {
f1b875a0 923 flags = RXapif_ALL;
192b9cd1 924 } else {
f1b875a0 925 flags = RXapif_ONE;
192b9cd1
AB
926 }
927
80305961 928 SP -= items;
fdae9473 929 PUTBACK;
80305961 930
f1b875a0 931 ret = CALLREG_NAMED_BUFF_ALL(rx, (flags | RXapif_REGNAMES));
192b9cd1
AB
932
933 SPAGAIN;
934
192b9cd1
AB
935 if (!ret)
936 XSRETURN_UNDEF;
937
502c6561 938 av = MUTABLE_AV(SvRV(ret));
b9f2b683 939 length = av_tindex(av);
192b9cd1 940
2102d7a2 941 EXTEND(SP, length+1); /* better extend stack just once */
192b9cd1
AB
942 for (i = 0; i <= length; i++) {
943 entry = av_fetch(av, i, FALSE);
944
945 if (!entry)
946 Perl_croak(aTHX_ "NULL array element in re::regnames()");
947
2102d7a2 948 mPUSHs(SvREFCNT_inc_simple_NN(*entry));
80305961 949 }
ec83ea38
MHM
950
951 SvREFCNT_dec(ret);
952
192b9cd1
AB
953 PUTBACK;
954 return;
80305961
YO
955}
956
15eb3045 957XS(XS_re_regexp_pattern); /* prototype to pass -Wmissing-prototypes */
192c1e27
JH
958XS(XS_re_regexp_pattern)
959{
192c1e27
JH
960 dXSARGS;
961 REGEXP *re;
1c23e2bd 962 U8 const gimme = GIMME_V;
192c1e27 963
22d874e2
DD
964 EXTEND(SP, 2);
965 SP -= items;
192c1e27 966 if (items != 1)
afa74d42 967 croak_xs_usage(cv, "sv");
192c1e27 968
192c1e27
JH
969 /*
970 Checks if a reference is a regex or not. If the parameter is
971 not a ref, or is not the result of a qr// then returns false
972 in scalar context and an empty list in list context.
973 Otherwise in list context it returns the pattern and the
974 modifiers, in scalar context it returns the pattern just as it
975 would if the qr// was stringified normally, regardless as
486ec47a 976 to the class of the variable and any stringification overloads
192c1e27
JH
977 on the object.
978 */
979
980 if ((re = SvRX(ST(0)))) /* assign deliberate */
981 {
22c985d5 982 /* Houston, we have a regex! */
192c1e27 983 SV *pattern;
192c1e27 984
b1dcc8e2 985 if ( gimme == G_ARRAY ) {
9de15fec 986 STRLEN left = 0;
a62b1201 987 char reflags[sizeof(INT_PAT_MODS) + MAX_CHARSET_NAME_LENGTH];
69af1167
SH
988 const char *fptr;
989 char ch;
990 U16 match_flags;
991
192c1e27
JH
992 /*
993 we are in list context so stringify
994 the modifiers that apply. We ignore "negative
a62b1201 995 modifiers" in this scenario, and the default character set
192c1e27
JH
996 */
997
a62b1201
KW
998 if (get_regex_charset(RX_EXTFLAGS(re)) != REGEX_DEPENDS_CHARSET) {
999 STRLEN len;
1000 const char* const name = get_regex_charset_name(RX_EXTFLAGS(re),
1001 &len);
1002 Copy(name, reflags + left, len, char);
1003 left += len;
9de15fec 1004 }
69af1167 1005 fptr = INT_PAT_MODS;
73134a2e 1006 match_flags = (U16)((RX_EXTFLAGS(re) & RXf_PMf_COMPILETIME)
192c1e27
JH
1007 >> RXf_PMf_STD_PMMOD_SHIFT);
1008
1009 while((ch = *fptr++)) {
1010 if(match_flags & 1) {
1011 reflags[left++] = ch;
1012 }
1013 match_flags >>= 1;
1014 }
1015
fb632ce3
NC
1016 pattern = newSVpvn_flags(RX_PRECOMP(re),RX_PRELEN(re),
1017 (RX_UTF8(re) ? SVf_UTF8 : 0) | SVs_TEMP);
192c1e27
JH
1018
1019 /* return the pattern and the modifiers */
2102d7a2
S
1020 PUSHs(pattern);
1021 PUSHs(newSVpvn_flags(reflags, left, SVs_TEMP));
192c1e27
JH
1022 XSRETURN(2);
1023 } else {
1024 /* Scalar, so use the string that Perl would return */
33be4c61 1025 /* return the pattern in (?msixn:..) format */
192c1e27 1026#if PERL_VERSION >= 11
daba3364 1027 pattern = sv_2mortal(newSVsv(MUTABLE_SV(re)));
192c1e27 1028#else
fb632ce3
NC
1029 pattern = newSVpvn_flags(RX_WRAPPED(re), RX_WRAPLEN(re),
1030 (RX_UTF8(re) ? SVf_UTF8 : 0) | SVs_TEMP);
192c1e27 1031#endif
22d874e2 1032 PUSHs(pattern);
192c1e27
JH
1033 XSRETURN(1);
1034 }
1035 } else {
1036 /* It ain't a regexp folks */
b1dcc8e2 1037 if ( gimme == G_ARRAY ) {
192c1e27 1038 /* return the empty list */
7b46bf4c 1039 XSRETURN_EMPTY;
192c1e27
JH
1040 } else {
1041 /* Because of the (?:..) wrapping involved in a
1042 stringified pattern it is impossible to get a
1043 result for a real regexp that would evaluate to
1044 false. Therefore we can return PL_sv_no to signify
1045 that the object is not a regex, this means that one
1046 can say
1047
1048 if (regex($might_be_a_regex) eq '(?:foo)') { }
1049
1050 and not worry about undefined values.
1051 */
1052 XSRETURN_NO;
1053 }
1054 }
661d43c4 1055 NOT_REACHED; /* NOTREACHED */
192c1e27
JH
1056}
1057
b7a8ab8f 1058#include "vutil.h"
abc6d738
FC
1059#include "vxs.inc"
1060
eff5b9d5
NC
1061struct xsub_details {
1062 const char *name;
1063 XSUBADDR_t xsub;
1064 const char *proto;
1065};
1066
a9b7658f 1067static const struct xsub_details details[] = {
eff5b9d5
NC
1068 {"UNIVERSAL::isa", XS_UNIVERSAL_isa, NULL},
1069 {"UNIVERSAL::can", XS_UNIVERSAL_can, NULL},
1070 {"UNIVERSAL::DOES", XS_UNIVERSAL_DOES, NULL},
abc6d738
FC
1071#define VXS_XSUB_DETAILS
1072#include "vxs.inc"
1073#undef VXS_XSUB_DETAILS
eff5b9d5
NC
1074 {"utf8::is_utf8", XS_utf8_is_utf8, NULL},
1075 {"utf8::valid", XS_utf8_valid, NULL},
1076 {"utf8::encode", XS_utf8_encode, NULL},
1077 {"utf8::decode", XS_utf8_decode, NULL},
1078 {"utf8::upgrade", XS_utf8_upgrade, NULL},
1079 {"utf8::downgrade", XS_utf8_downgrade, NULL},
1080 {"utf8::native_to_unicode", XS_utf8_native_to_unicode, NULL},
1081 {"utf8::unicode_to_native", XS_utf8_unicode_to_native, NULL},
1082 {"Internals::SvREADONLY", XS_Internals_SvREADONLY, "\\[$%@];$"},
2c6c1df5 1083 {"constant::_make_const", XS_constant__make_const, "\\[$@]"},
eff5b9d5
NC
1084 {"Internals::SvREFCNT", XS_Internals_SvREFCNT, "\\[$%@];$"},
1085 {"Internals::hv_clear_placeholders", XS_Internals_hv_clear_placehold, "\\%"},
1086 {"PerlIO::get_layers", XS_PerlIO_get_layers, "*;@"},
8bf4c401
YO
1087 {"Hash::Util::bucket_ratio", XS_hash_util_bucket_ratio, "\\%"},
1088 {"Hash::Util::num_buckets", XS_hash_util_num_buckets, "\\%"},
1089 {"Hash::Util::used_buckets", XS_hash_util_used_buckets, "\\%"},
eff5b9d5
NC
1090 {"re::is_regexp", XS_re_is_regexp, "$"},
1091 {"re::regname", XS_re_regname, ";$$"},
1092 {"re::regnames", XS_re_regnames, ";$"},
1093 {"re::regnames_count", XS_re_regnames_count, ""},
1094 {"re::regexp_pattern", XS_re_regexp_pattern, "$"},
eff5b9d5
NC
1095};
1096
273e254d
KW
1097STATIC OP*
1098optimize_out_native_convert_function(pTHX_ OP* entersubop,
1099 GV* namegv,
1100 SV* protosv)
1101{
1102 /* Optimizes out an identity function, i.e., one that just returns its
1103 * argument. The passed in function is assumed to be an identity function,
1104 * with no checking. This is designed to be called for utf8_to_native()
1105 * and native_to_utf8() on ASCII platforms, as they just return their
1106 * arguments, but it could work on any such function.
1107 *
1108 * The code is mostly just cargo-culted from Memoize::Lift */
1109
1110 OP *pushop, *argop;
614f287f 1111 OP *parent;
273e254d
KW
1112 SV* prototype = newSVpvs("$");
1113
1114 PERL_UNUSED_ARG(protosv);
1115
1116 assert(entersubop->op_type == OP_ENTERSUB);
1117
1118 entersubop = ck_entersub_args_proto(entersubop, namegv, prototype);
614f287f 1119 parent = entersubop;
273e254d
KW
1120
1121 SvREFCNT_dec(prototype);
1122
1123 pushop = cUNOPx(entersubop)->op_first;
bac7a184 1124 if (! OpHAS_SIBLING(pushop)) {
614f287f 1125 parent = pushop;
273e254d
KW
1126 pushop = cUNOPx(pushop)->op_first;
1127 }
614f287f 1128 argop = OpSIBLING(pushop);
273e254d
KW
1129
1130 /* Carry on without doing the optimization if it is not something we're
1131 * expecting, so continues to work */
1132 if ( ! argop
bac7a184 1133 || ! OpHAS_SIBLING(argop)
614f287f 1134 || OpHAS_SIBLING(OpSIBLING(argop))
273e254d
KW
1135 ) {
1136 return entersubop;
1137 }
1138
614f287f
DM
1139 /* cut argop from the subtree */
1140 (void)op_sibling_splice(parent, pushop, 1, NULL);
273e254d
KW
1141
1142 op_free(entersubop);
1143 return argop;
1144}
1145
eff5b9d5
NC
1146void
1147Perl_boot_core_UNIVERSAL(pTHX)
1148{
eff5b9d5 1149 static const char file[] = __FILE__;
7a6ecb12 1150 const struct xsub_details *xsub = details;
c3caa5c3 1151 const struct xsub_details *end = C_ARRAY_END(details);
eff5b9d5
NC
1152
1153 do {
1154 newXS_flags(xsub->name, xsub->xsub, file, xsub->proto, 0);
1155 } while (++xsub < end);
1156
273e254d
KW
1157#ifndef EBCDIC
1158 { /* On ASCII platforms these functions just return their argument, so can
1159 be optimized away */
1160
1161 CV* to_native_cv = get_cv("utf8::unicode_to_native", 0);
1162 CV* to_unicode_cv = get_cv("utf8::native_to_unicode", 0);
1163
1164 cv_set_call_checker(to_native_cv,
1165 optimize_out_native_convert_function,
1166 (SV*) to_native_cv);
1167 cv_set_call_checker(to_unicode_cv,
1168 optimize_out_native_convert_function,
1169 (SV*) to_unicode_cv);
1170 }
1171#endif
1172
eff5b9d5 1173 /* Providing a Regexp::DESTROY fixes #21347. See test in t/op/ref.t */
bad4ae38
FC
1174 {
1175 CV * const cv =
1176 newCONSTSUB(get_hv("Regexp::", GV_ADD), "DESTROY", NULL);
5513c2cf
DD
1177 char ** cvfile = &CvFILE(cv);
1178 char * oldfile = *cvfile;
bad4ae38 1179 CvDYNFILE_off(cv);
5513c2cf
DD
1180 *cvfile = (char *)file;
1181 Safefree(oldfile);
bad4ae38 1182 }
eff5b9d5 1183}
80305961 1184
241d1a3b 1185/*
14d04a33 1186 * ex: set ts=8 sts=4 sw=4 et:
37442d52 1187 */