1 /* This file is part of the "version" CPAN distribution. Please avoid
2 editing it in the perl core. */
5 # define VXS_CLASS "version"
7 # define VXS_CLASS "version::vxs"
10 #ifdef VXS_XSUB_DETAILS
12 {"UNIVERSAL::VERSION", XS_UNIVERSAL_VERSION, NULL},
14 {VXS_CLASS "::_VERSION", XS_UNIVERSAL_VERSION, NULL},
16 {VXS_CLASS "::()", XS_version_noop, NULL},
17 {VXS_CLASS "::new", XS_version_new, NULL},
18 {VXS_CLASS "::parse", XS_version_new, NULL},
19 {VXS_CLASS "::(\"\"", XS_version_stringify, NULL},
20 {VXS_CLASS "::stringify", XS_version_stringify, NULL},
21 {VXS_CLASS "::(0+", XS_version_numify, NULL},
22 {VXS_CLASS "::numify", XS_version_numify, NULL},
23 {VXS_CLASS "::normal", XS_version_normal, NULL},
24 {VXS_CLASS "::(cmp", XS_version_vcmp, NULL},
25 {VXS_CLASS "::(<=>", XS_version_vcmp, NULL},
27 {VXS_CLASS "::vcmp", XS_version_vcmp, NULL},
29 {VXS_CLASS "::VCMP", XS_version_vcmp, NULL},
31 {VXS_CLASS "::(bool", XS_version_boolean, NULL},
32 {VXS_CLASS "::boolean", XS_version_boolean, NULL},
33 {VXS_CLASS "::(+", XS_version_noop, NULL},
34 {VXS_CLASS "::(-", XS_version_noop, NULL},
35 {VXS_CLASS "::(*", XS_version_noop, NULL},
36 {VXS_CLASS "::(/", XS_version_noop, NULL},
37 {VXS_CLASS "::(+=", XS_version_noop, NULL},
38 {VXS_CLASS "::(-=", XS_version_noop, NULL},
39 {VXS_CLASS "::(*=", XS_version_noop, NULL},
40 {VXS_CLASS "::(/=", XS_version_noop, NULL},
41 {VXS_CLASS "::(abs", XS_version_noop, NULL},
42 {VXS_CLASS "::(nomethod", XS_version_noop, NULL},
43 {VXS_CLASS "::noop", XS_version_noop, NULL},
44 {VXS_CLASS "::is_alpha", XS_version_is_alpha, NULL},
45 {VXS_CLASS "::qv", XS_version_qv, NULL},
46 {VXS_CLASS "::declare", XS_version_qv, NULL},
47 {VXS_CLASS "::is_qv", XS_version_is_qv, NULL},
57 # define HEKfARG(arg) ((void*)(sv_2mortal(newSVhek(arg))))
62 # define HvNAME_HEK HvNAME_get
63 # define HEKfARG(arg) arg
67 XS(XS_UNIVERSAL_VERSION)
80 Perl_croak(aTHX_ "Usage: UNIVERSAL::VERSION(sv, ...)");
87 Perl_croak(aTHX_ "Cannot find version of an unblessed reference");
91 pkg = gv_stashsv(sv, FALSE);
94 gvp = pkg ? (GV**)hv_fetchs(pkg,"VERSION",FALSE) : (GV**)NULL;
96 if (gvp && isGV(gv = *gvp) && (sv = GvSV(gv)) && SvOK(sv)) {
97 sv = sv_mortalcopy(sv);
98 if ( ! ISA_CLASS_OBJ(sv, "version::vxs"))
99 UPG_VERSION(sv, FALSE);
103 sv = ret = &PL_sv_undef;
112 const HVNAME* const name = HvNAME_HEK(pkg);
113 #if PERL_VERSION == 5
114 Perl_croak(aTHX_ "%s version %s required--this is only version ",
115 name, SvPVx_nolen_const(req));
118 "%"HEKf" does not define $%"HEKf
119 "::VERSION--version check failed",
120 HEKfARG(name), HEKfARG(name));
124 #if PERL_VERSION >= 8
126 "%"SVf" defines neither package nor VERSION--version check failed",
129 Perl_croak(aTHX_ "%s does not define $%s::VERSION--version check failed",
130 SvPVx_nolen_const(ST(0)),
131 SvPVx_nolen_const(ST(0)) );
136 if ( ! ISA_CLASS_OBJ(req, "version")) {
137 /* req may very well be R/O, so create a new object */
138 req = sv_2mortal( NEW_VERSION(req) );
141 if ( VCMP( req, sv ) > 0 ) {
142 if ( hv_exists(MUTABLE_HV(SvRV(req)), "qv", 2 ) ) {
147 req = VSTRINGIFY(req);
150 Perl_croak(aTHX_ "%"HEKf" version %"SVf" required--"
151 "this is only version %"SVf"", HEKfARG(HvNAME_HEK(pkg)),
152 SVfARG(sv_2mortal(req)),
153 SVfARG(sv_2mortal(sv)));
158 /* if the package's $VERSION is not undef, it is upgraded to be a version object */
159 if (ISA_CLASS_OBJ(sv, "version")) {
160 ST(0) = sv_2mortal(VSTRINGIFY(sv));
172 if (items > 3 || items < 1)
173 croak_xs_usage(cv, "class, version");
179 const char *classname;
182 /* Just in case this is something like a tied hash */
185 if ( sv_isobject(ST(0)) ) { /* get the class if called as an object method */
186 const HV * stash = SvSTASH(SvRV(ST(0)));
187 classname = HvNAME(stash);
188 len = HvNAMELEN(stash);
189 flags = HvNAMEUTF8(stash) ? SVf_UTF8 : 0;
192 classname = SvPV(ST(0), len);
193 flags = SvUTF8(ST(0));
196 if ( items == 1 || ! SvOK(vs) ) { /* no param or explicit undef */
197 /* create empty object */
201 else if ( items == 3 ) {
203 Perl_sv_setpvf(aTHX_ vs,"v%s",SvPV_nolen_const(ST(2)));
206 rv = new_version(vs);
207 if ( strnNE(classname,"version", len) ) /* inherited new() */
208 sv_bless(rv, gv_stashpvn(classname, len, GV_ADD | flags));
216 XS(XS_version_stringify)
221 croak_xs_usage(cv, "lobj, ...");
226 if (sv_isobject(lobj) && sv_derived_from(lobj, "version")) {
230 Perl_croak(aTHX_ "lobj is not of type version");
232 mPUSHs(vstringify(lobj));
239 XS(XS_version_numify)
244 croak_xs_usage(cv, "lobj, ...");
249 if (sv_isobject(lobj) && sv_derived_from(lobj, "version")) {
253 Perl_croak(aTHX_ "lobj is not of type version");
255 mPUSHs(vnumify(lobj));
262 XS(XS_version_normal)
267 croak_xs_usage(cv, "lobj, ...");
272 if (sv_isobject(lobj) && sv_derived_from(lobj, "version")) {
276 Perl_croak(aTHX_ "lobj is not of type version");
278 mPUSHs(vnormal(lobj));
290 croak_xs_usage(cv, "lobj, ...");
295 if (sv_isobject(lobj) && sv_derived_from(lobj, "version")) {
299 Perl_croak(aTHX_ "lobj is not of type version");
305 const IV swap = (IV)SvIV(ST(2));
307 if ( !sv_isobject(robj) || !sv_derived_from(robj, "version") )
309 robj = new_version(SvOK(robj) ? robj : newSVpvs_flags("0", SVs_TEMP));
316 rs = newSViv(vcmp(rvs,lobj));
320 rs = newSViv(vcmp(lobj,rvs));
331 XS(XS_version_boolean)
336 croak_xs_usage(cv, "lobj, ...");
338 if (sv_isobject(ST(0)) && sv_derived_from(ST(0), "version")) {
339 SV * const lobj = SvRV(ST(0));
342 sv_2mortal(new_version(
343 sv_2mortal(newSVpvs("0"))
352 Perl_croak(aTHX_ "lobj is not of type version");
360 croak_xs_usage(cv, "lobj, ...");
361 if (sv_isobject(ST(0)) && sv_derived_from(ST(0), "version"))
362 Perl_croak(aTHX_ "operation not supported with version object");
364 Perl_croak(aTHX_ "lobj is not of type version");
365 #ifndef HASATTRIBUTE_NORETURN
370 XS(XS_version_is_alpha)
375 croak_xs_usage(cv, "lobj");
377 if (sv_isobject(ST(0)) && sv_derived_from(ST(0), "version")) {
378 SV * const lobj = ST(0);
379 if ( hv_exists(MUTABLE_HV(SvRV(lobj)), "alpha", 5 ) )
387 Perl_croak(aTHX_ "lobj is not of type version");
400 const char * classname = "";
408 Perl_croak(aTHX_ "Invalid version format (version required)");
410 if ( sv_isobject(ST(0)) ) { /* class called as an object method */
411 const HV * stash = SvSTASH(SvRV(ST(0)));
412 classname = HvNAME(stash);
413 len = HvNAMELEN(stash);
414 flags = HvNAMEUTF8(stash) ? SVf_UTF8 : 0;
417 classname = SvPV(ST(0), len);
418 flags = SvUTF8(ST(0));
421 if ( !SvVOK(ver) ) { /* not already a v-string */
423 sv_setsv(rv,ver); /* make a duplicate */
424 upg_version(rv, TRUE);
426 rv = sv_2mortal(new_version(ver));
429 && strnNE(classname,"version", len) ) { /* inherited new() */
430 sv_bless(rv, gv_stashpvn(classname, len, GV_ADD | flags));
443 croak_xs_usage(cv, "lobj");
445 if (sv_isobject(ST(0)) && sv_derived_from(ST(0), "version")) {
446 SV * const lobj = ST(0);
447 if ( hv_exists(MUTABLE_HV(SvRV(lobj)), "qv", 2 ) )
455 Perl_croak(aTHX_ "lobj is not of type version");