including lib/gslextras and the linear regression features. Jason
is also an important contributor to GSL, which is used by PSPP.
-* Rob van Son wrote the routine for calculation of the significance
-of the Wilcoxon matched pairs signed rank statistic used by the
- NPAR TEST command.
-
We also thank past contributors:
* Michael Kiefte contributed bug fixes and other enhancements.
* Patrick Kobly contributed bug fixes and other enhancements.
+
+* Rob van Son wrote the original version of the routine for
+ calculation of the significance of the Wilcoxon matched pairs signed
+ rank statistic used by the NPAR TEST command.
+
4. Type `make install' to install the programs and any data files
and documentation. Ordinarily you will need root permissions to
- do this; if you cannot get root permissions, see "Installation
- Names", below.
+ do this. The "su" and "sudo" commands are common ways to obtain
+ root permissions. If you cannot get root permissions, see
+ "Installation Names", below.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
of libraries are detected. Use of this option is not recommended.
If you use it, some features may be missing and the build may fail
with obscure error messages.
-
+
+`--enable-relocatable'
+ This option is useful for building a package which can be installed
+ into an arbitrary directory and freely copied to any other directory.
+ If you use this option, you will probably want to install the pspp
+ with a command similar to "make install DESTDIR=<distination>".
Defining Variables
==================
include $(top_srcdir)/glade/automake.mk
endif
+if WITH_PERL_MODULE
+include $(top_srcdir)/perl-module/automake.mk
+endif
+
PHONY += $(DIST_HOOKS)
dist-hook: $(DIST_HOOKS)
.PHONY: $(PHONY)
PSPP NEWS -- history of user-visible changes.
-Time-stamp: <2008-10-11 10:04:51 blp>
-Copyright (C) 1996-9, 2000, 2008 Free Software Foundation, Inc.
+Time-stamp: <2009-02-05 20:31:51 blp>
+Copyright (C) 1996-9, 2000, 2008, 2009 Free Software Foundation, Inc.
See the end for copying conditions.
Please send PSPP bug reports to bug-gnu-pspp@gnu.org.
+Changes from 0.7.1 to 0.7.2:
+
+ * Updated Perl module interface.
+
+Changes from 0.7.0 to 0.7.1:
+
+ * Added a perl module to facilitate reading and writing of pspp system
+ files from perl programs.
+
Changes from 0.6.1 to 0.7.0:
* Custom variable and data file attributes are now supported.
byteswap \
c-ctype \
c-strtod \
+ close \
crypto/md4 \
dirname \
environ \
dnl Initialize.
AC_PREREQ(2.60)
-AC_INIT([pspp],[0.7.0],[bug-gnu-pspp@gnu.org])
+AC_INIT([pspp],[0.7.2],[bug-gnu-pspp@gnu.org])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE
AM_CONDITIONAL(WITHCHARTS, test x"$with_libplot" != x"no")
+AC_ARG_VAR([PSPP_LDFLAGS], [linker flags to be used for linking the pspp binary only])
+AC_ARG_VAR([PSPPIRE_LDFLAGS], [linker flags to be used for linking the psppire binary only])
+
+
AC_ARG_WITH(
gui,
[AS_HELP_STRING([--without-gui], [don't build the PSPPIRE gui])])
fi
AM_CONDITIONAL(WITH_GUI_TOOLS, test x"$with_gui_tools" = x"yes")
+AM_CONDITIONAL(WITH_PERL_MODULE, test x"$cross_compiling" != x"yes")
+
AC_SEARCH_LIBS([cblas_dsdot], [gslcblas],,[PSPP_REQUIRED_PREREQ([libgslcblas])])
AC_SEARCH_LIBS([gsl_cdf_binomial_P], [gsl],,[PSPP_REQUIRED_PREREQ([libgsl (version 1.8 or later)])])
PSPP_GSL_NEEDS_FGNU89_INLINE
## Process this file with automake to produce Makefile.in -*- makefile -*-
include $(top_srcdir)/lib/linreg/automake.mk
-include $(top_srcdir)/lib/misc/automake.mk
if WITHGUI
include $(top_srcdir)/lib/gtk-contrib/automake.mk
+++ /dev/null
-This is not part of the GNU PSPP program, but is used with GNU PSPP.
-
+++ /dev/null
-## Process this file with automake to produce Makefile.in -*- makefile -*-
-
-noinst_LTLIBRARIES += lib/misc/libmisc.la
-
-lib_misc_libmisc_la_SOURCES = \
- lib/misc/wx-mp-sr.c lib/misc/wx-mp-sr.h
-
-EXTRA_DIST += lib/misc/README
+++ /dev/null
-#include <config.h>
-#include "wx-mp-sr.h"
-
-/*********************************************************************
-*
-* Calculate the exact level of significance for a
-* Wilcoxon Matched-Pair Signed-Ranks Test using the sample's
-* Sum of Ranks W and the sample size (i.e., number of pairs) N.
-* This whole routine can be run as a stand-alone program.
-*
-* Use:
-* WX-MP-SR W N
-*
-* Copyright 1996, Rob van Son
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License along
-* with this program; if not, write to the Free Software Foundation, Inc.,
-* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*
-* -------------------------------------------------------
-* Rob van Son
-* Institute of Phonetic Sciences & IFOTT
-* University of Amsterdam, Spuistraat 210
-* NL-1012VT Amsterdam, The Netherlands
-* Tel.: (+31) 205252196 Fax.: (+31) 205252197
-* Email: r.j.j.h.vanson@uva.nl
-* WWW page: http://www.fon.hum.uva.nl/rob
-* -------------------------------------------------------
-*
-* This is the actual routine that calculates the exact (two-tailed)
-* level of significance for the Wilcoxon Matched-Pairs Signed-Ranks
-* test. The inputs are the Sum of Ranks of either the positive of
-* negative samples (W) and the sample size (N).
-* The Level of significance is calculated by checking for each
-* possible outcome (2**N possibilities) whether the sum of ranks
-* is larger than or equal to the observed Sum of Ranks (W).
-*
-* NOTE: The execution-time scales like ~ N*2**N, i.e., N*pow(2, N),
-* which is more than exponential. Adding a single pair to the sample
-* (i.e., increase N by 1) will more than double the time needed to
-* complete the calculations (apart from an additive constant).
-* The execution-time of this program can easily outrun your
-* patience.
-*
-***********************************************************************/
-
-double LevelOfSignificanceWXMPSR(double Winput, long int N)
-{
- unsigned long int W, MaximalW, NumberOfPossibilities, CountLarger;
- unsigned long int i, RankSum, j;
- double p;
-
- /* Determine Wmax, i.e., work with the largest Rank Sum */
- MaximalW = N*(N+1)/2;
- if(Winput < MaximalW/2)Winput = MaximalW - Winput;
- W = Winput; /* Convert to long int */
- if(W != Winput)++W; /* Increase to next full integer */
-
- /* The total number of possible outcomes is 2**N */
- NumberOfPossibilities = 1 << N;
-
- /* Initialize and loop. The loop-interior will be run 2**N times. */
- CountLarger = 0;
- /* Generate all distributions of sign over ranks as bit-patterns (i). */
- for(i=0; i < NumberOfPossibilities; ++i)
- {
- RankSum = 0;
- /*
- Shift "sign" bits out of i to determine the Sum of Ranks (j).
- */
- for(j=0; j < N; ++j)
- {
- if((i >> j) & 1)RankSum += j + 1;
- };
- /*
- * Count the number of "samples" that have a Sum of Ranks larger than
- * or equal to the one found (i.e., >= W).
- */
- if(RankSum >= W)++CountLarger;
- };
- /*****************************************************************
- * The level of significance is the number of outcomes with a
- * sum of ranks equal to or larger than the one found (W)
- * divided by the total number of possible outcomes.
- * The level is doubled to get the two-tailed result.
- ******************************************************************/
- p = 2*((double)CountLarger) / ((double)NumberOfPossibilities);
-
- return p;
-}
-
+++ /dev/null
-#ifndef WX_MP_SR
-#define WX_MP_SR 1
-
-double LevelOfSignificanceWXMPSR(double Winput, long int N);
-
-#endif
--- /dev/null
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+
--- /dev/null
+Revision history for Perl extension Pspp.
+
+0.7.0 Sun Jan 11 10:35:56 2009
+ Integrated the module into Pspp's build environment. Added support for
+ reading from an existing system file.
+
+0.4.3 Sat May 19 14:24:05 2007
+ - first release
+
+0.01 Fri Apr 6 14:13:45 2007
+ - original version; created by h2xs 1.23 with options
+ -A -n Pspp pspp/src/libpspp/version.h
+
--- /dev/null
+=pod
+
+=head1 PSPP::Examples
+
+This page shows some simple examples of using the PSPP module.
+See L<PSPP> for details on each of the subroutines.
+
+=head2 A Simple example
+
+This example creates a system file called F<foo.sav>, containing one
+variable called "id". It contains no data.
+
+ use PSPP;
+
+ my $dict = PSPP::Dict->new ();
+ my $var = PSPP::Var->new ($dict, "id");
+
+ my $sysfile = PSPP::Sysfile->new ("foo.sav", $dict);
+ $sysfile->close();
+
+
+=head2 A slightly more complex example
+
+In this example there are three variables, called "id", "name" and "dob".
+Their formats are F2.0, A80 and DATETIME17 respectively.
+
+ use PSPP;
+
+ my $dict = PSPP::Dict->new ();
+ PSPP::Var->new ($dict, "id",
+ (fmt=>PSPP::Fmt::F, width=>2, decimals=>0) );
+
+ PSPP::Var->new ($dict, "name", (fmt=>PSPP::Fmt::A, width=>80) );
+ PSPP::Var->new ($dict, "dob", (fmt=>PSPP::Fmt::DATETIME) );
+
+ my $sysfile = PSPP::Sysfile->new ("foo.sav", $dict);
+ $sysfile->close();
+
+=head2 Changing the properties of variables
+
+After a variable has been created, parameters may be set for it.
+
+ use PSPP;
+
+ my $dict = PSPP::Dict->new ();
+ my $var1 = PSPP::Var->new ($dict, "id");
+
+ $var1->set_label ("A unique identifier");
+ $var1->add_value_label (0, "Zero");
+ $var1->add_value_label (1, "One");
+
+
+=head2 Appending data to the file
+
+When a file is created, it contains no data. Data is added by
+appending cases to the file.
+
+This example creates a file with 3 cases.
+
+ use PSPP;
+
+ my $dict = PSPP::Dict->new ();
+ PSPP::Var->new ($dict, "id",
+ (fmt=>PSPP::Fmt::F, width=>2, decimals=>0) );
+
+ PSPP::Var->new ($dict, "name", (fmt=>PSPP::Fmt::A, width=>8) );
+
+ my $sysfile = PSPP::Sysfile->new ("foo.sav", $dict);
+
+ $sysfile->append_case ( [1, "Alf"] );
+ $sysfile->append_case ( [2, "Bert"] );
+ $sysfile->append_case ( [3, "Charlie"] );
+
+ $sysfile->close();
+
+=head2 Variables with differing input and output formats
+
+By default, a variable's output format corresponds to the input format.
+However, the output format may be changed after the variable has
+been created.
+
+This example shows how to create a DATETIME variable using the current time
+as its value. Since pspp uses a different epoch to perl, the constant
+PSPP::PERL_EPOCH needs to be added to the value returned from time(), in order
+that it be correctly represented by pspp.
+
+ use PSPP;
+
+ my $dict = PSPP::Dict->new ();
+
+ my $var1 = PSPP::Var->new ($dict, "entrytime",
+ (fmt=>PSPP::Fmt::F) );
+
+ $var1->set_output_format ( (fmt=>PSPP::Fmt::DATETIME, width=>20) );
+
+ my $sysfile = PSPP::Sysfile->new ("foo.sav", $dict);
+
+ my $now = time ();
+
+ $sysfile->append_case ( [ $now + PSPP::PERL_EPOCH] )
+ || die "Cant write case";
+
+ $sysfile->close();
+
+=head2 Reading data
+
+Data can be read from a system file or other source:
+
+ use PSPP;
+
+ my $sf = PSPP::Reader->open ("foo.sav");
+
+ my $dict = $sf->get_dict ();
+
+
+Once opened, the dictionary can be used like any other.
+
+ for ($v = 0 ; $v < $dict->get_var_cnt() ; $v++)
+ {
+ my $var = $dict->get_var ($v);
+
+ # Print the variables
+ my $name = $var->get_name ();
+ my $label = $var->get_label ();
+ print "Var: $name, Label: $label\n";
+
+ # Retrieve and print the value labels
+ my $vl = $var->get_value_labels ();
+ print "$_: $vl->{$_}\n" for keys %$vl;
+ }
+
+
+Reading of data must be done sequentially using the C<get_next_case> method.
+
+ while (my $c = $sf->get_next_case () )
+ {
+ my $v;
+ for ($v = 0; $v < $dict->get_var_cnt(); $v++)
+ {
+ print "val$v: @$c[$v] ";
+ }
+ print "\n";
+ }
+
+
+=cut
\ No newline at end of file
--- /dev/null
+Changes
+const-c.inc
+const-xs.inc
+COPYING
+Examples.pod
+lib/PSPP.pm
+Makefile.PL
+MANIFEST
+ppport.h
+PSPP.xs
+README
+t/Pspp.t
+typemap
--- /dev/null
+use 5.008008;
+use ExtUtils::MakeMaker;
+# See lib/ExtUtils/MakeMaker.pm for details of how to influence
+# the contents of the Makefile that is written.
+
+
+do 'pspp-module-config' || do {
+ my $build = prompt ("Enter the location of the build directory of the configured pspp source:", "" );
+ my $src = $top_srcdir;
+
+ %Locations = (SourceDir => "$src", BuildDir => "$build");
+};
+
+WriteMakefile(
+ FULLPERL => "PSPP_TEST_CMD=\"$Locations{BuildDir}/src/ui/terminal/pspp -B $Locations{SourceDir}/config\" \$(PERL)",
+ NAME => 'PSPP',
+ DISTNAME => 'PSPP-Perl',
+ VERSION_FROM => "$Locations{BuildDir}/src/libpspp/version.c",
+ PREREQ_PM => {POSIX=>0},
+ PM => {"lib/PSPP.pm", "\$(INST_LIBDIR)/PSPP.pm"},
+ ($] >= 5.005 ? ## Add these new keywords supported since 5.005
+ (ABSTRACT_FROM => 'lib/PSPP.pm', # retrieve abstract from module
+ AUTHOR => 'John Darrington <john@darrington.wattle.id.au>') : ()),
+ INC => "-I $Locations{SourceDir} -I $Locations{SourceDir}/src -I $Locations{SourceDir}/gl -I $Locations{BuildDir}/gl -I $Locations{BuildDir}",
+ MYEXTLIB => "$Locations{BuildDir}/src/.libs/libpspp-core.\$(DLEXT)",
+ MAN3PODS => {"lib/PSPP.pm", "\$(INST_MAN3DIR)/PSPP.3pm",
+ "Examples.pod", "\$(INST_MAN3DIR)/PSPP::Examples.3pm"}
+);
+
+if (eval {require ExtUtils::Constant; 1}) {
+ # If you edit these definitions to change the constants used by this module,
+ # you will need to use the generated const-c.inc and const-xs.inc
+ # files to replace their "fallback" counterparts before distributing your
+ # changes.
+ my @names = (qw());
+ ExtUtils::Constant::WriteConstants(
+ NAME => 'PSPP',
+ NAMES => \@names,
+ DEFAULT_TYPE => 'IV',
+ C_FILE => 'const-c.inc',
+ XS_FILE => 'const-xs.inc',
+ );
+
+}
+else {
+ use File::Copy;
+ use File::Spec;
+ foreach my $file ('const-c.inc', 'const-xs.inc') {
+ my $fallback = File::Spec->catfile('fallback', $file);
+ copy ($fallback, $file) or die "Can't copy $fallback to $file: $!";
+ }
+}
--- /dev/null
+/* PSPP - computes sample statistics.
+ Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+
+#include <config.h>
+
+#include "ppport.h"
+
+#include "minmax.h"
+#include <libpspp/message.h>
+#include <libpspp/version.h>
+#include <gl/xalloc.h>
+#include <data/dictionary.h>
+#include <data/case.h>
+#include <data/casereader.h>
+#include <data/variable.h>
+#include <data/attributes.h>
+#include <data/file-handle-def.h>
+#include <data/sys-file-writer.h>
+#include <data/sys-file-reader.h>
+#include <data/value.h>
+#include <data/value-labels.h>
+#include <data/format.h>
+#include <data/data-in.h>
+#include <string.h>
+
+typedef struct fmt_spec input_format ;
+typedef struct fmt_spec output_format ;
+
+
+/* A thin wrapper around sfm_writer */
+struct sysfile_info
+{
+ bool opened;
+
+ /* A pointer to the writer. The writer is owned by the struct */
+ struct casewriter *writer;
+
+ /* A pointer to the dictionary. Owned externally */
+ const struct dictionary *dict;
+
+ /* The scalar containing the dictionary */
+ SV *dict_sv;
+};
+
+
+/* A thin wrapper around sfm_reader */
+struct sysreader_info
+{
+ struct sfm_read_info opts;
+
+ /* A pointer to the reader. The reader is owned by the struct */
+ struct casereader *reader;
+
+ /* A pointer to the dictionary. */
+ struct dictionary *dict;
+};
+
+
+
+/* A message handler which writes messages to PSPP::errstr */
+static void
+message_handler (const struct msg *m)
+{
+ SV *errstr = get_sv("PSPP::errstr", TRUE);
+ sv_setpv (errstr, m->text);
+}
+
+static int
+sysfile_close (struct sysfile_info *sfi)
+{
+ int retval ;
+ if ( ! sfi->opened )
+ return 0;
+
+ retval = casewriter_destroy (sfi->writer);
+ if (retval > 0 )
+ sfi->opened = false;
+
+ return retval;
+}
+
+static void
+scalar_to_value (union value *val, SV *scalar, const struct variable *var)
+{
+ if ( var_is_numeric (var))
+ {
+ if ( SvNOK (scalar) || SvIOK (scalar) )
+ val->f = SvNV (scalar);
+ else
+ val->f = SYSMIS;
+ }
+ else
+ {
+ STRLEN len;
+ const char *p = SvPV (scalar, len);
+ memset (val->s, ' ', var_get_width (var));
+ memcpy (val->s, p, len);
+ }
+}
+
+
+static SV *
+value_to_scalar (const union value *val, const struct variable *var)
+{
+ if ( var_is_numeric (var))
+ {
+ if ( var_is_value_missing (var, val, MV_SYSTEM))
+ return newSVpvn ("", 0);
+
+ return newSVnv (val->f);
+ }
+ else
+ return newSVpvn (val->s, var_get_width (var));
+}
+
+
+static void
+var_set_input_format (struct variable *v, input_format ip_fmt)
+{
+ struct fmt_spec *if_copy = malloc (sizeof (*if_copy));
+ memcpy (if_copy, &ip_fmt, sizeof (ip_fmt));
+ var_attach_aux (v, if_copy, var_dtor_free);
+}
+
+static union value *
+make_value_from_scalar (SV *val, const struct variable *var)
+{
+ union value *uv = value_create (var_get_width (var));
+ scalar_to_value (uv, val, var);
+ return uv;
+}
+
+
+MODULE = PSPP
+
+MODULE = PSPP PACKAGE = PSPP
+
+void
+onBoot (ver)
+ const char *ver
+CODE:
+ assert (0 == strcmp (ver, bare_version));
+ msg_init (NULL, message_handler);
+ settings_init (0, 0);
+ fh_init ();
+
+SV *
+format_value (val, var)
+ SV *val
+ struct variable *var
+CODE:
+ SV *ret;
+ const struct fmt_spec *fmt = var_get_print_format (var);
+ union value *uv = make_value_from_scalar (val, var);
+ char *s;
+ s = malloc (fmt->w);
+ memset (s, '\0', fmt->w);
+ data_out (uv, fmt, s);
+ free (uv);
+ ret = newSVpv (s, fmt->w);
+ free (s);
+ RETVAL = ret;
+ OUTPUT:
+RETVAL
+
+
+int
+value_is_missing (val, var)
+ SV *val
+ struct variable *var
+CODE:
+ union value *uv = make_value_from_scalar (val, var);
+ int ret = var_is_value_missing (var, uv, MV_ANY);
+ free (uv);
+ RETVAL = ret;
+ OUTPUT:
+RETVAL
+
+
+
+MODULE = PSPP PACKAGE = PSPP::Dict
+
+struct dictionary *
+pxs_dict_new()
+CODE:
+ RETVAL = dict_create ();
+OUTPUT:
+ RETVAL
+
+
+void
+DESTROY (dict)
+ struct dictionary *dict
+CODE:
+ dict_destroy (dict);
+
+
+int
+get_var_cnt (dict)
+ struct dictionary *dict
+CODE:
+ RETVAL = dict_get_var_cnt (dict);
+OUTPUT:
+RETVAL
+
+void
+set_label (dict, label)
+ struct dictionary *dict
+ char *label
+CODE:
+ dict_set_label (dict, label);
+
+void
+set_documents (dict, docs)
+ struct dictionary *dict
+ char *docs
+CODE:
+ dict_set_documents (dict, docs);
+
+
+void
+add_document (dict, doc)
+ struct dictionary *dict
+ char *doc
+CODE:
+ dict_add_document_line (dict, doc);
+
+
+void
+clear_documents (dict)
+ struct dictionary *dict
+CODE:
+ dict_clear_documents (dict);
+
+
+void
+set_weight (dict, var)
+ struct dictionary *dict
+ struct variable *var
+CODE:
+ dict_set_weight (dict, var);
+
+
+struct variable *
+pxs_get_variable (dict, idx)
+ struct dictionary *dict
+ SV *idx
+INIT:
+ SV *errstr = get_sv("PSPP::errstr", TRUE);
+ sv_setpv (errstr, "");
+ if ( SvIV (idx) >= dict_get_var_cnt (dict))
+ {
+ sv_setpv (errstr, "The dictionary doesn't have that many variables.");
+ XSRETURN_UNDEF;
+ }
+CODE:
+ RETVAL = dict_get_var (dict, SvIV (idx));
+ OUTPUT:
+RETVAL
+
+
+struct variable *
+pxs_get_var_by_name (dict, name)
+ struct dictionary *dict
+ const char *name
+INIT:
+ SV *errstr = get_sv("PSPP::errstr", TRUE);
+ sv_setpv (errstr, "");
+CODE:
+ struct variable *var = dict_lookup_var (dict, name);
+ if ( ! var )
+ sv_setpv (errstr, "No such variable.");
+ RETVAL = var;
+ OUTPUT:
+RETVAL
+
+
+MODULE = PSPP PACKAGE = PSPP::Var
+
+
+struct variable *
+pxs_dict_create_var (dict, name, ip_fmt)
+ struct dictionary * dict
+ char *name
+ input_format ip_fmt
+INIT:
+ SV *errstr = get_sv("PSPP::errstr", TRUE);
+ sv_setpv (errstr, "");
+ if ( ! var_is_plausible_name (name, false))
+ {
+ sv_setpv (errstr, "The variable name is not valid.");
+ XSRETURN_UNDEF;
+ }
+CODE:
+ struct fmt_spec op_fmt;
+
+ struct variable *v;
+ op_fmt = fmt_for_output_from_input (&ip_fmt);
+ v = dict_create_var (dict, name,
+ fmt_is_string (op_fmt.type) ? op_fmt.w : 0);
+ if ( NULL == v )
+ {
+ sv_setpv (errstr, "The variable could not be created (probably already exists).");
+ XSRETURN_UNDEF;
+ }
+ var_set_both_formats (v, &op_fmt);
+ var_set_input_format (v, ip_fmt);
+ RETVAL = v;
+OUTPUT:
+ RETVAL
+
+
+int
+set_missing_values (var, v1, ...)
+ struct variable *var;
+ SV *v1;
+INIT:
+ int i;
+ union value val[3];
+
+ if ( items > 4 )
+ croak ("No more than 3 missing values are permitted");
+
+ for (i = 0; i < items - 1; ++i)
+ scalar_to_value (&val[i], ST(i+1), var);
+CODE:
+ struct missing_values mv;
+ mv_init (&mv, var_get_width (var));
+ for (i = 0 ; i < items - 1; ++i )
+ mv_add_value (&mv, &val[i]);
+ var_set_missing_values (var, &mv);
+
+
+void
+set_label (var, label)
+ struct variable *var;
+ char *label
+CODE:
+ var_set_label (var, label);
+
+
+void
+clear_value_labels (var)
+ struct variable *var;
+CODE:
+ var_clear_value_labels (var);
+
+void
+pxs_set_write_format (var, fmt)
+ struct variable *var
+ output_format fmt
+CODE:
+ var_set_write_format (var, &fmt);
+
+
+void
+pxs_set_print_format (var, fmt)
+ struct variable *var
+ output_format fmt
+CODE:
+ var_set_print_format (var, &fmt);
+
+void
+pxs_set_output_format (var, fmt)
+ struct variable *var
+ output_format fmt
+CODE:
+ var_set_both_formats (var, &fmt);
+
+
+int
+add_value_label (var, key, label)
+ struct variable *var
+ SV *key
+ char *label
+INIT:
+ SV *errstr = get_sv("PSPP::errstr", TRUE);
+ sv_setpv (errstr, "");
+CODE:
+ union value the_value;
+
+ if ( var_is_numeric (var))
+ {
+ if ( ! looks_like_number (key))
+ {
+ sv_setpv (errstr, "Cannot add label with string key to a numeric variable");
+ XSRETURN_IV (0);
+ }
+ the_value.f = SvNV (key);
+ }
+ else
+ {
+ if ( var_is_long_string (var) )
+ {
+ sv_setpv (errstr, "Cannot add label to a long string variable");
+ XSRETURN_IV (0);
+ }
+ strncpy (the_value.s, SvPV_nolen(key), MAX_SHORT_STRING);
+ }
+ if (! var_add_value_label (var, &the_value, label) )
+ {
+ sv_setpv (errstr, "Something went wrong");
+ XSRETURN_IV (0);
+ }
+ XSRETURN_IV (1);
+
+
+SV *
+get_attributes (var)
+ struct variable *var
+CODE:
+ HV *attrhash = (HV *) sv_2mortal ((SV *) newHV());
+
+ struct attrset *as = var_get_attributes (var);
+
+ if ( as )
+ {
+ struct attrset_iterator iter;
+ struct attribute *attr;
+
+ for (attr = attrset_first (as, &iter);
+ attr;
+ attr = attrset_next (as, &iter))
+ {
+ int i;
+ const char *name = attribute_get_name (attr);
+
+ AV *values = newAV ();
+
+ for (i = 0 ; i < attribute_get_n_values (attr); ++i )
+ {
+ const char *value = attribute_get_value (attr, i);
+ av_push (values, newSVpv (value, 0));
+ }
+
+ hv_store (attrhash, name, strlen (name),
+ newRV_noinc ((SV*) values), 0);
+ }
+ }
+
+ RETVAL = newRV ((SV *) attrhash);
+ OUTPUT:
+RETVAL
+
+
+const char *
+get_name (var)
+ struct variable * var
+CODE:
+ RETVAL = var_get_name (var);
+ OUTPUT:
+RETVAL
+
+
+const char *
+get_label (var)
+ struct variable * var
+CODE:
+ RETVAL = var_get_label (var);
+ OUTPUT:
+RETVAL
+
+
+SV *
+get_value_labels (var)
+ struct variable *var
+CODE:
+ HV *labelhash = (HV *) sv_2mortal ((SV *) newHV());
+ struct val_lab *vl;
+ struct val_labs_iterator *viter = NULL;
+ const struct val_labs *labels = var_get_value_labels (var);
+
+ if ( labels )
+ {
+ for (vl = val_labs_first (labels, &viter);
+ vl;
+ vl = val_labs_next (labels, &viter))
+ {
+ SV *sv = value_to_scalar (&vl->value, var);
+ STRLEN len;
+ const char *s = SvPV (sv, len);
+ hv_store (labelhash, s, len, newSVpv (vl->label, 0), 0);
+ }
+ }
+
+ RETVAL = newRV ((SV *) labelhash);
+ OUTPUT:
+RETVAL
+
+
+
+MODULE = PSPP PACKAGE = PSPP::Sysfile
+
+
+struct sysfile_info *
+pxs_create_sysfile (name, dict_ref, opts_hr)
+ char *name
+ SV *dict_ref
+ SV *opts_hr
+INIT:
+ SV *dict_sv = SvRV (dict_ref);
+ struct dictionary *dict = (void *) SvIV (dict_sv);
+ struct sfm_write_options opts;
+ if (!SvROK (opts_hr))
+ {
+ opts = sfm_writer_default_options ();
+ }
+ else
+ {
+ HV *opt_h = (HV *) SvRV (opts_hr);
+ SV** readonly = hv_fetch(opt_h, "readonly", 8, 0);
+ SV** compress = hv_fetch(opt_h, "compress", 8, 0);
+ SV** version = hv_fetch(opt_h, "version", 7, 0);
+
+ opts.create_writeable = readonly ? ! SvIV (*readonly) : true;
+ opts.compress = compress ? SvIV (*compress) : false;
+ opts.version = version ? SvIV (*version) : 3 ;
+ }
+CODE:
+ struct file_handle *fh =
+ fh_create_file (NULL, name, fh_default_properties () );
+ struct sysfile_info *sfi = xmalloc (sizeof (*sfi));
+ sfi->writer = sfm_open_writer (fh, dict, opts);
+ sfi->dict = dict;
+ sfi->opened = true;
+ sfi->dict_sv = dict_sv;
+ SvREFCNT_inc (sfi->dict_sv);
+
+ RETVAL = sfi;
+ OUTPUT:
+RETVAL
+
+int
+close (sfi)
+ struct sysfile_info *sfi
+CODE:
+ RETVAL = sysfile_close (sfi);
+OUTPUT:
+ RETVAL
+
+void
+DESTROY (sfi)
+ struct sysfile_info *sfi
+CODE:
+ sysfile_close (sfi);
+ SvREFCNT_dec (sfi->dict_sv);
+ free (sfi);
+
+int
+append_case (sfi, ccase)
+ struct sysfile_info *sfi
+ SV *ccase
+INIT:
+ SV *errstr = get_sv("PSPP::errstr", TRUE);
+ sv_setpv (errstr, "");
+ if ( (!SvROK(ccase)))
+ {
+ XSRETURN_UNDEF;
+ }
+CODE:
+ int i = 0;
+ AV *av_case = (AV*) SvRV (ccase);
+
+ const struct variable **vv;
+ size_t nv;
+ struct ccase *c;
+ SV *sv;
+
+ if ( av_len (av_case) >= dict_get_var_cnt (sfi->dict))
+ XSRETURN_UNDEF;
+
+ c = case_create (dict_get_next_value_idx (sfi->dict));
+
+ dict_get_vars (sfi->dict, &vv, &nv, 1u << DC_ORDINARY | 1u << DC_SYSTEM);
+
+ for (sv = av_shift (av_case); SvOK (sv); sv = av_shift (av_case))
+ {
+ const struct variable *v = vv[i++];
+ const struct fmt_spec *ifmt = var_get_aux (v);
+
+ /* If an input format has been set, then use it.
+ Otherwise just convert the raw value.
+ */
+ if ( ifmt )
+ {
+ struct substring ss = ss_cstr (SvPV_nolen (sv));
+ if ( ! data_in (ss, LEGACY_NATIVE, ifmt->type, 0, 0, 0,
+ case_data_rw (c, v),
+ var_get_width (v)) )
+ {
+ RETVAL = 0;
+ goto finish;
+ }
+ }
+ else
+ {
+ scalar_to_value (case_data_rw (c, v), sv, v);
+ }
+ }
+
+ /* The remaining variables must be sysmis or blank string */
+ while (i < dict_get_var_cnt (sfi->dict))
+ {
+ const struct variable *v = vv[i++];
+ union value *val = case_data_rw (c, v);
+ if ( var_is_numeric (v))
+ val->f = SYSMIS;
+ else
+ memset (val->s, ' ', var_get_width (v));
+ }
+ RETVAL = casewriter_write (sfi->writer, c);
+ finish:
+ free (vv);
+OUTPUT:
+ RETVAL
+
+
+\f
+
+MODULE = PSPP PACKAGE = PSPP::Reader
+
+struct sysreader_info *
+pxs_open_sysfile (name)
+ char * name
+CODE:
+ struct casereader *reader;
+ struct sysreader_info *sri = NULL;
+ struct file_handle *fh =
+ fh_create_file (NULL, name, fh_default_properties () );
+
+ sri = xmalloc (sizeof (*sri));
+ sri->reader = sfm_open_reader (fh, &sri->dict, &sri->opts);
+
+ if ( NULL == sri->reader)
+ {
+ free (sri);
+ sri = NULL;
+ }
+
+ RETVAL = sri;
+ OUTPUT:
+RETVAL
+
+
+struct dictionary *
+pxs_get_dict (reader)
+ struct sysreader_info *reader;
+CODE:
+ RETVAL = reader->dict;
+ OUTPUT:
+RETVAL
+
+
+void
+get_next_case (sfr)
+ struct sysreader_info *sfr;
+PPCODE:
+ struct ccase *c;
+
+ if (c = casereader_read (sfr->reader))
+ {
+ int v;
+
+ EXTEND (SP, dict_get_var_cnt (sfr->dict));
+ for (v = 0; v < dict_get_var_cnt (sfr->dict); ++v )
+ {
+ const struct variable *var = dict_get_var (sfr->dict, v);
+ const union value *val = case_data (c, var);
+
+ PUSHs (sv_2mortal (value_to_scalar (val, var)));
+ }
+
+ case_unref (c);
+ }
--- /dev/null
+PSPP version 0.7
+================
+
+This module provides an interface allowing perl programs to create pspp
+system files.
+
+INSTALLATION
+
+To install you must have first installed and built pspp 0.7.2 or
+later. Pspp is not required to use this module, only to install
+it.
+
+To install this module type the following:
+
+ perl Makefile.PL
+ make
+ make test
+ make install
+
+
+
+DEPENDENCIES
+
+This module requires the POSIX module.
+
+The modules Test::More, Text::Diff, File::Temp and the pspp source are
+required during installation, but are not needed to run the module.
+
+
+COPYRIGHT AND LICENCE
+
+Copyright (C) 2007, 2009 by Free Software Foundation
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.
+
--- /dev/null
+## Process this file with automake to produce Makefile.in -*- makefile -*-
+
+# PSPP
+
+module_sources = \
+ perl-module/Changes \
+ perl-module/COPYING \
+ perl-module/Examples.pod \
+ perl-module/Makefile.PL \
+ perl-module/MANIFEST \
+ perl-module/ppport.h \
+ perl-module/PSPP.xs \
+ perl-module/README \
+ perl-module/typemap \
+ perl-module/lib/PSPP.pm \
+ perl-module/t/Pspp.t
+
+perl-module/pspp-module-config: Makefile
+ target=`mktemp`;\
+ echo '%Locations = (' > $$target ;\
+ printf " SourceDir => '" >> $$target ;\
+ (cd $(top_srcdir) && echo `pwd`\', ) >> $$target ;\
+ printf " BuildDir => '" >> $$target ;\
+ (cd $(top_builddir) && echo `pwd`\' ) >> $$target ;\
+ echo ');' >> $$target ;\
+ cp $$target $(top_builddir)/perl-module/pspp-module-config
+
+perl-module/Makefile: perl-module/Makefile.PL perl-module/pspp-module-config
+ cd perl-module && $(PERL) Makefile.PL PREFIX=$(prefix)
+
+perl-module/PSPP-Perl-$(VERSION).tar.gz: $(module_sources)
+ $(RM) $@
+ cd perl-module && $(MAKE) $(AM_MAKEFLAGS) tardist
+
+PHONY += module-make
+module-make: perl-module/Makefile
+ cd perl-module && $(MAKE) $(AM_MAKEFLAGS)
+
+all-local:
+ if test x"$(top_builddir)" != x"$(top_srcdir)" ; then \
+ for f in $(module_sources); do \
+ destdir=`dirname $$f` ;\
+ mkdir -p $$destdir ;\
+ if test "$(top_srcdir)/$$f" -nt "$(top_builddir)/$$f" ; then \
+ cp $(top_srcdir)/$$f $$destdir ; \
+ echo cp $(top_srcdir)/$$f $$destdir ; \
+ fi ; \
+ done \
+ fi
+ $(MAKE) $(AM_MAKEFLAGS) module-make perl-module/PSPP-Perl-$(VERSION).tar.gz
+
+check-local:
+ loc=`pwd` ; cd $(top_builddir)/src/.libs ; llp=`pwd` ; cd $$loc ; \
+ LANG=C LD_LIBRARY_PATH=$$llp sh -c "cd perl-module && $(MAKE) $(AM_MAKEFLAGS) test"
+
+
+clean-local:
+ cd perl-module && $(MAKE) $(AM_MAKEFLAGS) clean
+ if test x"$(top_builddir)" != x"$(top_srcdir)" ; then \
+ $(RM) $(module_sources) ; \
+ fi
+ $(RM) perl-module/Makefile.old
+
+CLEANFILES += \
+ perl-module/PSPP-Perl-$(VERSION).tar.gz \
+ perl-module/pspp-module-config \
+ perl-module/const-c.inc \
+ perl-module/const-xs.inc
+
+EXTRA_DIST += $(module_sources)
--- /dev/null
+use 5.008008;
+use strict;
+use warnings;
+
+=head1 NAME
+
+PSPP-Perl - Perl extension to PSPP
+
+=head1 SYNOPSIS
+
+ use PSPP;
+
+=head1 DESCRIPTION
+
+PSPP-Perl provides an interface to the libraries used by pspp to read and
+write system files.
+
+=head1 EXPORT
+
+None by default.
+
+=cut
+BEGIN {
+ $PSPP::VERSION='0.7.2';
+ require XSLoader;
+ XSLoader::load('PSPP', $PSPP::VERSION);
+}
+
+PSPP::onBoot($PSPP::VERSION);
+
+=pod
+
+=head1 PROGRAMMER'S INTERFACE
+
+The subroutines in this package return zero or unref on error.
+When errors occur, a string describing the error is written
+to C<$PSPP::errstr>.
+
+=cut
+
+package PSPP;
+use POSIX ;
+
+use constant { SYSMIS => -(POSIX::DBL_MAX),
+ PERL_EPOCH => 12219379200 # Number of seconds between
+ # 14th October 1582
+ # and
+ # 1st January 1970
+ };
+
+
+
+package PSPP::Dict;
+
+=pod
+
+=head2 PSPP::Dict::new
+
+Creates a new dictionary. This returned dictionary will be empty.
+Returns undef on failure.
+
+=head3 set_documents ($string)
+
+Sets the documents (comments) to C<string>.
+
+=head3 add_document ($string)
+
+Appends C<string> to the documents.
+
+=head3 clear_documents ()
+
+Removes all documents.
+
+=head3 set_weight ($var)
+
+Sets the weighting variable to C<var>.
+
+=cut
+
+sub new
+{
+ my $class = shift;
+ my $self = pxs_dict_new ();
+ bless ($self, $class);
+ return $self;
+}
+
+=pod
+
+=head3 get_var_cnt ()
+
+Returns the number of variables in the dictionary.
+
+=head3 get_var ($idx)
+
+Returns the C<idx>th variable from the dictionary.
+Returns undef if C<idx> is greater than or equal to the number
+of variables in the dictionary.
+
+=cut
+
+sub get_var
+{
+ my $dict = shift;
+ my $idx = shift;
+ my $var = pxs_get_variable ($dict, $idx);
+
+ if ( ref $var )
+ {
+ bless ($var, "PSPP::Var");
+ }
+ return $var;
+}
+
+=pod
+
+=head3 get_var_by_name ($name)
+
+Returns the variable from the dictionary whose name is C<name>.
+If there is no such variable, a null reference will be returned.
+
+=cut
+
+sub get_var_by_name
+{
+ my $dict = shift;
+ my $name = shift;
+ my $var = pxs_get_var_by_name ($dict, $name);
+
+ if ( ref $var )
+ {
+ bless ($var, "PSPP::Var");
+ }
+ return $var;
+}
+
+
+package PSPP::Fmt;
+
+=pod
+
+=head2 PSPP::Fmt
+
+Contains constants used to denote variable format types.
+The identifiers are the same as those used in pspp to denote formats.
+For example C<PSPP::Fmt::F> defines floating point format, and
+C<PSPP::Fmt::A> denotes string format.
+
+=cut
+
+# These must correspond to the values in src/data/format.h
+use constant {
+ F => 0,
+ COMMA => 1,
+ DOT => 2,
+ DOLLAR => 3,
+ PCT => 4,
+ E => 5,
+ CCA => 6,
+ CCB => 7,
+ CCC => 8,
+ CCD => 9,
+ CCE => 10,
+ N => 11,
+ Z => 12,
+ P => 13,
+ PK => 14,
+ IB => 15,
+ PIB => 16,
+ PIBHEX => 17,
+ RB => 18,
+ RBHEX => 19,
+ DATE => 20,
+ ADATE => 21,
+ EDATE => 22,
+ JDATE => 23,
+ SDATE => 24,
+ QYR => 25,
+ MOYR => 26,
+ WKYR => 27,
+ DATETIME => 28,
+ TIME => 29,
+ DTIME => 30,
+ WKDAY => 31,
+ MONTH => 32,
+ A => 33,
+ AHEX => 34
+};
+
+
+=head2 PSPP::Var
+
+=cut
+
+package PSPP::Var;
+
+=head3 new ($dict, $name, %input_fmt)
+
+Creates and returns a new variable in the dictionary C<dict>. The
+new variable will have the name C<name>.
+The input format is set by the C<input_fmt> parameter
+(See L</PSPP::Fmt>).
+By default, the write and print formats are the same as the input format.
+The write and print formats may be changed (See L</set_write_format>),
+L</set_print_format>). The input format may not be changed after
+the variable has been created.
+If the variable cannot be created, undef is returned.
+
+=cut
+
+sub new
+{
+ my $class = shift;
+ my $dict = shift;
+ my $name = shift;
+ my %format = @_;
+ my $self = pxs_dict_create_var ($dict, $name, \%format);
+ if ( ref $self )
+ {
+ bless ($self, $class);
+ }
+ return $self;
+}
+
+=pod
+
+=head3 set_label ($label)
+
+Sets the variable label to C<label>.
+
+
+=cut
+
+=pod
+
+=head3 set_write_format (%fmt)
+
+Sets the write format to C<fmt>. <fmt> is a hash containing the keys:
+
+=over 2
+
+=item FMT
+
+A constant denoting the format type. See L</PSPP::Fmt>.
+
+=item decimals
+
+An integer denoting the number of decimal places for the format.
+
+=item width
+
+An integer denoting the number of width of the format.
+
+=back
+
+On error the subroutine returns zero.
+
+=cut
+
+sub set_write_format
+{
+ my $var = shift;
+ my %format = @_;
+ pxs_set_write_format ($var, \%format);
+}
+
+=pod
+
+=head3 set_print_format (%fmt)
+
+Sets the print format to C<fmt>.
+On error the subroutine returns zero.
+
+=cut
+
+sub set_print_format
+{
+ my $var = shift;
+ my %format = @_;
+ pxs_set_print_format ($var, \%format);
+}
+
+=pod
+
+=head3 set_output_format (%fmt)
+
+Sets the write and print formats to C<fmt>. This is the same as
+calling set_write_format followed by set_print_format.
+On error the subroutine returns zero.
+
+=cut
+
+
+sub set_output_format
+{
+ my $var = shift;
+ my %format = @_;
+ pxs_set_output_format ($var, \%format);
+}
+
+=pod
+
+=head3 clear_value_labels ()
+
+Removes all value labels from the variable.
+
+=cut
+
+
+=pod
+
+=head3 add_value_label ($key, $label)
+
+Adds the value label C<label> to the variable for the value C<key>.
+On error the subroutine returns zero.
+
+=head3 add_value_labels (@array)
+
+=cut
+
+sub add_value_labels
+{
+ my $var = shift;
+ my %values = @_;
+ my @li;
+
+ my $n = 0;
+ while ( @li = each %values )
+ {
+ if ( $var->add_value_label ($li[0], "$li[1]") )
+ {
+ $n++;
+ }
+ }
+
+ return $n;
+}
+
+=pod
+
+=head3 set_value_labels ($key, $value)
+
+C<Set_value_labels> is identical to calling L</clear_value_labels>
+followed by L</add_value_labels>.
+On error the subroutine returns zero.
+
+=cut
+
+sub set_value_labels
+{
+ my $self = shift;
+ my %labels = @_;
+ $self->clear_value_labels () ;
+ $self->add_value_labels (%labels);
+}
+
+=pod
+
+=head3 set_missing_values ($val1 [, $val2[, $val3] ])
+
+Sets the missing values for the variable.
+No more than three missing values may be specified.
+
+=head3 get_attributes()
+
+Returns a reference to a hash of the custom variable attributes.
+Each value of the hash is a reference to an array containing the
+attribute values.
+
+=head3 get_name ()
+
+Returns the name of the variable.
+
+=head3 get_label ()
+
+Returns the label of the variable or undef if there is no label.
+
+=head3 get_value_labels ()
+
+Returns a reference to a hash containing the value labels for the variable.
+The hash is keyed by data values which correpond to the labels.
+
+=cut
+
+package PSPP::Sysfile;
+
+=pod
+
+=head2 PSPP::Sysfile
+
+=head3 new ($filename, $dict [,%opts])
+
+Creates a new system file from the dictionary C<dict>. The file will
+be written to the file called C<filename>.
+C<opt>, if specified, is a hash containing optional parameters for the
+system file. Currently, the only supported parameter is
+C<compress>. If C<compress> is non zero, then the system file written
+will be in the compressed format.
+On error, undef is returned.
+
+
+=head3 append_case (@case)
+
+Appends a case to the system file.
+C<Case> is an array of scalars, each of which are the values of
+the variables in the dictionary corresponding to the system file.
+The special value C<PSPP::SYSMIS> may be used to indicate that a value
+is system missing.
+If the array contains less elements than variables in the dictionary,
+remaining values will be set to system missing.
+
+=cut
+
+sub new
+{
+ my $class = shift;
+ my $filename = shift;
+ my $dict = shift;
+ my $opts = shift;
+
+ my $self = pxs_create_sysfile ($filename, $dict, $opts);
+
+ if ( ref $self )
+ {
+ bless ($self, $class);
+ }
+ return $self;
+}
+
+=pod
+
+=head3 close ()
+
+Closes the system file.
+
+This subroutine closes the system file and flushes it to disk. No
+further cases may be written once the file has been closed.
+The system file will be automatically closed when it goes out of scope.
+
+=cut
+
+package PSPP::Reader;
+
+=pod
+
+=head2 PSPP::Reader
+
+=cut
+
+sub open
+{
+ my $class = shift;
+ my $filename = shift;
+
+ my $self = pxs_open_sysfile ($filename);
+
+ if ( ref $self )
+ {
+ bless ($self, $class);
+ }
+ return $self;
+}
+
+=pod
+
+=head3 open ($filename)
+
+Opens a system file for reading.
+
+Open is used to read data from an existing system file.
+It creates and returns a PSPP::Reader object which can be used to read
+data and dictionary information from C<filename>.
+
+=cut
+
+sub get_dict
+{
+ my $reader = shift;
+
+ my $dict = pxs_get_dict ($reader);
+
+ bless ($dict, "PSPP::Dict");
+
+ return $dict;
+}
+
+=pod
+
+=head3 get_dict ()
+
+Returns the dictionary associated with the reader.
+
+=head3 get_next_case ()
+
+Retrieves the next case from the reader.
+This method returns an array of scalars, each of which are the values of
+the data in the system file.
+The first call to C<get_next_case> after C<open> has been called retrieves
+the first case in the system file. Each subsequent call retrieves the next
+case. If there are no more cases to be read, the function returns an empty
+list.
+
+If the case contains system missing values, these values are set to the
+empty string.
+
+=head2 Miscellaneous subroutines
+
+The following subroutines provide (hopefully) useful information about the
+values retrieved from a reader.
+
+=head3 PSPP::format_value ($value, $variable)
+
+Returns a scalar containing a string representing C<value> formatted accoring
+to the print format of C<variable>.
+In the most common ussage, C<value> should be a value of C<variable>.
+
+
+=head3 PSPP::value_is_missing ($value, $variable)
+
+Returns non-zero if C<value> is either system missing, or if it matches the
+user missing criteria for C<variable>.
+
+=cut
+
+1;
+__END__
+
+
+=head1 AUTHOR
+
+John Darrington, E<lt>john@darrington.wattle.id.auE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2007, 2008, 2009 by Free Software Foundation
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+=cut
--- /dev/null
+#if 0
+<<'SKIP';
+#endif
+/*
+----------------------------------------------------------------------
+
+ ppport.h -- Perl/Pollution/Portability Version 3.06_01
+
+ Automatically created by Devel::PPPort running under
+ perl 5.008008 on Fri Apr 6 14:13:45 2007.
+
+ Do NOT edit this file directly! -- Edit PPPort_pm.PL and the
+ includes in parts/inc/ instead.
+
+ Use 'perldoc ppport.h' to view the documentation below.
+
+----------------------------------------------------------------------
+
+SKIP
+
+=pod
+
+=head1 NAME
+
+ppport.h - Perl/Pollution/Portability version 3.06_01
+
+=head1 SYNOPSIS
+
+ perl ppport.h [options] [source files]
+
+ Searches current directory for files if no [source files] are given
+
+ --help show short help
+
+ --patch=file write one patch file with changes
+ --copy=suffix write changed copies with suffix
+ --diff=program use diff program and options
+
+ --compat-version=version provide compatibility with Perl version
+ --cplusplus accept C++ comments
+
+ --quiet don't output anything except fatal errors
+ --nodiag don't show diagnostics
+ --nohints don't show hints
+ --nochanges don't suggest changes
+ --nofilter don't filter input files
+
+ --list-provided list provided API
+ --list-unsupported list unsupported API
+ --api-info=name show Perl API portability information
+
+=head1 COMPATIBILITY
+
+This version of F<ppport.h> is designed to support operation with Perl
+installations back to 5.003, and has been tested up to 5.9.3.
+
+=head1 OPTIONS
+
+=head2 --help
+
+Display a brief usage summary.
+
+=head2 --patch=I<file>
+
+If this option is given, a single patch file will be created if
+any changes are suggested. This requires a working diff program
+to be installed on your system.
+
+=head2 --copy=I<suffix>
+
+If this option is given, a copy of each file will be saved with
+the given suffix that contains the suggested changes. This does
+not require any external programs.
+
+If neither C<--patch> or C<--copy> are given, the default is to
+simply print the diffs for each file. This requires either
+C<Text::Diff> or a C<diff> program to be installed.
+
+=head2 --diff=I<program>
+
+Manually set the diff program and options to use. The default
+is to use C<Text::Diff>, when installed, and output unified
+context diffs.
+
+=head2 --compat-version=I<version>
+
+Tell F<ppport.h> to check for compatibility with the given
+Perl version. The default is to check for compatibility with Perl
+version 5.003. You can use this option to reduce the output
+of F<ppport.h> if you intend to be backward compatible only
+up to a certain Perl version.
+
+=head2 --cplusplus
+
+Usually, F<ppport.h> will detect C++ style comments and
+replace them with C style comments for portability reasons.
+Using this option instructs F<ppport.h> to leave C++
+comments untouched.
+
+=head2 --quiet
+
+Be quiet. Don't print anything except fatal errors.
+
+=head2 --nodiag
+
+Don't output any diagnostic messages. Only portability
+alerts will be printed.
+
+=head2 --nohints
+
+Don't output any hints. Hints often contain useful portability
+notes.
+
+=head2 --nochanges
+
+Don't suggest any changes. Only give diagnostic output and hints
+unless these are also deactivated.
+
+=head2 --nofilter
+
+Don't filter the list of input files. By default, files not looking
+like source code (i.e. not *.xs, *.c, *.cc, *.cpp or *.h) are skipped.
+
+=head2 --list-provided
+
+Lists the API elements for which compatibility is provided by
+F<ppport.h>. Also lists if it must be explicitly requested,
+if it has dependencies, and if there are hints for it.
+
+=head2 --list-unsupported
+
+Lists the API elements that are known not to be supported by
+F<ppport.h> and below which version of Perl they probably
+won't be available or work.
+
+=head2 --api-info=I<name>
+
+Show portability information for API elements matching I<name>.
+If I<name> is surrounded by slashes, it is interpreted as a regular
+expression.
+
+=head1 DESCRIPTION
+
+In order for a Perl extension (XS) module to be as portable as possible
+across differing versions of Perl itself, certain steps need to be taken.
+
+=over 4
+
+=item *
+
+Including this header is the first major one. This alone will give you
+access to a large part of the Perl API that hasn't been available in
+earlier Perl releases. Use
+
+ perl ppport.h --list-provided
+
+to see which API elements are provided by ppport.h.
+
+=item *
+
+You should avoid using deprecated parts of the API. For example, using
+global Perl variables without the C<PL_> prefix is deprecated. Also,
+some API functions used to have a C<perl_> prefix. Using this form is
+also deprecated. You can safely use the supported API, as F<ppport.h>
+will provide wrappers for older Perl versions.
+
+=item *
+
+If you use one of a few functions that were not present in earlier
+versions of Perl, and that can't be provided using a macro, you have
+to explicitly request support for these functions by adding one or
+more C<#define>s in your source code before the inclusion of F<ppport.h>.
+
+These functions will be marked C<explicit> in the list shown by
+C<--list-provided>.
+
+Depending on whether you module has a single or multiple files that
+use such functions, you want either C<static> or global variants.
+
+For a C<static> function, use:
+
+ #define NEED_function
+
+For a global function, use:
+
+ #define NEED_function_GLOBAL
+
+Note that you mustn't have more than one global request for one
+function in your project.
+
+ Function Static Request Global Request
+ -----------------------------------------------------------------------------------------
+ eval_pv() NEED_eval_pv NEED_eval_pv_GLOBAL
+ grok_bin() NEED_grok_bin NEED_grok_bin_GLOBAL
+ grok_hex() NEED_grok_hex NEED_grok_hex_GLOBAL
+ grok_number() NEED_grok_number NEED_grok_number_GLOBAL
+ grok_numeric_radix() NEED_grok_numeric_radix NEED_grok_numeric_radix_GLOBAL
+ grok_oct() NEED_grok_oct NEED_grok_oct_GLOBAL
+ newCONSTSUB() NEED_newCONSTSUB NEED_newCONSTSUB_GLOBAL
+ newRV_noinc() NEED_newRV_noinc NEED_newRV_noinc_GLOBAL
+ sv_2pv_nolen() NEED_sv_2pv_nolen NEED_sv_2pv_nolen_GLOBAL
+ sv_2pvbyte() NEED_sv_2pvbyte NEED_sv_2pvbyte_GLOBAL
+ sv_catpvf_mg() NEED_sv_catpvf_mg NEED_sv_catpvf_mg_GLOBAL
+ sv_catpvf_mg_nocontext() NEED_sv_catpvf_mg_nocontext NEED_sv_catpvf_mg_nocontext_GLOBAL
+ sv_setpvf_mg() NEED_sv_setpvf_mg NEED_sv_setpvf_mg_GLOBAL
+ sv_setpvf_mg_nocontext() NEED_sv_setpvf_mg_nocontext NEED_sv_setpvf_mg_nocontext_GLOBAL
+ vnewSVpvf() NEED_vnewSVpvf NEED_vnewSVpvf_GLOBAL
+
+To avoid namespace conflicts, you can change the namespace of the
+explicitly exported functions using the C<DPPP_NAMESPACE> macro.
+Just C<#define> the macro before including C<ppport.h>:
+
+ #define DPPP_NAMESPACE MyOwnNamespace_
+ #include "ppport.h"
+
+The default namespace is C<DPPP_>.
+
+=back
+
+The good thing is that most of the above can be checked by running
+F<ppport.h> on your source code. See the next section for
+details.
+
+=head1 EXAMPLES
+
+To verify whether F<ppport.h> is needed for your module, whether you
+should make any changes to your code, and whether any special defines
+should be used, F<ppport.h> can be run as a Perl script to check your
+source code. Simply say:
+
+ perl ppport.h
+
+The result will usually be a list of patches suggesting changes
+that should at least be acceptable, if not necessarily the most
+efficient solution, or a fix for all possible problems.
+
+If you know that your XS module uses features only available in
+newer Perl releases, if you're aware that it uses C++ comments,
+and if you want all suggestions as a single patch file, you could
+use something like this:
+
+ perl ppport.h --compat-version=5.6.0 --cplusplus --patch=test.diff
+
+If you only want your code to be scanned without any suggestions
+for changes, use:
+
+ perl ppport.h --nochanges
+
+You can specify a different C<diff> program or options, using
+the C<--diff> option:
+
+ perl ppport.h --diff='diff -C 10'
+
+This would output context diffs with 10 lines of context.
+
+To display portability information for the C<newSVpvn> function,
+use:
+
+ perl ppport.h --api-info=newSVpvn
+
+Since the argument to C<--api-info> can be a regular expression,
+you can use
+
+ perl ppport.h --api-info=/_nomg$/
+
+to display portability information for all C<_nomg> functions or
+
+ perl ppport.h --api-info=/./
+
+to display information for all known API elements.
+
+=head1 BUGS
+
+If this version of F<ppport.h> is causing failure during
+the compilation of this module, please check if newer versions
+of either this module or C<Devel::PPPort> are available on CPAN
+before sending a bug report.
+
+If F<ppport.h> was generated using the latest version of
+C<Devel::PPPort> and is causing failure of this module, please
+file a bug report using the CPAN Request Tracker at L<http://rt.cpan.org/>.
+
+Please include the following information:
+
+=over 4
+
+=item 1.
+
+The complete output from running "perl -V"
+
+=item 2.
+
+This file.
+
+=item 3.
+
+The name and version of the module you were trying to build.
+
+=item 4.
+
+A full log of the build that failed.
+
+=item 5.
+
+Any other information that you think could be relevant.
+
+=back
+
+For the latest version of this code, please get the C<Devel::PPPort>
+module from CPAN.
+
+=head1 COPYRIGHT
+
+Version 3.x, Copyright (c) 2004-2005, Marcus Holland-Moritz.
+
+Version 2.x, Copyright (C) 2001, Paul Marquess.
+
+Version 1.x, Copyright (C) 1999, Kenneth Albanowski.
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+See L<Devel::PPPort>.
+
+=cut
+
+use strict;
+
+my %opt = (
+ quiet => 0,
+ diag => 1,
+ hints => 1,
+ changes => 1,
+ cplusplus => 0,
+ filter => 1,
+);
+
+my($ppport) = $0 =~ /([\w.]+)$/;
+my $LF = '(?:\r\n|[\r\n])'; # line feed
+my $HS = "[ \t]"; # horizontal whitespace
+
+eval {
+ require Getopt::Long;
+ Getopt::Long::GetOptions(\%opt, qw(
+ help quiet diag! filter! hints! changes! cplusplus
+ patch=s copy=s diff=s compat-version=s
+ list-provided list-unsupported api-info=s
+ )) or usage();
+};
+
+if ($@ and grep /^-/, @ARGV) {
+ usage() if "@ARGV" =~ /^--?h(?:elp)?$/;
+ die "Getopt::Long not found. Please don't use any options.\n";
+}
+
+usage() if $opt{help};
+
+if (exists $opt{'compat-version'}) {
+ my($r,$v,$s) = eval { parse_version($opt{'compat-version'}) };
+ if ($@) {
+ die "Invalid version number format: '$opt{'compat-version'}'\n";
+ }
+ die "Only Perl 5 is supported\n" if $r != 5;
+ die "Invalid version number: $opt{'compat-version'}\n" if $v >= 1000 || $s >= 1000;
+ $opt{'compat-version'} = sprintf "%d.%03d%03d", $r, $v, $s;
+}
+else {
+ $opt{'compat-version'} = 5;
+}
+
+# Never use C comments in this file!!!!!
+my $ccs = '/'.'*';
+my $cce = '*'.'/';
+my $rccs = quotemeta $ccs;
+my $rcce = quotemeta $cce;
+
+my %API = map { /^(\w+)\|([^|]*)\|([^|]*)\|(\w*)$/
+ ? ( $1 => {
+ ($2 ? ( base => $2 ) : ()),
+ ($3 ? ( todo => $3 ) : ()),
+ (index($4, 'v') >= 0 ? ( varargs => 1 ) : ()),
+ (index($4, 'p') >= 0 ? ( provided => 1 ) : ()),
+ (index($4, 'n') >= 0 ? ( nothxarg => 1 ) : ()),
+ } )
+ : die "invalid spec: $_" } qw(
+AvFILLp|5.004050||p
+AvFILL|||
+CLASS|||n
+CX_CURPAD_SAVE|||
+CX_CURPAD_SV|||
+CopFILEAV|5.006000||p
+CopFILEGV_set|5.006000||p
+CopFILEGV|5.006000||p
+CopFILESV|5.006000||p
+CopFILE_set|5.006000||p
+CopFILE|5.006000||p
+CopSTASHPV_set|5.006000||p
+CopSTASHPV|5.006000||p
+CopSTASH_eq|5.006000||p
+CopSTASH_set|5.006000||p
+CopSTASH|5.006000||p
+CopyD|5.009002||p
+Copy|||
+CvPADLIST|||
+CvSTASH|||
+CvWEAKOUTSIDE|||
+DEFSV|5.004050||p
+END_EXTERN_C|5.005000||p
+ENTER|||
+ERRSV|5.004050||p
+EXTEND|||
+EXTERN_C|5.005000||p
+FREETMPS|||
+GIMME_V||5.004000|n
+GIMME|||n
+GROK_NUMERIC_RADIX|5.007002||p
+G_ARRAY|||
+G_DISCARD|||
+G_EVAL|||
+G_NOARGS|||
+G_SCALAR|||
+G_VOID||5.004000|
+GetVars|||
+GvSV|||
+Gv_AMupdate|||
+HEf_SVKEY||5.004000|
+HeHASH||5.004000|
+HeKEY||5.004000|
+HeKLEN||5.004000|
+HePV||5.004000|
+HeSVKEY_force||5.004000|
+HeSVKEY_set||5.004000|
+HeSVKEY||5.004000|
+HeVAL||5.004000|
+HvNAME|||
+INT2PTR|5.006000||p
+IN_LOCALE_COMPILETIME|5.007002||p
+IN_LOCALE_RUNTIME|5.007002||p
+IN_LOCALE|5.007002||p
+IN_PERL_COMPILETIME|5.008001||p
+IS_NUMBER_GREATER_THAN_UV_MAX|5.007002||p
+IS_NUMBER_INFINITY|5.007002||p
+IS_NUMBER_IN_UV|5.007002||p
+IS_NUMBER_NAN|5.007003||p
+IS_NUMBER_NEG|5.007002||p
+IS_NUMBER_NOT_INT|5.007002||p
+IVSIZE|5.006000||p
+IVTYPE|5.006000||p
+IVdf|5.006000||p
+LEAVE|||
+LVRET|||
+MARK|||
+MY_CXT_CLONE|5.009002||p
+MY_CXT_INIT|5.007003||p
+MY_CXT|5.007003||p
+MoveD|5.009002||p
+Move|||
+NEWSV|||
+NOOP|5.005000||p
+NUM2PTR|5.006000||p
+NVTYPE|5.006000||p
+NVef|5.006001||p
+NVff|5.006001||p
+NVgf|5.006001||p
+Newc|||
+Newz|||
+New|||
+Nullav|||
+Nullch|||
+Nullcv|||
+Nullhv|||
+Nullsv|||
+ORIGMARK|||
+PAD_BASE_SV|||
+PAD_CLONE_VARS|||
+PAD_COMPNAME_FLAGS|||
+PAD_COMPNAME_GEN_set|||
+PAD_COMPNAME_GEN|||
+PAD_COMPNAME_OURSTASH|||
+PAD_COMPNAME_PV|||
+PAD_COMPNAME_TYPE|||
+PAD_RESTORE_LOCAL|||
+PAD_SAVE_LOCAL|||
+PAD_SAVE_SETNULLPAD|||
+PAD_SETSV|||
+PAD_SET_CUR_NOSAVE|||
+PAD_SET_CUR|||
+PAD_SVl|||
+PAD_SV|||
+PERL_BCDVERSION|5.009003||p
+PERL_GCC_BRACE_GROUPS_FORBIDDEN|5.008001||p
+PERL_INT_MAX|5.004000||p
+PERL_INT_MIN|5.004000||p
+PERL_LONG_MAX|5.004000||p
+PERL_LONG_MIN|5.004000||p
+PERL_MAGIC_arylen|5.007002||p
+PERL_MAGIC_backref|5.007002||p
+PERL_MAGIC_bm|5.007002||p
+PERL_MAGIC_collxfrm|5.007002||p
+PERL_MAGIC_dbfile|5.007002||p
+PERL_MAGIC_dbline|5.007002||p
+PERL_MAGIC_defelem|5.007002||p
+PERL_MAGIC_envelem|5.007002||p
+PERL_MAGIC_env|5.007002||p
+PERL_MAGIC_ext|5.007002||p
+PERL_MAGIC_fm|5.007002||p
+PERL_MAGIC_glob|5.007002||p
+PERL_MAGIC_isaelem|5.007002||p
+PERL_MAGIC_isa|5.007002||p
+PERL_MAGIC_mutex|5.007002||p
+PERL_MAGIC_nkeys|5.007002||p
+PERL_MAGIC_overload_elem|5.007002||p
+PERL_MAGIC_overload_table|5.007002||p
+PERL_MAGIC_overload|5.007002||p
+PERL_MAGIC_pos|5.007002||p
+PERL_MAGIC_qr|5.007002||p
+PERL_MAGIC_regdata|5.007002||p
+PERL_MAGIC_regdatum|5.007002||p
+PERL_MAGIC_regex_global|5.007002||p
+PERL_MAGIC_shared_scalar|5.007003||p
+PERL_MAGIC_shared|5.007003||p
+PERL_MAGIC_sigelem|5.007002||p
+PERL_MAGIC_sig|5.007002||p
+PERL_MAGIC_substr|5.007002||p
+PERL_MAGIC_sv|5.007002||p
+PERL_MAGIC_taint|5.007002||p
+PERL_MAGIC_tiedelem|5.007002||p
+PERL_MAGIC_tiedscalar|5.007002||p
+PERL_MAGIC_tied|5.007002||p
+PERL_MAGIC_utf8|5.008001||p
+PERL_MAGIC_uvar_elem|5.007003||p
+PERL_MAGIC_uvar|5.007002||p
+PERL_MAGIC_vec|5.007002||p
+PERL_MAGIC_vstring|5.008001||p
+PERL_QUAD_MAX|5.004000||p
+PERL_QUAD_MIN|5.004000||p
+PERL_REVISION|5.006000||p
+PERL_SCAN_ALLOW_UNDERSCORES|5.007003||p
+PERL_SCAN_DISALLOW_PREFIX|5.007003||p
+PERL_SCAN_GREATER_THAN_UV_MAX|5.007003||p
+PERL_SCAN_SILENT_ILLDIGIT|5.008001||p
+PERL_SHORT_MAX|5.004000||p
+PERL_SHORT_MIN|5.004000||p
+PERL_SUBVERSION|5.006000||p
+PERL_UCHAR_MAX|5.004000||p
+PERL_UCHAR_MIN|5.004000||p
+PERL_UINT_MAX|5.004000||p
+PERL_UINT_MIN|5.004000||p
+PERL_ULONG_MAX|5.004000||p
+PERL_ULONG_MIN|5.004000||p
+PERL_UNUSED_DECL|5.007002||p
+PERL_UQUAD_MAX|5.004000||p
+PERL_UQUAD_MIN|5.004000||p
+PERL_USHORT_MAX|5.004000||p
+PERL_USHORT_MIN|5.004000||p
+PERL_VERSION|5.006000||p
+PL_DBsingle|||pn
+PL_DBsub|||pn
+PL_DBtrace|||n
+PL_Sv|5.005000||p
+PL_compiling|5.004050||p
+PL_copline|5.005000||p
+PL_curcop|5.004050||p
+PL_curstash|5.004050||p
+PL_debstash|5.004050||p
+PL_defgv|5.004050||p
+PL_diehook|5.004050||p
+PL_dirty|5.004050||p
+PL_dowarn|||pn
+PL_errgv|5.004050||p
+PL_hexdigit|5.005000||p
+PL_hints|5.005000||p
+PL_last_in_gv|||n
+PL_modglobal||5.005000|n
+PL_na|5.004050||pn
+PL_no_modify|5.006000||p
+PL_ofs_sv|||n
+PL_perl_destruct_level|5.004050||p
+PL_perldb|5.004050||p
+PL_ppaddr|5.006000||p
+PL_rsfp_filters|5.004050||p
+PL_rsfp|5.004050||p
+PL_rs|||n
+PL_stack_base|5.004050||p
+PL_stack_sp|5.004050||p
+PL_stdingv|5.004050||p
+PL_sv_arenaroot|5.004050||p
+PL_sv_no|5.004050||pn
+PL_sv_undef|5.004050||pn
+PL_sv_yes|5.004050||pn
+PL_tainted|5.004050||p
+PL_tainting|5.004050||p
+POPi|||n
+POPl|||n
+POPn|||n
+POPpbytex||5.007001|n
+POPpx||5.005030|n
+POPp|||n
+POPs|||n
+PTR2IV|5.006000||p
+PTR2NV|5.006000||p
+PTR2UV|5.006000||p
+PTR2ul|5.007001||p
+PTRV|5.006000||p
+PUSHMARK|||
+PUSHi|||
+PUSHmortal|5.009002||p
+PUSHn|||
+PUSHp|||
+PUSHs|||
+PUSHu|5.004000||p
+PUTBACK|||
+PerlIO_clearerr||5.007003|
+PerlIO_close||5.007003|
+PerlIO_eof||5.007003|
+PerlIO_error||5.007003|
+PerlIO_fileno||5.007003|
+PerlIO_fill||5.007003|
+PerlIO_flush||5.007003|
+PerlIO_get_base||5.007003|
+PerlIO_get_bufsiz||5.007003|
+PerlIO_get_cnt||5.007003|
+PerlIO_get_ptr||5.007003|
+PerlIO_read||5.007003|
+PerlIO_seek||5.007003|
+PerlIO_set_cnt||5.007003|
+PerlIO_set_ptrcnt||5.007003|
+PerlIO_setlinebuf||5.007003|
+PerlIO_stderr||5.007003|
+PerlIO_stdin||5.007003|
+PerlIO_stdout||5.007003|
+PerlIO_tell||5.007003|
+PerlIO_unread||5.007003|
+PerlIO_write||5.007003|
+Poison|5.008000||p
+RETVAL|||n
+Renewc|||
+Renew|||
+SAVECLEARSV|||
+SAVECOMPPAD|||
+SAVEPADSV|||
+SAVETMPS|||
+SAVE_DEFSV|5.004050||p
+SPAGAIN|||
+SP|||
+START_EXTERN_C|5.005000||p
+START_MY_CXT|5.007003||p
+STMT_END|||p
+STMT_START|||p
+ST|||
+SVt_IV|||
+SVt_NV|||
+SVt_PVAV|||
+SVt_PVCV|||
+SVt_PVHV|||
+SVt_PVMG|||
+SVt_PV|||
+Safefree|||
+Slab_Alloc|||
+Slab_Free|||
+StructCopy|||
+SvCUR_set|||
+SvCUR|||
+SvEND|||
+SvGETMAGIC|5.004050||p
+SvGROW|||
+SvIOK_UV||5.006000|
+SvIOK_notUV||5.006000|
+SvIOK_off|||
+SvIOK_only_UV||5.006000|
+SvIOK_only|||
+SvIOK_on|||
+SvIOKp|||
+SvIOK|||
+SvIVX|||
+SvIV_nomg|5.009001||p
+SvIV_set|||
+SvIVx|||
+SvIV|||
+SvIsCOW_shared_hash||5.008003|
+SvIsCOW||5.008003|
+SvLEN_set|||
+SvLEN|||
+SvLOCK||5.007003|
+SvMAGIC_set||5.009003|
+SvNIOK_off|||
+SvNIOKp|||
+SvNIOK|||
+SvNOK_off|||
+SvNOK_only|||
+SvNOK_on|||
+SvNOKp|||
+SvNOK|||
+SvNVX|||
+SvNV_set|||
+SvNVx|||
+SvNV|||
+SvOK|||
+SvOOK|||
+SvPOK_off|||
+SvPOK_only_UTF8||5.006000|
+SvPOK_only|||
+SvPOK_on|||
+SvPOKp|||
+SvPOK|||
+SvPVX|||
+SvPV_force_nomg|5.007002||p
+SvPV_force|||
+SvPV_nolen|5.006000||p
+SvPV_nomg|5.007002||p
+SvPV_set|||
+SvPVbyte_force||5.009002|
+SvPVbyte_nolen||5.006000|
+SvPVbytex_force||5.006000|
+SvPVbytex||5.006000|
+SvPVbyte|5.006000||p
+SvPVutf8_force||5.006000|
+SvPVutf8_nolen||5.006000|
+SvPVutf8x_force||5.006000|
+SvPVutf8x||5.006000|
+SvPVutf8||5.006000|
+SvPVx|||
+SvPV|||
+SvREFCNT_dec|||
+SvREFCNT_inc|||
+SvREFCNT|||
+SvROK_off|||
+SvROK_on|||
+SvROK|||
+SvRV_set||5.009003|
+SvRV|||
+SvSETMAGIC|||
+SvSHARE||5.007003|
+SvSTASH_set||5.009003|
+SvSTASH|||
+SvSetMagicSV_nosteal||5.004000|
+SvSetMagicSV||5.004000|
+SvSetSV_nosteal||5.004000|
+SvSetSV|||
+SvTAINTED_off||5.004000|
+SvTAINTED_on||5.004000|
+SvTAINTED||5.004000|
+SvTAINT|||
+SvTRUE|||
+SvTYPE|||
+SvUNLOCK||5.007003|
+SvUOK||5.007001|
+SvUPGRADE|||
+SvUTF8_off||5.006000|
+SvUTF8_on||5.006000|
+SvUTF8||5.006000|
+SvUVXx|5.004000||p
+SvUVX|5.004000||p
+SvUV_nomg|5.009001||p
+SvUV_set||5.009003|
+SvUVx|5.004000||p
+SvUV|5.004000||p
+SvVOK||5.008001|
+THIS|||n
+UNDERBAR|5.009002||p
+UVSIZE|5.006000||p
+UVTYPE|5.006000||p
+UVXf|5.007001||p
+UVof|5.006000||p
+UVuf|5.006000||p
+UVxf|5.006000||p
+XCPT_CATCH|5.009002||p
+XCPT_RETHROW|5.009002||p
+XCPT_TRY_END|5.009002||p
+XCPT_TRY_START|5.009002||p
+XPUSHi|||
+XPUSHmortal|5.009002||p
+XPUSHn|||
+XPUSHp|||
+XPUSHs|||
+XPUSHu|5.004000||p
+XSRETURN_EMPTY|||
+XSRETURN_IV|||
+XSRETURN_NO|||
+XSRETURN_NV|||
+XSRETURN_PV|||
+XSRETURN_UNDEF|||
+XSRETURN_UV|5.008001||p
+XSRETURN_YES|||
+XSRETURN|||
+XST_mIV|||
+XST_mNO|||
+XST_mNV|||
+XST_mPV|||
+XST_mUNDEF|||
+XST_mUV|5.008001||p
+XST_mYES|||
+XS_VERSION_BOOTCHECK|||
+XS_VERSION|||
+XS|||
+ZeroD|5.009002||p
+Zero|||
+_aMY_CXT|5.007003||p
+_pMY_CXT|5.007003||p
+aMY_CXT_|5.007003||p
+aMY_CXT|5.007003||p
+aTHX_|5.006000||p
+aTHX|5.006000||p
+add_data|||
+allocmy|||
+amagic_call|||
+any_dup|||
+ao|||
+append_elem|||
+append_list|||
+apply_attrs_my|||
+apply_attrs_string||5.006001|
+apply_attrs|||
+apply|||
+asIV|||
+asUV|||
+atfork_lock||5.007003|n
+atfork_unlock||5.007003|n
+av_arylen_p||5.009003|
+av_clear|||
+av_delete||5.006000|
+av_exists||5.006000|
+av_extend|||
+av_fake|||
+av_fetch|||
+av_fill|||
+av_len|||
+av_make|||
+av_pop|||
+av_push|||
+av_reify|||
+av_shift|||
+av_store|||
+av_undef|||
+av_unshift|||
+ax|||n
+bad_type|||
+bind_match|||
+block_end|||
+block_gimme||5.004000|
+block_start|||
+boolSV|5.004000||p
+boot_core_PerlIO|||
+boot_core_UNIVERSAL|||
+boot_core_xsutils|||
+bytes_from_utf8||5.007001|
+bytes_to_utf8||5.006001|
+cache_re|||
+call_argv|5.006000||p
+call_atexit||5.006000|
+call_body|||
+call_list_body|||
+call_list||5.004000|
+call_method|5.006000||p
+call_pv|5.006000||p
+call_sv|5.006000||p
+calloc||5.007002|n
+cando|||
+cast_i32||5.006000|
+cast_iv||5.006000|
+cast_ulong||5.006000|
+cast_uv||5.006000|
+check_uni|||
+checkcomma|||
+checkposixcc|||
+ck_anoncode|||
+ck_bitop|||
+ck_concat|||
+ck_defined|||
+ck_delete|||
+ck_die|||
+ck_eof|||
+ck_eval|||
+ck_exec|||
+ck_exists|||
+ck_exit|||
+ck_ftst|||
+ck_fun|||
+ck_glob|||
+ck_grep|||
+ck_index|||
+ck_join|||
+ck_lengthconst|||
+ck_lfun|||
+ck_listiob|||
+ck_match|||
+ck_method|||
+ck_null|||
+ck_open|||
+ck_repeat|||
+ck_require|||
+ck_retarget|||
+ck_return|||
+ck_rfun|||
+ck_rvconst|||
+ck_sassign|||
+ck_select|||
+ck_shift|||
+ck_sort|||
+ck_spair|||
+ck_split|||
+ck_subr|||
+ck_substr|||
+ck_svconst|||
+ck_trunc|||
+ck_unpack|||
+cl_and|||
+cl_anything|||
+cl_init_zero|||
+cl_init|||
+cl_is_anything|||
+cl_or|||
+closest_cop|||
+convert|||
+cop_free|||
+cr_textfilter|||
+croak_nocontext|||vn
+croak|||v
+csighandler||5.007001|n
+custom_op_desc||5.007003|
+custom_op_name||5.007003|
+cv_ckproto|||
+cv_clone|||
+cv_const_sv||5.004000|
+cv_dump|||
+cv_undef|||
+cx_dump||5.005000|
+cx_dup|||
+cxinc|||
+dAXMARK||5.009003|
+dAX|5.007002||p
+dITEMS|5.007002||p
+dMARK|||
+dMY_CXT_SV|5.007003||p
+dMY_CXT|5.007003||p
+dNOOP|5.006000||p
+dORIGMARK|||
+dSP|||
+dTHR|5.004050||p
+dTHXa|5.006000||p
+dTHXoa|5.006000||p
+dTHX|5.006000||p
+dUNDERBAR|5.009002||p
+dXCPT|5.009002||p
+dXSARGS|||
+dXSI32|||
+dXSTARG|5.006000||p
+deb_curcv|||
+deb_nocontext|||vn
+deb_stack_all|||
+deb_stack_n|||
+debop||5.005000|
+debprofdump||5.005000|
+debprof|||
+debstackptrs||5.007003|
+debstack||5.007003|
+deb||5.007003|v
+del_he|||
+del_sv|||
+delimcpy||5.004000|
+depcom|||
+deprecate_old|||
+deprecate|||
+despatch_signals||5.007001|
+die_nocontext|||vn
+die_where|||
+die|||v
+dirp_dup|||
+div128|||
+djSP|||
+do_aexec5|||
+do_aexec|||
+do_aspawn|||
+do_binmode||5.004050|
+do_chomp|||
+do_chop|||
+do_close|||
+do_dump_pad|||
+do_eof|||
+do_exec3|||
+do_execfree|||
+do_exec|||
+do_gv_dump||5.006000|
+do_gvgv_dump||5.006000|
+do_hv_dump||5.006000|
+do_ipcctl|||
+do_ipcget|||
+do_join|||
+do_kv|||
+do_magic_dump||5.006000|
+do_msgrcv|||
+do_msgsnd|||
+do_oddball|||
+do_op_dump||5.006000|
+do_open9||5.006000|
+do_openn||5.007001|
+do_open||5.004000|
+do_pipe|||
+do_pmop_dump||5.006000|
+do_print|||
+do_readline|||
+do_seek|||
+do_semop|||
+do_shmio|||
+do_spawn_nowait|||
+do_spawn|||
+do_sprintf|||
+do_sv_dump||5.006000|
+do_sysseek|||
+do_tell|||
+do_trans_complex_utf8|||
+do_trans_complex|||
+do_trans_count_utf8|||
+do_trans_count|||
+do_trans_simple_utf8|||
+do_trans_simple|||
+do_trans|||
+do_vecget|||
+do_vecset|||
+do_vop|||
+docatch_body|||
+docatch|||
+doeval|||
+dofile|||
+dofindlabel|||
+doform|||
+doing_taint||5.008001|n
+dooneliner|||
+doopen_pm|||
+doparseform|||
+dopoptoeval|||
+dopoptolabel|||
+dopoptoloop|||
+dopoptosub_at|||
+dopoptosub|||
+dounwind|||
+dowantarray|||
+dump_all||5.006000|
+dump_eval||5.006000|
+dump_fds|||
+dump_form||5.006000|
+dump_indent||5.006000|v
+dump_mstats|||
+dump_packsubs||5.006000|
+dump_sub||5.006000|
+dump_vindent||5.006000|
+dumpuntil|||
+dup_attrlist|||
+emulate_eaccess|||
+eval_pv|5.006000||p
+eval_sv|5.006000||p
+expect_number|||
+fbm_compile||5.005000|
+fbm_instr||5.005000|
+fd_on_nosuid_fs|||
+filter_add|||
+filter_del|||
+filter_gets|||
+filter_read|||
+find_beginning|||
+find_byclass|||
+find_in_my_stash|||
+find_runcv|||
+find_rundefsvoffset||5.009002|
+find_script|||
+find_uninit_var|||
+fold_constants|||
+forbid_setid|||
+force_ident|||
+force_list|||
+force_next|||
+force_version|||
+force_word|||
+form_nocontext|||vn
+form||5.004000|v
+fp_dup|||
+fprintf_nocontext|||vn
+free_global_struct|||
+free_tied_hv_pool|||
+free_tmps|||
+gen_constant_list|||
+get_av|5.006000||p
+get_context||5.006000|n
+get_cv|5.006000||p
+get_db_sub|||
+get_debug_opts|||
+get_hash_seed|||
+get_hv|5.006000||p
+get_mstats|||
+get_no_modify|||
+get_num|||
+get_op_descs||5.005000|
+get_op_names||5.005000|
+get_opargs|||
+get_ppaddr||5.006000|
+get_sv|5.006000||p
+get_vtbl||5.005030|
+getcwd_sv||5.007002|
+getenv_len|||
+gp_dup|||
+gp_free|||
+gp_ref|||
+grok_bin|5.007003||p
+grok_hex|5.007003||p
+grok_number|5.007002||p
+grok_numeric_radix|5.007002||p
+grok_oct|5.007003||p
+group_end|||
+gv_AVadd|||
+gv_HVadd|||
+gv_IOadd|||
+gv_autoload4||5.004000|
+gv_check|||
+gv_dump||5.006000|
+gv_efullname3||5.004000|
+gv_efullname4||5.006001|
+gv_efullname|||
+gv_ename|||
+gv_fetchfile|||
+gv_fetchmeth_autoload||5.007003|
+gv_fetchmethod_autoload||5.004000|
+gv_fetchmethod|||
+gv_fetchmeth|||
+gv_fetchpvn_flags||5.009002|
+gv_fetchpv|||
+gv_fetchsv||5.009002|
+gv_fullname3||5.004000|
+gv_fullname4||5.006001|
+gv_fullname|||
+gv_handler||5.007001|
+gv_init_sv|||
+gv_init|||
+gv_share|||
+gv_stashpvn|5.006000||p
+gv_stashpv|||
+gv_stashsv|||
+he_dup|||
+hek_dup|||
+hfreeentries|||
+hsplit|||
+hv_assert||5.009001|
+hv_auxinit|||
+hv_clear_placeholders||5.009001|
+hv_clear|||
+hv_delayfree_ent||5.004000|
+hv_delete_common|||
+hv_delete_ent||5.004000|
+hv_delete|||
+hv_eiter_p||5.009003|
+hv_eiter_set||5.009003|
+hv_exists_ent||5.004000|
+hv_exists|||
+hv_fetch_common|||
+hv_fetch_ent||5.004000|
+hv_fetch|||
+hv_free_ent||5.004000|
+hv_iterinit|||
+hv_iterkeysv||5.004000|
+hv_iterkey|||
+hv_iternext_flags||5.008000|
+hv_iternextsv|||
+hv_iternext|||
+hv_iterval|||
+hv_ksplit||5.004000|
+hv_magic_check|||
+hv_magic|||
+hv_name_set||5.009003|
+hv_notallowed|||
+hv_placeholders_get||5.009003|
+hv_placeholders_p||5.009003|
+hv_placeholders_set||5.009003|
+hv_riter_p||5.009003|
+hv_riter_set||5.009003|
+hv_scalar||5.009001|
+hv_store_ent||5.004000|
+hv_store_flags||5.008000|
+hv_store|||
+hv_undef|||
+ibcmp_locale||5.004000|
+ibcmp_utf8||5.007003|
+ibcmp|||
+incl_perldb|||
+incline|||
+incpush|||
+ingroup|||
+init_argv_symbols|||
+init_debugger|||
+init_global_struct|||
+init_i18nl10n||5.006000|
+init_i18nl14n||5.006000|
+init_ids|||
+init_interp|||
+init_lexer|||
+init_main_stash|||
+init_perllib|||
+init_postdump_symbols|||
+init_predump_symbols|||
+init_stacks||5.005000|
+init_tm||5.007002|
+instr|||
+intro_my|||
+intuit_method|||
+intuit_more|||
+invert|||
+io_close|||
+isALNUM|||
+isALPHA|||
+isDIGIT|||
+isLOWER|||
+isSPACE|||
+isUPPER|||
+is_an_int|||
+is_gv_magical_sv|||
+is_gv_magical|||
+is_handle_constructor|||
+is_list_assignment|||
+is_lvalue_sub||5.007001|
+is_uni_alnum_lc||5.006000|
+is_uni_alnumc_lc||5.006000|
+is_uni_alnumc||5.006000|
+is_uni_alnum||5.006000|
+is_uni_alpha_lc||5.006000|
+is_uni_alpha||5.006000|
+is_uni_ascii_lc||5.006000|
+is_uni_ascii||5.006000|
+is_uni_cntrl_lc||5.006000|
+is_uni_cntrl||5.006000|
+is_uni_digit_lc||5.006000|
+is_uni_digit||5.006000|
+is_uni_graph_lc||5.006000|
+is_uni_graph||5.006000|
+is_uni_idfirst_lc||5.006000|
+is_uni_idfirst||5.006000|
+is_uni_lower_lc||5.006000|
+is_uni_lower||5.006000|
+is_uni_print_lc||5.006000|
+is_uni_print||5.006000|
+is_uni_punct_lc||5.006000|
+is_uni_punct||5.006000|
+is_uni_space_lc||5.006000|
+is_uni_space||5.006000|
+is_uni_upper_lc||5.006000|
+is_uni_upper||5.006000|
+is_uni_xdigit_lc||5.006000|
+is_uni_xdigit||5.006000|
+is_utf8_alnumc||5.006000|
+is_utf8_alnum||5.006000|
+is_utf8_alpha||5.006000|
+is_utf8_ascii||5.006000|
+is_utf8_char_slow|||
+is_utf8_char||5.006000|
+is_utf8_cntrl||5.006000|
+is_utf8_digit||5.006000|
+is_utf8_graph||5.006000|
+is_utf8_idcont||5.008000|
+is_utf8_idfirst||5.006000|
+is_utf8_lower||5.006000|
+is_utf8_mark||5.006000|
+is_utf8_print||5.006000|
+is_utf8_punct||5.006000|
+is_utf8_space||5.006000|
+is_utf8_string_loclen||5.009003|
+is_utf8_string_loc||5.008001|
+is_utf8_string||5.006001|
+is_utf8_upper||5.006000|
+is_utf8_xdigit||5.006000|
+isa_lookup|||
+items|||n
+ix|||n
+jmaybe|||
+keyword|||
+leave_scope|||
+lex_end|||
+lex_start|||
+linklist|||
+listkids|||
+list|||
+load_module_nocontext|||vn
+load_module||5.006000|v
+localize|||
+looks_like_number|||
+lop|||
+mPUSHi|5.009002||p
+mPUSHn|5.009002||p
+mPUSHp|5.009002||p
+mPUSHu|5.009002||p
+mXPUSHi|5.009002||p
+mXPUSHn|5.009002||p
+mXPUSHp|5.009002||p
+mXPUSHu|5.009002||p
+magic_clear_all_env|||
+magic_clearenv|||
+magic_clearpack|||
+magic_clearsig|||
+magic_dump||5.006000|
+magic_existspack|||
+magic_freearylen_p|||
+magic_freeovrld|||
+magic_freeregexp|||
+magic_getarylen|||
+magic_getdefelem|||
+magic_getglob|||
+magic_getnkeys|||
+magic_getpack|||
+magic_getpos|||
+magic_getsig|||
+magic_getsubstr|||
+magic_gettaint|||
+magic_getuvar|||
+magic_getvec|||
+magic_get|||
+magic_killbackrefs|||
+magic_len|||
+magic_methcall|||
+magic_methpack|||
+magic_nextpack|||
+magic_regdata_cnt|||
+magic_regdatum_get|||
+magic_regdatum_set|||
+magic_scalarpack|||
+magic_set_all_env|||
+magic_setamagic|||
+magic_setarylen|||
+magic_setbm|||
+magic_setcollxfrm|||
+magic_setdbline|||
+magic_setdefelem|||
+magic_setenv|||
+magic_setfm|||
+magic_setglob|||
+magic_setisa|||
+magic_setmglob|||
+magic_setnkeys|||
+magic_setpack|||
+magic_setpos|||
+magic_setregexp|||
+magic_setsig|||
+magic_setsubstr|||
+magic_settaint|||
+magic_setutf8|||
+magic_setuvar|||
+magic_setvec|||
+magic_set|||
+magic_sizepack|||
+magic_wipepack|||
+magicname|||
+make_trie|||
+malloced_size|||n
+malloc||5.007002|n
+markstack_grow|||
+measure_struct|||
+memEQ|5.004000||p
+memNE|5.004000||p
+mem_collxfrm|||
+mess_alloc|||
+mess_nocontext|||vn
+mess||5.006000|v
+method_common|||
+mfree||5.007002|n
+mg_clear|||
+mg_copy|||
+mg_dup|||
+mg_find|||
+mg_free|||
+mg_get|||
+mg_length||5.005000|
+mg_localize|||
+mg_magical|||
+mg_set|||
+mg_size||5.005000|
+mini_mktime||5.007002|
+missingterm|||
+mode_from_discipline|||
+modkids|||
+mod|||
+moreswitches|||
+mul128|||
+mulexp10|||n
+my_atof2||5.007002|
+my_atof||5.006000|
+my_attrs|||
+my_bcopy|||n
+my_betoh16|||n
+my_betoh32|||n
+my_betoh64|||n
+my_betohi|||n
+my_betohl|||n
+my_betohs|||n
+my_bzero|||n
+my_chsize|||
+my_exit_jump|||
+my_exit|||
+my_failure_exit||5.004000|
+my_fflush_all||5.006000|
+my_fork||5.007003|n
+my_htobe16|||n
+my_htobe32|||n
+my_htobe64|||n
+my_htobei|||n
+my_htobel|||n
+my_htobes|||n
+my_htole16|||n
+my_htole32|||n
+my_htole64|||n
+my_htolei|||n
+my_htolel|||n
+my_htoles|||n
+my_htonl|||
+my_kid|||
+my_letoh16|||n
+my_letoh32|||n
+my_letoh64|||n
+my_letohi|||n
+my_letohl|||n
+my_letohs|||n
+my_lstat|||
+my_memcmp||5.004000|n
+my_memset|||n
+my_ntohl|||
+my_pclose||5.004000|
+my_popen_list||5.007001|
+my_popen||5.004000|
+my_setenv|||
+my_socketpair||5.007003|n
+my_stat|||
+my_strftime||5.007002|
+my_swabn|||n
+my_swap|||
+my_unexec|||
+my|||
+newANONATTRSUB||5.006000|
+newANONHASH|||
+newANONLIST|||
+newANONSUB|||
+newASSIGNOP|||
+newATTRSUB||5.006000|
+newAVREF|||
+newAV|||
+newBINOP|||
+newCONDOP|||
+newCONSTSUB|5.006000||p
+newCVREF|||
+newDEFSVOP|||
+newFORM|||
+newFOROP|||
+newGVOP|||
+newGVREF|||
+newGVgen|||
+newHVREF|||
+newHVhv||5.005000|
+newHV|||
+newIO|||
+newLISTOP|||
+newLOGOP|||
+newLOOPEX|||
+newLOOPOP|||
+newMYSUB||5.006000|
+newNULLLIST|||
+newOP|||
+newPADOP||5.006000|
+newPMOP|||
+newPROG|||
+newPVOP|||
+newRANGE|||
+newRV_inc|5.004000||p
+newRV_noinc|5.006000||p
+newRV|||
+newSLICEOP|||
+newSTATEOP|||
+newSUB|||
+newSVOP|||
+newSVREF|||
+newSVhek||5.009003|
+newSViv|||
+newSVnv|||
+newSVpvf_nocontext|||vn
+newSVpvf||5.004000|v
+newSVpvn_share||5.007001|
+newSVpvn|5.006000||p
+newSVpv|||
+newSVrv|||
+newSVsv|||
+newSVuv|5.006000||p
+newSV|||
+newUNOP|||
+newWHILEOP||5.009003|
+newXSproto||5.006000|
+newXS||5.006000|
+new_collate||5.006000|
+new_constant|||
+new_ctype||5.006000|
+new_he|||
+new_logop|||
+new_numeric||5.006000|
+new_stackinfo||5.005000|
+new_version||5.009000|
+next_symbol|||
+nextargv|||
+nextchar|||
+ninstr|||
+no_bareword_allowed|||
+no_fh_allowed|||
+no_op|||
+not_a_number|||
+nothreadhook||5.008000|
+nuke_stacks|||
+num_overflow|||n
+oopsAV|||
+oopsCV|||
+oopsHV|||
+op_clear|||
+op_const_sv|||
+op_dump||5.006000|
+op_free|||
+op_null||5.007002|
+op_refcnt_lock||5.009002|
+op_refcnt_unlock||5.009002|
+open_script|||
+pMY_CXT_|5.007003||p
+pMY_CXT|5.007003||p
+pTHX_|5.006000||p
+pTHX|5.006000||p
+pack_cat||5.007003|
+pack_rec|||
+package|||
+packlist||5.008001|
+pad_add_anon|||
+pad_add_name|||
+pad_alloc|||
+pad_block_start|||
+pad_check_dup|||
+pad_compname_type|||
+pad_findlex|||
+pad_findmy|||
+pad_fixup_inner_anons|||
+pad_free|||
+pad_leavemy|||
+pad_new|||
+pad_push|||
+pad_reset|||
+pad_setsv|||
+pad_sv|||
+pad_swipe|||
+pad_tidy|||
+pad_undef|||
+parse_body|||
+parse_unicode_opts|||
+path_is_absolute|||
+peep|||
+pending_ident|||
+perl_alloc_using|||n
+perl_alloc|||n
+perl_clone_using|||n
+perl_clone|||n
+perl_construct|||n
+perl_destruct||5.007003|n
+perl_free|||n
+perl_parse||5.006000|n
+perl_run|||n
+pidgone|||
+pmflag|||
+pmop_dump||5.006000|
+pmruntime|||
+pmtrans|||
+pop_scope|||
+pregcomp|||
+pregexec|||
+pregfree|||
+prepend_elem|||
+printf_nocontext|||vn
+ptr_table_clear|||
+ptr_table_fetch|||
+ptr_table_free|||
+ptr_table_new|||
+ptr_table_split|||
+ptr_table_store|||
+push_scope|||
+put_byte|||
+pv_display||5.006000|
+pv_uni_display||5.007003|
+qerror|||
+re_croak2|||
+re_dup|||
+re_intuit_start||5.006000|
+re_intuit_string||5.006000|
+realloc||5.007002|n
+reentrant_free|||
+reentrant_init|||
+reentrant_retry|||vn
+reentrant_size|||
+refkids|||
+refto|||
+ref|||
+reg_node|||
+reganode|||
+regatom|||
+regbranch|||
+regclass_swash||5.007003|
+regclass|||
+regcp_set_to|||
+regcppop|||
+regcppush|||
+regcurly|||
+regdump||5.005000|
+regexec_flags||5.005000|
+reghop3|||
+reghopmaybe3|||
+reghopmaybe|||
+reghop|||
+reginclass|||
+reginitcolors||5.006000|
+reginsert|||
+regmatch|||
+regnext||5.005000|
+regoptail|||
+regpiece|||
+regpposixcc|||
+regprop|||
+regrepeat_hard|||
+regrepeat|||
+regtail|||
+regtry|||
+reguni|||
+regwhite|||
+reg|||
+repeatcpy|||
+report_evil_fh|||
+report_uninit|||
+require_errno|||
+require_pv||5.006000|
+rninstr|||
+rsignal_restore|||
+rsignal_save|||
+rsignal_state||5.004000|
+rsignal||5.004000|
+run_body|||
+runops_debug||5.005000|
+runops_standard||5.005000|
+rvpv_dup|||
+rxres_free|||
+rxres_restore|||
+rxres_save|||
+safesyscalloc||5.006000|n
+safesysfree||5.006000|n
+safesysmalloc||5.006000|n
+safesysrealloc||5.006000|n
+same_dirent|||
+save_I16||5.004000|
+save_I32|||
+save_I8||5.006000|
+save_aelem||5.004050|
+save_alloc||5.006000|
+save_aptr|||
+save_ary|||
+save_bool||5.008001|
+save_clearsv|||
+save_delete|||
+save_destructor_x||5.006000|
+save_destructor||5.006000|
+save_freeop|||
+save_freepv|||
+save_freesv|||
+save_generic_pvref||5.006001|
+save_generic_svref||5.005030|
+save_gp||5.004000|
+save_hash|||
+save_hek_flags|||
+save_helem||5.004050|
+save_hints||5.005000|
+save_hptr|||
+save_int|||
+save_item|||
+save_iv||5.005000|
+save_lines|||
+save_list|||
+save_long|||
+save_magic|||
+save_mortalizesv||5.007001|
+save_nogv|||
+save_op|||
+save_padsv||5.007001|
+save_pptr|||
+save_re_context||5.006000|
+save_scalar_at|||
+save_scalar|||
+save_set_svflags||5.009000|
+save_shared_pvref||5.007003|
+save_sptr|||
+save_svref|||
+save_threadsv||5.005000|
+save_vptr||5.006000|
+savepvn|||
+savepv|||
+savesharedpv||5.007003|
+savestack_grow_cnt||5.008001|
+savestack_grow|||
+savesvpv||5.009002|
+sawparens|||
+scalar_mod_type|||
+scalarboolean|||
+scalarkids|||
+scalarseq|||
+scalarvoid|||
+scalar|||
+scan_bin||5.006000|
+scan_commit|||
+scan_const|||
+scan_formline|||
+scan_heredoc|||
+scan_hex|||
+scan_ident|||
+scan_inputsymbol|||
+scan_num||5.007001|
+scan_oct|||
+scan_pat|||
+scan_str|||
+scan_subst|||
+scan_trans|||
+scan_version||5.009001|
+scan_vstring||5.008001|
+scan_word|||
+scope|||
+screaminstr||5.005000|
+seed|||
+set_context||5.006000|n
+set_csh|||
+set_numeric_local||5.006000|
+set_numeric_radix||5.006000|
+set_numeric_standard||5.006000|
+setdefout|||
+setenv_getix|||
+share_hek_flags|||
+share_hek|||
+si_dup|||
+sighandler|||n
+simplify_sort|||
+skipspace|||
+sortsv||5.007003|
+ss_dup|||
+stack_grow|||
+start_glob|||
+start_subparse||5.004000|
+stashpv_hvname_match||5.009003|
+stdize_locale|||
+strEQ|||
+strGE|||
+strGT|||
+strLE|||
+strLT|||
+strNE|||
+str_to_version||5.006000|
+strnEQ|||
+strnNE|||
+study_chunk|||
+sub_crush_depth|||
+sublex_done|||
+sublex_push|||
+sublex_start|||
+sv_2bool|||
+sv_2cv|||
+sv_2io|||
+sv_2iuv_non_preserve|||
+sv_2iv_flags||5.009001|
+sv_2iv|||
+sv_2mortal|||
+sv_2nv|||
+sv_2pv_flags||5.007002|
+sv_2pv_nolen|5.006000||p
+sv_2pvbyte_nolen|||
+sv_2pvbyte|5.006000||p
+sv_2pvutf8_nolen||5.006000|
+sv_2pvutf8||5.006000|
+sv_2pv|||
+sv_2uv_flags||5.009001|
+sv_2uv|5.004000||p
+sv_add_arena|||
+sv_add_backref|||
+sv_backoff|||
+sv_bless|||
+sv_cat_decode||5.008001|
+sv_catpv_mg|5.006000||p
+sv_catpvf_mg_nocontext|||pvn
+sv_catpvf_mg|5.006000|5.004000|pv
+sv_catpvf_nocontext|||vn
+sv_catpvf||5.004000|v
+sv_catpvn_flags||5.007002|
+sv_catpvn_mg|5.006000||p
+sv_catpvn_nomg|5.007002||p
+sv_catpvn|||
+sv_catpv|||
+sv_catsv_flags||5.007002|
+sv_catsv_mg|5.006000||p
+sv_catsv_nomg|5.007002||p
+sv_catsv|||
+sv_chop|||
+sv_clean_all|||
+sv_clean_objs|||
+sv_clear|||
+sv_cmp_locale||5.004000|
+sv_cmp|||
+sv_collxfrm|||
+sv_compile_2op||5.008001|
+sv_copypv||5.007003|
+sv_dec|||
+sv_del_backref|||
+sv_derived_from||5.004000|
+sv_dump|||
+sv_dup|||
+sv_eq|||
+sv_force_normal_flags||5.007001|
+sv_force_normal||5.006000|
+sv_free2|||
+sv_free_arenas|||
+sv_free|||
+sv_gets||5.004000|
+sv_grow|||
+sv_inc|||
+sv_insert|||
+sv_isa|||
+sv_isobject|||
+sv_iv||5.005000|
+sv_len_utf8||5.006000|
+sv_len|||
+sv_magicext||5.007003|
+sv_magic|||
+sv_mortalcopy|||
+sv_newmortal|||
+sv_newref|||
+sv_nolocking||5.007003|
+sv_nosharing||5.007003|
+sv_nounlocking||5.007003|
+sv_nv||5.005000|
+sv_peek||5.005000|
+sv_pos_b2u||5.006000|
+sv_pos_u2b||5.006000|
+sv_pvbyten_force||5.006000|
+sv_pvbyten||5.006000|
+sv_pvbyte||5.006000|
+sv_pvn_force_flags||5.007002|
+sv_pvn_force|||p
+sv_pvn_nomg|5.007003||p
+sv_pvn|5.006000||p
+sv_pvutf8n_force||5.006000|
+sv_pvutf8n||5.006000|
+sv_pvutf8||5.006000|
+sv_pv||5.006000|
+sv_recode_to_utf8||5.007003|
+sv_reftype|||
+sv_release_COW|||
+sv_release_IVX|||
+sv_replace|||
+sv_report_used|||
+sv_reset|||
+sv_rvweaken||5.006000|
+sv_setiv_mg|5.006000||p
+sv_setiv|||
+sv_setnv_mg|5.006000||p
+sv_setnv|||
+sv_setpv_mg|5.006000||p
+sv_setpvf_mg_nocontext|||pvn
+sv_setpvf_mg|5.006000|5.004000|pv
+sv_setpvf_nocontext|||vn
+sv_setpvf||5.004000|v
+sv_setpviv_mg||5.008001|
+sv_setpviv||5.008001|
+sv_setpvn_mg|5.006000||p
+sv_setpvn|||
+sv_setpv|||
+sv_setref_iv|||
+sv_setref_nv|||
+sv_setref_pvn|||
+sv_setref_pv|||
+sv_setref_uv||5.007001|
+sv_setsv_cow|||
+sv_setsv_flags||5.007002|
+sv_setsv_mg|5.006000||p
+sv_setsv_nomg|5.007002||p
+sv_setsv|||
+sv_setuv_mg|5.006000||p
+sv_setuv|5.006000||p
+sv_tainted||5.004000|
+sv_taint||5.004000|
+sv_true||5.005000|
+sv_unglob|||
+sv_uni_display||5.007003|
+sv_unmagic|||
+sv_unref_flags||5.007001|
+sv_unref|||
+sv_untaint||5.004000|
+sv_upgrade|||
+sv_usepvn_mg|5.006000||p
+sv_usepvn|||
+sv_utf8_decode||5.006000|
+sv_utf8_downgrade||5.006000|
+sv_utf8_encode||5.006000|
+sv_utf8_upgrade_flags||5.007002|
+sv_utf8_upgrade||5.007001|
+sv_uv|5.006000||p
+sv_vcatpvf_mg|5.006000|5.004000|p
+sv_vcatpvfn||5.004000|
+sv_vcatpvf|5.006000|5.004000|p
+sv_vsetpvf_mg|5.006000|5.004000|p
+sv_vsetpvfn||5.004000|
+sv_vsetpvf|5.006000|5.004000|p
+svtype|||
+swallow_bom|||
+swash_fetch||5.007002|
+swash_init||5.006000|
+sys_intern_clear|||
+sys_intern_dup|||
+sys_intern_init|||
+taint_env|||
+taint_proper|||
+tmps_grow||5.006000|
+toLOWER|||
+toUPPER|||
+to_byte_substr|||
+to_uni_fold||5.007003|
+to_uni_lower_lc||5.006000|
+to_uni_lower||5.007003|
+to_uni_title_lc||5.006000|
+to_uni_title||5.007003|
+to_uni_upper_lc||5.006000|
+to_uni_upper||5.007003|
+to_utf8_case||5.007003|
+to_utf8_fold||5.007003|
+to_utf8_lower||5.007003|
+to_utf8_substr|||
+to_utf8_title||5.007003|
+to_utf8_upper||5.007003|
+tokeq|||
+tokereport|||
+too_few_arguments|||
+too_many_arguments|||
+unlnk|||
+unpack_rec|||
+unpack_str||5.007003|
+unpackstring||5.008001|
+unshare_hek_or_pvn|||
+unshare_hek|||
+unsharepvn||5.004000|
+upg_version||5.009000|
+usage|||
+utf16_textfilter|||
+utf16_to_utf8_reversed||5.006001|
+utf16_to_utf8||5.006001|
+utf16rev_textfilter|||
+utf8_distance||5.006000|
+utf8_hop||5.006000|
+utf8_length||5.007001|
+utf8_mg_pos_init|||
+utf8_mg_pos|||
+utf8_to_bytes||5.006001|
+utf8_to_uvchr||5.007001|
+utf8_to_uvuni||5.007001|
+utf8n_to_uvchr||5.007001|
+utf8n_to_uvuni||5.007001|
+utilize|||
+uvchr_to_utf8_flags||5.007003|
+uvchr_to_utf8||5.007001|
+uvuni_to_utf8_flags||5.007003|
+uvuni_to_utf8||5.007001|
+validate_suid|||
+varname|||
+vcmp||5.009000|
+vcroak||5.006000|
+vdeb||5.007003|
+vdie|||
+vform||5.006000|
+visit|||
+vivify_defelem|||
+vivify_ref|||
+vload_module||5.006000|
+vmess||5.006000|
+vnewSVpvf|5.006000|5.004000|p
+vnormal||5.009002|
+vnumify||5.009000|
+vstringify||5.009000|
+vwarner||5.006000|
+vwarn||5.006000|
+wait4pid|||
+warn_nocontext|||vn
+warner_nocontext|||vn
+warner||5.006000|v
+warn|||v
+watch|||
+whichsig|||
+write_to_stderr|||
+yyerror|||
+yylex|||
+yyparse|||
+yywarn|||
+);
+
+if (exists $opt{'list-unsupported'}) {
+ my $f;
+ for $f (sort { lc $a cmp lc $b } keys %API) {
+ next unless $API{$f}{todo};
+ print "$f ", '.'x(40-length($f)), " ", format_version($API{$f}{todo}), "\n";
+ }
+ exit 0;
+}
+
+# Scan for possible replacement candidates
+
+my(%replace, %need, %hints, %depends);
+my $replace = 0;
+my $hint = '';
+
+while (<DATA>) {
+ if ($hint) {
+ if (m{^\s*\*\s(.*?)\s*$}) {
+ $hints{$hint} ||= ''; # suppress warning with older perls
+ $hints{$hint} .= "$1\n";
+ }
+ else {
+ $hint = '';
+ }
+ }
+ $hint = $1 if m{^\s*$rccs\sHint:\s+(\w+)\s*$};
+
+ $replace = $1 if m{^\s*$rccs\s+Replace:\s+(\d+)\s+$rcce\s*$};
+ $replace{$2} = $1 if $replace and m{^\s*#\s*define\s+(\w+)(?:\([^)]*\))?\s+(\w+)};
+ $replace{$2} = $1 if m{^\s*#\s*define\s+(\w+)(?:\([^)]*\))?\s+(\w+).*$rccs\s+Replace\s+$rcce};
+ $replace{$1} = $2 if m{^\s*$rccs\s+Replace (\w+) with (\w+)\s+$rcce\s*$};
+
+ if (m{^\s*$rccs\s+(\w+)\s+depends\s+on\s+(\w+(\s*,\s*\w+)*)\s+$rcce\s*$}) {
+ push @{$depends{$1}}, map { s/\s+//g; $_ } split /,/, $2;
+ }
+
+ $need{$1} = 1 if m{^#if\s+defined\(NEED_(\w+)(?:_GLOBAL)?\)};
+}
+
+if (exists $opt{'api-info'}) {
+ my $f;
+ my $count = 0;
+ my $match = $opt{'api-info'} =~ m!^/(.*)/$! ? $1 : "^\Q$opt{'api-info'}\E\$";
+ for $f (sort { lc $a cmp lc $b } keys %API) {
+ next unless $f =~ /$match/;
+ print "\n=== $f ===\n\n";
+ my $info = 0;
+ if ($API{$f}{base} || $API{$f}{todo}) {
+ my $base = format_version($API{$f}{base} || $API{$f}{todo});
+ print "Supported at least starting from perl-$base.\n";
+ $info++;
+ }
+ if ($API{$f}{provided}) {
+ my $todo = $API{$f}{todo} ? format_version($API{$f}{todo}) : "5.003";
+ print "Support by $ppport provided back to perl-$todo.\n";
+ print "Support needs to be explicitly requested by NEED_$f.\n" if exists $need{$f};
+ print "Depends on: ", join(', ', @{$depends{$f}}), ".\n" if exists $depends{$f};
+ print "$hints{$f}" if exists $hints{$f};
+ $info++;
+ }
+ unless ($info) {
+ print "No portability information available.\n";
+ }
+ $count++;
+ }
+ if ($count > 0) {
+ print "\n";
+ }
+ else {
+ print "Found no API matching '$opt{'api-info'}'.\n";
+ }
+ exit 0;
+}
+
+if (exists $opt{'list-provided'}) {
+ my $f;
+ for $f (sort { lc $a cmp lc $b } keys %API) {
+ next unless $API{$f}{provided};
+ my @flags;
+ push @flags, 'explicit' if exists $need{$f};
+ push @flags, 'depend' if exists $depends{$f};
+ push @flags, 'hint' if exists $hints{$f};
+ my $flags = @flags ? ' ['.join(', ', @flags).']' : '';
+ print "$f$flags\n";
+ }
+ exit 0;
+}
+
+my @files;
+my @srcext = qw( xs c h cc cpp );
+my $srcext = join '|', @srcext;
+
+if (@ARGV) {
+ my %seen;
+ @files = grep { -f && !exists $seen{$_} } map { glob $_ } @ARGV;
+}
+else {
+ eval {
+ require File::Find;
+ File::Find::find(sub {
+ $File::Find::name =~ /\.($srcext)$/i
+ and push @files, $File::Find::name;
+ }, '.');
+ };
+ if ($@) {
+ @files = map { glob "*.$_" } @srcext;
+ }
+}
+
+if (!@ARGV || $opt{filter}) {
+ my(@in, @out);
+ my %xsc = map { /(.*)\.xs$/ ? ("$1.c" => 1, "$1.cc" => 1) : () } @files;
+ for (@files) {
+ my $out = exists $xsc{$_} || /\b\Q$ppport\E$/i || !/\.($srcext)$/i;
+ push @{ $out ? \@out : \@in }, $_;
+ }
+ if (@ARGV && @out) {
+ warning("Skipping the following files (use --nofilter to avoid this):\n| ", join "\n| ", @out);
+ }
+ @files = @in;
+}
+
+unless (@files) {
+ die "No input files given!\n";
+}
+
+my(%files, %global, %revreplace);
+%revreplace = reverse %replace;
+my $filename;
+my $patch_opened = 0;
+
+for $filename (@files) {
+ unless (open IN, "<$filename") {
+ warn "Unable to read from $filename: $!\n";
+ next;
+ }
+
+ info("Scanning $filename ...");
+
+ my $c = do { local $/; <IN> };
+ close IN;
+
+ my %file = (orig => $c, changes => 0);
+
+ # temporarily remove C comments from the code
+ my @ccom;
+ $c =~ s{
+ (
+ [^"'/]+
+ |
+ (?:"[^"\\]*(?:\\.[^"\\]*)*" [^"'/]*)+
+ |
+ (?:'[^'\\]*(?:\\.[^'\\]*)*' [^"'/]*)+
+ )
+ |
+ (/ (?:
+ \*[^*]*\*+(?:[^$ccs][^*]*\*+)* /
+ |
+ /[^\r\n]*
+ ))
+ }{
+ defined $2 and push @ccom, $2;
+ defined $1 ? $1 : "$ccs$#ccom$cce";
+ }egsx;
+
+ $file{ccom} = \@ccom;
+ $file{code} = $c;
+ $file{has_inc_ppport} = ($c =~ /#.*include.*\Q$ppport\E/);
+
+ my $func;
+
+ for $func (keys %API) {
+ my $match = $func;
+ $match .= "|$revreplace{$func}" if exists $revreplace{$func};
+ if ($c =~ /\b(?:Perl_)?($match)\b/) {
+ $file{uses_replace}{$1}++ if exists $revreplace{$func} && $1 eq $revreplace{$func};
+ $file{uses_Perl}{$func}++ if $c =~ /\bPerl_$func\b/;
+ if (exists $API{$func}{provided}) {
+ if (!exists $API{$func}{base} || $API{$func}{base} > $opt{'compat-version'}) {
+ $file{uses}{$func}++;
+ my @deps = rec_depend($func);
+ if (@deps) {
+ $file{uses_deps}{$func} = \@deps;
+ for (@deps) {
+ $file{uses}{$_} = 0 unless exists $file{uses}{$_};
+ }
+ }
+ for ($func, @deps) {
+ if (exists $need{$_}) {
+ $file{needs}{$_} = 'static';
+ }
+ }
+ }
+ }
+ if (exists $API{$func}{todo} && $API{$func}{todo} > $opt{'compat-version'}) {
+ if ($c =~ /\b$func\b/) {
+ $file{uses_todo}{$func}++;
+ }
+ }
+ }
+ }
+
+ while ($c =~ /^$HS*#$HS*define$HS+(NEED_(\w+?)(_GLOBAL)?)\b/mg) {
+ if (exists $need{$2}) {
+ $file{defined $3 ? 'needed_global' : 'needed_static'}{$2}++;
+ }
+ else {
+ warning("Possibly wrong #define $1 in $filename");
+ }
+ }
+
+ for (qw(uses needs uses_todo needed_global needed_static)) {
+ for $func (keys %{$file{$_}}) {
+ push @{$global{$_}{$func}}, $filename;
+ }
+ }
+
+ $files{$filename} = \%file;
+}
+
+# Globally resolve NEED_'s
+my $need;
+for $need (keys %{$global{needs}}) {
+ if (@{$global{needs}{$need}} > 1) {
+ my @targets = @{$global{needs}{$need}};
+ my @t = grep $files{$_}{needed_global}{$need}, @targets;
+ @targets = @t if @t;
+ @t = grep /\.xs$/i, @targets;
+ @targets = @t if @t;
+ my $target = shift @targets;
+ $files{$target}{needs}{$need} = 'global';
+ for (@{$global{needs}{$need}}) {
+ $files{$_}{needs}{$need} = 'extern' if $_ ne $target;
+ }
+ }
+}
+
+for $filename (@files) {
+ exists $files{$filename} or next;
+
+ info("=== Analyzing $filename ===");
+
+ my %file = %{$files{$filename}};
+ my $func;
+ my $c = $file{code};
+
+ for $func (sort keys %{$file{uses_Perl}}) {
+ if ($API{$func}{varargs}) {
+ my $changes = ($c =~ s{\b(Perl_$func\s*\(\s*)(?!aTHX_?)(\)|[^\s)]*\))}
+ { $1 . ($2 eq ')' ? 'aTHX' : 'aTHX_ ') . $2 }ge);
+ if ($changes) {
+ warning("Doesn't pass interpreter argument aTHX to Perl_$func");
+ $file{changes} += $changes;
+ }
+ }
+ else {
+ warning("Uses Perl_$func instead of $func");
+ $file{changes} += ($c =~ s{\bPerl_$func(\s*)\((\s*aTHX_?)?\s*}
+ {$func$1(}g);
+ }
+ }
+
+ for $func (sort keys %{$file{uses_replace}}) {
+ warning("Uses $func instead of $replace{$func}");
+ $file{changes} += ($c =~ s/\b$func\b/$replace{$func}/g);
+ }
+
+ for $func (sort keys %{$file{uses}}) {
+ next unless $file{uses}{$func}; # if it's only a dependency
+ if (exists $file{uses_deps}{$func}) {
+ diag("Uses $func, which depends on ", join(', ', @{$file{uses_deps}{$func}}));
+ }
+ elsif (exists $replace{$func}) {
+ warning("Uses $func instead of $replace{$func}");
+ $file{changes} += ($c =~ s/\b$func\b/$replace{$func}/g);
+ }
+ else {
+ diag("Uses $func");
+ }
+ hint($func);
+ }
+
+ for $func (sort keys %{$file{uses_todo}}) {
+ warning("Uses $func, which may not be portable below perl ",
+ format_version($API{$func}{todo}));
+ }
+
+ for $func (sort keys %{$file{needed_static}}) {
+ my $message = '';
+ if (not exists $file{uses}{$func}) {
+ $message = "No need to define NEED_$func if $func is never used";
+ }
+ elsif (exists $file{needs}{$func} && $file{needs}{$func} ne 'static') {
+ $message = "No need to define NEED_$func when already needed globally";
+ }
+ if ($message) {
+ diag($message);
+ $file{changes} += ($c =~ s/^$HS*#$HS*define$HS+NEED_$func\b.*$LF//mg);
+ }
+ }
+
+ for $func (sort keys %{$file{needed_global}}) {
+ my $message = '';
+ if (not exists $global{uses}{$func}) {
+ $message = "No need to define NEED_${func}_GLOBAL if $func is never used";
+ }
+ elsif (exists $file{needs}{$func}) {
+ if ($file{needs}{$func} eq 'extern') {
+ $message = "No need to define NEED_${func}_GLOBAL when already needed globally";
+ }
+ elsif ($file{needs}{$func} eq 'static') {
+ $message = "No need to define NEED_${func}_GLOBAL when only used in this file";
+ }
+ }
+ if ($message) {
+ diag($message);
+ $file{changes} += ($c =~ s/^$HS*#$HS*define$HS+NEED_${func}_GLOBAL\b.*$LF//mg);
+ }
+ }
+
+ $file{needs_inc_ppport} = keys %{$file{uses}};
+
+ if ($file{needs_inc_ppport}) {
+ my $pp = '';
+
+ for $func (sort keys %{$file{needs}}) {
+ my $type = $file{needs}{$func};
+ next if $type eq 'extern';
+ my $suffix = $type eq 'global' ? '_GLOBAL' : '';
+ unless (exists $file{"needed_$type"}{$func}) {
+ if ($type eq 'global') {
+ diag("Files [@{$global{needs}{$func}}] need $func, adding global request");
+ }
+ else {
+ diag("File needs $func, adding static request");
+ }
+ $pp .= "#define NEED_$func$suffix\n";
+ }
+ }
+
+ if ($pp && ($c =~ s/^(?=$HS*#$HS*define$HS+NEED_\w+)/$pp/m)) {
+ $pp = '';
+ $file{changes}++;
+ }
+
+ unless ($file{has_inc_ppport}) {
+ diag("Needs to include '$ppport'");
+ $pp .= qq(#include "$ppport"\n)
+ }
+
+ if ($pp) {
+ $file{changes} += ($c =~ s/^($HS*#$HS*define$HS+NEED_\w+.*?)^/$1$pp/ms)
+ || ($c =~ s/^(?=$HS*#$HS*include.*\Q$ppport\E)/$pp/m)
+ || ($c =~ s/^($HS*#$HS*include.*XSUB.*\s*?)^/$1$pp/m)
+ || ($c =~ s/^/$pp/);
+ }
+ }
+ else {
+ if ($file{has_inc_ppport}) {
+ diag("No need to include '$ppport'");
+ $file{changes} += ($c =~ s/^$HS*?#$HS*include.*\Q$ppport\E.*?$LF//m);
+ }
+ }
+
+ # put back in our C comments
+ my $ix;
+ my $cppc = 0;
+ my @ccom = @{$file{ccom}};
+ for $ix (0 .. $#ccom) {
+ if (!$opt{cplusplus} && $ccom[$ix] =~ s!^//!!) {
+ $cppc++;
+ $file{changes} += $c =~ s/$rccs$ix$rcce/$ccs$ccom[$ix] $cce/;
+ }
+ else {
+ $c =~ s/$rccs$ix$rcce/$ccom[$ix]/;
+ }
+ }
+
+ if ($cppc) {
+ my $s = $cppc != 1 ? 's' : '';
+ warning("Uses $cppc C++ style comment$s, which is not portable");
+ }
+
+ if ($file{changes}) {
+ if (exists $opt{copy}) {
+ my $newfile = "$filename$opt{copy}";
+ if (-e $newfile) {
+ error("'$newfile' already exists, refusing to write copy of '$filename'");
+ }
+ else {
+ local *F;
+ if (open F, ">$newfile") {
+ info("Writing copy of '$filename' with changes to '$newfile'");
+ print F $c;
+ close F;
+ }
+ else {
+ error("Cannot open '$newfile' for writing: $!");
+ }
+ }
+ }
+ elsif (exists $opt{patch} || $opt{changes}) {
+ if (exists $opt{patch}) {
+ unless ($patch_opened) {
+ if (open PATCH, ">$opt{patch}") {
+ $patch_opened = 1;
+ }
+ else {
+ error("Cannot open '$opt{patch}' for writing: $!");
+ delete $opt{patch};
+ $opt{changes} = 1;
+ goto fallback;
+ }
+ }
+ mydiff(\*PATCH, $filename, $c);
+ }
+ else {
+fallback:
+ info("Suggested changes:");
+ mydiff(\*STDOUT, $filename, $c);
+ }
+ }
+ else {
+ my $s = $file{changes} == 1 ? '' : 's';
+ info("$file{changes} potentially required change$s detected");
+ }
+ }
+ else {
+ info("Looks good");
+ }
+}
+
+close PATCH if $patch_opened;
+
+exit 0;
+
+
+sub mydiff
+{
+ local *F = shift;
+ my($file, $str) = @_;
+ my $diff;
+
+ if (exists $opt{diff}) {
+ $diff = run_diff($opt{diff}, $file, $str);
+ }
+
+ if (!defined $diff and can_use('Text::Diff')) {
+ $diff = Text::Diff::diff($file, \$str, { STYLE => 'Unified' });
+ $diff = <<HEADER . $diff;
+--- $file
++++ $file.patched
+HEADER
+ }
+
+ if (!defined $diff) {
+ $diff = run_diff('diff -u', $file, $str);
+ }
+
+ if (!defined $diff) {
+ $diff = run_diff('diff', $file, $str);
+ }
+
+ if (!defined $diff) {
+ error("Cannot generate a diff. Please install Text::Diff or use --copy.");
+ return;
+ }
+
+ print F $diff;
+
+}
+
+sub run_diff
+{
+ my($prog, $file, $str) = @_;
+ my $tmp = 'dppptemp';
+ my $suf = 'aaa';
+ my $diff = '';
+ local *F;
+
+ while (-e "$tmp.$suf") { $suf++ }
+ $tmp = "$tmp.$suf";
+
+ if (open F, ">$tmp") {
+ print F $str;
+ close F;
+
+ if (open F, "$prog $file $tmp |") {
+ while (<F>) {
+ s/\Q$tmp\E/$file.patched/;
+ $diff .= $_;
+ }
+ close F;
+ unlink $tmp;
+ return $diff;
+ }
+
+ unlink $tmp;
+ }
+ else {
+ error("Cannot open '$tmp' for writing: $!");
+ }
+
+ return undef;
+}
+
+sub can_use
+{
+ eval "use @_;";
+ return $@ eq '';
+}
+
+sub rec_depend
+{
+ my $func = shift;
+ my %seen;
+ return () unless exists $depends{$func};
+ grep !$seen{$_}++, map { ($_, rec_depend($_)) } @{$depends{$func}};
+}
+
+sub parse_version
+{
+ my $ver = shift;
+
+ if ($ver =~ /^(\d+)\.(\d+)\.(\d+)$/) {
+ return ($1, $2, $3);
+ }
+ elsif ($ver !~ /^\d+\.[\d_]+$/) {
+ die "cannot parse version '$ver'\n";
+ }
+
+ $ver =~ s/_//g;
+ $ver =~ s/$/000000/;
+
+ my($r,$v,$s) = $ver =~ /(\d+)\.(\d{3})(\d{3})/;
+
+ $v = int $v;
+ $s = int $s;
+
+ if ($r < 5 || ($r == 5 && $v < 6)) {
+ if ($s % 10) {
+ die "cannot parse version '$ver'\n";
+ }
+ }
+
+ return ($r, $v, $s);
+}
+
+sub format_version
+{
+ my $ver = shift;
+
+ $ver =~ s/$/000000/;
+ my($r,$v,$s) = $ver =~ /(\d+)\.(\d{3})(\d{3})/;
+
+ $v = int $v;
+ $s = int $s;
+
+ if ($r < 5 || ($r == 5 && $v < 6)) {
+ if ($s % 10) {
+ die "invalid version '$ver'\n";
+ }
+ $s /= 10;
+
+ $ver = sprintf "%d.%03d", $r, $v;
+ $s > 0 and $ver .= sprintf "_%02d", $s;
+
+ return $ver;
+ }
+
+ return sprintf "%d.%d.%d", $r, $v, $s;
+}
+
+sub info
+{
+ $opt{quiet} and return;
+ print @_, "\n";
+}
+
+sub diag
+{
+ $opt{quiet} and return;
+ $opt{diag} and print @_, "\n";
+}
+
+sub warning
+{
+ $opt{quiet} and return;
+ print "*** ", @_, "\n";
+}
+
+sub error
+{
+ print "*** ERROR: ", @_, "\n";
+}
+
+my %given_hints;
+sub hint
+{
+ $opt{quiet} and return;
+ $opt{hints} or return;
+ my $func = shift;
+ exists $hints{$func} or return;
+ $given_hints{$func}++ and return;
+ my $hint = $hints{$func};
+ $hint =~ s/^/ /mg;
+ print " --- hint for $func ---\n", $hint;
+}
+
+sub usage
+{
+ my($usage) = do { local(@ARGV,$/)=($0); <> } =~ /^=head\d$HS+SYNOPSIS\s*^(.*?)\s*^=/ms;
+ my %M = ( 'I' => '*' );
+ $usage =~ s/^\s*perl\s+\S+/$^X $0/;
+ $usage =~ s/([A-Z])<([^>]+)>/$M{$1}$2$M{$1}/g;
+
+ print <<ENDUSAGE;
+
+Usage: $usage
+
+See perldoc $0 for details.
+
+ENDUSAGE
+
+ exit 2;
+}
+
+__DATA__
+*/
+
+#ifndef _P_P_PORTABILITY_H_
+#define _P_P_PORTABILITY_H_
+
+#ifndef DPPP_NAMESPACE
+# define DPPP_NAMESPACE DPPP_
+#endif
+
+#define DPPP_CAT2(x,y) CAT2(x,y)
+#define DPPP_(name) DPPP_CAT2(DPPP_NAMESPACE, name)
+
+#ifndef PERL_REVISION
+# if !defined(__PATCHLEVEL_H_INCLUDED__) && !(defined(PATCHLEVEL) && defined(SUBVERSION))
+# define PERL_PATCHLEVEL_H_IMPLICIT
+# include <patchlevel.h>
+# endif
+# if !(defined(PERL_VERSION) || (defined(SUBVERSION) && defined(PATCHLEVEL)))
+# include <could_not_find_Perl_patchlevel.h>
+# endif
+# ifndef PERL_REVISION
+# define PERL_REVISION (5)
+ /* Replace: 1 */
+# define PERL_VERSION PATCHLEVEL
+# define PERL_SUBVERSION SUBVERSION
+ /* Replace PERL_PATCHLEVEL with PERL_VERSION */
+ /* Replace: 0 */
+# endif
+#endif
+
+#define PERL_BCDVERSION ((PERL_REVISION * 0x1000000L) + (PERL_VERSION * 0x1000L) + PERL_SUBVERSION)
+
+/* It is very unlikely that anyone will try to use this with Perl 6
+ (or greater), but who knows.
+ */
+#if PERL_REVISION != 5
+# error ppport.h only works with Perl version 5
+#endif /* PERL_REVISION != 5 */
+
+#ifdef I_LIMITS
+# include <limits.h>
+#endif
+
+#ifndef PERL_UCHAR_MIN
+# define PERL_UCHAR_MIN ((unsigned char)0)
+#endif
+
+#ifndef PERL_UCHAR_MAX
+# ifdef UCHAR_MAX
+# define PERL_UCHAR_MAX ((unsigned char)UCHAR_MAX)
+# else
+# ifdef MAXUCHAR
+# define PERL_UCHAR_MAX ((unsigned char)MAXUCHAR)
+# else
+# define PERL_UCHAR_MAX ((unsigned char)~(unsigned)0)
+# endif
+# endif
+#endif
+
+#ifndef PERL_USHORT_MIN
+# define PERL_USHORT_MIN ((unsigned short)0)
+#endif
+
+#ifndef PERL_USHORT_MAX
+# ifdef USHORT_MAX
+# define PERL_USHORT_MAX ((unsigned short)USHORT_MAX)
+# else
+# ifdef MAXUSHORT
+# define PERL_USHORT_MAX ((unsigned short)MAXUSHORT)
+# else
+# ifdef USHRT_MAX
+# define PERL_USHORT_MAX ((unsigned short)USHRT_MAX)
+# else
+# define PERL_USHORT_MAX ((unsigned short)~(unsigned)0)
+# endif
+# endif
+# endif
+#endif
+
+#ifndef PERL_SHORT_MAX
+# ifdef SHORT_MAX
+# define PERL_SHORT_MAX ((short)SHORT_MAX)
+# else
+# ifdef MAXSHORT /* Often used in <values.h> */
+# define PERL_SHORT_MAX ((short)MAXSHORT)
+# else
+# ifdef SHRT_MAX
+# define PERL_SHORT_MAX ((short)SHRT_MAX)
+# else
+# define PERL_SHORT_MAX ((short) (PERL_USHORT_MAX >> 1))
+# endif
+# endif
+# endif
+#endif
+
+#ifndef PERL_SHORT_MIN
+# ifdef SHORT_MIN
+# define PERL_SHORT_MIN ((short)SHORT_MIN)
+# else
+# ifdef MINSHORT
+# define PERL_SHORT_MIN ((short)MINSHORT)
+# else
+# ifdef SHRT_MIN
+# define PERL_SHORT_MIN ((short)SHRT_MIN)
+# else
+# define PERL_SHORT_MIN (-PERL_SHORT_MAX - ((3 & -1) == 3))
+# endif
+# endif
+# endif
+#endif
+
+#ifndef PERL_UINT_MAX
+# ifdef UINT_MAX
+# define PERL_UINT_MAX ((unsigned int)UINT_MAX)
+# else
+# ifdef MAXUINT
+# define PERL_UINT_MAX ((unsigned int)MAXUINT)
+# else
+# define PERL_UINT_MAX (~(unsigned int)0)
+# endif
+# endif
+#endif
+
+#ifndef PERL_UINT_MIN
+# define PERL_UINT_MIN ((unsigned int)0)
+#endif
+
+#ifndef PERL_INT_MAX
+# ifdef INT_MAX
+# define PERL_INT_MAX ((int)INT_MAX)
+# else
+# ifdef MAXINT /* Often used in <values.h> */
+# define PERL_INT_MAX ((int)MAXINT)
+# else
+# define PERL_INT_MAX ((int)(PERL_UINT_MAX >> 1))
+# endif
+# endif
+#endif
+
+#ifndef PERL_INT_MIN
+# ifdef INT_MIN
+# define PERL_INT_MIN ((int)INT_MIN)
+# else
+# ifdef MININT
+# define PERL_INT_MIN ((int)MININT)
+# else
+# define PERL_INT_MIN (-PERL_INT_MAX - ((3 & -1) == 3))
+# endif
+# endif
+#endif
+
+#ifndef PERL_ULONG_MAX
+# ifdef ULONG_MAX
+# define PERL_ULONG_MAX ((unsigned long)ULONG_MAX)
+# else
+# ifdef MAXULONG
+# define PERL_ULONG_MAX ((unsigned long)MAXULONG)
+# else
+# define PERL_ULONG_MAX (~(unsigned long)0)
+# endif
+# endif
+#endif
+
+#ifndef PERL_ULONG_MIN
+# define PERL_ULONG_MIN ((unsigned long)0L)
+#endif
+
+#ifndef PERL_LONG_MAX
+# ifdef LONG_MAX
+# define PERL_LONG_MAX ((long)LONG_MAX)
+# else
+# ifdef MAXLONG
+# define PERL_LONG_MAX ((long)MAXLONG)
+# else
+# define PERL_LONG_MAX ((long) (PERL_ULONG_MAX >> 1))
+# endif
+# endif
+#endif
+
+#ifndef PERL_LONG_MIN
+# ifdef LONG_MIN
+# define PERL_LONG_MIN ((long)LONG_MIN)
+# else
+# ifdef MINLONG
+# define PERL_LONG_MIN ((long)MINLONG)
+# else
+# define PERL_LONG_MIN (-PERL_LONG_MAX - ((3 & -1) == 3))
+# endif
+# endif
+#endif
+
+#if defined(HAS_QUAD) && (defined(convex) || defined(uts))
+# ifndef PERL_UQUAD_MAX
+# ifdef ULONGLONG_MAX
+# define PERL_UQUAD_MAX ((unsigned long long)ULONGLONG_MAX)
+# else
+# ifdef MAXULONGLONG
+# define PERL_UQUAD_MAX ((unsigned long long)MAXULONGLONG)
+# else
+# define PERL_UQUAD_MAX (~(unsigned long long)0)
+# endif
+# endif
+# endif
+
+# ifndef PERL_UQUAD_MIN
+# define PERL_UQUAD_MIN ((unsigned long long)0L)
+# endif
+
+# ifndef PERL_QUAD_MAX
+# ifdef LONGLONG_MAX
+# define PERL_QUAD_MAX ((long long)LONGLONG_MAX)
+# else
+# ifdef MAXLONGLONG
+# define PERL_QUAD_MAX ((long long)MAXLONGLONG)
+# else
+# define PERL_QUAD_MAX ((long long) (PERL_UQUAD_MAX >> 1))
+# endif
+# endif
+# endif
+
+# ifndef PERL_QUAD_MIN
+# ifdef LONGLONG_MIN
+# define PERL_QUAD_MIN ((long long)LONGLONG_MIN)
+# else
+# ifdef MINLONGLONG
+# define PERL_QUAD_MIN ((long long)MINLONGLONG)
+# else
+# define PERL_QUAD_MIN (-PERL_QUAD_MAX - ((3 & -1) == 3))
+# endif
+# endif
+# endif
+#endif
+
+/* This is based on code from 5.003 perl.h */
+#ifdef HAS_QUAD
+# ifdef cray
+#ifndef IVTYPE
+# define IVTYPE int
+#endif
+
+#ifndef IV_MIN
+# define IV_MIN PERL_INT_MIN
+#endif
+
+#ifndef IV_MAX
+# define IV_MAX PERL_INT_MAX
+#endif
+
+#ifndef UV_MIN
+# define UV_MIN PERL_UINT_MIN
+#endif
+
+#ifndef UV_MAX
+# define UV_MAX PERL_UINT_MAX
+#endif
+
+# ifdef INTSIZE
+#ifndef IVSIZE
+# define IVSIZE INTSIZE
+#endif
+
+# endif
+# else
+# if defined(convex) || defined(uts)
+#ifndef IVTYPE
+# define IVTYPE long long
+#endif
+
+#ifndef IV_MIN
+# define IV_MIN PERL_QUAD_MIN
+#endif
+
+#ifndef IV_MAX
+# define IV_MAX PERL_QUAD_MAX
+#endif
+
+#ifndef UV_MIN
+# define UV_MIN PERL_UQUAD_MIN
+#endif
+
+#ifndef UV_MAX
+# define UV_MAX PERL_UQUAD_MAX
+#endif
+
+# ifdef LONGLONGSIZE
+#ifndef IVSIZE
+# define IVSIZE LONGLONGSIZE
+#endif
+
+# endif
+# else
+#ifndef IVTYPE
+# define IVTYPE long
+#endif
+
+#ifndef IV_MIN
+# define IV_MIN PERL_LONG_MIN
+#endif
+
+#ifndef IV_MAX
+# define IV_MAX PERL_LONG_MAX
+#endif
+
+#ifndef UV_MIN
+# define UV_MIN PERL_ULONG_MIN
+#endif
+
+#ifndef UV_MAX
+# define UV_MAX PERL_ULONG_MAX
+#endif
+
+# ifdef LONGSIZE
+#ifndef IVSIZE
+# define IVSIZE LONGSIZE
+#endif
+
+# endif
+# endif
+# endif
+#ifndef IVSIZE
+# define IVSIZE 8
+#endif
+
+#ifndef PERL_QUAD_MIN
+# define PERL_QUAD_MIN IV_MIN
+#endif
+
+#ifndef PERL_QUAD_MAX
+# define PERL_QUAD_MAX IV_MAX
+#endif
+
+#ifndef PERL_UQUAD_MIN
+# define PERL_UQUAD_MIN UV_MIN
+#endif
+
+#ifndef PERL_UQUAD_MAX
+# define PERL_UQUAD_MAX UV_MAX
+#endif
+
+#else
+#ifndef IVTYPE
+# define IVTYPE long
+#endif
+
+#ifndef IV_MIN
+# define IV_MIN PERL_LONG_MIN
+#endif
+
+#ifndef IV_MAX
+# define IV_MAX PERL_LONG_MAX
+#endif
+
+#ifndef UV_MIN
+# define UV_MIN PERL_ULONG_MIN
+#endif
+
+#ifndef UV_MAX
+# define UV_MAX PERL_ULONG_MAX
+#endif
+
+#endif
+
+#ifndef IVSIZE
+# ifdef LONGSIZE
+# define IVSIZE LONGSIZE
+# else
+# define IVSIZE 4 /* A bold guess, but the best we can make. */
+# endif
+#endif
+#ifndef UVTYPE
+# define UVTYPE unsigned IVTYPE
+#endif
+
+#ifndef UVSIZE
+# define UVSIZE IVSIZE
+#endif
+
+#ifndef sv_setuv
+# define sv_setuv(sv, uv) \
+ STMT_START { \
+ UV TeMpUv = uv; \
+ if (TeMpUv <= IV_MAX) \
+ sv_setiv(sv, TeMpUv); \
+ else \
+ sv_setnv(sv, (double)TeMpUv); \
+ } STMT_END
+#endif
+
+#ifndef newSVuv
+# define newSVuv(uv) ((uv) <= IV_MAX ? newSViv((IV)uv) : newSVnv((NV)uv))
+#endif
+#ifndef sv_2uv
+# define sv_2uv(sv) ((PL_Sv = (sv)), (UV) (SvNOK(PL_Sv) ? SvNV(PL_Sv) : sv_2nv(PL_Sv)))
+#endif
+
+#ifndef SvUVX
+# define SvUVX(sv) ((UV)SvIVX(sv))
+#endif
+
+#ifndef SvUVXx
+# define SvUVXx(sv) SvUVX(sv)
+#endif
+
+#ifndef SvUV
+# define SvUV(sv) (SvIOK(sv) ? SvUVX(sv) : sv_2uv(sv))
+#endif
+
+#ifndef SvUVx
+# define SvUVx(sv) ((PL_Sv = (sv)), SvUV(PL_Sv))
+#endif
+
+/* Hint: sv_uv
+ * Always use the SvUVx() macro instead of sv_uv().
+ */
+#ifndef sv_uv
+# define sv_uv(sv) SvUVx(sv)
+#endif
+#ifndef XST_mUV
+# define XST_mUV(i,v) (ST(i) = sv_2mortal(newSVuv(v)) )
+#endif
+
+#ifndef XSRETURN_UV
+# define XSRETURN_UV(v) STMT_START { XST_mUV(0,v); XSRETURN(1); } STMT_END
+#endif
+#ifndef PUSHu
+# define PUSHu(u) STMT_START { sv_setuv(TARG, (UV)(u)); PUSHTARG; } STMT_END
+#endif
+
+#ifndef XPUSHu
+# define XPUSHu(u) STMT_START { sv_setuv(TARG, (UV)(u)); XPUSHTARG; } STMT_END
+#endif
+
+#if (PERL_VERSION < 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION <= 5))
+/* Replace: 1 */
+# define PL_DBsingle DBsingle
+# define PL_DBsub DBsub
+# define PL_Sv Sv
+# define PL_compiling compiling
+# define PL_copline copline
+# define PL_curcop curcop
+# define PL_curstash curstash
+# define PL_debstash debstash
+# define PL_defgv defgv
+# define PL_diehook diehook
+# define PL_dirty dirty
+# define PL_dowarn dowarn
+# define PL_errgv errgv
+# define PL_hexdigit hexdigit
+# define PL_hints hints
+# define PL_na na
+# define PL_no_modify no_modify
+# define PL_perl_destruct_level perl_destruct_level
+# define PL_perldb perldb
+# define PL_ppaddr ppaddr
+# define PL_rsfp_filters rsfp_filters
+# define PL_rsfp rsfp
+# define PL_stack_base stack_base
+# define PL_stack_sp stack_sp
+# define PL_stdingv stdingv
+# define PL_sv_arenaroot sv_arenaroot
+# define PL_sv_no sv_no
+# define PL_sv_undef sv_undef
+# define PL_sv_yes sv_yes
+# define PL_tainted tainted
+# define PL_tainting tainting
+/* Replace: 0 */
+#endif
+
+#ifndef PERL_UNUSED_DECL
+# ifdef HASATTRIBUTE
+# if (defined(__GNUC__) && defined(__cplusplus)) || defined(__INTEL_COMPILER)
+# define PERL_UNUSED_DECL
+# else
+# define PERL_UNUSED_DECL __attribute__((unused))
+# endif
+# else
+# define PERL_UNUSED_DECL
+# endif
+#endif
+#ifndef NOOP
+# define NOOP (void)0
+#endif
+
+#ifndef dNOOP
+# define dNOOP extern int Perl___notused PERL_UNUSED_DECL
+#endif
+
+#ifndef NVTYPE
+# if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE)
+# define NVTYPE long double
+# else
+# define NVTYPE double
+# endif
+typedef NVTYPE NV;
+#endif
+
+#ifndef INT2PTR
+
+# if (IVSIZE == PTRSIZE) && (UVSIZE == PTRSIZE)
+# define PTRV UV
+# define INT2PTR(any,d) (any)(d)
+# else
+# if PTRSIZE == LONGSIZE
+# define PTRV unsigned long
+# else
+# define PTRV unsigned
+# endif
+# define INT2PTR(any,d) (any)(PTRV)(d)
+# endif
+
+# define NUM2PTR(any,d) (any)(PTRV)(d)
+# define PTR2IV(p) INT2PTR(IV,p)
+# define PTR2UV(p) INT2PTR(UV,p)
+# define PTR2NV(p) NUM2PTR(NV,p)
+
+# if PTRSIZE == LONGSIZE
+# define PTR2ul(p) (unsigned long)(p)
+# else
+# define PTR2ul(p) INT2PTR(unsigned long,p)
+# endif
+
+#endif /* !INT2PTR */
+
+#undef START_EXTERN_C
+#undef END_EXTERN_C
+#undef EXTERN_C
+#ifdef __cplusplus
+# define START_EXTERN_C extern "C" {
+# define END_EXTERN_C }
+# define EXTERN_C extern "C"
+#else
+# define START_EXTERN_C
+# define END_EXTERN_C
+# define EXTERN_C extern
+#endif
+
+#ifndef PERL_GCC_BRACE_GROUPS_FORBIDDEN
+# if defined(__STRICT_ANSI__) && defined(PERL_GCC_PEDANTIC)
+# define PERL_GCC_BRACE_GROUPS_FORBIDDEN
+# endif
+#endif
+
+#undef STMT_START
+#undef STMT_END
+#if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN) && !defined(__cplusplus)
+# define STMT_START (void)( /* gcc supports ``({ STATEMENTS; })'' */
+# define STMT_END )
+#else
+# if defined(VOIDFLAGS) && (VOIDFLAGS) && (defined(sun) || defined(__sun__)) && !defined(__GNUC__)
+# define STMT_START if (1)
+# define STMT_END else (void)0
+# else
+# define STMT_START do
+# define STMT_END while (0)
+# endif
+#endif
+#ifndef boolSV
+# define boolSV(b) ((b) ? &PL_sv_yes : &PL_sv_no)
+#endif
+
+/* DEFSV appears first in 5.004_56 */
+#ifndef DEFSV
+# define DEFSV GvSV(PL_defgv)
+#endif
+
+#ifndef SAVE_DEFSV
+# define SAVE_DEFSV SAVESPTR(GvSV(PL_defgv))
+#endif
+
+/* Older perls (<=5.003) lack AvFILLp */
+#ifndef AvFILLp
+# define AvFILLp AvFILL
+#endif
+#ifndef ERRSV
+# define ERRSV get_sv("@",FALSE)
+#endif
+#ifndef newSVpvn
+# define newSVpvn(data,len) ((data) \
+ ? ((len) ? newSVpv((data), (len)) : newSVpv("", 0)) \
+ : newSV(0))
+#endif
+
+/* Hint: gv_stashpvn
+ * This function's backport doesn't support the length parameter, but
+ * rather ignores it. Portability can only be ensured if the length
+ * parameter is used for speed reasons, but the length can always be
+ * correctly computed from the string argument.
+ */
+#ifndef gv_stashpvn
+# define gv_stashpvn(str,len,create) gv_stashpv(str,create)
+#endif
+
+/* Replace: 1 */
+#ifndef get_cv
+# define get_cv perl_get_cv
+#endif
+
+#ifndef get_sv
+# define get_sv perl_get_sv
+#endif
+
+#ifndef get_av
+# define get_av perl_get_av
+#endif
+
+#ifndef get_hv
+# define get_hv perl_get_hv
+#endif
+
+/* Replace: 0 */
+
+#ifdef HAS_MEMCMP
+#ifndef memNE
+# define memNE(s1,s2,l) (memcmp(s1,s2,l))
+#endif
+
+#ifndef memEQ
+# define memEQ(s1,s2,l) (!memcmp(s1,s2,l))
+#endif
+
+#else
+#ifndef memNE
+# define memNE(s1,s2,l) (bcmp(s1,s2,l))
+#endif
+
+#ifndef memEQ
+# define memEQ(s1,s2,l) (!bcmp(s1,s2,l))
+#endif
+
+#endif
+#ifndef MoveD
+# define MoveD(s,d,n,t) memmove((char*)(d),(char*)(s), (n) * sizeof(t))
+#endif
+
+#ifndef CopyD
+# define CopyD(s,d,n,t) memcpy((char*)(d),(char*)(s), (n) * sizeof(t))
+#endif
+
+#ifdef HAS_MEMSET
+#ifndef ZeroD
+# define ZeroD(d,n,t) memzero((char*)(d), (n) * sizeof(t))
+#endif
+
+#else
+#ifndef ZeroD
+# define ZeroD(d,n,t) ((void)memzero((char*)(d), (n) * sizeof(t)),d)
+#endif
+
+#endif
+#ifndef Poison
+# define Poison(d,n,t) (void)memset((char*)(d), 0xAB, (n) * sizeof(t))
+#endif
+#ifndef dUNDERBAR
+# define dUNDERBAR dNOOP
+#endif
+
+#ifndef UNDERBAR
+# define UNDERBAR DEFSV
+#endif
+#ifndef dAX
+# define dAX I32 ax = MARK - PL_stack_base + 1
+#endif
+
+#ifndef dITEMS
+# define dITEMS I32 items = SP - MARK
+#endif
+#ifndef dXSTARG
+# define dXSTARG SV * targ = sv_newmortal()
+#endif
+#ifndef dTHR
+# define dTHR dNOOP
+#endif
+#ifndef dTHX
+# define dTHX dNOOP
+#endif
+
+#ifndef dTHXa
+# define dTHXa(x) dNOOP
+#endif
+#ifndef pTHX
+# define pTHX void
+#endif
+
+#ifndef pTHX_
+# define pTHX_
+#endif
+
+#ifndef aTHX
+# define aTHX
+#endif
+
+#ifndef aTHX_
+# define aTHX_
+#endif
+#ifndef dTHXoa
+# define dTHXoa(x) dTHXa(x)
+#endif
+#ifndef PUSHmortal
+# define PUSHmortal PUSHs(sv_newmortal())
+#endif
+
+#ifndef mPUSHp
+# define mPUSHp(p,l) sv_setpvn_mg(PUSHmortal, (p), (l))
+#endif
+
+#ifndef mPUSHn
+# define mPUSHn(n) sv_setnv_mg(PUSHmortal, (NV)(n))
+#endif
+
+#ifndef mPUSHi
+# define mPUSHi(i) sv_setiv_mg(PUSHmortal, (IV)(i))
+#endif
+
+#ifndef mPUSHu
+# define mPUSHu(u) sv_setuv_mg(PUSHmortal, (UV)(u))
+#endif
+#ifndef XPUSHmortal
+# define XPUSHmortal XPUSHs(sv_newmortal())
+#endif
+
+#ifndef mXPUSHp
+# define mXPUSHp(p,l) STMT_START { EXTEND(sp,1); sv_setpvn_mg(PUSHmortal, (p), (l)); } STMT_END
+#endif
+
+#ifndef mXPUSHn
+# define mXPUSHn(n) STMT_START { EXTEND(sp,1); sv_setnv_mg(PUSHmortal, (NV)(n)); } STMT_END
+#endif
+
+#ifndef mXPUSHi
+# define mXPUSHi(i) STMT_START { EXTEND(sp,1); sv_setiv_mg(PUSHmortal, (IV)(i)); } STMT_END
+#endif
+
+#ifndef mXPUSHu
+# define mXPUSHu(u) STMT_START { EXTEND(sp,1); sv_setuv_mg(PUSHmortal, (UV)(u)); } STMT_END
+#endif
+
+/* Replace: 1 */
+#ifndef call_sv
+# define call_sv perl_call_sv
+#endif
+
+#ifndef call_pv
+# define call_pv perl_call_pv
+#endif
+
+#ifndef call_argv
+# define call_argv perl_call_argv
+#endif
+
+#ifndef call_method
+# define call_method perl_call_method
+#endif
+#ifndef eval_sv
+# define eval_sv perl_eval_sv
+#endif
+
+/* Replace: 0 */
+
+/* Replace perl_eval_pv with eval_pv */
+/* eval_pv depends on eval_sv */
+
+#ifndef eval_pv
+#if defined(NEED_eval_pv)
+static SV* DPPP_(my_eval_pv)(char *p, I32 croak_on_error);
+static
+#else
+extern SV* DPPP_(my_eval_pv)(char *p, I32 croak_on_error);
+#endif
+
+#ifdef eval_pv
+# undef eval_pv
+#endif
+#define eval_pv(a,b) DPPP_(my_eval_pv)(aTHX_ a,b)
+#define Perl_eval_pv DPPP_(my_eval_pv)
+
+#if defined(NEED_eval_pv) || defined(NEED_eval_pv_GLOBAL)
+
+SV*
+DPPP_(my_eval_pv)(char *p, I32 croak_on_error)
+{
+ dSP;
+ SV* sv = newSVpv(p, 0);
+
+ PUSHMARK(sp);
+ eval_sv(sv, G_SCALAR);
+ SvREFCNT_dec(sv);
+
+ SPAGAIN;
+ sv = POPs;
+ PUTBACK;
+
+ if (croak_on_error && SvTRUE(GvSV(errgv)))
+ croak(SvPVx(GvSV(errgv), na));
+
+ return sv;
+}
+
+#endif
+#endif
+#ifndef newRV_inc
+# define newRV_inc(sv) newRV(sv) /* Replace */
+#endif
+
+#ifndef newRV_noinc
+#if defined(NEED_newRV_noinc)
+static SV * DPPP_(my_newRV_noinc)(SV *sv);
+static
+#else
+extern SV * DPPP_(my_newRV_noinc)(SV *sv);
+#endif
+
+#ifdef newRV_noinc
+# undef newRV_noinc
+#endif
+#define newRV_noinc(a) DPPP_(my_newRV_noinc)(aTHX_ a)
+#define Perl_newRV_noinc DPPP_(my_newRV_noinc)
+
+#if defined(NEED_newRV_noinc) || defined(NEED_newRV_noinc_GLOBAL)
+SV *
+DPPP_(my_newRV_noinc)(SV *sv)
+{
+ SV *rv = (SV *)newRV(sv);
+ SvREFCNT_dec(sv);
+ return rv;
+}
+#endif
+#endif
+
+/* Hint: newCONSTSUB
+ * Returns a CV* as of perl-5.7.1. This return value is not supported
+ * by Devel::PPPort.
+ */
+
+/* newCONSTSUB from IO.xs is in the core starting with 5.004_63 */
+#if ((PERL_VERSION < 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION < 63))) && ((PERL_VERSION != 4) || (PERL_SUBVERSION != 5))
+#if defined(NEED_newCONSTSUB)
+static void DPPP_(my_newCONSTSUB)(HV *stash, char *name, SV *sv);
+static
+#else
+extern void DPPP_(my_newCONSTSUB)(HV *stash, char *name, SV *sv);
+#endif
+
+#ifdef newCONSTSUB
+# undef newCONSTSUB
+#endif
+#define newCONSTSUB(a,b,c) DPPP_(my_newCONSTSUB)(aTHX_ a,b,c)
+#define Perl_newCONSTSUB DPPP_(my_newCONSTSUB)
+
+#if defined(NEED_newCONSTSUB) || defined(NEED_newCONSTSUB_GLOBAL)
+
+void
+DPPP_(my_newCONSTSUB)(HV *stash, char *name, SV *sv)
+{
+ U32 oldhints = PL_hints;
+ HV *old_cop_stash = PL_curcop->cop_stash;
+ HV *old_curstash = PL_curstash;
+ line_t oldline = PL_curcop->cop_line;
+ PL_curcop->cop_line = PL_copline;
+
+ PL_hints &= ~HINT_BLOCK_SCOPE;
+ if (stash)
+ PL_curstash = PL_curcop->cop_stash = stash;
+
+ newSUB(
+
+#if ((PERL_VERSION < 3) || ((PERL_VERSION == 3) && (PERL_SUBVERSION < 22)))
+ start_subparse(),
+#elif ((PERL_VERSION == 3) && (PERL_SUBVERSION == 22))
+ start_subparse(0),
+#else /* 5.003_23 onwards */
+ start_subparse(FALSE, 0),
+#endif
+
+ newSVOP(OP_CONST, 0, newSVpv(name,0)),
+ newSVOP(OP_CONST, 0, &PL_sv_no), /* SvPV(&PL_sv_no) == "" -- GMB */
+ newSTATEOP(0, Nullch, newSVOP(OP_CONST, 0, sv))
+ );
+
+ PL_hints = oldhints;
+ PL_curcop->cop_stash = old_cop_stash;
+ PL_curstash = old_curstash;
+ PL_curcop->cop_line = oldline;
+}
+#endif
+#endif
+
+/*
+ * Boilerplate macros for initializing and accessing interpreter-local
+ * data from C. All statics in extensions should be reworked to use
+ * this, if you want to make the extension thread-safe. See ext/re/re.xs
+ * for an example of the use of these macros.
+ *
+ * Code that uses these macros is responsible for the following:
+ * 1. #define MY_CXT_KEY to a unique string, e.g. "DynaLoader_guts"
+ * 2. Declare a typedef named my_cxt_t that is a structure that contains
+ * all the data that needs to be interpreter-local.
+ * 3. Use the START_MY_CXT macro after the declaration of my_cxt_t.
+ * 4. Use the MY_CXT_INIT macro such that it is called exactly once
+ * (typically put in the BOOT: section).
+ * 5. Use the members of the my_cxt_t structure everywhere as
+ * MY_CXT.member.
+ * 6. Use the dMY_CXT macro (a declaration) in all the functions that
+ * access MY_CXT.
+ */
+
+#if defined(MULTIPLICITY) || defined(PERL_OBJECT) || \
+ defined(PERL_CAPI) || defined(PERL_IMPLICIT_CONTEXT)
+
+#ifndef START_MY_CXT
+
+/* This must appear in all extensions that define a my_cxt_t structure,
+ * right after the definition (i.e. at file scope). The non-threads
+ * case below uses it to declare the data as static. */
+#define START_MY_CXT
+
+#if (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION < 68 ))
+/* Fetches the SV that keeps the per-interpreter data. */
+#define dMY_CXT_SV \
+ SV *my_cxt_sv = get_sv(MY_CXT_KEY, FALSE)
+#else /* >= perl5.004_68 */
+#define dMY_CXT_SV \
+ SV *my_cxt_sv = *hv_fetch(PL_modglobal, MY_CXT_KEY, \
+ sizeof(MY_CXT_KEY)-1, TRUE)
+#endif /* < perl5.004_68 */
+
+/* This declaration should be used within all functions that use the
+ * interpreter-local data. */
+#define dMY_CXT \
+ dMY_CXT_SV; \
+ my_cxt_t *my_cxtp = INT2PTR(my_cxt_t*,SvUV(my_cxt_sv))
+
+/* Creates and zeroes the per-interpreter data.
+ * (We allocate my_cxtp in a Perl SV so that it will be released when
+ * the interpreter goes away.) */
+#define MY_CXT_INIT \
+ dMY_CXT_SV; \
+ /* newSV() allocates one more than needed */ \
+ my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\
+ Zero(my_cxtp, 1, my_cxt_t); \
+ sv_setuv(my_cxt_sv, PTR2UV(my_cxtp))
+
+/* This macro must be used to access members of the my_cxt_t structure.
+ * e.g. MYCXT.some_data */
+#define MY_CXT (*my_cxtp)
+
+/* Judicious use of these macros can reduce the number of times dMY_CXT
+ * is used. Use is similar to pTHX, aTHX etc. */
+#define pMY_CXT my_cxt_t *my_cxtp
+#define pMY_CXT_ pMY_CXT,
+#define _pMY_CXT ,pMY_CXT
+#define aMY_CXT my_cxtp
+#define aMY_CXT_ aMY_CXT,
+#define _aMY_CXT ,aMY_CXT
+
+#endif /* START_MY_CXT */
+
+#ifndef MY_CXT_CLONE
+/* Clones the per-interpreter data. */
+#define MY_CXT_CLONE \
+ dMY_CXT_SV; \
+ my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\
+ Copy(INT2PTR(my_cxt_t*, SvUV(my_cxt_sv)), my_cxtp, 1, my_cxt_t);\
+ sv_setuv(my_cxt_sv, PTR2UV(my_cxtp))
+#endif
+
+#else /* single interpreter */
+
+#ifndef START_MY_CXT
+
+#define START_MY_CXT static my_cxt_t my_cxt;
+#define dMY_CXT_SV dNOOP
+#define dMY_CXT dNOOP
+#define MY_CXT_INIT NOOP
+#define MY_CXT my_cxt
+
+#define pMY_CXT void
+#define pMY_CXT_
+#define _pMY_CXT
+#define aMY_CXT
+#define aMY_CXT_
+#define _aMY_CXT
+
+#endif /* START_MY_CXT */
+
+#ifndef MY_CXT_CLONE
+#define MY_CXT_CLONE NOOP
+#endif
+
+#endif
+
+#ifndef IVdf
+# if IVSIZE == LONGSIZE
+# define IVdf "ld"
+# define UVuf "lu"
+# define UVof "lo"
+# define UVxf "lx"
+# define UVXf "lX"
+# else
+# if IVSIZE == INTSIZE
+# define IVdf "d"
+# define UVuf "u"
+# define UVof "o"
+# define UVxf "x"
+# define UVXf "X"
+# endif
+# endif
+#endif
+
+#ifndef NVef
+# if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE) && \
+ defined(PERL_PRIfldbl) /* Not very likely, but let's try anyway. */
+# define NVef PERL_PRIeldbl
+# define NVff PERL_PRIfldbl
+# define NVgf PERL_PRIgldbl
+# else
+# define NVef "e"
+# define NVff "f"
+# define NVgf "g"
+# endif
+#endif
+
+#ifndef SvPV_nolen
+
+#if defined(NEED_sv_2pv_nolen)
+static char * DPPP_(my_sv_2pv_nolen)(pTHX_ register SV *sv);
+static
+#else
+extern char * DPPP_(my_sv_2pv_nolen)(pTHX_ register SV *sv);
+#endif
+
+#ifdef sv_2pv_nolen
+# undef sv_2pv_nolen
+#endif
+#define sv_2pv_nolen(a) DPPP_(my_sv_2pv_nolen)(aTHX_ a)
+#define Perl_sv_2pv_nolen DPPP_(my_sv_2pv_nolen)
+
+#if defined(NEED_sv_2pv_nolen) || defined(NEED_sv_2pv_nolen_GLOBAL)
+
+char *
+DPPP_(my_sv_2pv_nolen)(pTHX_ register SV *sv)
+{
+ STRLEN n_a;
+ return sv_2pv(sv, &n_a);
+}
+
+#endif
+
+/* Hint: sv_2pv_nolen
+ * Use the SvPV_nolen() macro instead of sv_2pv_nolen().
+ */
+
+/* SvPV_nolen depends on sv_2pv_nolen */
+#define SvPV_nolen(sv) \
+ ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \
+ ? SvPVX(sv) : sv_2pv_nolen(sv))
+
+#endif
+
+#ifdef SvPVbyte
+
+/* Hint: SvPVbyte
+ * Does not work in perl-5.6.1, ppport.h implements a version
+ * borrowed from perl-5.7.3.
+ */
+
+#if ((PERL_VERSION < 7) || ((PERL_VERSION == 7) && (PERL_SUBVERSION < 0)))
+
+#if defined(NEED_sv_2pvbyte)
+static char * DPPP_(my_sv_2pvbyte)(pTHX_ register SV *sv, STRLEN *lp);
+static
+#else
+extern char * DPPP_(my_sv_2pvbyte)(pTHX_ register SV *sv, STRLEN *lp);
+#endif
+
+#ifdef sv_2pvbyte
+# undef sv_2pvbyte
+#endif
+#define sv_2pvbyte(a,b) DPPP_(my_sv_2pvbyte)(aTHX_ a,b)
+#define Perl_sv_2pvbyte DPPP_(my_sv_2pvbyte)
+
+#if defined(NEED_sv_2pvbyte) || defined(NEED_sv_2pvbyte_GLOBAL)
+
+char *
+DPPP_(my_sv_2pvbyte)(pTHX_ register SV *sv, STRLEN *lp)
+{
+ sv_utf8_downgrade(sv,0);
+ return SvPV(sv,*lp);
+}
+
+#endif
+
+/* Hint: sv_2pvbyte
+ * Use the SvPVbyte() macro instead of sv_2pvbyte().
+ */
+
+#undef SvPVbyte
+
+/* SvPVbyte depends on sv_2pvbyte */
+#define SvPVbyte(sv, lp) \
+ ((SvFLAGS(sv) & (SVf_POK|SVf_UTF8)) == (SVf_POK) \
+ ? ((lp = SvCUR(sv)), SvPVX(sv)) : sv_2pvbyte(sv, &lp))
+
+#endif
+
+#else
+
+# define SvPVbyte SvPV
+# define sv_2pvbyte sv_2pv
+
+#endif
+
+/* sv_2pvbyte_nolen depends on sv_2pv_nolen */
+#ifndef sv_2pvbyte_nolen
+# define sv_2pvbyte_nolen sv_2pv_nolen
+#endif
+
+/* Hint: sv_pvn
+ * Always use the SvPV() macro instead of sv_pvn().
+ */
+#ifndef sv_pvn
+# define sv_pvn(sv, len) SvPV(sv, len)
+#endif
+
+/* Hint: sv_pvn_force
+ * Always use the SvPV_force() macro instead of sv_pvn_force().
+ */
+#ifndef sv_pvn_force
+# define sv_pvn_force(sv, len) SvPV_force(sv, len)
+#endif
+
+#if ((PERL_VERSION > 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION >= 0))) && !defined(vnewSVpvf)
+#if defined(NEED_vnewSVpvf)
+static SV * DPPP_(my_vnewSVpvf)(pTHX_ const char * pat, va_list * args);
+static
+#else
+extern SV * DPPP_(my_vnewSVpvf)(pTHX_ const char * pat, va_list * args);
+#endif
+
+#ifdef vnewSVpvf
+# undef vnewSVpvf
+#endif
+#define vnewSVpvf(a,b) DPPP_(my_vnewSVpvf)(aTHX_ a,b)
+#define Perl_vnewSVpvf DPPP_(my_vnewSVpvf)
+
+#if defined(NEED_vnewSVpvf) || defined(NEED_vnewSVpvf_GLOBAL)
+
+SV *
+DPPP_(my_vnewSVpvf)(pTHX_ const char *pat, va_list *args)
+{
+ register SV *sv = newSV(0);
+ sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*));
+ return sv;
+}
+
+#endif
+#endif
+
+/* sv_vcatpvf depends on sv_vcatpvfn */
+#if ((PERL_VERSION > 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION >= 0))) && !defined(sv_vcatpvf)
+# define sv_vcatpvf(sv, pat, args) sv_vcatpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*))
+#endif
+
+/* sv_vsetpvf depends on sv_vsetpvfn */
+#if ((PERL_VERSION > 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION >= 0))) && !defined(sv_vsetpvf)
+# define sv_vsetpvf(sv, pat, args) sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*))
+#endif
+
+/* sv_catpvf_mg depends on sv_vcatpvfn, sv_catpvf_mg_nocontext */
+#if ((PERL_VERSION > 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION >= 0))) && !defined(sv_catpvf_mg)
+#if defined(NEED_sv_catpvf_mg)
+static void DPPP_(my_sv_catpvf_mg)(pTHX_ SV * sv, const char * pat, ...);
+static
+#else
+extern void DPPP_(my_sv_catpvf_mg)(pTHX_ SV * sv, const char * pat, ...);
+#endif
+
+#define Perl_sv_catpvf_mg DPPP_(my_sv_catpvf_mg)
+
+#if defined(NEED_sv_catpvf_mg) || defined(NEED_sv_catpvf_mg_GLOBAL)
+
+void
+DPPP_(my_sv_catpvf_mg)(pTHX_ SV *sv, const char *pat, ...)
+{
+ va_list args;
+ va_start(args, pat);
+ sv_vcatpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*));
+ SvSETMAGIC(sv);
+ va_end(args);
+}
+
+#endif
+#endif
+
+/* sv_catpvf_mg_nocontext depends on sv_vcatpvfn */
+#ifdef PERL_IMPLICIT_CONTEXT
+#if ((PERL_VERSION > 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION >= 0))) && !defined(sv_catpvf_mg_nocontext)
+#if defined(NEED_sv_catpvf_mg_nocontext)
+static void DPPP_(my_sv_catpvf_mg_nocontext)(SV * sv, const char * pat, ...);
+static
+#else
+extern void DPPP_(my_sv_catpvf_mg_nocontext)(SV * sv, const char * pat, ...);
+#endif
+
+#define sv_catpvf_mg_nocontext DPPP_(my_sv_catpvf_mg_nocontext)
+#define Perl_sv_catpvf_mg_nocontext DPPP_(my_sv_catpvf_mg_nocontext)
+
+#if defined(NEED_sv_catpvf_mg_nocontext) || defined(NEED_sv_catpvf_mg_nocontext_GLOBAL)
+
+void
+DPPP_(my_sv_catpvf_mg_nocontext)(SV *sv, const char *pat, ...)
+{
+ dTHX;
+ va_list args;
+ va_start(args, pat);
+ sv_vcatpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*));
+ SvSETMAGIC(sv);
+ va_end(args);
+}
+
+#endif
+#endif
+#endif
+
+#ifndef sv_catpvf_mg
+# ifdef PERL_IMPLICIT_CONTEXT
+# define sv_catpvf_mg Perl_sv_catpvf_mg_nocontext
+# else
+# define sv_catpvf_mg Perl_sv_catpvf_mg
+# endif
+#endif
+
+/* sv_vcatpvf_mg depends on sv_vcatpvfn */
+#if ((PERL_VERSION > 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION >= 0))) && !defined(sv_vcatpvf_mg)
+# define sv_vcatpvf_mg(sv, pat, args) \
+ STMT_START { \
+ sv_vcatpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)); \
+ SvSETMAGIC(sv); \
+ } STMT_END
+#endif
+
+/* sv_setpvf_mg depends on sv_vsetpvfn, sv_setpvf_mg_nocontext */
+#if ((PERL_VERSION > 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION >= 0))) && !defined(sv_setpvf_mg)
+#if defined(NEED_sv_setpvf_mg)
+static void DPPP_(my_sv_setpvf_mg)(pTHX_ SV * sv, const char * pat, ...);
+static
+#else
+extern void DPPP_(my_sv_setpvf_mg)(pTHX_ SV * sv, const char * pat, ...);
+#endif
+
+#define Perl_sv_setpvf_mg DPPP_(my_sv_setpvf_mg)
+
+#if defined(NEED_sv_setpvf_mg) || defined(NEED_sv_setpvf_mg_GLOBAL)
+
+void
+DPPP_(my_sv_setpvf_mg)(pTHX_ SV *sv, const char *pat, ...)
+{
+ va_list args;
+ va_start(args, pat);
+ sv_vsetpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*));
+ SvSETMAGIC(sv);
+ va_end(args);
+}
+
+#endif
+#endif
+
+/* sv_setpvf_mg_nocontext depends on sv_vsetpvfn */
+#ifdef PERL_IMPLICIT_CONTEXT
+#if ((PERL_VERSION > 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION >= 0))) && !defined(sv_setpvf_mg_nocontext)
+#if defined(NEED_sv_setpvf_mg_nocontext)
+static void DPPP_(my_sv_setpvf_mg_nocontext)(SV * sv, const char * pat, ...);
+static
+#else
+extern void DPPP_(my_sv_setpvf_mg_nocontext)(SV * sv, const char * pat, ...);
+#endif
+
+#define sv_setpvf_mg_nocontext DPPP_(my_sv_setpvf_mg_nocontext)
+#define Perl_sv_setpvf_mg_nocontext DPPP_(my_sv_setpvf_mg_nocontext)
+
+#if defined(NEED_sv_setpvf_mg_nocontext) || defined(NEED_sv_setpvf_mg_nocontext_GLOBAL)
+
+void
+DPPP_(my_sv_setpvf_mg_nocontext)(SV *sv, const char *pat, ...)
+{
+ dTHX;
+ va_list args;
+ va_start(args, pat);
+ sv_vsetpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*));
+ SvSETMAGIC(sv);
+ va_end(args);
+}
+
+#endif
+#endif
+#endif
+
+#ifndef sv_setpvf_mg
+# ifdef PERL_IMPLICIT_CONTEXT
+# define sv_setpvf_mg Perl_sv_setpvf_mg_nocontext
+# else
+# define sv_setpvf_mg Perl_sv_setpvf_mg
+# endif
+#endif
+
+/* sv_vsetpvf_mg depends on sv_vsetpvfn */
+#if ((PERL_VERSION > 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION >= 0))) && !defined(sv_vsetpvf_mg)
+# define sv_vsetpvf_mg(sv, pat, args) \
+ STMT_START { \
+ sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)); \
+ SvSETMAGIC(sv); \
+ } STMT_END
+#endif
+#ifndef SvGETMAGIC
+# define SvGETMAGIC(x) STMT_START { if (SvGMAGICAL(x)) mg_get(x); } STMT_END
+#endif
+#ifndef PERL_MAGIC_sv
+# define PERL_MAGIC_sv '\0'
+#endif
+
+#ifndef PERL_MAGIC_overload
+# define PERL_MAGIC_overload 'A'
+#endif
+
+#ifndef PERL_MAGIC_overload_elem
+# define PERL_MAGIC_overload_elem 'a'
+#endif
+
+#ifndef PERL_MAGIC_overload_table
+# define PERL_MAGIC_overload_table 'c'
+#endif
+
+#ifndef PERL_MAGIC_bm
+# define PERL_MAGIC_bm 'B'
+#endif
+
+#ifndef PERL_MAGIC_regdata
+# define PERL_MAGIC_regdata 'D'
+#endif
+
+#ifndef PERL_MAGIC_regdatum
+# define PERL_MAGIC_regdatum 'd'
+#endif
+
+#ifndef PERL_MAGIC_env
+# define PERL_MAGIC_env 'E'
+#endif
+
+#ifndef PERL_MAGIC_envelem
+# define PERL_MAGIC_envelem 'e'
+#endif
+
+#ifndef PERL_MAGIC_fm
+# define PERL_MAGIC_fm 'f'
+#endif
+
+#ifndef PERL_MAGIC_regex_global
+# define PERL_MAGIC_regex_global 'g'
+#endif
+
+#ifndef PERL_MAGIC_isa
+# define PERL_MAGIC_isa 'I'
+#endif
+
+#ifndef PERL_MAGIC_isaelem
+# define PERL_MAGIC_isaelem 'i'
+#endif
+
+#ifndef PERL_MAGIC_nkeys
+# define PERL_MAGIC_nkeys 'k'
+#endif
+
+#ifndef PERL_MAGIC_dbfile
+# define PERL_MAGIC_dbfile 'L'
+#endif
+
+#ifndef PERL_MAGIC_dbline
+# define PERL_MAGIC_dbline 'l'
+#endif
+
+#ifndef PERL_MAGIC_mutex
+# define PERL_MAGIC_mutex 'm'
+#endif
+
+#ifndef PERL_MAGIC_shared
+# define PERL_MAGIC_shared 'N'
+#endif
+
+#ifndef PERL_MAGIC_shared_scalar
+# define PERL_MAGIC_shared_scalar 'n'
+#endif
+
+#ifndef PERL_MAGIC_collxfrm
+# define PERL_MAGIC_collxfrm 'o'
+#endif
+
+#ifndef PERL_MAGIC_tied
+# define PERL_MAGIC_tied 'P'
+#endif
+
+#ifndef PERL_MAGIC_tiedelem
+# define PERL_MAGIC_tiedelem 'p'
+#endif
+
+#ifndef PERL_MAGIC_tiedscalar
+# define PERL_MAGIC_tiedscalar 'q'
+#endif
+
+#ifndef PERL_MAGIC_qr
+# define PERL_MAGIC_qr 'r'
+#endif
+
+#ifndef PERL_MAGIC_sig
+# define PERL_MAGIC_sig 'S'
+#endif
+
+#ifndef PERL_MAGIC_sigelem
+# define PERL_MAGIC_sigelem 's'
+#endif
+
+#ifndef PERL_MAGIC_taint
+# define PERL_MAGIC_taint 't'
+#endif
+
+#ifndef PERL_MAGIC_uvar
+# define PERL_MAGIC_uvar 'U'
+#endif
+
+#ifndef PERL_MAGIC_uvar_elem
+# define PERL_MAGIC_uvar_elem 'u'
+#endif
+
+#ifndef PERL_MAGIC_vstring
+# define PERL_MAGIC_vstring 'V'
+#endif
+
+#ifndef PERL_MAGIC_vec
+# define PERL_MAGIC_vec 'v'
+#endif
+
+#ifndef PERL_MAGIC_utf8
+# define PERL_MAGIC_utf8 'w'
+#endif
+
+#ifndef PERL_MAGIC_substr
+# define PERL_MAGIC_substr 'x'
+#endif
+
+#ifndef PERL_MAGIC_defelem
+# define PERL_MAGIC_defelem 'y'
+#endif
+
+#ifndef PERL_MAGIC_glob
+# define PERL_MAGIC_glob '*'
+#endif
+
+#ifndef PERL_MAGIC_arylen
+# define PERL_MAGIC_arylen '#'
+#endif
+
+#ifndef PERL_MAGIC_pos
+# define PERL_MAGIC_pos '.'
+#endif
+
+#ifndef PERL_MAGIC_backref
+# define PERL_MAGIC_backref '<'
+#endif
+
+#ifndef PERL_MAGIC_ext
+# define PERL_MAGIC_ext '~'
+#endif
+
+/* That's the best we can do... */
+#ifndef SvPV_force_nomg
+# define SvPV_force_nomg SvPV_force
+#endif
+
+#ifndef SvPV_nomg
+# define SvPV_nomg SvPV
+#endif
+
+#ifndef sv_catpvn_nomg
+# define sv_catpvn_nomg sv_catpvn
+#endif
+
+#ifndef sv_catsv_nomg
+# define sv_catsv_nomg sv_catsv
+#endif
+
+#ifndef sv_setsv_nomg
+# define sv_setsv_nomg sv_setsv
+#endif
+
+#ifndef sv_pvn_nomg
+# define sv_pvn_nomg sv_pvn
+#endif
+
+#ifndef SvIV_nomg
+# define SvIV_nomg SvIV
+#endif
+
+#ifndef SvUV_nomg
+# define SvUV_nomg SvUV
+#endif
+
+#ifndef sv_catpv_mg
+# define sv_catpv_mg(sv, ptr) \
+ STMT_START { \
+ SV *TeMpSv = sv; \
+ sv_catpv(TeMpSv,ptr); \
+ SvSETMAGIC(TeMpSv); \
+ } STMT_END
+#endif
+
+#ifndef sv_catpvn_mg
+# define sv_catpvn_mg(sv, ptr, len) \
+ STMT_START { \
+ SV *TeMpSv = sv; \
+ sv_catpvn(TeMpSv,ptr,len); \
+ SvSETMAGIC(TeMpSv); \
+ } STMT_END
+#endif
+
+#ifndef sv_catsv_mg
+# define sv_catsv_mg(dsv, ssv) \
+ STMT_START { \
+ SV *TeMpSv = dsv; \
+ sv_catsv(TeMpSv,ssv); \
+ SvSETMAGIC(TeMpSv); \
+ } STMT_END
+#endif
+
+#ifndef sv_setiv_mg
+# define sv_setiv_mg(sv, i) \
+ STMT_START { \
+ SV *TeMpSv = sv; \
+ sv_setiv(TeMpSv,i); \
+ SvSETMAGIC(TeMpSv); \
+ } STMT_END
+#endif
+
+#ifndef sv_setnv_mg
+# define sv_setnv_mg(sv, num) \
+ STMT_START { \
+ SV *TeMpSv = sv; \
+ sv_setnv(TeMpSv,num); \
+ SvSETMAGIC(TeMpSv); \
+ } STMT_END
+#endif
+
+#ifndef sv_setpv_mg
+# define sv_setpv_mg(sv, ptr) \
+ STMT_START { \
+ SV *TeMpSv = sv; \
+ sv_setpv(TeMpSv,ptr); \
+ SvSETMAGIC(TeMpSv); \
+ } STMT_END
+#endif
+
+#ifndef sv_setpvn_mg
+# define sv_setpvn_mg(sv, ptr, len) \
+ STMT_START { \
+ SV *TeMpSv = sv; \
+ sv_setpvn(TeMpSv,ptr,len); \
+ SvSETMAGIC(TeMpSv); \
+ } STMT_END
+#endif
+
+#ifndef sv_setsv_mg
+# define sv_setsv_mg(dsv, ssv) \
+ STMT_START { \
+ SV *TeMpSv = dsv; \
+ sv_setsv(TeMpSv,ssv); \
+ SvSETMAGIC(TeMpSv); \
+ } STMT_END
+#endif
+
+#ifndef sv_setuv_mg
+# define sv_setuv_mg(sv, i) \
+ STMT_START { \
+ SV *TeMpSv = sv; \
+ sv_setuv(TeMpSv,i); \
+ SvSETMAGIC(TeMpSv); \
+ } STMT_END
+#endif
+
+#ifndef sv_usepvn_mg
+# define sv_usepvn_mg(sv, ptr, len) \
+ STMT_START { \
+ SV *TeMpSv = sv; \
+ sv_usepvn(TeMpSv,ptr,len); \
+ SvSETMAGIC(TeMpSv); \
+ } STMT_END
+#endif
+
+#ifdef USE_ITHREADS
+#ifndef CopFILE
+# define CopFILE(c) ((c)->cop_file)
+#endif
+
+#ifndef CopFILEGV
+# define CopFILEGV(c) (CopFILE(c) ? gv_fetchfile(CopFILE(c)) : Nullgv)
+#endif
+
+#ifndef CopFILE_set
+# define CopFILE_set(c,pv) ((c)->cop_file = savepv(pv))
+#endif
+
+#ifndef CopFILESV
+# define CopFILESV(c) (CopFILE(c) ? GvSV(gv_fetchfile(CopFILE(c))) : Nullsv)
+#endif
+
+#ifndef CopFILEAV
+# define CopFILEAV(c) (CopFILE(c) ? GvAV(gv_fetchfile(CopFILE(c))) : Nullav)
+#endif
+
+#ifndef CopSTASHPV
+# define CopSTASHPV(c) ((c)->cop_stashpv)
+#endif
+
+#ifndef CopSTASHPV_set
+# define CopSTASHPV_set(c,pv) ((c)->cop_stashpv = ((pv) ? savepv(pv) : Nullch))
+#endif
+
+#ifndef CopSTASH
+# define CopSTASH(c) (CopSTASHPV(c) ? gv_stashpv(CopSTASHPV(c),GV_ADD) : Nullhv)
+#endif
+
+#ifndef CopSTASH_set
+# define CopSTASH_set(c,hv) CopSTASHPV_set(c, (hv) ? HvNAME(hv) : Nullch)
+#endif
+
+#ifndef CopSTASH_eq
+# define CopSTASH_eq(c,hv) ((hv) && (CopSTASHPV(c) == HvNAME(hv) \
+ || (CopSTASHPV(c) && HvNAME(hv) \
+ && strEQ(CopSTASHPV(c), HvNAME(hv)))))
+#endif
+
+#else
+#ifndef CopFILEGV
+# define CopFILEGV(c) ((c)->cop_filegv)
+#endif
+
+#ifndef CopFILEGV_set
+# define CopFILEGV_set(c,gv) ((c)->cop_filegv = (GV*)SvREFCNT_inc(gv))
+#endif
+
+#ifndef CopFILE_set
+# define CopFILE_set(c,pv) CopFILEGV_set((c), gv_fetchfile(pv))
+#endif
+
+#ifndef CopFILESV
+# define CopFILESV(c) (CopFILEGV(c) ? GvSV(CopFILEGV(c)) : Nullsv)
+#endif
+
+#ifndef CopFILEAV
+# define CopFILEAV(c) (CopFILEGV(c) ? GvAV(CopFILEGV(c)) : Nullav)
+#endif
+
+#ifndef CopFILE
+# define CopFILE(c) (CopFILESV(c) ? SvPVX(CopFILESV(c)) : Nullch)
+#endif
+
+#ifndef CopSTASH
+# define CopSTASH(c) ((c)->cop_stash)
+#endif
+
+#ifndef CopSTASH_set
+# define CopSTASH_set(c,hv) ((c)->cop_stash = (hv))
+#endif
+
+#ifndef CopSTASHPV
+# define CopSTASHPV(c) (CopSTASH(c) ? HvNAME(CopSTASH(c)) : Nullch)
+#endif
+
+#ifndef CopSTASHPV_set
+# define CopSTASHPV_set(c,pv) CopSTASH_set((c), gv_stashpv(pv,GV_ADD))
+#endif
+
+#ifndef CopSTASH_eq
+# define CopSTASH_eq(c,hv) (CopSTASH(c) == (hv))
+#endif
+
+#endif /* USE_ITHREADS */
+#ifndef IN_PERL_COMPILETIME
+# define IN_PERL_COMPILETIME (PL_curcop == &PL_compiling)
+#endif
+
+#ifndef IN_LOCALE_RUNTIME
+# define IN_LOCALE_RUNTIME (PL_curcop->op_private & HINT_LOCALE)
+#endif
+
+#ifndef IN_LOCALE_COMPILETIME
+# define IN_LOCALE_COMPILETIME (PL_hints & HINT_LOCALE)
+#endif
+
+#ifndef IN_LOCALE
+# define IN_LOCALE (IN_PERL_COMPILETIME ? IN_LOCALE_COMPILETIME : IN_LOCALE_RUNTIME)
+#endif
+#ifndef IS_NUMBER_IN_UV
+# define IS_NUMBER_IN_UV 0x01
+#endif
+
+#ifndef IS_NUMBER_GREATER_THAN_UV_MAX
+# define IS_NUMBER_GREATER_THAN_UV_MAX 0x02
+#endif
+
+#ifndef IS_NUMBER_NOT_INT
+# define IS_NUMBER_NOT_INT 0x04
+#endif
+
+#ifndef IS_NUMBER_NEG
+# define IS_NUMBER_NEG 0x08
+#endif
+
+#ifndef IS_NUMBER_INFINITY
+# define IS_NUMBER_INFINITY 0x10
+#endif
+
+#ifndef IS_NUMBER_NAN
+# define IS_NUMBER_NAN 0x20
+#endif
+
+/* GROK_NUMERIC_RADIX depends on grok_numeric_radix */
+#ifndef GROK_NUMERIC_RADIX
+# define GROK_NUMERIC_RADIX(sp, send) grok_numeric_radix(sp, send)
+#endif
+#ifndef PERL_SCAN_GREATER_THAN_UV_MAX
+# define PERL_SCAN_GREATER_THAN_UV_MAX 0x02
+#endif
+
+#ifndef PERL_SCAN_SILENT_ILLDIGIT
+# define PERL_SCAN_SILENT_ILLDIGIT 0x04
+#endif
+
+#ifndef PERL_SCAN_ALLOW_UNDERSCORES
+# define PERL_SCAN_ALLOW_UNDERSCORES 0x01
+#endif
+
+#ifndef PERL_SCAN_DISALLOW_PREFIX
+# define PERL_SCAN_DISALLOW_PREFIX 0x02
+#endif
+
+#ifndef grok_numeric_radix
+#if defined(NEED_grok_numeric_radix)
+static bool DPPP_(my_grok_numeric_radix)(pTHX_ const char ** sp, const char * send);
+static
+#else
+extern bool DPPP_(my_grok_numeric_radix)(pTHX_ const char ** sp, const char * send);
+#endif
+
+#ifdef grok_numeric_radix
+# undef grok_numeric_radix
+#endif
+#define grok_numeric_radix(a,b) DPPP_(my_grok_numeric_radix)(aTHX_ a,b)
+#define Perl_grok_numeric_radix DPPP_(my_grok_numeric_radix)
+
+#if defined(NEED_grok_numeric_radix) || defined(NEED_grok_numeric_radix_GLOBAL)
+bool
+DPPP_(my_grok_numeric_radix)(pTHX_ const char **sp, const char *send)
+{
+#ifdef USE_LOCALE_NUMERIC
+#ifdef PL_numeric_radix_sv
+ if (PL_numeric_radix_sv && IN_LOCALE) {
+ STRLEN len;
+ char* radix = SvPV(PL_numeric_radix_sv, len);
+ if (*sp + len <= send && memEQ(*sp, radix, len)) {
+ *sp += len;
+ return TRUE;
+ }
+ }
+#else
+ /* older perls don't have PL_numeric_radix_sv so the radix
+ * must manually be requested from locale.h
+ */
+#include <locale.h>
+ dTHR; /* needed for older threaded perls */
+ struct lconv *lc = localeconv();
+ char *radix = lc->decimal_point;
+ if (radix && IN_LOCALE) {
+ STRLEN len = strlen(radix);
+ if (*sp + len <= send && memEQ(*sp, radix, len)) {
+ *sp += len;
+ return TRUE;
+ }
+ }
+#endif /* PERL_VERSION */
+#endif /* USE_LOCALE_NUMERIC */
+ /* always try "." if numeric radix didn't match because
+ * we may have data from different locales mixed */
+ if (*sp < send && **sp == '.') {
+ ++*sp;
+ return TRUE;
+ }
+ return FALSE;
+}
+#endif
+#endif
+
+/* grok_number depends on grok_numeric_radix */
+
+#ifndef grok_number
+#if defined(NEED_grok_number)
+static int DPPP_(my_grok_number)(pTHX_ const char * pv, STRLEN len, UV * valuep);
+static
+#else
+extern int DPPP_(my_grok_number)(pTHX_ const char * pv, STRLEN len, UV * valuep);
+#endif
+
+#ifdef grok_number
+# undef grok_number
+#endif
+#define grok_number(a,b,c) DPPP_(my_grok_number)(aTHX_ a,b,c)
+#define Perl_grok_number DPPP_(my_grok_number)
+
+#if defined(NEED_grok_number) || defined(NEED_grok_number_GLOBAL)
+int
+DPPP_(my_grok_number)(pTHX_ const char *pv, STRLEN len, UV *valuep)
+{
+ const char *s = pv;
+ const char *send = pv + len;
+ const UV max_div_10 = UV_MAX / 10;
+ const char max_mod_10 = UV_MAX % 10;
+ int numtype = 0;
+ int sawinf = 0;
+ int sawnan = 0;
+
+ while (s < send && isSPACE(*s))
+ s++;
+ if (s == send) {
+ return 0;
+ } else if (*s == '-') {
+ s++;
+ numtype = IS_NUMBER_NEG;
+ }
+ else if (*s == '+')
+ s++;
+
+ if (s == send)
+ return 0;
+
+ /* next must be digit or the radix separator or beginning of infinity */
+ if (isDIGIT(*s)) {
+ /* UVs are at least 32 bits, so the first 9 decimal digits cannot
+ overflow. */
+ UV value = *s - '0';
+ /* This construction seems to be more optimiser friendly.
+ (without it gcc does the isDIGIT test and the *s - '0' separately)
+ With it gcc on arm is managing 6 instructions (6 cycles) per digit.
+ In theory the optimiser could deduce how far to unroll the loop
+ before checking for overflow. */
+ if (++s < send) {
+ int digit = *s - '0';
+ if (digit >= 0 && digit <= 9) {
+ value = value * 10 + digit;
+ if (++s < send) {
+ digit = *s - '0';
+ if (digit >= 0 && digit <= 9) {
+ value = value * 10 + digit;
+ if (++s < send) {
+ digit = *s - '0';
+ if (digit >= 0 && digit <= 9) {
+ value = value * 10 + digit;
+ if (++s < send) {
+ digit = *s - '0';
+ if (digit >= 0 && digit <= 9) {
+ value = value * 10 + digit;
+ if (++s < send) {
+ digit = *s - '0';
+ if (digit >= 0 && digit <= 9) {
+ value = value * 10 + digit;
+ if (++s < send) {
+ digit = *s - '0';
+ if (digit >= 0 && digit <= 9) {
+ value = value * 10 + digit;
+ if (++s < send) {
+ digit = *s - '0';
+ if (digit >= 0 && digit <= 9) {
+ value = value * 10 + digit;
+ if (++s < send) {
+ digit = *s - '0';
+ if (digit >= 0 && digit <= 9) {
+ value = value * 10 + digit;
+ if (++s < send) {
+ /* Now got 9 digits, so need to check
+ each time for overflow. */
+ digit = *s - '0';
+ while (digit >= 0 && digit <= 9
+ && (value < max_div_10
+ || (value == max_div_10
+ && digit <= max_mod_10))) {
+ value = value * 10 + digit;
+ if (++s < send)
+ digit = *s - '0';
+ else
+ break;
+ }
+ if (digit >= 0 && digit <= 9
+ && (s < send)) {
+ /* value overflowed.
+ skip the remaining digits, don't
+ worry about setting *valuep. */
+ do {
+ s++;
+ } while (s < send && isDIGIT(*s));
+ numtype |=
+ IS_NUMBER_GREATER_THAN_UV_MAX;
+ goto skip_value;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ numtype |= IS_NUMBER_IN_UV;
+ if (valuep)
+ *valuep = value;
+
+ skip_value:
+ if (GROK_NUMERIC_RADIX(&s, send)) {
+ numtype |= IS_NUMBER_NOT_INT;
+ while (s < send && isDIGIT(*s)) /* optional digits after the radix */
+ s++;
+ }
+ }
+ else if (GROK_NUMERIC_RADIX(&s, send)) {
+ numtype |= IS_NUMBER_NOT_INT | IS_NUMBER_IN_UV; /* valuep assigned below */
+ /* no digits before the radix means we need digits after it */
+ if (s < send && isDIGIT(*s)) {
+ do {
+ s++;
+ } while (s < send && isDIGIT(*s));
+ if (valuep) {
+ /* integer approximation is valid - it's 0. */
+ *valuep = 0;
+ }
+ }
+ else
+ return 0;
+ } else if (*s == 'I' || *s == 'i') {
+ s++; if (s == send || (*s != 'N' && *s != 'n')) return 0;
+ s++; if (s == send || (*s != 'F' && *s != 'f')) return 0;
+ s++; if (s < send && (*s == 'I' || *s == 'i')) {
+ s++; if (s == send || (*s != 'N' && *s != 'n')) return 0;
+ s++; if (s == send || (*s != 'I' && *s != 'i')) return 0;
+ s++; if (s == send || (*s != 'T' && *s != 't')) return 0;
+ s++; if (s == send || (*s != 'Y' && *s != 'y')) return 0;
+ s++;
+ }
+ sawinf = 1;
+ } else if (*s == 'N' || *s == 'n') {
+ /* XXX TODO: There are signaling NaNs and quiet NaNs. */
+ s++; if (s == send || (*s != 'A' && *s != 'a')) return 0;
+ s++; if (s == send || (*s != 'N' && *s != 'n')) return 0;
+ s++;
+ sawnan = 1;
+ } else
+ return 0;
+
+ if (sawinf) {
+ numtype &= IS_NUMBER_NEG; /* Keep track of sign */
+ numtype |= IS_NUMBER_INFINITY | IS_NUMBER_NOT_INT;
+ } else if (sawnan) {
+ numtype &= IS_NUMBER_NEG; /* Keep track of sign */
+ numtype |= IS_NUMBER_NAN | IS_NUMBER_NOT_INT;
+ } else if (s < send) {
+ /* we can have an optional exponent part */
+ if (*s == 'e' || *s == 'E') {
+ /* The only flag we keep is sign. Blow away any "it's UV" */
+ numtype &= IS_NUMBER_NEG;
+ numtype |= IS_NUMBER_NOT_INT;
+ s++;
+ if (s < send && (*s == '-' || *s == '+'))
+ s++;
+ if (s < send && isDIGIT(*s)) {
+ do {
+ s++;
+ } while (s < send && isDIGIT(*s));
+ }
+ else
+ return 0;
+ }
+ }
+ while (s < send && isSPACE(*s))
+ s++;
+ if (s >= send)
+ return numtype;
+ if (len == 10 && memEQ(pv, "0 but true", 10)) {
+ if (valuep)
+ *valuep = 0;
+ return IS_NUMBER_IN_UV;
+ }
+ return 0;
+}
+#endif
+#endif
+
+/*
+ * The grok_* routines have been modified to use warn() instead of
+ * Perl_warner(). Also, 'hexdigit' was the former name of PL_hexdigit,
+ * which is why the stack variable has been renamed to 'xdigit'.
+ */
+
+#ifndef grok_bin
+#if defined(NEED_grok_bin)
+static UV DPPP_(my_grok_bin)(pTHX_ char *start, STRLEN *len_p, I32 *flags, NV *result);
+static
+#else
+extern UV DPPP_(my_grok_bin)(pTHX_ char *start, STRLEN *len_p, I32 *flags, NV *result);
+#endif
+
+#ifdef grok_bin
+# undef grok_bin
+#endif
+#define grok_bin(a,b,c,d) DPPP_(my_grok_bin)(aTHX_ a,b,c,d)
+#define Perl_grok_bin DPPP_(my_grok_bin)
+
+#if defined(NEED_grok_bin) || defined(NEED_grok_bin_GLOBAL)
+UV
+DPPP_(my_grok_bin)(pTHX_ char *start, STRLEN *len_p, I32 *flags, NV *result)
+{
+ const char *s = start;
+ STRLEN len = *len_p;
+ UV value = 0;
+ NV value_nv = 0;
+
+ const UV max_div_2 = UV_MAX / 2;
+ bool allow_underscores = *flags & PERL_SCAN_ALLOW_UNDERSCORES;
+ bool overflowed = FALSE;
+
+ if (!(*flags & PERL_SCAN_DISALLOW_PREFIX)) {
+ /* strip off leading b or 0b.
+ for compatibility silently suffer "b" and "0b" as valid binary
+ numbers. */
+ if (len >= 1) {
+ if (s[0] == 'b') {
+ s++;
+ len--;
+ }
+ else if (len >= 2 && s[0] == '0' && s[1] == 'b') {
+ s+=2;
+ len-=2;
+ }
+ }
+ }
+
+ for (; len-- && *s; s++) {
+ char bit = *s;
+ if (bit == '0' || bit == '1') {
+ /* Write it in this wonky order with a goto to attempt to get the
+ compiler to make the common case integer-only loop pretty tight.
+ With gcc seems to be much straighter code than old scan_bin. */
+ redo:
+ if (!overflowed) {
+ if (value <= max_div_2) {
+ value = (value << 1) | (bit - '0');
+ continue;
+ }
+ /* Bah. We're just overflowed. */
+ warn("Integer overflow in binary number");
+ overflowed = TRUE;
+ value_nv = (NV) value;
+ }
+ value_nv *= 2.0;
+ /* If an NV has not enough bits in its mantissa to
+ * represent a UV this summing of small low-order numbers
+ * is a waste of time (because the NV cannot preserve
+ * the low-order bits anyway): we could just remember when
+ * did we overflow and in the end just multiply value_nv by the
+ * right amount. */
+ value_nv += (NV)(bit - '0');
+ continue;
+ }
+ if (bit == '_' && len && allow_underscores && (bit = s[1])
+ && (bit == '0' || bit == '1'))
+ {
+ --len;
+ ++s;
+ goto redo;
+ }
+ if (!(*flags & PERL_SCAN_SILENT_ILLDIGIT))
+ warn("Illegal binary digit '%c' ignored", *s);
+ break;
+ }
+
+ if ( ( overflowed && value_nv > 4294967295.0)
+#if UVSIZE > 4
+ || (!overflowed && value > 0xffffffff )
+#endif
+ ) {
+ warn("Binary number > 0b11111111111111111111111111111111 non-portable");
+ }
+ *len_p = s - start;
+ if (!overflowed) {
+ *flags = 0;
+ return value;
+ }
+ *flags = PERL_SCAN_GREATER_THAN_UV_MAX;
+ if (result)
+ *result = value_nv;
+ return UV_MAX;
+}
+#endif
+#endif
+
+#ifndef grok_hex
+#if defined(NEED_grok_hex)
+static UV DPPP_(my_grok_hex)(pTHX_ char *start, STRLEN *len_p, I32 *flags, NV *result);
+static
+#else
+extern UV DPPP_(my_grok_hex)(pTHX_ char *start, STRLEN *len_p, I32 *flags, NV *result);
+#endif
+
+#ifdef grok_hex
+# undef grok_hex
+#endif
+#define grok_hex(a,b,c,d) DPPP_(my_grok_hex)(aTHX_ a,b,c,d)
+#define Perl_grok_hex DPPP_(my_grok_hex)
+
+#if defined(NEED_grok_hex) || defined(NEED_grok_hex_GLOBAL)
+UV
+DPPP_(my_grok_hex)(pTHX_ char *start, STRLEN *len_p, I32 *flags, NV *result)
+{
+ const char *s = start;
+ STRLEN len = *len_p;
+ UV value = 0;
+ NV value_nv = 0;
+
+ const UV max_div_16 = UV_MAX / 16;
+ bool allow_underscores = *flags & PERL_SCAN_ALLOW_UNDERSCORES;
+ bool overflowed = FALSE;
+ const char *xdigit;
+
+ if (!(*flags & PERL_SCAN_DISALLOW_PREFIX)) {
+ /* strip off leading x or 0x.
+ for compatibility silently suffer "x" and "0x" as valid hex numbers.
+ */
+ if (len >= 1) {
+ if (s[0] == 'x') {
+ s++;
+ len--;
+ }
+ else if (len >= 2 && s[0] == '0' && s[1] == 'x') {
+ s+=2;
+ len-=2;
+ }
+ }
+ }
+
+ for (; len-- && *s; s++) {
+ xdigit = strchr((char *) PL_hexdigit, *s);
+ if (xdigit) {
+ /* Write it in this wonky order with a goto to attempt to get the
+ compiler to make the common case integer-only loop pretty tight.
+ With gcc seems to be much straighter code than old scan_hex. */
+ redo:
+ if (!overflowed) {
+ if (value <= max_div_16) {
+ value = (value << 4) | ((xdigit - PL_hexdigit) & 15);
+ continue;
+ }
+ warn("Integer overflow in hexadecimal number");
+ overflowed = TRUE;
+ value_nv = (NV) value;
+ }
+ value_nv *= 16.0;
+ /* If an NV has not enough bits in its mantissa to
+ * represent a UV this summing of small low-order numbers
+ * is a waste of time (because the NV cannot preserve
+ * the low-order bits anyway): we could just remember when
+ * did we overflow and in the end just multiply value_nv by the
+ * right amount of 16-tuples. */
+ value_nv += (NV)((xdigit - PL_hexdigit) & 15);
+ continue;
+ }
+ if (*s == '_' && len && allow_underscores && s[1]
+ && (xdigit = strchr((char *) PL_hexdigit, s[1])))
+ {
+ --len;
+ ++s;
+ goto redo;
+ }
+ if (!(*flags & PERL_SCAN_SILENT_ILLDIGIT))
+ warn("Illegal hexadecimal digit '%c' ignored", *s);
+ break;
+ }
+
+ if ( ( overflowed && value_nv > 4294967295.0)
+#if UVSIZE > 4
+ || (!overflowed && value > 0xffffffff )
+#endif
+ ) {
+ warn("Hexadecimal number > 0xffffffff non-portable");
+ }
+ *len_p = s - start;
+ if (!overflowed) {
+ *flags = 0;
+ return value;
+ }
+ *flags = PERL_SCAN_GREATER_THAN_UV_MAX;
+ if (result)
+ *result = value_nv;
+ return UV_MAX;
+}
+#endif
+#endif
+
+#ifndef grok_oct
+#if defined(NEED_grok_oct)
+static UV DPPP_(my_grok_oct)(pTHX_ char *start, STRLEN *len_p, I32 *flags, NV *result);
+static
+#else
+extern UV DPPP_(my_grok_oct)(pTHX_ char *start, STRLEN *len_p, I32 *flags, NV *result);
+#endif
+
+#ifdef grok_oct
+# undef grok_oct
+#endif
+#define grok_oct(a,b,c,d) DPPP_(my_grok_oct)(aTHX_ a,b,c,d)
+#define Perl_grok_oct DPPP_(my_grok_oct)
+
+#if defined(NEED_grok_oct) || defined(NEED_grok_oct_GLOBAL)
+UV
+DPPP_(my_grok_oct)(pTHX_ char *start, STRLEN *len_p, I32 *flags, NV *result)
+{
+ const char *s = start;
+ STRLEN len = *len_p;
+ UV value = 0;
+ NV value_nv = 0;
+
+ const UV max_div_8 = UV_MAX / 8;
+ bool allow_underscores = *flags & PERL_SCAN_ALLOW_UNDERSCORES;
+ bool overflowed = FALSE;
+
+ for (; len-- && *s; s++) {
+ /* gcc 2.95 optimiser not smart enough to figure that this subtraction
+ out front allows slicker code. */
+ int digit = *s - '0';
+ if (digit >= 0 && digit <= 7) {
+ /* Write it in this wonky order with a goto to attempt to get the
+ compiler to make the common case integer-only loop pretty tight.
+ */
+ redo:
+ if (!overflowed) {
+ if (value <= max_div_8) {
+ value = (value << 3) | digit;
+ continue;
+ }
+ /* Bah. We're just overflowed. */
+ warn("Integer overflow in octal number");
+ overflowed = TRUE;
+ value_nv = (NV) value;
+ }
+ value_nv *= 8.0;
+ /* If an NV has not enough bits in its mantissa to
+ * represent a UV this summing of small low-order numbers
+ * is a waste of time (because the NV cannot preserve
+ * the low-order bits anyway): we could just remember when
+ * did we overflow and in the end just multiply value_nv by the
+ * right amount of 8-tuples. */
+ value_nv += (NV)digit;
+ continue;
+ }
+ if (digit == ('_' - '0') && len && allow_underscores
+ && (digit = s[1] - '0') && (digit >= 0 && digit <= 7))
+ {
+ --len;
+ ++s;
+ goto redo;
+ }
+ /* Allow \octal to work the DWIM way (that is, stop scanning
+ * as soon as non-octal characters are seen, complain only iff
+ * someone seems to want to use the digits eight and nine). */
+ if (digit == 8 || digit == 9) {
+ if (!(*flags & PERL_SCAN_SILENT_ILLDIGIT))
+ warn("Illegal octal digit '%c' ignored", *s);
+ }
+ break;
+ }
+
+ if ( ( overflowed && value_nv > 4294967295.0)
+#if UVSIZE > 4
+ || (!overflowed && value > 0xffffffff )
+#endif
+ ) {
+ warn("Octal number > 037777777777 non-portable");
+ }
+ *len_p = s - start;
+ if (!overflowed) {
+ *flags = 0;
+ return value;
+ }
+ *flags = PERL_SCAN_GREATER_THAN_UV_MAX;
+ if (result)
+ *result = value_nv;
+ return UV_MAX;
+}
+#endif
+#endif
+
+#ifdef NO_XSLOCKS
+# ifdef dJMPENV
+# define dXCPT dJMPENV; int rEtV = 0
+# define XCPT_TRY_START JMPENV_PUSH(rEtV); if (rEtV == 0)
+# define XCPT_TRY_END JMPENV_POP;
+# define XCPT_CATCH if (rEtV != 0)
+# define XCPT_RETHROW JMPENV_JUMP(rEtV)
+# else
+# define dXCPT Sigjmp_buf oldTOP; int rEtV = 0
+# define XCPT_TRY_START Copy(top_env, oldTOP, 1, Sigjmp_buf); rEtV = Sigsetjmp(top_env, 1); if (rEtV == 0)
+# define XCPT_TRY_END Copy(oldTOP, top_env, 1, Sigjmp_buf);
+# define XCPT_CATCH if (rEtV != 0)
+# define XCPT_RETHROW Siglongjmp(top_env, rEtV)
+# endif
+#endif
+
+#endif /* _P_P_PORTABILITY_H_ */
+
+/* End of File ppport.h */
--- /dev/null
+# -*-perl-*-
+# Before `make install' is performed this script should be runnable with
+# `make test'. After `make install' it should work as `perl PSPP.t'
+
+#########################
+
+# change 'tests => 1' to 'tests => last_test_to_print';
+
+use Test::More tests => 37;
+use Text::Diff;
+use File::Temp qw/ tempfile tempdir /;
+BEGIN { use_ok('PSPP') };
+
+#########################
+
+sub compare
+{
+ my $file = shift;
+ my $pattern = shift;
+ return ! diff ("$file", \$pattern);
+}
+
+my $pspp_cmd = $ENV{PSPP_TEST_CMD};
+
+if ( ! $pspp_cmd)
+{
+ $pspp_cmd="pspp";
+}
+
+sub run_pspp_syntax
+{
+ my $tempdir = shift;
+ my $syntax = shift;
+
+ my $syntaxfile = "$tempdir/foo.sps";
+
+ open (FH, ">$syntaxfile");
+ print FH "$syntax";
+ close (FH);
+
+ system ("cd $tempdir; $pspp_cmd -o raw-ascii $syntaxfile");
+}
+
+sub run_pspp_syntax_cmp
+{
+ my $tempdir = shift;
+ my $syntax = shift;
+
+ my $result = shift;
+
+ run_pspp_syntax ($tempdir, $syntax);
+
+ my $diff = diff ("$tempdir/pspp.list", \$result);
+
+ if ( ! ($diff eq ""))
+ {
+ diag ("$diff");
+ }
+
+ return ($diff eq "");
+}
+
+
+# Insert your test code below, the Test::More module is used here so read
+# its man page ( perldoc Test::More ) for help writing this test script.
+
+{
+ my $d = PSPP::Dict->new();
+ ok (ref $d, "Dictionary Creation");
+ ok ($d->get_var_cnt () == 0);
+
+ $d->set_label ("My Dictionary");
+ $d->set_documents ("These Documents");
+
+ # Tests for variable creation
+
+ my $var0 = PSPP::Var->new ($d, "le");
+ ok (!ref $var0, "Trap illegal variable name");
+ ok ($d->get_var_cnt () == 0);
+
+ $var0 = PSPP::Var->new ($d, "legal");
+ ok (ref $var0, "Accept legal variable name");
+ ok ($d->get_var_cnt () == 1);
+
+ my $var1 = PSPP::Var->new ($d, "legal");
+ ok (!ref $var1, "Trap duplicate variable name");
+ ok ($d->get_var_cnt () == 1);
+
+ $var1 = PSPP::Var->new ($d, "money",
+ (fmt=>PSPP::Fmt::DOLLAR,
+ width=>4, decimals=>2) );
+ ok (ref $var1, "Accept valid format");
+ ok ($d->get_var_cnt () == 2);
+
+ $d->set_weight ($var1);
+
+
+ # Tests for system file creation
+ # Make sure a system file can be created
+ {
+ my $tempdir = tempdir( CLEANUP => 1 );
+ my $tempfile = "$tempdir/testfile.sav";
+ my $syntaxfile = "$tempdir/syntax.sps";
+ my $sysfile = PSPP::Sysfile->new ("$tempfile", $d);
+ ok (ref $sysfile, "Create sysfile object");
+
+ $sysfile->close ();
+ ok (-s "$tempfile", "Write system file");
+ }
+}
+
+
+# Make sure we can write cases to a file
+{
+ my $d = PSPP::Dict->new();
+ PSPP::Var->new ($d, "id",
+ (
+ fmt=>PSPP::Fmt::F,
+ width=>2,
+ decimals=>0
+ )
+ );
+
+ PSPP::Var->new ($d, "name",
+ (
+ fmt=>PSPP::Fmt::A,
+ width=>20,
+ )
+ );
+
+ $d->set_documents ("This should not appear");
+ $d->clear_documents ();
+ $d->add_document ("This is a document line");
+
+ $d->set_label ("This is the file label");
+
+ # Check that we can write system files
+ {
+ my $tempdir = tempdir( CLEANUP => 1 );
+ my $tempfile = "$tempdir/testfile.sav";
+ my $sysfile = PSPP::Sysfile->new ("$tempfile", $d);
+
+ my $res = $sysfile->append_case ( [34, "frederick"]);
+ ok ($res, "Append Case");
+
+ $res = $sysfile->append_case ( [34, "frederick", "extra"]);
+ ok (!$res, "Appending Case with too many variables");
+
+ $sysfile->close ();
+ ok (-s "$tempfile", "existance");
+ }
+
+ # Check that sysfiles are closed properly
+ {
+ my $tempdir = tempdir( CLEANUP => 1 );
+ my $tempfile = "$tempdir/testfile.sav";
+ {
+ my $sysfile = PSPP::Sysfile->new ("$tempfile", $d);
+
+ my $res = $sysfile->append_case ( [21, "wheelbarrow"]);
+ ok ($res, "Append Case 2");
+
+ # Don't close. We want to test that the destructor does that
+ # automatically
+ }
+ ok (-s "$tempfile", "existance2");
+
+ ok (run_pspp_syntax_cmp ($tempdir, <<SYNTAX, <<RESULT), "Check output");
+
+ GET FILE='$tempfile'.
+ DISPLAY DICTIONARY.
+ DISPLAY FILE LABEL.
+ DISPLAY DOCUMENTS.
+ LIST.
+SYNTAX
+1.1 DISPLAY.
++--------+-------------------------------------------+--------+
+|Variable|Description |Position|
+#========#===========================================#========#
+|id |Format: F2.0 | 1|
+| |Measure: Scale | |
+| |Display Alignment: Right | |
+| |Display Width: 8 | |
++--------+-------------------------------------------+--------+
+|name |Format: A20 | 2|
+| |Measure: Nominal | |
+| |Display Alignment: Left | |
+| |Display Width: 20 | |
++--------+-------------------------------------------+--------+
+
+File label:
+This is the file label
+
+Documents in the active file:
+
+This is a document line
+
+id name
+-- --------------------
+21 wheelbarrow
+
+RESULT
+
+
+ }
+
+ # Now do some tests to make sure all the variable parameters
+ # can be written properly.
+
+ {
+ my $tempdir = tempdir( CLEANUP => 1 );
+ my $tempfile = "$tempdir/testfile.sav";
+ my $dict = PSPP::Dict->new();
+ ok (ref $dict, "Dictionary Creation 2");
+
+ my $int = PSPP::Var->new ($dict, "integer",
+ (width=>8, decimals=>0) );
+
+ $int->set_label ("My Integer");
+
+ $int->add_value_label (99, "Silly");
+ $int->clear_value_labels ();
+ $int->add_value_label (0, "Zero");
+ $int->add_value_label (1, "Unity");
+ $int->add_value_label (2, "Duality");
+
+ my $str = PSPP::Var->new ($dict, "string",
+ (fmt=>PSPP::Fmt::A, width=>8) );
+
+
+ $str->set_label ("My String");
+ ok ($str->add_value_label ("xx", "foo"), "Value label for short string");
+ diag ($PSPP::errstr);
+ $str->add_value_label ("yy", "bar");
+
+ $str->set_missing_values ("this", "that");
+
+ my $longstr = PSPP::Var->new ($dict, "longstring",
+ (fmt=>PSPP::Fmt::A, width=>9) );
+
+
+ $longstr->set_label ("My Long String");
+ my $re = $longstr->add_value_label ("xxx", "xfoo");
+ ok (($re == 0), "Long strings cant have labels");
+
+ ok ($PSPP::errstr eq "Cannot add label to a long string variable", "Error msg");
+
+ $int->set_missing_values (9, 99);
+
+ my $sysfile = PSPP::Sysfile->new ("$tempfile", $dict);
+
+
+ $sysfile->close ();
+
+ ok (run_pspp_syntax_cmp ($tempdir, <<SYNTAX, <<RESULT), "Check output 2");
+GET FILE='$tempfile'.
+DISPLAY DICTIONARY.
+SYNTAX
+1.1 DISPLAY.
++----------+-----------------------------------------+--------+
+|Variable |Description |Position|
+#==========#=========================================#========#
+|integer |My Integer | 1|
+| |Format: F8.0 | |
+| |Measure: Scale | |
+| |Display Alignment: Right | |
+| |Display Width: 8 | |
+| |Missing Values: 9; 99 | |
+| +-----+-----------------------------------+ |
+| | 0|Zero | |
+| | 1|Unity | |
+| | 2|Duality | |
++----------+-----+-----------------------------------+--------+
+|string |My String | 2|
+| |Format: A8 | |
+| |Measure: Nominal | |
+| |Display Alignment: Left | |
+| |Display Width: 8 | |
+| |Missing Values: "this "; "that " | |
+| +-----+-----------------------------------+ |
+| | xx|foo | |
+| | yy|bar | |
++----------+-----+-----------------------------------+--------+
+|longstring|My Long String | 3|
+| |Format: A9 | |
+| |Measure: Nominal | |
+| |Display Alignment: Left | |
+| |Display Width: 9 | |
++----------+-----------------------------------------+--------+
+
+RESULT
+
+ }
+
+}
+
+sub generate_sav_file
+{
+ my $filename = shift;
+ my $tempdir = shift;
+
+ run_pspp_syntax_cmp ($tempdir, <<SYNTAX, <<RESULT);
+data list notable list /string (a8) longstring (a12) numeric (f10) date (date11) dollar (dollar8.2) datetime (datetime17)
+begin data.
+1111 One 1 1/1/1 1 1/1/1+01:01
+2222 Two 2 2/2/2 2 2/2/2+02:02
+3333 Three 3 3/3/3 3 3/3/3+03:03
+. . . . .
+5555 Five 5 5/5/5 5 5/5/5+05:05
+end data.
+
+
+variable labels string 'A Short String Variable'
+ /longstring 'A Long String Variable'
+ /numeric 'A Numeric Variable'
+ /date 'A Date Variable'
+ /dollar 'A Dollar Variable'
+ /datetime 'A Datetime Variable'.
+
+
+missing values numeric (9, 5, 999).
+
+missing values string ("3333").
+
+add value labels
+ /string '1111' 'ones' '2222' 'twos' '3333' 'threes'
+ /numeric 1 'Unity' 2 'Duality' 3 'Thripality'.
+
+variable attribute
+ variables = numeric
+ attribute=colour[1]('blue') colour[2]('pink') colour[3]('violet')
+ attribute=size('large') nationality('foreign').
+
+
+save outfile='$filename'.
+SYNTAX
+
+RESULT
+
+}
+
+
+# Test to make sure that the dictionary survives the sysfile.
+# Thanks to Rob Messer for reporting this problem
+{
+ my $tempdir = tempdir( CLEANUP => 1 );
+ my $tempfile = "$tempdir/testfile.sav";
+ my $sysfile ;
+
+ {
+ my $d = PSPP::Dict->new();
+
+ PSPP::Var->new ($d, "id",
+ (
+ fmt=>PSPP::Fmt::F,
+ width=>2,
+ decimals=>0
+ )
+ );
+
+ $sysfile = PSPP::Sysfile->new ("$tempfile", $d);
+ }
+
+ my $res = $sysfile->append_case ([3]);
+
+ ok ($res, "Dictionary survives sysfile");
+}
+
+
+# Basic reader test
+{
+ my $tempdir = tempdir( CLEANUP => 1 );
+
+ generate_sav_file ("$tempdir/in.sav", "$tempdir");
+
+ my $sf = PSPP::Reader->open ("$tempdir/in.sav");
+
+ my $dict = $sf->get_dict ();
+
+ open (MYFILE, ">$tempdir/out.txt");
+ for ($v = 0 ; $v < $dict->get_var_cnt() ; $v++)
+ {
+ my $var = $dict->get_var ($v);
+ my $name = $var->get_name ();
+ my $label = $var->get_label ();
+
+ print MYFILE "Variable $v is \"$name\", label is \"$label\"\n";
+
+ my $vl = $var->get_value_labels ();
+
+ print MYFILE "Value Labels:\n";
+ print MYFILE "$_ => $vl->{$_}\n" for keys %$vl;
+ }
+
+ while (my @c = $sf->get_next_case () )
+ {
+ for ($v = 0; $v < $dict->get_var_cnt(); $v++)
+ {
+ print MYFILE "val$v: \"$c[$v]\"\n";
+ }
+ print MYFILE "\n";
+ }
+
+ close (MYFILE);
+
+ok (compare ("$tempdir/out.txt", <<EOF), "Basic reader operation");
+Variable 0 is "string", label is "A Short String Variable"
+Value Labels:
+3333 => threes
+1111 => ones
+2222 => twos
+Variable 1 is "longstring", label is "A Long String Variable"
+Value Labels:
+Variable 2 is "numeric", label is "A Numeric Variable"
+Value Labels:
+1 => Unity
+3 => Thripality
+2 => Duality
+Variable 3 is "date", label is "A Date Variable"
+Value Labels:
+Variable 4 is "dollar", label is "A Dollar Variable"
+Value Labels:
+Variable 5 is "datetime", label is "A Datetime Variable"
+Value Labels:
+val0: "1111 "
+val1: "One "
+val2: "1"
+val3: "13197686400"
+val4: "1"
+val5: "13197690060"
+
+val0: "2222 "
+val1: "Two "
+val2: "2"
+val3: "13231987200"
+val4: "2"
+val5: "13231994520"
+
+val0: "3333 "
+val1: "Three "
+val2: "3"
+val3: "13266028800"
+val4: "3"
+val5: "13266039780"
+
+val0: ". "
+val1: ". "
+val2: ""
+val3: ""
+val4: ""
+val5: ""
+
+val0: "5555 "
+val1: "Five "
+val2: "5"
+val3: "13334630400"
+val4: "5"
+val5: "13334648700"
+
+EOF
+
+}
+
+
+# Check that we can stream one file into another
+{
+ my $tempdir = tempdir( CLEANUP => 1 );
+
+ generate_sav_file ("$tempdir/in.sav", "$tempdir");
+
+ my $input = PSPP::Reader->open ("$tempdir/in.sav");
+
+ my $dict = $input->get_dict ();
+
+ my $output = PSPP::Sysfile->new ("$tempdir/out.sav", $dict);
+
+ while (my (@c) = $input->get_next_case () )
+ {
+ $output->append_case (\@c);
+ }
+
+ $output->close ();
+
+
+ #Check the two files are the same (except for metadata)
+
+ run_pspp_syntax ($tempdir, <<SYNTAX);
+ get file='$tempdir/in.sav'.
+ display dictionary.
+ list.
+
+SYNTAX
+
+ system ("cp $tempdir/pspp.list $tempdir/in.txt");
+
+ run_pspp_syntax ($tempdir, <<SYNTAX);
+ get file='$tempdir/out.sav'.
+ display dictionary.
+ list.
+
+SYNTAX
+
+ ok (! diff ("$tempdir/pspp.list", "$tempdir/in.txt"), "Streaming of files");
+}
+
+
+
+# Check that the format_value function works properly
+{
+ my $tempdir = tempdir( CLEANUP => 1 );
+
+ run_pspp_syntax ($tempdir, <<SYNTAX);
+
+data list list /d (datetime17).
+begin data.
+11/9/2001+08:20
+end data.
+
+save outfile='$tempdir/dd.sav'.
+
+SYNTAX
+
+ my $sf = PSPP::Reader->open ("$tempdir/dd.sav");
+
+ my $dict = $sf->get_dict ();
+
+ my (@c) = $sf->get_next_case ();
+
+ my $var = $dict->get_var (0);
+ my $val = $c[0];
+ my $formatted = PSPP::format_value ($val, $var);
+ my $str = gmtime ($val - PSPP::PERL_EPOCH);
+ print "Formatted string is \"$formatted\"\n";
+ ok ( $formatted eq "11-SEP-2001 08:20", "format_value function");
+ ok ( $str eq "Tue Sep 11 08:20:00 2001", "Perl representation of time");
+}
+
+
+# Check that attempting to open a non-existent file results in an error
+{
+ my $tempdir = tempdir( CLEANUP => 1 );
+
+ unlink ("$tempdir/no-such-file.sav");
+
+ my $sf = PSPP::Reader->open ("$tempdir/no-such-file.sav");
+
+ ok ( !ref $sf, "Returns undef on opening failure");
+
+ ok ("$PSPP::errstr" eq "Error opening \"$tempdir/no-such-file.sav\" for reading as a system file: No such file or directory.",
+ "Error string on open failure");
+}
+
+
+# Missing value tests.
+{
+ my $tempdir = tempdir( CLEANUP => 1 );
+
+ generate_sav_file ("$tempdir/in.sav", "$tempdir");
+
+ my $sf = PSPP::Reader->open ("$tempdir/in.sav");
+
+ my $dict = $sf->get_dict ();
+
+
+ my (@c) = $sf->get_next_case ();
+
+ my $stringvar = $dict->get_var (0);
+ my $numericvar = $dict->get_var (2);
+ my $val = $c[0];
+
+ ok ( !PSPP::value_is_missing ($val, $stringvar), "Missing Value Negative String");
+
+ $val = $c[2];
+
+ ok ( !PSPP::value_is_missing ($val, $numericvar), "Missing Value Negative Num");
+
+ @c = $sf->get_next_case ();
+ @c = $sf->get_next_case ();
+
+ $val = $c[0];
+ ok ( PSPP::value_is_missing ($val, $stringvar), "Missing Value Positive");
+
+ @c = $sf->get_next_case ();
+ $val = $c[2];
+ ok ( PSPP::value_is_missing ($val, $numericvar), "Missing Value Positive SYS");
+
+ @c = $sf->get_next_case ();
+ $val = $c[2];
+ ok ( PSPP::value_is_missing ($val, $numericvar), "Missing Value Positive Num");
+}
+
+
+#Test reading of custom attributes
+{
+ my $tempdir = tempdir( CLEANUP => 1 );
+
+ generate_sav_file ("$tempdir/in.sav", "$tempdir");
+
+ my $sf = PSPP::Reader->open ("$tempdir/in.sav");
+
+ my $dict = $sf->get_dict ();
+
+ my $var = $dict->get_var_by_name ("numeric");
+
+ my $attr = $var->get_attributes ();
+
+ open (MYFILE, ">$tempdir/out.txt");
+
+ foreach $k (keys %$attr)
+ {
+ my $ll = $attr->{$k};
+ print MYFILE "$k =>";
+ print MYFILE map "$_\n", join ', ', @$ll;
+ }
+
+ close (MYFILE);
+
+ ok (compare ("$tempdir/out.txt", <<EOF), "Custom Attributes");
+colour =>blue, pink, violet
+nationality =>foreign
+size =>large
+EOF
+
+}
--- /dev/null
+TYPEMAP
+ struct dictionary * T_PTRREF
+ struct variable * T_PTRREF
+ struct sysfile_info * T_PTRREF
+ struct sysreader_info * T_PTRREF
+ input_format INPUT_FMT_SPEC
+ output_format OUTPUT_FMT_SPEC
+
+
+INPUT
+OUTPUT_FMT_SPEC
+ {
+ HV *hv = (HV *) SvRV ($arg);
+ SV** the_format = hv_fetch (hv, \"fmt\", 3, 0);
+ SV** decimals = hv_fetch (hv, \"decimals\", 8, 0);
+ SV** width = hv_fetch (hv, \"width\", 5, 0);
+
+ $var.type = the_format ? SvIV (*the_format) : FMT_F;
+ $var.w = width ? SvIV (*width) : 8;
+ $var.d = decimals ? SvIV (*decimals) :
+ fmt_takes_decimals ($var.type) ?
+ MIN (2, fmt_max_output_decimals ($var.type, $var.w)) : 0;
+ if ( ! fmt_check_output (&$var))
+ {
+ char buf[FMT_STRING_LEN_MAX + 1];
+ fmt_to_string (&$var, buf);
+ croak (\"%s is an invalid output format\", buf);
+ }
+
+ }
+
+
+INPUT_FMT_SPEC
+ {
+ HV *hv = (HV *) SvRV ($arg);
+ SV** the_format = hv_fetch (hv, \"fmt\", 3, 0);
+ SV** decimals = hv_fetch (hv, \"decimals\", 8, 0);
+ SV** width = hv_fetch (hv, \"width\", 5, 0);
+
+
+ $var.type = the_format ? SvIV (*the_format) : FMT_F;
+ $var.w = width ? SvIV (*width) : 8;
+ $var.d = decimals ? SvIV (*decimals) :
+ fmt_takes_decimals ($var.type) ?
+ MIN (2, fmt_max_input_decimals ($var.type, $var.w)) : 0;
+ if ( ! fmt_check_input (&$var))
+ {
+ char buf[FMT_STRING_LEN_MAX + 1];
+ fmt_to_string (&$var, buf);
+ croak (\"%s is an invalid input format\", buf);
+ }
+
+ }
msgstr ""
"Project-Id-Version: PSPP 0.7.0\n"
"Report-Msgid-Bugs-To: pspp-dev@gnu.org\n"
-"POT-Creation-Date: 2008-12-14 11:19+0900\n"
+"POT-Creation-Date: 2009-01-08 16:40+0900\n"
"PO-Revision-Date: 2008-11-05 08:17+0900\n"
"Last-Translator: John Darrington <john@darrington.wattle.id.au>\n"
"Language-Team: John Darrington <john@darrington.wattle.id.au>\n"
msgstr ""
#: src/data/format.c:327 src/data/sys-file-reader.c:655
-#: src/ui/gui/data-editor.glade:1197 src/ui/gui/psppire.glade:2176
+#: src/ui/gui/data-editor.glade:1197 src/ui/gui/psppire.glade:2136
#: src/ui/gui/psppire-var-store.c:557
msgid "String"
msgstr ""
#: src/data/format.c:327 src/data/sys-file-reader.c:655
-#: src/ui/gui/data-editor.glade:1086 src/ui/gui/psppire.glade:2131
+#: src/ui/gui/data-editor.glade:1086 src/ui/gui/psppire.glade:2211
#: src/ui/gui/psppire-var-store.c:550
msgid "Numeric"
msgstr ""
"Support for Gnumeric files was not compiled into this installation of PSPP"
msgstr ""
-#: src/data/gnumeric-reader.c:366
+#: src/data/gnumeric-reader.c:365
#, c-format
msgid "Error opening \"%s\" for reading as a gnumeric file: %s."
msgstr ""
-#: src/data/gnumeric-reader.c:386
+#: src/data/gnumeric-reader.c:385
#, c-format
msgid "Invalid cell range \"%s\""
msgstr ""
-#: src/data/gnumeric-reader.c:523 src/data/psql-reader.c:184
+#: src/data/gnumeric-reader.c:522 src/data/psql-reader.c:182
#, c-format
msgid "Cannot create variable name from %s"
msgstr ""
-#: src/data/gnumeric-reader.c:535
+#: src/data/gnumeric-reader.c:534
#, c-format
msgid "Selected sheet or range of spreadsheet \"%s\" is empty."
msgstr ""
"installation of PSPP"
msgstr ""
-#: src/data/psql-reader.c:239
+#: src/data/psql-reader.c:237
msgid "Memory error whilst opening psql source"
msgstr ""
-#: src/data/psql-reader.c:245
+#: src/data/psql-reader.c:243
#, c-format
msgid "Error opening psql source: %s."
msgstr ""
-#: src/data/psql-reader.c:260
+#: src/data/psql-reader.c:258
#, c-format
msgid ""
"Postgres server is version %s. Reading from versions earlier than 8.0 is not "
"supported."
msgstr ""
-#: src/data/psql-reader.c:280
+#: src/data/psql-reader.c:278
msgid ""
"Connection is unencrypted, but unencrypted connections have not been "
"permitted."
msgstr ""
-#: src/data/psql-reader.c:307 src/data/psql-reader.c:332
-#: src/data/psql-reader.c:342
+#: src/data/psql-reader.c:305 src/data/psql-reader.c:330
+#: src/data/psql-reader.c:340
#, c-format
msgid "Error from psql source: %s."
msgstr ""
-#: src/data/psql-reader.c:437
+#: src/data/psql-reader.c:435
#, c-format
msgid "Unsupported OID %d. SYSMIS values will be inserted."
msgstr ""
#. TRANSLATORS: this fragment will be interpolated into
#. messages in fh_lock() that identify types of files.
-#: src/data/sys-file-reader.c:214 src/data/sys-file-writer.c:196
+#: src/data/sys-file-reader.c:214 src/data/sys-file-writer.c:197
msgid "system file"
msgstr ""
msgid "Unexpected end of file."
msgstr ""
-#: src/data/sys-file-writer.c:169
+#: src/data/sys-file-writer.c:170
#, c-format
msgid "Unknown system file version %d. Treating as version %d."
msgstr ""
-#: src/data/sys-file-writer.c:208
+#: src/data/sys-file-writer.c:209
#, c-format
msgid "Error opening \"%s\" for writing as a system file: %s."
msgstr ""
-#: src/data/sys-file-writer.c:813
+#: src/data/sys-file-writer.c:814
#, c-format
msgid "An I/O error occurred writing system file \"%s\"."
msgstr ""
-#: src/data/variable.c:236
+#: src/data/variable.c:240
#, c-format
msgid ""
"Character `%c' (in %s) may not appear as the first character in a variable "
"name."
msgstr ""
-#: src/data/variable.c:248
+#: src/data/variable.c:252
#, c-format
msgid "Character `%c' (in %s) may not appear in a variable name."
msgstr ""
-#: src/data/variable.c:276
+#: src/data/variable.c:280
msgid "Variable name cannot be empty string."
msgstr ""
-#: src/data/variable.c:282
+#: src/data/variable.c:286
#, c-format
msgid "Variable name %s exceeds %d-character limit."
msgstr ""
-#: src/data/variable.c:290
+#: src/data/variable.c:294
#, c-format
msgid "`%s' may not be used as a variable name because it is a reserved word."
msgstr ""
"name."
msgstr ""
-#: src/language/data-io/combine-files.c:738
+#: src/language/data-io/combine-files.c:737
#, c-format
msgid "Encountered %zu sets of duplicate cases in the master file."
msgstr ""
msgid "Cannot place variable %s on record %d when RECORDS=%d is specified."
msgstr ""
-#: src/language/data-io/data-parser.c:455
-#: src/language/data-io/data-parser.c:464
+#: src/language/data-io/data-parser.c:458
+#: src/language/data-io/data-parser.c:467
msgid "Quoted string extends beyond end of line."
msgstr ""
-#: src/language/data-io/data-parser.c:519
+#: src/language/data-io/data-parser.c:522
#, c-format
msgid "Partial case of %d of %d records discarded."
msgstr ""
-#: src/language/data-io/data-parser.c:565
+#: src/language/data-io/data-parser.c:568
#, c-format
msgid "Partial case discarded. The first variable missing was %s."
msgstr ""
-#: src/language/data-io/data-parser.c:602
+#: src/language/data-io/data-parser.c:605
#, c-format
msgid ""
"Missing value(s) for all variables from %s onward. These will be filled "
"with the system-missing value or blanks, as appropriate."
msgstr ""
-#: src/language/data-io/data-parser.c:621
+#: src/language/data-io/data-parser.c:624
msgid "Record ends in data not part of any field."
msgstr ""
-#: src/language/data-io/data-parser.c:641
-#: src/language/data-io/data-parser.c:682 src/language/data-io/print.c:403
+#: src/language/data-io/data-parser.c:644
+#: src/language/data-io/data-parser.c:685 src/language/data-io/print.c:403
#: src/language/dictionary/split-file.c:84
#: src/language/dictionary/sys-file-info.c:162
#: src/language/dictionary/sys-file-info.c:386
#: src/language/dictionary/sys-file-info.c:709
-#: src/language/stats/descriptives.c:883 src/ui/gui/dict-display.c:245
+#: src/language/stats/descriptives.c:885 src/ui/gui/dict-display.c:245
msgid "Variable"
msgstr ""
-#: src/language/data-io/data-parser.c:642 src/language/data-io/print.c:404
+#: src/language/data-io/data-parser.c:645 src/language/data-io/print.c:404
msgid "Record"
msgstr ""
-#: src/language/data-io/data-parser.c:643 src/language/data-io/print.c:405
+#: src/language/data-io/data-parser.c:646 src/language/data-io/print.c:405
#: src/ui/gui/crosstabs.glade:92 src/ui/gui/psppire-var-sheet.c:517
#: src/ui/gui/psppire-var-store.c:770
msgid "Columns"
msgstr ""
-#: src/language/data-io/data-parser.c:644
-#: src/language/data-io/data-parser.c:683 src/language/data-io/print.c:406
+#: src/language/data-io/data-parser.c:647
+#: src/language/data-io/data-parser.c:686 src/language/data-io/print.c:406
msgid "Format"
msgstr ""
-#: src/language/data-io/data-parser.c:663
+#: src/language/data-io/data-parser.c:666
#, c-format
msgid "Reading %d record from %s."
msgid_plural "Reading %d records from %s."
msgstr[0] ""
msgstr[1] ""
-#: src/language/data-io/data-parser.c:699
+#: src/language/data-io/data-parser.c:702
#, c-format
msgid "Reading free-form data from %s."
msgstr ""
msgid "Input program did not create any variables."
msgstr ""
-#: src/language/data-io/inpt-pgm.c:287
+#: src/language/data-io/inpt-pgm.c:286
msgid "COLUMN subcommand multiply specified."
msgstr ""
-#: src/language/data-io/inpt-pgm.c:337
+#: src/language/data-io/inpt-pgm.c:336
msgid ""
"REREAD: Column numbers must be positive finite numbers. Column set to 1."
msgstr ""
msgid "`/FORMAT WEIGHT' specified, but weighting is not on."
msgstr ""
-#: src/language/data-io/list.q:467
+#: src/language/data-io/list.q:468
msgid "Line"
msgstr ""
msgstr ""
#: src/language/dictionary/missing-values.c:56
-#: src/language/stats/aggregate.c:459
+#: src/language/stats/aggregate.c:458
msgid "expecting `('"
msgstr ""
#: src/language/dictionary/split-file.c:85
#: src/language/dictionary/sys-file-info.c:480
#: src/language/dictionary/sys-file-info.c:629
-#: src/language/stats/crosstabs.q:1155 src/language/stats/crosstabs.q:1182
-#: src/language/stats/crosstabs.q:1202 src/language/stats/crosstabs.q:1224
-#: src/language/stats/examine.q:1939 src/language/stats/frequencies.q:1055
-#: src/language/stats/frequencies.q:1179 src/language/stats/reliability.q:572
+#: src/language/stats/crosstabs.q:1156 src/language/stats/crosstabs.q:1183
+#: src/language/stats/crosstabs.q:1203 src/language/stats/crosstabs.q:1225
+#: src/language/stats/examine.q:1941 src/language/stats/frequencies.q:1056
+#: src/language/stats/frequencies.q:1180 src/language/stats/reliability.q:572
#: src/language/stats/reliability.q:583
msgid "Value"
msgstr ""
#: src/language/dictionary/split-file.c:86
#: src/language/dictionary/sys-file-info.c:390
#: src/language/dictionary/sys-file-info.c:630 src/ui/gui/crosstabs.glade:275
-#: src/ui/gui/psppire.glade:2099 src/ui/gui/psppire-var-sheet.c:514
+#: src/ui/gui/psppire.glade:2101 src/ui/gui/psppire-var-sheet.c:514
#: src/ui/gui/psppire-var-store.c:767
msgid "Label"
msgstr ""
msgid "File:"
msgstr ""
-#: src/language/dictionary/sys-file-info.c:115 src/ui/gui/psppire.glade:2052
+#: src/language/dictionary/sys-file-info.c:115 src/ui/gui/psppire.glade:2040
#: src/ui/gui/recode.glade:841
msgid "Label:"
msgstr ""
msgid "Unknown identifier %s."
msgstr ""
-#: src/language/expressions/parse.c:885 src/language/stats/aggregate.c:517
+#: src/language/expressions/parse.c:885 src/language/stats/aggregate.c:516
msgid "expecting `)'"
msgstr ""
"has no effect. Output data will be sorted the same way as the input data."
msgstr ""
-#: src/language/stats/aggregate.c:424
+#: src/language/stats/aggregate.c:423
msgid "expecting aggregation function"
msgstr ""
-#: src/language/stats/aggregate.c:442
+#: src/language/stats/aggregate.c:441
#, c-format
msgid "Unknown aggregation function %s."
msgstr ""
-#: src/language/stats/aggregate.c:498
+#: src/language/stats/aggregate.c:497
#, c-format
msgid "Missing argument %zu to %s."
msgstr ""
-#: src/language/stats/aggregate.c:507
+#: src/language/stats/aggregate.c:506
#, c-format
msgid "Arguments to %s must be of same type as source variables."
msgstr ""
-#: src/language/stats/aggregate.c:529
+#: src/language/stats/aggregate.c:528
#, c-format
msgid ""
"Number of source variables (%zu) does not match number of target variables (%"
"zu)."
msgstr ""
-#: src/language/stats/aggregate.c:545
+#: src/language/stats/aggregate.c:544
#, c-format
msgid ""
"The value arguments passed to the %s function are out-of-order. They will "
"be treated as if they had been specified in the correct order."
msgstr ""
-#: src/language/stats/aggregate.c:615
+#: src/language/stats/aggregate.c:614
#, c-format
msgid ""
"Variable name %s is not unique within the aggregate file dictionary, which "
msgstr ""
#: src/language/stats/binomial.c:205 src/language/stats/chisquare.c:223
-#: src/language/stats/chisquare.c:283 src/language/stats/crosstabs.q:862
-#: src/language/stats/crosstabs.q:1062 src/language/stats/crosstabs.q:1785
-#: src/language/stats/examine.q:1198 src/language/stats/frequencies.q:1132
+#: src/language/stats/chisquare.c:283 src/language/stats/crosstabs.q:863
+#: src/language/stats/crosstabs.q:1063 src/language/stats/crosstabs.q:1786
+#: src/language/stats/examine.q:1200 src/language/stats/frequencies.q:1133
#: src/language/stats/oneway.q:304 src/language/stats/oneway.q:470
#: src/language/stats/regression.q:309 src/language/stats/reliability.q:705
-#: src/language/stats/wilcoxon.c:246 src/ui/gui/crosstabs-dialog.c:59
+#: src/language/stats/wilcoxon.c:240 src/ui/gui/crosstabs-dialog.c:59
msgid "Total"
msgstr ""
#: src/language/stats/binomial.c:237 src/language/stats/chisquare.c:246
-#: src/language/stats/crosstabs.q:1180 src/language/stats/crosstabs.q:1221
+#: src/language/stats/crosstabs.q:1181 src/language/stats/crosstabs.q:1222
msgid "Category"
msgstr ""
-#: src/language/stats/binomial.c:238 src/language/stats/crosstabs.q:872
-#: src/language/stats/examine.q:1271 src/language/stats/frequencies.q:1400
+#: src/language/stats/binomial.c:238 src/language/stats/crosstabs.q:873
+#: src/language/stats/examine.q:1273 src/language/stats/frequencies.q:1401
#: src/language/stats/npar-summary.c:122 src/language/stats/oneway.q:386
#: src/language/stats/reliability.q:708 src/language/stats/t-test.q:693
#: src/language/stats/t-test.q:716 src/language/stats/t-test.q:850
-#: src/language/stats/t-test.q:1387 src/language/stats/wilcoxon.c:229
+#: src/language/stats/t-test.q:1387 src/language/stats/wilcoxon.c:223
msgid "N"
msgstr ""
msgid "Frequencies"
msgstr ""
-#: src/language/stats/chisquare.c:297 src/language/stats/wilcoxon.c:297
+#: src/language/stats/chisquare.c:297 src/language/stats/wilcoxon.c:291
msgid "Test Statistics"
msgstr ""
msgid "Chi-Square"
msgstr ""
-#: src/language/stats/chisquare.c:312 src/language/stats/crosstabs.q:1156
+#: src/language/stats/chisquare.c:312 src/language/stats/crosstabs.q:1157
#: src/language/stats/oneway.q:277 src/language/stats/oneway.q:683
#: src/language/stats/regression.q:302 src/language/stats/t-test.q:1001
#: src/language/stats/t-test.q:1193 src/language/stats/t-test.q:1286
msgid "Maximum value (%ld) less than minimum value (%ld)."
msgstr ""
-#: src/language/stats/crosstabs.q:857
+#: src/language/stats/crosstabs.q:858
msgid "Summary."
msgstr ""
-#: src/language/stats/crosstabs.q:859 src/language/stats/examine.q:1259
+#: src/language/stats/crosstabs.q:860 src/language/stats/examine.q:1261
#: src/language/stats/reliability.q:696
msgid "Cases"
msgstr ""
-#: src/language/stats/crosstabs.q:860 src/language/stats/examine.q:1196
-#: src/language/stats/frequencies.q:1053 src/language/stats/frequencies.q:1401
+#: src/language/stats/crosstabs.q:861 src/language/stats/examine.q:1198
+#: src/language/stats/frequencies.q:1054 src/language/stats/frequencies.q:1402
#: src/language/stats/reliability.q:699
msgid "Valid"
msgstr ""
-#: src/language/stats/crosstabs.q:861 src/language/stats/examine.q:1197
-#: src/language/stats/frequencies.q:1123 src/language/stats/frequencies.q:1402
+#: src/language/stats/crosstabs.q:862 src/language/stats/examine.q:1199
+#: src/language/stats/frequencies.q:1124 src/language/stats/frequencies.q:1403
#: src/ui/gui/psppire-var-sheet.c:516 src/ui/gui/psppire-var-store.c:769
msgid "Missing"
msgstr ""
-#: src/language/stats/crosstabs.q:873 src/language/stats/examine.q:1274
-#: src/language/stats/frequencies.q:1057 src/language/stats/frequencies.q:1058
-#: src/language/stats/frequencies.q:1059
+#: src/language/stats/crosstabs.q:874 src/language/stats/examine.q:1276
+#: src/language/stats/frequencies.q:1058 src/language/stats/frequencies.q:1059
+#: src/language/stats/frequencies.q:1060
msgid "Percent"
msgstr ""
-#: src/language/stats/crosstabs.q:1114
+#: src/language/stats/crosstabs.q:1115
msgid "count"
msgstr ""
-#: src/language/stats/crosstabs.q:1115
+#: src/language/stats/crosstabs.q:1116
msgid "row %"
msgstr ""
-#: src/language/stats/crosstabs.q:1116
+#: src/language/stats/crosstabs.q:1117
msgid "column %"
msgstr ""
-#: src/language/stats/crosstabs.q:1117
+#: src/language/stats/crosstabs.q:1118
msgid "total %"
msgstr ""
-#: src/language/stats/crosstabs.q:1118
+#: src/language/stats/crosstabs.q:1119
msgid "expected"
msgstr ""
-#: src/language/stats/crosstabs.q:1119
+#: src/language/stats/crosstabs.q:1120
msgid "residual"
msgstr ""
-#: src/language/stats/crosstabs.q:1120
+#: src/language/stats/crosstabs.q:1121
msgid "std. resid."
msgstr ""
-#: src/language/stats/crosstabs.q:1121
+#: src/language/stats/crosstabs.q:1122
msgid "adj. resid."
msgstr ""
-#: src/language/stats/crosstabs.q:1151
+#: src/language/stats/crosstabs.q:1152
msgid "Chi-square tests."
msgstr ""
-#: src/language/stats/crosstabs.q:1154 src/language/stats/crosstabs.q:1181
-#: src/language/stats/crosstabs.q:1201 src/language/stats/crosstabs.q:1222
-#: src/language/stats/examine.q:1736 src/ui/gui/checkbox-treeview.c:94
+#: src/language/stats/crosstabs.q:1155 src/language/stats/crosstabs.q:1182
+#: src/language/stats/crosstabs.q:1202 src/language/stats/crosstabs.q:1223
+#: src/language/stats/examine.q:1738 src/ui/gui/checkbox-treeview.c:94
msgid "Statistic"
msgstr ""
-#: src/language/stats/crosstabs.q:1158
+#: src/language/stats/crosstabs.q:1159
msgid "Asymp. Sig. (2-sided)"
msgstr ""
-#: src/language/stats/crosstabs.q:1160
+#: src/language/stats/crosstabs.q:1161
msgid "Exact. Sig. (2-sided)"
msgstr ""
-#: src/language/stats/crosstabs.q:1162
+#: src/language/stats/crosstabs.q:1163
msgid "Exact. Sig. (1-sided)"
msgstr ""
-#: src/language/stats/crosstabs.q:1177
+#: src/language/stats/crosstabs.q:1178
msgid "Symmetric measures."
msgstr ""
-#: src/language/stats/crosstabs.q:1183 src/language/stats/crosstabs.q:1225
+#: src/language/stats/crosstabs.q:1184 src/language/stats/crosstabs.q:1226
msgid "Asymp. Std. Error"
msgstr ""
-#: src/language/stats/crosstabs.q:1184 src/language/stats/crosstabs.q:1226
+#: src/language/stats/crosstabs.q:1185 src/language/stats/crosstabs.q:1227
msgid "Approx. T"
msgstr ""
-#: src/language/stats/crosstabs.q:1185 src/language/stats/crosstabs.q:1227
+#: src/language/stats/crosstabs.q:1186 src/language/stats/crosstabs.q:1228
msgid "Approx. Sig."
msgstr ""
-#: src/language/stats/crosstabs.q:1196
+#: src/language/stats/crosstabs.q:1197
msgid "Risk estimate."
msgstr ""
-#: src/language/stats/crosstabs.q:1200
+#: src/language/stats/crosstabs.q:1201
#, c-format
msgid "95%% Confidence Interval"
msgstr ""
-#: src/language/stats/crosstabs.q:1203 src/language/stats/t-test.q:1005
+#: src/language/stats/crosstabs.q:1204 src/language/stats/t-test.q:1005
#: src/language/stats/t-test.q:1190 src/language/stats/t-test.q:1289
msgid "Lower"
msgstr ""
-#: src/language/stats/crosstabs.q:1204 src/language/stats/t-test.q:1006
+#: src/language/stats/crosstabs.q:1205 src/language/stats/t-test.q:1006
#: src/language/stats/t-test.q:1191 src/language/stats/t-test.q:1290
msgid "Upper"
msgstr ""
-#: src/language/stats/crosstabs.q:1218
+#: src/language/stats/crosstabs.q:1219
msgid "Directional measures."
msgstr ""
-#: src/language/stats/crosstabs.q:1223 src/ui/gui/psppire.glade:2223
+#: src/language/stats/crosstabs.q:1224 src/ui/gui/psppire.glade:2226
#: src/ui/gui/psppire-var-sheet.c:511 src/ui/gui/psppire-var-store.c:764
msgid "Type"
msgstr ""
-#: src/language/stats/crosstabs.q:1976
+#: src/language/stats/crosstabs.q:1977
msgid "Pearson Chi-Square"
msgstr ""
-#: src/language/stats/crosstabs.q:1977
+#: src/language/stats/crosstabs.q:1978
msgid "Likelihood Ratio"
msgstr ""
-#: src/language/stats/crosstabs.q:1978
+#: src/language/stats/crosstabs.q:1979
msgid "Fisher's Exact Test"
msgstr ""
-#: src/language/stats/crosstabs.q:1979
+#: src/language/stats/crosstabs.q:1980
msgid "Continuity Correction"
msgstr ""
-#: src/language/stats/crosstabs.q:1980
+#: src/language/stats/crosstabs.q:1981
msgid "Linear-by-Linear Association"
msgstr ""
-#: src/language/stats/crosstabs.q:2017 src/language/stats/crosstabs.q:2087
-#: src/language/stats/crosstabs.q:2146
+#: src/language/stats/crosstabs.q:2018 src/language/stats/crosstabs.q:2088
+#: src/language/stats/crosstabs.q:2147
msgid "N of Valid Cases"
msgstr ""
-#: src/language/stats/crosstabs.q:2033 src/language/stats/crosstabs.q:2162
+#: src/language/stats/crosstabs.q:2034 src/language/stats/crosstabs.q:2163
msgid "Nominal by Nominal"
msgstr ""
-#: src/language/stats/crosstabs.q:2034 src/language/stats/crosstabs.q:2163
+#: src/language/stats/crosstabs.q:2035 src/language/stats/crosstabs.q:2164
msgid "Ordinal by Ordinal"
msgstr ""
-#: src/language/stats/crosstabs.q:2035
+#: src/language/stats/crosstabs.q:2036
msgid "Interval by Interval"
msgstr ""
-#: src/language/stats/crosstabs.q:2036
+#: src/language/stats/crosstabs.q:2037
msgid "Measure of Agreement"
msgstr ""
-#: src/language/stats/crosstabs.q:2041 src/ui/gui/crosstabs-dialog.c:41
+#: src/language/stats/crosstabs.q:2042 src/ui/gui/crosstabs-dialog.c:41
msgid "Phi"
msgstr ""
-#: src/language/stats/crosstabs.q:2042
+#: src/language/stats/crosstabs.q:2043
msgid "Cramer's V"
msgstr ""
-#: src/language/stats/crosstabs.q:2043
+#: src/language/stats/crosstabs.q:2044
msgid "Contingency Coefficient"
msgstr ""
-#: src/language/stats/crosstabs.q:2044
+#: src/language/stats/crosstabs.q:2045
msgid "Kendall's tau-b"
msgstr ""
-#: src/language/stats/crosstabs.q:2045
+#: src/language/stats/crosstabs.q:2046
msgid "Kendall's tau-c"
msgstr ""
-#: src/language/stats/crosstabs.q:2046 src/ui/gui/crosstabs-dialog.c:48
+#: src/language/stats/crosstabs.q:2047 src/ui/gui/crosstabs-dialog.c:48
msgid "Gamma"
msgstr ""
-#: src/language/stats/crosstabs.q:2047
+#: src/language/stats/crosstabs.q:2048
msgid "Spearman Correlation"
msgstr ""
-#: src/language/stats/crosstabs.q:2048
+#: src/language/stats/crosstabs.q:2049
msgid "Pearson's R"
msgstr ""
-#: src/language/stats/crosstabs.q:2049 src/ui/gui/crosstabs-dialog.c:50
+#: src/language/stats/crosstabs.q:2050 src/ui/gui/crosstabs-dialog.c:50
msgid "Kappa"
msgstr ""
-#: src/language/stats/crosstabs.q:2119
+#: src/language/stats/crosstabs.q:2120
#, c-format
msgid "Odds Ratio for %s (%g / %g)"
msgstr ""
-#: src/language/stats/crosstabs.q:2122
+#: src/language/stats/crosstabs.q:2123
#, c-format
msgid "Odds Ratio for %s (%.*s / %.*s)"
msgstr ""
-#: src/language/stats/crosstabs.q:2130
+#: src/language/stats/crosstabs.q:2131
#, c-format
msgid "For cohort %s = %g"
msgstr ""
-#: src/language/stats/crosstabs.q:2133
+#: src/language/stats/crosstabs.q:2134
#, c-format
msgid "For cohort %s = %.*s"
msgstr ""
-#: src/language/stats/crosstabs.q:2164
+#: src/language/stats/crosstabs.q:2165
msgid "Nominal by Interval"
msgstr ""
-#: src/language/stats/crosstabs.q:2169 src/ui/gui/crosstabs-dialog.c:43
+#: src/language/stats/crosstabs.q:2170 src/ui/gui/crosstabs-dialog.c:43
msgid "Lambda"
msgstr ""
-#: src/language/stats/crosstabs.q:2170
+#: src/language/stats/crosstabs.q:2171
msgid "Goodman and Kruskal tau"
msgstr ""
-#: src/language/stats/crosstabs.q:2171
+#: src/language/stats/crosstabs.q:2172
msgid "Uncertainty Coefficient"
msgstr ""
-#: src/language/stats/crosstabs.q:2172
+#: src/language/stats/crosstabs.q:2173
msgid "Somers' d"
msgstr ""
-#: src/language/stats/crosstabs.q:2173 src/ui/gui/crosstabs-dialog.c:51
+#: src/language/stats/crosstabs.q:2174 src/ui/gui/crosstabs-dialog.c:51
msgid "Eta"
msgstr ""
-#: src/language/stats/crosstabs.q:2178
+#: src/language/stats/crosstabs.q:2179
msgid "Symmetric"
msgstr ""
-#: src/language/stats/crosstabs.q:2179 src/language/stats/crosstabs.q:2180
+#: src/language/stats/crosstabs.q:2180 src/language/stats/crosstabs.q:2181
#, c-format
msgid "%s Dependent"
msgstr ""
-#: src/language/stats/descriptives.c:102 src/language/stats/examine.q:1541
+#: src/language/stats/descriptives.c:102 src/language/stats/examine.q:1543
#: src/language/stats/frequencies.q:123 src/language/stats/npar-summary.c:125
#: src/language/stats/oneway.q:387 src/language/stats/t-test.q:694
#: src/language/stats/t-test.q:717 src/language/stats/t-test.q:849
msgid "Std Dev"
msgstr ""
-#: src/language/stats/descriptives.c:105 src/language/stats/examine.q:1572
+#: src/language/stats/descriptives.c:105 src/language/stats/examine.q:1574
#: src/language/stats/frequencies.q:128 src/ui/gui/descriptives-dialog.c:46
#: src/ui/gui/frequencies-dialog.c:45
msgid "Variance"
msgstr ""
-#: src/language/stats/descriptives.c:106 src/language/stats/examine.q:1608
+#: src/language/stats/descriptives.c:106 src/language/stats/examine.q:1610
#: src/language/stats/frequencies.q:129 src/ui/gui/descriptives-dialog.c:47
#: src/ui/gui/frequencies-dialog.c:50
msgid "Kurtosis"
msgid "S E Kurt"
msgstr ""
-#: src/language/stats/descriptives.c:108 src/language/stats/examine.q:1603
+#: src/language/stats/descriptives.c:108 src/language/stats/examine.q:1605
#: src/language/stats/frequencies.q:131 src/ui/gui/descriptives-dialog.c:48
#: src/ui/gui/frequencies-dialog.c:46
msgid "Skewness"
msgid "S E Skew"
msgstr ""
-#: src/language/stats/descriptives.c:110 src/language/stats/examine.q:1592
+#: src/language/stats/descriptives.c:110 src/language/stats/examine.q:1594
#: src/language/stats/frequencies.q:133 src/ui/gui/descriptives-dialog.c:43
#: src/ui/gui/frequencies-dialog.c:48
msgid "Range"
msgstr ""
-#: src/language/stats/descriptives.c:111 src/language/stats/examine.q:1582
+#: src/language/stats/descriptives.c:111 src/language/stats/examine.q:1584
#: src/language/stats/frequencies.q:134 src/language/stats/npar-summary.c:131
#: src/language/stats/oneway.q:400 src/ui/gui/descriptives-dialog.c:41
#: src/ui/gui/frequencies-dialog.c:42
msgid "Minimum"
msgstr ""
-#: src/language/stats/descriptives.c:112 src/language/stats/examine.q:1587
+#: src/language/stats/descriptives.c:112 src/language/stats/examine.q:1589
#: src/language/stats/frequencies.q:135 src/language/stats/npar-summary.c:134
#: src/language/stats/oneway.q:401 src/ui/gui/descriptives-dialog.c:42
#: src/ui/gui/frequencies-dialog.c:43
msgid "Target"
msgstr ""
-#: src/language/stats/descriptives.c:672
+#: src/language/stats/descriptives.c:673
#, c-format
msgid "Z-score of %s"
msgstr ""
-#: src/language/stats/descriptives.c:886
+#: src/language/stats/descriptives.c:888
msgid "Valid N"
msgstr ""
-#: src/language/stats/descriptives.c:887
+#: src/language/stats/descriptives.c:889
msgid "Missing N"
msgstr ""
-#: src/language/stats/descriptives.c:914
+#: src/language/stats/descriptives.c:916
#, c-format
msgid "Valid cases = %g; cases with missing value(s) = %g."
msgstr ""
#: src/language/stats/examine.q:337 src/language/stats/examine.q:490
-#: src/language/stats/examine.q:1047
+#: src/language/stats/examine.q:1048
msgid "Not creating plot because data set is empty."
msgstr ""
msgid "%s and %s are mutually exclusive"
msgstr ""
-#: src/language/stats/examine.q:1254 src/language/stats/reliability.q:673
+#: src/language/stats/examine.q:1256 src/language/stats/reliability.q:673
msgid "Case Processing Summary"
msgstr ""
-#: src/language/stats/examine.q:1546 src/language/stats/oneway.q:395
+#: src/language/stats/examine.q:1548 src/language/stats/oneway.q:395
#, c-format
msgid "%g%% Confidence Interval for Mean"
msgstr ""
-#: src/language/stats/examine.q:1552 src/language/stats/oneway.q:397
+#: src/language/stats/examine.q:1554 src/language/stats/oneway.q:397
msgid "Lower Bound"
msgstr ""
-#: src/language/stats/examine.q:1557 src/language/stats/oneway.q:398
+#: src/language/stats/examine.q:1559 src/language/stats/oneway.q:398
msgid "Upper Bound"
msgstr ""
-#: src/language/stats/examine.q:1562
+#: src/language/stats/examine.q:1564
#, c-format
msgid "5%% Trimmed Mean"
msgstr ""
-#: src/language/stats/examine.q:1567 src/language/stats/frequencies.q:125
+#: src/language/stats/examine.q:1569 src/language/stats/frequencies.q:125
#: src/ui/gui/frequencies-dialog.c:52
msgid "Median"
msgstr ""
-#: src/language/stats/examine.q:1577 src/language/stats/npar-summary.c:128
+#: src/language/stats/examine.q:1579 src/language/stats/npar-summary.c:128
#: src/language/stats/oneway.q:388 src/language/stats/t-test.q:695
#: src/language/stats/t-test.q:718 src/language/stats/t-test.q:851
#: src/language/stats/t-test.q:1188
msgid "Std. Deviation"
msgstr ""
-#: src/language/stats/examine.q:1597
+#: src/language/stats/examine.q:1599
msgid "Interquartile Range"
msgstr ""
-#: src/language/stats/examine.q:1733 src/language/stats/oneway.q:404
-#: src/ui/gui/examine.glade:307
+#: src/language/stats/examine.q:1735 src/language/stats/oneway.q:404
+#: src/ui/gui/examine.glade:310
msgid "Descriptives"
msgstr ""
-#: src/language/stats/examine.q:1739 src/language/stats/oneway.q:389
+#: src/language/stats/examine.q:1741 src/language/stats/oneway.q:389
#: src/language/stats/oneway.q:681 src/language/stats/regression.q:203
msgid "Std. Error"
msgstr ""
-#: src/language/stats/examine.q:1836 src/language/stats/examine.q:1841
+#: src/language/stats/examine.q:1838 src/language/stats/examine.q:1843
#: src/ui/gui/psppire-data-store.c:749 src/ui/gui/psppire-var-store.c:627
#: src/ui/gui/psppire-var-store.c:637 src/ui/gui/psppire-var-store.c:647
#: src/ui/gui/psppire-var-store.c:756
msgid "%d"
msgstr ""
-#: src/language/stats/examine.q:1919
+#: src/language/stats/examine.q:1921
msgid "Highest"
msgstr ""
-#: src/language/stats/examine.q:1924
+#: src/language/stats/examine.q:1926
msgid "Lowest"
msgstr ""
-#: src/language/stats/examine.q:1931
+#: src/language/stats/examine.q:1933
msgid "Extreme Values"
msgstr ""
-#: src/language/stats/examine.q:1935
+#: src/language/stats/examine.q:1937
msgid "Case Number"
msgstr ""
-#: src/language/stats/examine.q:2057
+#: src/language/stats/examine.q:2059
msgid "Tukey's Hinges"
msgstr ""
-#: src/language/stats/examine.q:2097 src/language/stats/examine.q:2115
-#: src/language/stats/frequencies.q:1412 src/language/stats/npar-summary.c:141
-#: src/ui/gui/examine.glade:328
+#: src/language/stats/examine.q:2099 src/language/stats/examine.q:2117
+#: src/language/stats/frequencies.q:1413 src/language/stats/npar-summary.c:141
+#: src/ui/gui/examine.glade:333
msgid "Percentiles"
msgstr ""
-#: src/language/stats/examine.q:2104
+#: src/language/stats/examine.q:2106
#, c-format
msgid "%g"
msgstr ""
msgid "Error rewinding FLIP source file: %s."
msgstr ""
-#: src/language/stats/flip.c:488
+#: src/language/stats/flip.c:487
#, c-format
msgid "Error reading FLIP temporary file: %s."
msgstr ""
-#: src/language/stats/flip.c:491
+#: src/language/stats/flip.c:490
msgid "Unexpected end of file reading FLIP temporary file."
msgstr ""
"MIN was specified as %g and MAX as %g. MIN and MAX will be ignored."
msgstr ""
-#: src/language/stats/frequencies.q:754
+#: src/language/stats/frequencies.q:755
#, c-format
msgid "Variable %s specified multiple times on VARIABLES subcommand."
msgstr ""
-#: src/language/stats/frequencies.q:817
+#: src/language/stats/frequencies.q:818
msgid "`)' expected after GROUPED interval list."
msgstr ""
-#: src/language/stats/frequencies.q:829
+#: src/language/stats/frequencies.q:830
#, c-format
msgid "Variables %s specified on GROUPED but not on VARIABLES."
msgstr ""
-#: src/language/stats/frequencies.q:836
+#: src/language/stats/frequencies.q:837
#, c-format
msgid "Variables %s specified multiple times on GROUPED subcommand."
msgstr ""
-#: src/language/stats/frequencies.q:1054 src/language/stats/frequencies.q:1147
-#: src/language/stats/frequencies.q:1148 src/language/stats/frequencies.q:1182
+#: src/language/stats/frequencies.q:1055 src/language/stats/frequencies.q:1148
+#: src/language/stats/frequencies.q:1149 src/language/stats/frequencies.q:1183
msgid "Cum"
msgstr ""
-#: src/language/stats/frequencies.q:1056 src/output/charts/plot-hist.c:140
+#: src/language/stats/frequencies.q:1057 src/output/charts/plot-hist.c:140
msgid "Frequency"
msgstr ""
-#: src/language/stats/frequencies.q:1077
+#: src/language/stats/frequencies.q:1078
msgid "Value Label"
msgstr ""
-#: src/language/stats/frequencies.q:1180
+#: src/language/stats/frequencies.q:1181
msgid "Freq"
msgstr ""
-#: src/language/stats/frequencies.q:1181 src/language/stats/frequencies.q:1183
+#: src/language/stats/frequencies.q:1182 src/language/stats/frequencies.q:1184
msgid "Pct"
msgstr ""
-#: src/language/stats/frequencies.q:1374
+#: src/language/stats/frequencies.q:1375
#, c-format
msgid "No valid data for variable %s; statistics not displayed."
msgstr ""
-#: src/language/stats/frequencies.q:1416
+#: src/language/stats/frequencies.q:1417
msgid "50 (Median)"
msgstr ""
msgid "Multivariate GLM not yet supported"
msgstr ""
-#: src/language/stats/glm.q:261 src/language/stats/regression.q:994
+#: src/language/stats/glm.q:262 src/language/stats/regression.q:996
msgid "No valid data found. This command was skipped."
msgstr ""
msgid "%s of %s"
msgstr ""
-#: src/language/stats/rank.q:599
+#: src/language/stats/rank.q:601
msgid "Cannot create new rank variable. All candidates in use."
msgstr ""
-#: src/language/stats/rank.q:692
+#: src/language/stats/rank.q:694
msgid "Variables Created By RANK"
msgstr ""
-#: src/language/stats/rank.q:716
+#: src/language/stats/rank.q:718
#, c-format
msgid "%s into %s(%s of %s using %s BY %s)"
msgstr ""
-#: src/language/stats/rank.q:727
+#: src/language/stats/rank.q:729
#, c-format
msgid "%s into %s(%s of %s BY %s)"
msgstr ""
-#: src/language/stats/rank.q:741
+#: src/language/stats/rank.q:743
#, c-format
msgid "%s into %s(%s of %s using %s)"
msgstr ""
-#: src/language/stats/rank.q:751
+#: src/language/stats/rank.q:753
#, c-format
msgid "%s into %s(%s of %s)"
msgstr ""
-#: src/language/stats/rank.q:764
+#: src/language/stats/rank.q:766
msgid ""
"FRACTION has been specified, but NORMAL and PROPORTION rank functions have "
"not been requested. The FRACTION subcommand will be ignored."
msgstr ""
-#: src/language/stats/rank.q:855
+#: src/language/stats/rank.q:857
#, c-format
msgid "Variable %s already exists."
msgstr ""
-#: src/language/stats/rank.q:860
+#: src/language/stats/rank.q:862
msgid "Too many variables in INTO clause."
msgstr ""
msgid "Coefficient Correlations"
msgstr ""
-#: src/language/stats/regression.q:807
+#: src/language/stats/regression.q:808
msgid ""
"The dependent variable is equal to the independent variable.The least "
"squares line is therefore Y=X.Standard errors and related statistics may be "
"meaningless."
msgstr ""
-#: src/language/stats/regression.q:898
+#: src/language/stats/regression.q:900
msgid "Dependent variable must be numeric."
msgstr ""
msgid "%s & %s"
msgstr ""
-#: src/language/stats/wilcoxon.c:216
+#: src/language/stats/wilcoxon.c:210
msgid "Ranks"
msgstr ""
-#: src/language/stats/wilcoxon.c:230
+#: src/language/stats/wilcoxon.c:224
msgid "Mean Rank"
msgstr ""
-#: src/language/stats/wilcoxon.c:231
+#: src/language/stats/wilcoxon.c:225
msgid "Sum of Ranks"
msgstr ""
-#: src/language/stats/wilcoxon.c:243
+#: src/language/stats/wilcoxon.c:237
msgid "Negative Ranks"
msgstr ""
-#: src/language/stats/wilcoxon.c:244
+#: src/language/stats/wilcoxon.c:238
msgid "Positive Ranks"
msgstr ""
-#: src/language/stats/wilcoxon.c:245
+#: src/language/stats/wilcoxon.c:239
msgid "Ties"
msgstr ""
-#: src/language/stats/wilcoxon.c:310
+#: src/language/stats/wilcoxon.c:304
msgid "Z"
msgstr ""
-#: src/language/stats/wilcoxon.c:311
+#: src/language/stats/wilcoxon.c:305
msgid "Asymp. Sig (2-tailed)"
msgstr ""
-#: src/language/stats/wilcoxon.c:315
+#: src/language/stats/wilcoxon.c:309
msgid "Exact Sig (2-tailed)"
msgstr ""
-#: src/language/stats/wilcoxon.c:316
+#: src/language/stats/wilcoxon.c:310
msgid "Exact Sig (1-tailed)"
msgstr ""
-#: src/language/stats/wilcoxon.c:319
+#: src/language/stats/wilcoxon.c:313
msgid "Point Probability"
msgstr ""
-#: src/language/stats/wilcoxon.c:358
+#: src/language/stats/wilcoxon.c:352
#, c-format
msgid ""
"Exact significance was not calculated after %.2f minutes. Skipping test."
msgid "Only USE ALL is currently implemented."
msgstr ""
-#: src/language/utilities/include.c:90
+#: src/language/utilities/include.c:92
msgid "Expecting BATCH or INTERACTIVE after SYNTAX."
msgstr ""
-#: src/language/utilities/include.c:107
+#: src/language/utilities/include.c:109
msgid "Expecting YES or NO after CD."
msgstr ""
-#: src/language/utilities/include.c:124
+#: src/language/utilities/include.c:126
msgid "Expecting CONTINUE or STOP after ERROR."
msgstr ""
-#: src/language/utilities/include.c:131
+#: src/language/utilities/include.c:133
#, c-format
msgid "Unexpected token: `%s'."
msgstr ""
-#: src/language/utilities/include.c:176
+#: src/language/utilities/include.c:178
msgid "expecting file name"
msgstr ""
-#: src/language/utilities/include.c:188
+#: src/language/utilities/include.c:190
#, c-format
msgid "Can't find `%s' in include file search path."
msgstr ""
+#: src/language/utilities/include.c:198
+#, c-format
+msgid "Unable to open `%s': %s."
+msgstr ""
+
#: src/language/utilities/permissions.c:73
#, c-format
msgid "Expecting %s or %s."
msgid " (Entered %s)"
msgstr ""
-#: src/language/xforms/compute.c:146 src/language/xforms/compute.c:194
+#: src/language/xforms/compute.c:149 src/language/xforms/compute.c:203
#, c-format
msgid ""
"When executing COMPUTE: SYSMIS is not a valid value as an index into vector %"
"s."
msgstr ""
-#: src/language/xforms/compute.c:150 src/language/xforms/compute.c:201
+#: src/language/xforms/compute.c:153 src/language/xforms/compute.c:210
#, c-format
msgid ""
"When executing COMPUTE: %g is not a valid value as an index into vector %s."
msgstr ""
-#: src/language/xforms/compute.c:344
+#: src/language/xforms/compute.c:354
#, c-format
msgid "There is no vector named %s."
msgstr ""
msgid "unknown configuration parameter `%s' for HTML device driver"
msgstr ""
-#: src/output/journal.c:68
+#: src/output/journal.c:69
#, c-format
msgid "error writing \"%s\""
msgstr ""
-#: src/output/journal.c:90
+#: src/output/journal.c:94
#, c-format
msgid "error creating \"%s\""
msgstr ""
msgid "reading \"%s\""
msgstr ""
-#: src/output/output.c:332 src/ui/gui/message-dialog.c:96
+#: src/output/output.c:332 src/ui/gui/message-dialog.c:95
#, c-format
msgid "syntax error"
msgstr ""
"bad box: (%d+%d=%d,%d+%d=%d)-(%d+%d=%d,%d+%d=%d) in table size (%d,%d)\n"
msgstr ""
-#: src/ui/gui/comments-dialog.c:58
+#: src/ui/gui/comments-dialog.c:57
#, c-format
msgid "Column Number: %d"
msgstr ""
msgid "Format..."
msgstr ""
-#: src/ui/gui/crosstabs.glade:138 src/ui/gui/examine.glade:246
+#: src/ui/gui/crosstabs.glade:138 src/ui/gui/examine.glade:247
#: src/ui/gui/regression.glade:31
msgid "Statistics..."
msgstr ""
msgid "Pivot"
msgstr ""
-#: src/ui/gui/crosstabs.glade:253 src/ui/gui/psppire.glade:778
+#: src/ui/gui/crosstabs.glade:253 src/ui/gui/psppire.glade:781
msgid "Ascending"
msgstr ""
msgid "Save As"
msgstr ""
-#: src/ui/gui/data-editor.c:1269 src/ui/gui/recode-dialog.c:928
-#: src/ui/gui/recode-dialog.c:1023
+#: src/ui/gui/data-editor.c:1269 src/ui/gui/recode-dialog.c:927
+#: src/ui/gui/recode-dialog.c:1022
msgid "New"
msgstr ""
msgid "Value Label:"
msgstr ""
-#: src/ui/gui/data-editor.glade:1570 src/ui/gui/psppire.glade:2544
+#: src/ui/gui/data-editor.glade:1570 src/ui/gui/psppire.glade:2548
#: src/ui/gui/recode.glade:185
msgid "Value:"
msgstr ""
-#: src/ui/gui/data-editor.glade:1707 src/ui/gui/examine.glade:423
+#: src/ui/gui/data-editor.glade:1707 src/ui/gui/examine.glade:432
#: src/ui/gui/t-test.glade:460
msgid "Missing Values"
msgstr ""
msgid "Options:"
msgstr ""
-#: src/ui/gui/examine.glade:132
-msgid "Dependent List:"
+#: src/ui/gui/examine.glade:49
+msgid "Label Cases by:"
msgstr ""
-#: src/ui/gui/examine.glade:180
+#: src/ui/gui/examine.glade:100
msgid "Factor List:"
msgstr ""
-#: src/ui/gui/examine.glade:218
-msgid "Label Cases by:"
+#: src/ui/gui/examine.glade:150
+msgid "Dependent List:"
msgstr ""
-#: src/ui/gui/examine.glade:255 src/ui/gui/t-test.glade:69
+#: src/ui/gui/examine.glade:257 src/ui/gui/t-test.glade:69
#: src/ui/gui/t-test.glade:629 src/ui/gui/t-test.glade:780
msgid "Options..."
msgstr ""
-#: src/ui/gui/examine.glade:316
+#: src/ui/gui/examine.glade:320
msgid "Extremes"
msgstr ""
-#: src/ui/gui/examine.glade:382
+#: src/ui/gui/examine.glade:388
msgid "Exclude cases listwise"
msgstr ""
-#: src/ui/gui/examine.glade:392
+#: src/ui/gui/examine.glade:399
msgid "Exclude cases pairwise"
msgstr ""
-#: src/ui/gui/examine.glade:406
+#: src/ui/gui/examine.glade:414
msgid "Repeat values"
msgstr ""
-#: src/ui/gui/find-dialog.c:659
+#: src/ui/gui/find-dialog.c:658
#, c-format
msgid "Bad regular expression: %s"
msgstr ""
msgid "Standard error of the kurtosis"
msgstr ""
-#: src/ui/gui/frequencies.glade:98 src/ui/gui/psppire.glade:265
-#: src/ui/gui/rank.glade:67
+#: src/ui/gui/frequencies.glade:98 src/ui/gui/psppire.glade:277
+#: src/ui/gui/rank.glade:103
msgid "Variable(s):"
msgstr ""
msgid "Maximum no of categories"
msgstr ""
-#: src/ui/gui/helper.c:139
+#: src/ui/gui/helper.c:161
msgid "Sorry. The help system hasn't yet been implemented."
msgstr ""
-#: src/ui/gui/helper.c:165
+#: src/ui/gui/helper.c:187
#, c-format
msgid "Cannot open reference manual: %s"
msgstr ""
msgid "Options affecting syntax and behavior:"
msgstr "Options affecting syntax and behaviour:"
-#: src/ui/gui/message-dialog.c:100
+#: src/ui/gui/message-dialog.c:99
msgid "data file error"
msgstr ""
-#: src/ui/gui/message-dialog.c:105
+#: src/ui/gui/message-dialog.c:104
msgid "PSPP error"
msgstr ""
-#: src/ui/gui/message-dialog.c:113
+#: src/ui/gui/message-dialog.c:112
msgid "syntax warning"
msgstr ""
-#: src/ui/gui/message-dialog.c:117
+#: src/ui/gui/message-dialog.c:116
msgid "data file warning"
msgstr ""
-#: src/ui/gui/message-dialog.c:122
+#: src/ui/gui/message-dialog.c:121
msgid "PSPP warning"
msgstr ""
-#: src/ui/gui/message-dialog.c:131
+#: src/ui/gui/message-dialog.c:130
msgid "syntax information"
msgstr ""
-#: src/ui/gui/message-dialog.c:135
+#: src/ui/gui/message-dialog.c:134
msgid "data file information"
msgstr ""
-#: src/ui/gui/message-dialog.c:140
+#: src/ui/gui/message-dialog.c:139
msgid "PSPP information"
msgstr ""
-#: src/ui/gui/message-dialog.c:216
+#: src/ui/gui/message-dialog.c:215
msgid "The PSPP processing engine reported the following message:"
msgid_plural "The PSPP processing engine reported the following messages:"
msgstr[0] ""
msgstr[1] ""
-#: src/ui/gui/message-dialog.c:223
+#: src/ui/gui/message-dialog.c:222
#, c-format
msgid "The PSPP processing engine reported %d message."
msgid_plural "The PSPP processing engine reported %d messages."
msgstr[0] ""
msgstr[1] ""
-#: src/ui/gui/message-dialog.c:230
+#: src/ui/gui/message-dialog.c:229
#, c-format
msgid "%d of these messages are displayed below."
msgid_plural "%d of these messages are displayed below."
msgid "Paste"
msgstr ""
-#: src/ui/gui/psppire.c:214
+#: src/ui/gui/psppire.c:226
msgid "_Reset"
msgstr ""
-#: src/ui/gui/psppire.c:215
+#: src/ui/gui/psppire.c:227
msgid "_Select"
msgstr ""
-#: src/ui/gui/psppire.c:251
+#: src/ui/gui/psppire.c:263
#, c-format
msgid "Cannot open %s: %s.\n"
msgstr ""
-#: src/ui/gui/psppire.c:268
+#: src/ui/gui/psppire.c:280
#, c-format
msgid "%s is neither a system nor portable file"
msgstr ""
msgid "var"
msgstr ""
-#: src/ui/gui/psppire.glade:11
+#: src/ui/gui/psppire.glade:10
msgid ""
"This is beta status software. Please report bugs to bug-gnu-pspp@gnu.org"
msgstr ""
-#: src/ui/gui/psppire.glade:73 src/ui/gui/psppire.glade:154
-#: src/ui/gui/weight-cases-dialog.c:80
+#: src/ui/gui/psppire.glade:72 src/ui/gui/psppire.glade:155
+#: src/ui/gui/weight-cases-dialog.c:79
msgid "Do not weight cases"
msgstr ""
msgid "Weight cases by"
msgstr ""
-#: src/ui/gui/psppire.glade:107
+#: src/ui/gui/psppire.glade:108
msgid "Frequency Variable"
msgstr ""
-#: src/ui/gui/psppire.glade:147
+#: src/ui/gui/psppire.glade:148
msgid "Current Status: "
msgstr ""
-#: src/ui/gui/psppire.glade:314
+#: src/ui/gui/psppire.glade:244
msgid "Name Variable:"
msgstr ""
msgid "Analyze all cases. Do not create groups."
msgstr "Analyse all cases. Do not create groups."
-#: src/ui/gui/psppire.glade:439
+#: src/ui/gui/psppire.glade:440
msgid "Compare groups."
msgstr ""
-#: src/ui/gui/psppire.glade:452
+#: src/ui/gui/psppire.glade:454
msgid "Organize output by groups."
msgstr "Organise output by groups."
-#: src/ui/gui/psppire.glade:499
+#: src/ui/gui/psppire.glade:502
msgid "Groups based on:"
msgstr ""
-#: src/ui/gui/psppire.glade:563
+#: src/ui/gui/psppire.glade:565
msgid "Sort the file by grouping variables."
msgstr ""
-#: src/ui/gui/psppire.glade:574
+#: src/ui/gui/psppire.glade:577
msgid "File is already sorted."
msgstr ""
-#: src/ui/gui/psppire.glade:618
+#: src/ui/gui/psppire.glade:622
msgid "Current Status : "
msgstr ""
-#: src/ui/gui/psppire.glade:626
+#: src/ui/gui/psppire.glade:630
msgid "Analysis by groups is off"
msgstr ""
-#: src/ui/gui/psppire.glade:725
+#: src/ui/gui/psppire.glade:729
msgid "Sort by:"
msgstr ""
-#: src/ui/gui/psppire.glade:788
+#: src/ui/gui/psppire.glade:792
msgid "Descending"
msgstr ""
-#: src/ui/gui/psppire.glade:804
+#: src/ui/gui/psppire.glade:809
msgid "Sort Order"
msgstr ""
-#: src/ui/gui/psppire.glade:873
+#: src/ui/gui/psppire.glade:878
msgid "Target Variable:"
msgstr ""
-#: src/ui/gui/psppire.glade:904
+#: src/ui/gui/psppire.glade:909
msgid "Type & Label"
msgstr ""
-#: src/ui/gui/psppire.glade:943
+#: src/ui/gui/psppire.glade:949
msgid "="
msgstr ""
-#: src/ui/gui/psppire.glade:989
+#: src/ui/gui/psppire.glade:995
msgid "Numeric Expressions:"
msgstr ""
-#: src/ui/gui/psppire.glade:1043
+#: src/ui/gui/psppire.glade:1049
msgid "Functions:"
msgstr ""
-#: src/ui/gui/psppire.glade:1107 src/ui/gui/psppire.glade:1253
+#: src/ui/gui/psppire.glade:1112 src/ui/gui/psppire.glade:1516
#: src/ui/gui/recode.glade:731
msgid "If..."
msgstr ""
-#: src/ui/gui/psppire.glade:1223
-msgid "All Cases"
+#: src/ui/gui/psppire.glade:1345
+msgid "Use filter variable"
msgstr ""
-#: src/ui/gui/psppire.glade:1239
-msgid "If condition is satisfied"
+#: src/ui/gui/psppire.glade:1398
+msgid "Based on time or case range"
msgstr ""
-#: src/ui/gui/psppire.glade:1291
-msgid "Random sample of cases"
+#: src/ui/gui/psppire.glade:1411
+msgid "Range..."
msgstr ""
-#: src/ui/gui/psppire.glade:1305
-msgid "Sample..."
+#: src/ui/gui/psppire.glade:1450
+msgid "Random sample of cases"
msgstr ""
-#: src/ui/gui/psppire.glade:1343
-msgid "Based on time or case range"
+#: src/ui/gui/psppire.glade:1464
+msgid "Sample..."
msgstr ""
-#: src/ui/gui/psppire.glade:1356
-msgid "Range..."
+#: src/ui/gui/psppire.glade:1502
+msgid "If condition is satisfied"
msgstr ""
-#: src/ui/gui/psppire.glade:1394
-msgid "Use filter variable"
+#: src/ui/gui/psppire.glade:1551
+msgid "All Cases"
msgstr ""
-#: src/ui/gui/psppire.glade:1556
+#: src/ui/gui/psppire.glade:1566
msgid "Select"
msgstr ""
-#: src/ui/gui/psppire.glade:1586
+#: src/ui/gui/psppire.glade:1595
msgid "Filtered"
msgstr ""
-#: src/ui/gui/psppire.glade:1596
+#: src/ui/gui/psppire.glade:1606
msgid "Deleted"
msgstr ""
-#: src/ui/gui/psppire.glade:1613
+#: src/ui/gui/psppire.glade:1624
msgid "Unselected Cases Are"
msgstr ""
-#: src/ui/gui/psppire.glade:1678
+#: src/ui/gui/psppire.glade:1689
msgid "Comments:"
msgstr ""
-#: src/ui/gui/psppire.glade:1720
+#: src/ui/gui/psppire.glade:1731
msgid "Display comments in output"
msgstr ""
-#: src/ui/gui/psppire.glade:1734
+#: src/ui/gui/psppire.glade:1746
msgid "Column Number: 0"
msgstr ""
-#: src/ui/gui/psppire.glade:1810
+#: src/ui/gui/psppire.glade:1822
msgid "Variable Information:"
msgstr ""
-#: src/ui/gui/psppire.glade:1836
-msgid ""
-"\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"\n"
-msgstr ""
-
-#: src/ui/gui/psppire.glade:1900
-msgid "Observation"
+#: src/ui/gui/psppire.glade:1931
+msgid "First case"
msgstr ""
-#: src/ui/gui/psppire.glade:1910
+#: src/ui/gui/psppire.glade:1944
msgid "Last case"
msgstr ""
-#: src/ui/gui/psppire.glade:1923
-msgid "First case"
+#: src/ui/gui/psppire.glade:1957
+msgid "Observation"
msgstr ""
-#: src/ui/gui/psppire.glade:2081
+#: src/ui/gui/psppire.glade:2021
msgid "Use expression as label"
msgstr ""
-#: src/ui/gui/psppire.glade:2187 src/ui/gui/psppire-var-sheet.c:512
+#: src/ui/gui/psppire.glade:2147 src/ui/gui/psppire-var-sheet.c:512
#: src/ui/gui/psppire-var-store.c:765
msgid "Width"
msgstr ""
-#: src/ui/gui/psppire.glade:2274
+#: src/ui/gui/psppire.glade:2277
msgid "Goto Case Number:"
msgstr ""
-#: src/ui/gui/psppire.glade:2410
+#: src/ui/gui/psppire.glade:2414
msgid "Sample Size"
msgstr ""
-#: src/ui/gui/psppire.glade:2513
+#: src/ui/gui/psppire.glade:2517
msgid "Variable:"
msgstr ""
-#: src/ui/gui/psppire.glade:2570
+#: src/ui/gui/psppire.glade:2574
msgid "Search value labels"
msgstr ""
-#: src/ui/gui/psppire.glade:2593
+#: src/ui/gui/psppire.glade:2598
msgid "Regular expression Match"
msgstr ""
-#: src/ui/gui/psppire.glade:2603
+#: src/ui/gui/psppire.glade:2609
msgid "Search substrings"
msgstr ""
-#: src/ui/gui/psppire.glade:2615
+#: src/ui/gui/psppire.glade:2622
msgid "Wrap around"
msgstr ""
-#: src/ui/gui/psppire.glade:2627
+#: src/ui/gui/psppire.glade:2635
msgid "Search backward"
msgstr ""
msgid "Custom"
msgstr ""
-#: src/ui/gui/rank.glade:111
+#: src/ui/gui/rank.glade:57
msgid "By:"
msgstr ""
-#: src/ui/gui/rank.glade:197
+#: src/ui/gui/rank.glade:196
msgid "_Smallest Value"
msgstr ""
-#: src/ui/gui/rank.glade:209
+#: src/ui/gui/rank.glade:208
msgid "_Largest Value"
msgstr ""
-#: src/ui/gui/rank.glade:228
+#: src/ui/gui/rank.glade:227
msgid "Assign rank 1 to:"
msgstr ""
-#: src/ui/gui/rank.glade:246
+#: src/ui/gui/rank.glade:245
msgid "_Display summary tables"
msgstr ""
-#: src/ui/gui/rank.glade:262
+#: src/ui/gui/rank.glade:261
msgid "Rank T_ypes"
msgstr ""
-#: src/ui/gui/rank.glade:273
+#: src/ui/gui/rank.glade:272
msgid "_Ties..."
msgstr ""
-#: src/ui/gui/rank.glade:343
-msgid "Ntiles"
+#: src/ui/gui/rank.glade:339
+msgid "Sum of case weights"
msgstr ""
-#: src/ui/gui/rank.glade:376
-msgid "Rank"
+#: src/ui/gui/rank.glade:355
+msgid "Fractional rank as %"
msgstr ""
-#: src/ui/gui/rank.glade:386
-msgid "Savage score"
+#: src/ui/gui/rank.glade:369
+msgid "Fractional rank"
msgstr ""
-#: src/ui/gui/rank.glade:400
-msgid "Fractional rank"
+#: src/ui/gui/rank.glade:383
+msgid "Savage score"
msgstr ""
-#: src/ui/gui/rank.glade:414
-msgid "Fractional rank as %"
+#: src/ui/gui/rank.glade:397
+msgid "Rank"
msgstr ""
-#: src/ui/gui/rank.glade:428
-msgid "Sum of case weights"
+#: src/ui/gui/rank.glade:411
+msgid "Ntiles"
msgstr ""
#: src/ui/gui/rank.glade:450
msgid "Normal Scores"
msgstr ""
-#: src/ui/gui/rank.glade:495
+#: src/ui/gui/rank.glade:494
msgid "Blom"
msgstr ""
-#: src/ui/gui/rank.glade:506
+#: src/ui/gui/rank.glade:505
msgid "Tukey"
msgstr ""
-#: src/ui/gui/rank.glade:520
+#: src/ui/gui/rank.glade:519
msgid "Rankit"
msgstr ""
-#: src/ui/gui/rank.glade:534
+#: src/ui/gui/rank.glade:533
msgid "Van der Wärden"
msgstr ""
-#: src/ui/gui/rank.glade:551
+#: src/ui/gui/rank.glade:550
msgid "Proportion Estimation Formula"
msgstr ""
-#: src/ui/gui/rank.glade:614
+#: src/ui/gui/rank.glade:612
msgid "_Mean"
msgstr ""
-#: src/ui/gui/rank.glade:626
+#: src/ui/gui/rank.glade:624
msgid "_Low"
msgstr ""
-#: src/ui/gui/rank.glade:642
+#: src/ui/gui/rank.glade:640
msgid "_High"
msgstr ""
-#: src/ui/gui/rank.glade:660
+#: src/ui/gui/rank.glade:658
msgid "_Sequential ranks to unique values"
msgstr ""
-#: src/ui/gui/rank.glade:680
+#: src/ui/gui/rank.glade:678
msgid "Rank Assigned to Ties"
msgstr ""
-#: src/ui/gui/recode-dialog.c:879
+#: src/ui/gui/recode-dialog.c:878
msgid "Recode into Different Variables"
msgstr ""
-#: src/ui/gui/recode-dialog.c:882
+#: src/ui/gui/recode-dialog.c:881
msgid "Recode into Same Variables"
msgstr ""
-#: src/ui/gui/recode-dialog.c:913 src/ui/gui/recode-dialog.c:1015
+#: src/ui/gui/recode-dialog.c:912 src/ui/gui/recode-dialog.c:1014
msgid "Old"
msgstr ""
-#: src/ui/gui/recode-dialog.c:1274
+#: src/ui/gui/recode-dialog.c:1273
msgid "Recode into Different Variables: Old and New Values "
msgstr ""
-#: src/ui/gui/recode-dialog.c:1275
+#: src/ui/gui/recode-dialog.c:1274
msgid "Recode into Same Variables: Old and New Values"
msgstr ""
msgid "Residuals"
msgstr ""
-#: src/ui/gui/select-cases-dialog.c:81
+#: src/ui/gui/select-cases-dialog.c:80
#, c-format
msgid "Approximately %3d%% of all cases."
msgstr ""
-#: src/ui/gui/select-cases-dialog.c:82
+#: src/ui/gui/select-cases-dialog.c:81
#, c-format
msgid "Exactly %3d cases from the first %3d cases."
msgstr ""
-#: src/ui/gui/select-cases-dialog.c:222
+#: src/ui/gui/select-cases-dialog.c:221
#, c-format
msgid "%d thru %d"
msgstr ""
msgid "Confidence Interval: %2d %%"
msgstr ""
-#: src/ui/gui/t-test-paired-samples.c:228
+#: src/ui/gui/t-test-paired-samples.c:227
msgid "Var 1"
msgstr ""
-#: src/ui/gui/t-test-paired-samples.c:229
+#: src/ui/gui/t-test-paired-samples.c:228
msgid "Var 2"
msgstr ""
-#: src/ui/gui/variable-info-dialog.c:89
+#: src/ui/gui/variable-info-dialog.c:88
#, c-format
msgid "Label: %s\n"
msgstr ""
-#: src/ui/gui/variable-info-dialog.c:98
+#: src/ui/gui/variable-info-dialog.c:97
#, c-format
msgid "Type: %s\n"
msgstr ""
-#: src/ui/gui/variable-info-dialog.c:102
+#: src/ui/gui/variable-info-dialog.c:101
#, c-format
msgid "Missing Values: %s\n"
msgstr ""
-#: src/ui/gui/variable-info-dialog.c:107
+#: src/ui/gui/variable-info-dialog.c:106
#, c-format
msgid "Measurement Level: %s\n"
msgstr ""
-#: src/ui/gui/variable-info-dialog.c:121
+#: src/ui/gui/variable-info-dialog.c:120
msgid "Value Labels:\n"
msgstr ""
-#: src/ui/gui/variable-info-dialog.c:133
+#: src/ui/gui/variable-info-dialog.c:132
#, c-format
msgid "%s %s\n"
msgstr ""
-#: src/ui/gui/weight-cases-dialog.c:86
+#: src/ui/gui/weight-cases-dialog.c:85
#, c-format
msgid "Weight cases by %s"
msgstr ""
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
corresponding source index. */
};
-static void translate_case (struct ccase *, struct ccase *, void *map_);
+static struct ccase *translate_case (struct ccase *, void *map_);
static bool destroy_case_map (void *map_);
/* Creates and returns an empty map. */
}
}
-/* Maps from SRC to DST, applying case map MAP. */
-void
-case_map_execute (const struct case_map *map,
- const struct ccase *src, struct ccase *dst)
-{
- size_t dst_idx;
+/* If MAP is nonnull, returns a new case that is the result of
+ applying case map MAP to SRC, and unrefs SRC.
- case_create (dst, map->value_cnt);
- for (dst_idx = 0; dst_idx < map->value_cnt; dst_idx++)
+ If MAP is null, returns SRC unchanged. */
+struct ccase *
+case_map_execute (const struct case_map *map, struct ccase *src)
+{
+ if (map != NULL)
{
- int src_idx = map->map[dst_idx];
- if (src_idx != -1)
- *case_data_rw_idx (dst, dst_idx) = *case_data_idx (src, src_idx);
+ struct ccase *dst;
+ size_t dst_idx;
+
+ dst = case_create (map->value_cnt);
+ for (dst_idx = 0; dst_idx < map->value_cnt; dst_idx++)
+ {
+ int src_idx = map->map[dst_idx];
+ if (src_idx != -1)
+ *case_data_rw_idx (dst, dst_idx) = *case_data_idx (src, src_idx);
+ }
+ case_unref (src);
+ return dst;
}
+ else
+ return src;
}
/* Returns the number of `union value's in cases created by
}
/* Casereader/casewriter translation callback. */
-static void
-translate_case (struct ccase *input, struct ccase *output, void *map_)
+static struct ccase *
+translate_case (struct ccase *input, void *map_)
{
struct case_map *map = map_;
- case_map_execute (map, input, output);
- case_destroy (input);
+ return case_map_execute (map, input);
}
/* Casereader/casewriter destruction callback. */
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
struct case_map *case_map_create (void);
void case_map_destroy (struct case_map *);
-void case_map_execute (const struct case_map *,
- const struct ccase *, struct ccase *);
+struct ccase *case_map_execute (const struct case_map *, struct ccase *);
size_t case_map_get_value_cnt (const struct case_map *);
/* PSPP - a program for statistical analysis.
- Copyright (C) 2008 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
struct case_matcher_input
{
struct subcase by_vars;
- const struct ccase *data;
+ struct ccase **data;
bool *is_minimal;
};
/* Adds a new input file to case matcher CM.
case_matcher_match() will compare the variables specified in
- BY in case DATA and set *IS_MINIMAL appropriately.
+ BY in case *DATA and set *IS_MINIMAL appropriately.
+ (The caller may change the case that *DATA points to from one
+ call to the next.)
All of the BY subcases provided to this function for a given
CM must be conformable (see subcase_conformable()). */
void
case_matcher_add_input (struct case_matcher *cm, const struct subcase *by,
- const struct ccase *data, bool *is_minimal)
+ struct ccase **data, bool *is_minimal)
{
struct case_matcher_input *input;
static int
compare_BY_3way (struct case_matcher_input *a, struct case_matcher_input *b)
{
- return subcase_compare_3way (&a->by_vars, a->data, &b->by_vars, b->data);
+ return subcase_compare_3way (&a->by_vars, *a->data, &b->by_vars, *b->data);
}
/* Compares the values of the BY variables in all of the nonnull
min = NULL;
for (file = cm->inputs; file < &cm->inputs[cm->n_inputs]; file++)
- if (!case_is_null (file->data))
+ if (*file->data != NULL)
{
int cmp = min != NULL ? compare_BY_3way (min, file) : 1;
if (cmp < 0)
{
for (file = cm->inputs; file < min; file++)
*file->is_minimal = false;
- subcase_extract (&min->by_vars, min->data, cm->by_values);
+ subcase_extract (&min->by_vars, *min->data, cm->by_values);
*by = cm->by_values;
return true;
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 2008 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
struct case_matcher *case_matcher_create (void);
void case_matcher_add_input (struct case_matcher *, const struct subcase *,
- const struct ccase *, bool *is_minimal);
+ struct ccase **, bool *is_minimal);
void case_matcher_destroy (struct case_matcher *);
bool case_matcher_match (struct case_matcher *, union value **by);
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
&& do_read (ctf, sizeof *values * value_cnt, values));
}
-/* Reads the case numbered CASE_IDX from CTF into C.
- Returns true if successful, false if CTF is tainted or an I/O
- error occurs during the operation.
+/* Reads the case numbered CASE_IDX from CTF.
+ Returns the case if successful or a null pointer if CTF is
+ tainted or an I/O error occurs during the operation.
The results of this function are undefined if the case read
from CTF had not previously been written. */
-bool
-case_tmpfile_get_case (const struct case_tmpfile *ctf, casenumber case_idx,
- struct ccase *c)
+struct ccase *
+case_tmpfile_get_case (const struct case_tmpfile *ctf, casenumber case_idx)
{
- case_create (c, ctf->value_cnt);
+ struct ccase *c = case_create (ctf->value_cnt);
if (case_tmpfile_get_values (ctf, case_idx, 0,
case_data_all_rw (c), ctf->value_cnt))
- return true;
+ return c;
else
{
- case_destroy (c);
- case_nullify (c);
- return false;
+ case_unref (c);
+ return NULL;
}
}
{
bool ok = case_tmpfile_put_values (ctf, case_idx, 0,
case_data_all (c), ctf->value_cnt);
- case_destroy (c);
+ case_unref (c);
return ok;
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
void case_tmpfile_force_error (struct case_tmpfile *);
const struct taint *case_tmpfile_get_taint (const struct case_tmpfile *);
-bool case_tmpfile_get_values (const struct case_tmpfile *,
+ bool case_tmpfile_get_values (const struct case_tmpfile *,
casenumber, size_t start_value,
union value[], size_t value_cnt);
-bool case_tmpfile_get_case (const struct case_tmpfile *,
- casenumber, struct ccase *);
+struct ccase *case_tmpfile_get_case (const struct case_tmpfile *, casenumber);
bool case_tmpfile_put_values (struct case_tmpfile *,
casenumber, size_t start_value,
/* PSPP - a program for statistical analysis.
- Copyright (C) 2004, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include <assert.h>
#include <limits.h>
+#include <stddef.h>
#include <stdlib.h>
#include <data/value.h>
#include "minmax.h"
#include "xalloc.h"
-/* Reference-counted case implementation. */
-struct case_data
- {
- size_t value_cnt; /* Number of values. */
- unsigned ref_cnt; /* Reference count. */
- union value values[1]; /* Values. */
- };
-
-/* Ensures that C does not share data with any other case. */
-static void
-case_unshare (struct ccase *c)
-{
- if (c->case_data->ref_cnt > 1)
- {
- struct case_data *cd = c->case_data;
- cd->ref_cnt--;
- case_create (c, cd->value_cnt);
- memcpy (c->case_data->values, cd->values,
- sizeof *cd->values * cd->value_cnt);
- }
-}
-
-/* Returns the number of bytes needed by a case with VALUE_CNT
+/* Returns the number of bytes needed by a case with N_VALUES
values. */
static size_t
-case_size (size_t value_cnt)
+case_size (size_t n_values)
{
- return (offsetof (struct case_data, values)
- + value_cnt * sizeof (union value));
+ return offsetof (struct ccase, values) + n_values * sizeof (union value);
}
-/* Initializes C as a null case. */
-void
-case_nullify (struct ccase *c)
+/* Returns true if case C contains COUNT cases starting at index
+ OFS, false if any of those values are out of range for case
+ C. */
+static inline bool UNUSED
+range_is_valid (const struct ccase *c, size_t ofs, size_t count)
{
- c->case_data = NULL;
+ return (count <= c->n_values
+ && ofs <= c->n_values
+ && ofs + count <= c->n_values);
}
-/* Returns true iff C is a null case. */
-bool
-case_is_null (const struct ccase *c)
-{
- return c->case_data == NULL;
-}
-
-/* Initializes C as a new case that can store VALUE_CNT values.
+/* Creates and returns a new case that can store N_VALUES values.
The values have indeterminate contents until explicitly
written. */
-void
-case_create (struct ccase *c, size_t value_cnt)
+struct ccase *
+case_create (size_t n_values)
{
- if (!case_try_create (c, value_cnt))
+ struct ccase *c = case_try_create (n_values);
+ if (c == NULL)
xalloc_die ();
+ return c;
}
-/* Initializes CLONE as a copy of ORIG. */
-void
-case_clone (struct ccase *clone, const struct ccase *orig)
+/* Like case_create, but returns a null pointer if not enough
+ memory is available. */
+struct ccase *
+case_try_create (size_t n_values)
{
- assert (orig->case_data->ref_cnt > 0);
-
- if (clone != orig)
- *clone = *orig;
- orig->case_data->ref_cnt++;
-#ifdef DEBUGGING
- case_unshare (clone);
-#endif
-}
-
-/* Replaces DST by SRC and nullifies SRC.
- DST and SRC must be initialized cases at entry. */
-void
-case_move (struct ccase *dst, struct ccase *src)
-{
- assert (src->case_data->ref_cnt > 0);
-
- if (dst != src)
+ struct ccase *c = malloc (case_size (n_values));
+ if (c)
{
- *dst = *src;
- case_nullify (src);
+ c->n_values = n_values;
+ c->ref_cnt = 1;
}
+ return c;
}
-/* Destroys case C. */
-void
-case_destroy (struct ccase *c)
+/* Resizes case C, which must not be shared, to N_VALUES union
+ values. If N_VALUES is greater than the current size of case
+ C, then the newly added values have indeterminate content that
+ the caller is responsible for initializing. Returns the new
+ case. */
+struct ccase *
+case_resize (struct ccase *c, size_t n_values)
{
- struct case_data *cd;
-
- cd = c->case_data;
- if (cd != NULL && --cd->ref_cnt == 0)
+ assert (!case_is_shared (c));
+ if (n_values != c->n_values)
{
- memset (cd->values, 0xcc, sizeof *cd->values * cd->value_cnt);
- cd->value_cnt = 0xdeadbeef;
- free (cd);
+ c->n_values = n_values;
+ return xrealloc (c, case_size (n_values));
}
+ else
+ return c;
}
-/* Returns the number of union values in C. */
-size_t
-case_get_value_cnt (const struct ccase *c)
-{
- return c->case_data->value_cnt;
-}
+/* case_unshare_and_resize(C, N) is equivalent to
+ case_resize(case_unshare(C), N), but it is faster if case C is
+ shared.
-/* Resizes case C to NEW_CNT union values. */
-void
-case_resize (struct ccase *c, size_t new_cnt)
+ Returns the new case.*/
+struct ccase *
+case_unshare_and_resize (struct ccase *c, size_t n_values)
{
- size_t old_cnt = case_get_value_cnt (c);
- if (old_cnt != new_cnt)
+ if (!case_is_shared (c))
+ return case_resize (c, n_values);
+ else
{
- struct ccase new;
-
- case_create (&new, new_cnt);
- case_copy (&new, 0, c, 0, MIN (old_cnt, new_cnt));
- case_swap (&new, c);
- case_destroy (&new);
+ struct ccase *new = case_create (n_values);
+ case_copy (new, 0, c, 0, MIN (n_values, c->n_values));
+ c->ref_cnt--;
+ return new;
}
}
-/* Swaps cases A and B. */
-void
-case_swap (struct ccase *a, struct ccase *b)
-{
- struct case_data *t = a->case_data;
- a->case_data = b->case_data;
- b->case_data = t;
-}
+/* Copies N_VALUES values from SRC (starting at SRC_IDX) to DST
+ (starting at DST_IDX).
-/* Attempts to create C as a new case that holds VALUE_CNT
- values. Returns true if successful, false if memory
- allocation failed. */
-bool
-case_try_create (struct ccase *c, size_t value_cnt)
-{
- c->case_data = malloc (case_size (value_cnt));
- if (c->case_data != NULL)
- {
- c->case_data->value_cnt = value_cnt;
- c->case_data->ref_cnt = 1;
- return true;
- }
-
- return false;
-}
-
-/* Tries to initialize CLONE as a copy of ORIG.
- Returns true if successful, false if memory allocation
- failed. */
-bool
-case_try_clone (struct ccase *clone, const struct ccase *orig)
-{
- case_clone (clone, orig);
- return true;
-}
-
-/* Copies VALUE_CNT values from SRC (starting at SRC_IDX) to DST
- (starting at DST_IDX). */
+ DST must not be shared. */
void
case_copy (struct ccase *dst, size_t dst_idx,
const struct ccase *src, size_t src_idx,
- size_t value_cnt)
+ size_t n_values)
{
- assert (dst->case_data->ref_cnt > 0);
- assert (dst_idx + value_cnt <= dst->case_data->value_cnt);
+ assert (!case_is_shared (dst));
+ assert (range_is_valid (dst, dst_idx, n_values));
+ assert (range_is_valid (src, src_idx, n_values));
- assert (src->case_data->ref_cnt > 0);
- assert (src_idx + value_cnt <= src->case_data->value_cnt);
-
- if (dst->case_data != src->case_data || dst_idx != src_idx)
- {
- case_unshare (dst);
- memmove (dst->case_data->values + dst_idx,
- src->case_data->values + src_idx,
- sizeof *dst->case_data->values * value_cnt);
- }
+ if (dst != src || dst_idx != src_idx)
+ memmove (dst->values + dst_idx, src->values + src_idx,
+ sizeof *dst->values * n_values);
}
-/* Copies VALUE_CNT values out of case C to VALUES, starting at
+/* Copies N_VALUES values out of case C to VALUES, starting at
the given START_IDX. */
void
case_copy_out (const struct ccase *c,
- size_t start_idx, union value *values, size_t value_cnt)
+ size_t start_idx, union value *values, size_t n_values)
{
- assert (c->case_data->ref_cnt > 0);
- assert (value_cnt <= c->case_data->value_cnt);
- assert (start_idx + value_cnt <= c->case_data->value_cnt);
-
- memcpy (values, c->case_data->values + start_idx,
- value_cnt * sizeof *values);
+ assert (range_is_valid (c, start_idx, n_values));
+ memcpy (values, c->values + start_idx, n_values * sizeof *values);
}
-/* Copies VALUE_CNT values from VALUES into case C, staring at
- the given START_IDX. */
+/* Copies N_VALUES values from VALUES into case C, starting at
+ the given START_IDX.
+
+ C must not be shared. */
void
case_copy_in (struct ccase *c,
- size_t start_idx, const union value *values, size_t value_cnt)
+ size_t start_idx, const union value *values, size_t n_values)
{
- assert (c->case_data->ref_cnt > 0);
- assert (value_cnt <= c->case_data->value_cnt);
- assert (start_idx + value_cnt <= c->case_data->value_cnt);
-
- case_unshare (c);
- memcpy (c->case_data->values + start_idx, values,
- value_cnt * sizeof *values);
+ assert (!case_is_shared (c));
+ assert (range_is_valid (c, start_idx, n_values));
+ memcpy (c->values + start_idx, values, n_values * sizeof *values);
}
/* Returns a pointer to the `union value' used for the
return case_data_idx (c, var_get_case_index (v));
}
-/* Returns the numeric value of the `union value' in C for
- variable V.
- Case C must be drawn from V's dictionary. */
-double
-case_num (const struct ccase *c, const struct variable *v)
+/* Returns a pointer to the `union value' used for the element of
+ C numbered IDX. The caller must not modify the returned
+ data. */
+const union value *
+case_data_idx (const struct ccase *c, size_t idx)
{
- return case_num_idx (c, var_get_case_index (v));
+ assert (idx < c->n_values);
+ return &c->values[idx];
}
-/* Returns the string value of the `union value' in C for
- variable V.
- Case C must be drawn from V's dictionary.
- (Note that the value is not null-terminated.)
- The caller must not modify the return value. */
-const char *
-case_str (const struct ccase *c, const struct variable *v)
-{
- return case_str_idx (c, var_get_case_index (v));
-}
+/* Returns a pointer to the `union value' used for the element of
+ C for variable V. Case C must be drawn from V's dictionary.
+ The caller is allowed to modify the returned data.
-/* Returns a pointer to the `union value' used for the
- element of C for variable V.
- Case C must be drawn from V's dictionary.
- The caller is allowed to modify the returned data. */
+ Case C must not be shared. */
union value *
case_data_rw (struct ccase *c, const struct variable *v)
{
/* Returns a pointer to the `union value' used for the
element of C numbered IDX.
- The caller must not modify the returned data. */
-const union value *
-case_data_idx (const struct ccase *c, size_t idx)
+ The caller is allowed to modify the returned data.
+
+ Case C must not be shared. */
+union value *
+case_data_rw_idx (struct ccase *c, size_t idx)
{
- assert (c->case_data->ref_cnt > 0);
- assert (idx < c->case_data->value_cnt);
+ assert (!case_is_shared (c));
+ assert (idx < c->n_values);
+ return &c->values[idx];
+}
- return &c->case_data->values[idx];
+/* Returns the numeric value of the `union value' in C for
+ variable V.
+ Case C must be drawn from V's dictionary. */
+double
+case_num (const struct ccase *c, const struct variable *v)
+{
+ return case_num_idx (c, var_get_case_index (v));
}
/* Returns the numeric value of the `union value' in C numbered
double
case_num_idx (const struct ccase *c, size_t idx)
{
- assert (c->case_data->ref_cnt > 0);
- assert (idx < c->case_data->value_cnt);
-
- return c->case_data->values[idx].f;
+ assert (idx < c->n_values);
+ return c->values[idx].f;
}
-/* Returns the string value of the `union value' in C numbered
- IDX.
- (Note that the value is not null-terminated.)
- The caller must not modify the return value. */
+/* Returns the string value of the `union value' in C for
+ variable V. Case C must be drawn from V's dictionary. The
+ caller must not modify the return value.
+
+ Like all "union value"s, the return value is not
+ null-terminated. */
const char *
-case_str_idx (const struct ccase *c, size_t idx)
+case_str (const struct ccase *c, const struct variable *v)
{
- assert (c->case_data->ref_cnt > 0);
- assert (idx < c->case_data->value_cnt);
-
- return c->case_data->values[idx].s;
+ return case_str_idx (c, var_get_case_index (v));
}
-/* Returns a pointer to the `union value' used for the
- element of C numbered IDX.
- The caller is allowed to modify the returned data. */
-union value *
-case_data_rw_idx (struct ccase *c, size_t idx)
-{
- assert (c->case_data->ref_cnt > 0);
- assert (idx < c->case_data->value_cnt);
+/* Returns the string value of the `union value' in C numbered
+ IDX. The caller must not modify the return value.
- case_unshare (c);
- return &c->case_data->values[idx];
+ Like all "union value"s, the return value is not
+ null-terminated. */
+const char *
+case_str_idx (const struct ccase *c, size_t idx)
+{
+ assert (idx < c->n_values);
+ return c->values[idx].s;
}
-/* Compares the values of the VAR_CNT variables in VP
+/* Compares the values of the N_VARS variables in VP
in cases A and B and returns a strcmp()-type result. */
int
case_compare (const struct ccase *a, const struct ccase *b,
- const struct variable *const *vp, size_t var_cnt)
+ const struct variable *const *vp, size_t n_vars)
{
- return case_compare_2dict (a, b, vp, vp, var_cnt);
+ return case_compare_2dict (a, b, vp, vp, n_vars);
}
-/* Compares the values of the VAR_CNT variables in VAP in case CA
- to the values of the VAR_CNT variables in VBP in CB
+/* Compares the values of the N_VARS variables in VAP in case CA
+ to the values of the N_VARS variables in VBP in CB
and returns a strcmp()-type result. */
int
case_compare_2dict (const struct ccase *ca, const struct ccase *cb,
const struct variable *const *vap,
- const struct variable *const *vbp,
- size_t var_cnt)
+ const struct variable *const *vbp,
+ size_t n_vars)
{
- for (; var_cnt-- > 0; vap++, vbp++)
+ for (; n_vars-- > 0; vap++, vbp++)
{
const struct variable *va = *vap;
const struct variable *vb = *vbp;
/* Returns a pointer to the array of `union value's used for C.
The caller must *not* modify the returned data.
- NOTE: This function breaks the case abstraction. It should
- *not* be used often. Prefer the other case functions. */
+ This function breaks the case abstraction. It should *not* be
+ commonly used. Prefer the other case functions. */
const union value *
case_data_all (const struct ccase *c)
{
- assert (c->case_data->ref_cnt > 0);
-
- return c->case_data->values;
+ return c->values;
}
/* Returns a pointer to the array of `union value's used for C.
The caller is allowed to modify the returned data.
- NOTE: This function breaks the case abstraction. It should
- *not* be used often. Prefer the other case functions. */
+ Case C must not be shared.
+
+ This function breaks the case abstraction. It should *not* be
+ commonly used. Prefer the other case functions. */
union value *
case_data_all_rw (struct ccase *c)
{
- assert (c->case_data->ref_cnt > 0);
+ assert (!case_is_shared (c));
+ return c->values;
+}
- case_unshare (c);
- return c->case_data->values;
+/* Internal helper function for case_unshare. */
+struct ccase *
+case_unshare__ (struct ccase *old)
+{
+ struct ccase *new = case_create (old->n_values);
+ memcpy (new->values, old->values, old->n_values * sizeof old->values[0]);
+ --old->ref_cnt;
+ return new;
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 2004, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include <limits.h>
#include <stddef.h>
#include <stdbool.h>
+#include <stdlib.h>
+#include <libpspp/compiler.h>
#include "value.h"
struct variable;
#define CASENUMBER_MAX LONG_MAX
typedef long int casenumber;
-/* Opaque structure that represents a case. Use accessor
- functions instead of accessing any members directly. Use
- case_move() or case_clone() instead of copying. */
+/* Reference-counted case implementation.
+
+ A newly created case has a single owner (the code that created
+ it), represented by an initial reference count of 1. Other
+ code that receives the case may keep a virtual copy of it by
+ calling case_ref, which increments the case's reference count.
+ When this is done, the case becomes shared between its
+ original owner and each piece of code that incremented the
+ reference count.
+
+ A shared case (one whose reference count is greater than 1)
+ must not be modified, because this would make the case change
+ in the view of every reference count holder, not just the one
+ that intended to change the case. Because the purpose of
+ keeping the reference count is to make a virtual copy of the
+ case, this is undesirable behavior. The case_unshare function
+ provides a solution, by making a new, unshared copy of a
+ shared case. */
struct ccase
{
- struct case_data *case_data; /* Actual data. */
+ size_t n_values; /* Number of values. */
+ size_t ref_cnt; /* Reference count. */
+ union value values[1]; /* Values. */
};
-void case_nullify (struct ccase *);
-bool case_is_null (const struct ccase *);
+struct ccase *case_create (size_t n_values) MALLOC_LIKE;
+struct ccase *case_try_create (size_t n_values) MALLOC_LIKE;
-void case_create (struct ccase *, size_t value_cnt);
-void case_clone (struct ccase *, const struct ccase *);
-void case_move (struct ccase *, struct ccase *);
-void case_destroy (struct ccase *);
+static inline struct ccase *case_unshare (struct ccase *) WARN_UNUSED_RESULT;
+static inline struct ccase *case_ref (const struct ccase *);
+static inline void case_unref (struct ccase *);
+static inline bool case_is_shared (const struct ccase *);
-size_t case_get_value_cnt (const struct ccase *);
+static inline size_t case_get_value_cnt (const struct ccase *);
-void case_resize (struct ccase *, size_t new_cnt);
-void case_swap (struct ccase *, struct ccase *);
-
-bool case_try_create (struct ccase *, size_t value_cnt);
-bool case_try_clone (struct ccase *, const struct ccase *);
+struct ccase *case_resize (struct ccase *, size_t new_cnt) WARN_UNUSED_RESULT;
+struct ccase *case_unshare_and_resize (struct ccase *, size_t new_cnt)
+ WARN_UNUSED_RESULT;
void case_copy (struct ccase *dst, size_t dst_idx,
const struct ccase *src, size_t src_idx,
size_t cnt);
void case_copy_out (const struct ccase *,
- size_t start_idx, union value *, size_t value_cnt);
+ size_t start_idx, union value *, size_t n_values);
void case_copy_in (struct ccase *,
- size_t start_idx, const union value *, size_t value_cnt);
+ size_t start_idx, const union value *, size_t n_values);
const union value *case_data (const struct ccase *, const struct variable *);
-double case_num (const struct ccase *, const struct variable *);
-const char *case_str (const struct ccase *, const struct variable *);
+const union value *case_data_idx (const struct ccase *, size_t idx);
union value *case_data_rw (struct ccase *, const struct variable *);
+union value *case_data_rw_idx (struct ccase *, size_t idx);
-const union value *case_data_idx (const struct ccase *, size_t idx);
+double case_num (const struct ccase *, const struct variable *);
double case_num_idx (const struct ccase *, size_t idx);
+
+const char *case_str (const struct ccase *, const struct variable *);
const char *case_str_idx (const struct ccase *, size_t idx);
-union value *case_data_rw_idx (struct ccase *, size_t idx);
int case_compare (const struct ccase *, const struct ccase *,
- const struct variable *const *, size_t var_cnt);
+ const struct variable *const *, size_t n_vars);
int case_compare_2dict (const struct ccase *, const struct ccase *,
const struct variable *const *,
const struct variable *const *,
- size_t var_cnt);
+ size_t n_vars);
const union value *case_data_all (const struct ccase *);
union value *case_data_all_rw (struct ccase *);
+\f
+struct ccase *case_unshare__ (struct ccase *);
+
+/* If C is a shared case, that is, if it has a reference count
+ greater than 1, makes a new unshared copy and returns it,
+ decrementing C's reference count. If C is not shared (its
+ reference count is 1), returns C.
+
+ This function should be used before attempting to modify any
+ of the data in a case that might be shared, e.g.:
+ c = case_unshare (c); // Make sure that C is not shared.
+ case_data_rw (c, myvar)->f = 1; // Modify data in C.
+*/
+static inline struct ccase *
+case_unshare (struct ccase *c)
+{
+ if (case_is_shared (c))
+ c = case_unshare__ (c);
+ return c;
+}
+
+/* Increments case C's reference count and returns C. Afterward,
+ case C is shared among its reference count holders. */
+static inline struct ccase *
+case_ref (const struct ccase *c_)
+{
+ struct ccase *c = (struct ccase *) c_;
+ c->ref_cnt++;
+ return c;
+}
+
+/* Decrements case C's reference count. Frees C if its
+ reference count drops to 0.
+
+ If C is a null pointer, this function has no effect. */
+static inline void
+case_unref (struct ccase *c)
+{
+ if (c != NULL && !--c->ref_cnt)
+ free (c);
+}
+
+/* Returns true if case C is shared. A case that is shared
+ cannot be modified directly. Instead, an unshared copy must
+ first be made with case_unshare(). */
+static inline bool
+case_is_shared (const struct ccase *c)
+{
+ return c->ref_cnt > 1;
+}
+
+/* Returns the number of union values in C. */
+static inline size_t
+case_get_value_cnt (const struct ccase *c)
+{
+ return c->n_values;
+}
#endif /* data/case.h */
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
if (grouper->same_group != NULL)
{
struct casewriter *writer;
- struct ccase group_case, tmp;
+ struct ccase *group_case, *tmp;
- if (!casereader_read (grouper->reader, &group_case))
+ group_case = casereader_read (grouper->reader);
+ if (group_case == NULL)
{
*reader = NULL;
return false;
}
writer = autopaging_writer_create (casereader_get_value_cnt (grouper->reader));
- case_clone (&tmp, &group_case);
- casewriter_write (writer, &tmp);
+ case_ref (group_case);
+ casewriter_write (writer, group_case);
- while (casereader_peek (grouper->reader, 0, &tmp)
- && grouper->same_group (&group_case, &tmp, grouper->aux))
+ while ((tmp = casereader_peek (grouper->reader, 0)) != NULL
+ && grouper->same_group (group_case, tmp, grouper->aux))
{
- struct ccase discard;
- casereader_read (grouper->reader, &discard);
- case_destroy (&discard);
- casewriter_write (writer, &tmp);
+ case_unref (casereader_read (grouper->reader));
+ casewriter_write (writer, tmp);
}
- case_destroy (&tmp);
- case_destroy (&group_case);
+ case_unref (group_case);
*reader = casewriter_make_reader (writer);
return true;
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
init_list_mark (&ci->left_values, &ci->preinited_values, LEAVE_LEFT, d);
}
-/* Initializes variables in C as described by CI. */
+/* Initializes variables in *C as described by CI.
+ C must not be shared. */
void
caseinit_init_vars (const struct caseinit *ci, struct ccase *c)
{
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
}
/* Internal read function for filtering casereader. */
-static bool
-casereader_filter_read (struct casereader *reader UNUSED, void *filter_,
- struct ccase *c)
+static struct ccase *
+casereader_filter_read (struct casereader *reader UNUSED, void *filter_)
{
struct casereader_filter *filter = filter_;
for (;;)
{
- if (!casereader_read (filter->subreader, c))
- return false;
+ struct ccase *c = casereader_read (filter->subreader);
+ if (c == NULL)
+ return NULL;
else if (filter->include (c, filter->aux))
- return true;
+ return c;
else if (filter->exclude != NULL)
casewriter_write (filter->exclude, c);
else
- case_destroy (c);
+ case_unref (c);
}
}
casewriter, if there is one. */
if (filter->exclude != NULL)
{
- struct ccase c;
- while (casereader_read (filter->subreader, &c))
- if (filter->include (&c, filter->aux))
- case_destroy (&c);
+ struct ccase *c;
+ while ((c = casereader_read (filter->subreader)) != NULL)
+ if (filter->include (c, filter->aux))
+ case_unref (c);
else
- casewriter_write (filter->exclude, &c);
+ casewriter_write (filter->exclude, c);
}
casereader_destroy (filter->subreader);
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
{
/* Mandatory.
- Reads the next case from READER into case C, which the
- casereader must create and which the client is responsible
- for destroying. If successful, returns true and advances
- READER to the next case, so that the next call to this
- function will read the next case. The case just read will
- never be read again by a call to this function for READER.
+ Reads the next case from READER. If successful, returns
+ the case and advances READER, so that the next call to
+ this function will read the following case. The case just
+ read will never be read again by a call to this function
+ for READER.
- At end of file or upon an I/O error, returns false. After
- false is returned once, this function will not be called
- again for the given READER.
+ If a case is successfully returned, the client is
+ responsible for calling case_unref upon it when it is no
+ longer needed.
+
+ At end of file or upon an I/O error, returns a null
+ pointer. After null is returned once, this function will
+ not be called again for the given READER.
If an I/O error occurs, this function should call
casereader_force_error on READER. */
- bool (*read) (struct casereader *reader, void *aux, struct ccase *c);
+ struct ccase *(*read) (struct casereader *reader, void *aux);
/* Mandatory.
(But it might be easier to use the random-access
casereader wrapper instead.)
- Reads the case at 0-based offset IDX from the beginning of
- READER into case C, which the casereader must create and
- which the client is responsible for destroying.
+ Reads and returns the case at 0-based offset IDX from the
+ beginning of READER. If a case is successfully returned,
+ the client is responsible for calling case_unref upon it
+ when it is no longer needed.
- At end of file or upon an I/O error, returns false. If
- this function returns false, then it will never be called
- again for an equal or greater value of IDX, and the "read"
- member function will never be called to advance as far as
- IDX cases further into the casereader. That is, returning
- false indicates that the casereader has fewer than IDX
- cases left.
+ At end of file or upon an I/O error, returns a null
+ pointer. If this function returns null, then it will
+ never be called again for an equal or greater value of
+ IDX, and the "read" member function will never be called
+ to advance as far as IDX cases further into the
+ casereader. That is, returning null indicates that the
+ casereader has fewer than IDX cases left.
If an I/O error occurs, this function should call
casereader_force_error on READER. */
- bool (*peek) (struct casereader *reader, void *aux, casenumber idx,
- struct ccase *c);
+ struct ccase *(*peek) (struct casereader *reader, void *aux,
+ casenumber idx);
};
struct casereader *
/* Mandatory.
Reads the case at 0-based offset IDX from the beginning of
- READER into case C, which the casereader must create and
- which the client is responsible for destroying.
-
- At end of file or upon an I/O error, returns false. If
- this function returns false, then it will never be called
- again for an equal or greater value of IDX, and the "read"
- member function will never be called to advance as far as
- IDX cases further into the casereader. That is, returning
- false indicates that the casereader has fewer than IDX
- cases.
+ READER. If a case is successfully returned, the client is
+ responsible for calling case_unref upon it when it is no
+ longer needed.
+
+ At end of file or upon an I/O error, returns a null
+ pointer. If this function returns null, then it will
+ never be called again for an equal or greater value of
+ IDX, and the "read" member function will never be called
+ to advance as far as IDX cases further into the
+ casereader. That is, returning null indicates that the
+ casereader has fewer than IDX cases.
If an I/O error occurs, this function should call
casereader_force_error on READER. */
- bool (*read) (struct casereader *reader, void *aux, casenumber idx,
- struct ccase *c);
+ struct ccase *(*read) (struct casereader *reader, void *aux,
+ casenumber idx);
/* Mandatory.
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
{
struct casereader *subreader; /* Source of input cases. */
- void (*translate) (struct ccase *input, struct ccase *output, void *aux);
+ struct ccase *(*translate) (struct ccase *input, void *aux);
bool (*destroy) (void *aux);
void *aux;
};
/* Creates and returns a new casereader whose cases are produced
by reading from SUBREADER and passing through TRANSLATE, which
- must create case OUTPUT, with OUTPUT_VALUE_CNT values, and
- populate it based on INPUT and auxiliary data AUX. TRANSLATE
- must also destroy INPUT.
+ must return the translated case, with OUTPUT_VALUE_CNT values,
+ and populate it based on INPUT and auxiliary data AUX.
+ TRANSLATE must destroy its input case.
When the translating casereader is destroyed, DESTROY will be
called to allow any state maintained by TRANSLATE to be freed.
struct casereader *
casereader_create_translator (struct casereader *subreader,
size_t output_value_cnt,
- void (*translate) (struct ccase *input,
- struct ccase *output,
- void *aux),
+ struct ccase *(*translate) (struct ccase *input,
+ void *aux),
bool (*destroy) (void *aux),
void *aux)
{
}
/* Internal read function for translating casereader. */
-static bool
+static struct ccase *
casereader_translator_read (struct casereader *reader UNUSED,
- void *ct_, struct ccase *c)
+ void *ct_)
{
struct casereader_translator *ct = ct_;
- struct ccase tmp;
-
- if (casereader_read (ct->subreader, &tmp))
- {
- ct->translate (&tmp, c, ct->aux);
- return true;
- }
- else
- return false;
+ struct ccase *tmp = casereader_read (ct->subreader);
+ if (tmp)
+ tmp = ct->translate (tmp, ct->aux);
+ return tmp;
}
/* Internal destroy function for translating casereader. */
static bool can_destroy (void *can_);
-static void can_translate (struct ccase *input, struct ccase *output,
- void *can_);
+static struct ccase *can_translate (struct ccase *, void *can_);
/* Creates and returns a new casereader whose cases are produced
by reading from SUBREADER and appending an additional value,
}
-static void
-can_translate (struct ccase *input, struct ccase *output, void *can_)
+static struct ccase *
+can_translate (struct ccase *c, void *can_)
{
struct casereader_append_numeric *can = can_;
- double new_value = can->func (input, can->n++, can->aux);
- case_nullify (output);
- case_move (output, input);
- case_resize (output, can->value_ofs + 1);
- case_data_rw_idx (output, can->value_ofs)->f = new_value;
+ double new_value = can->func (c, can->n++, can->aux);
+ c = case_unshare_and_resize (c, can->value_ofs + 1);
+ case_data_rw_idx (c, can->value_ofs)->f = new_value;
+ return c;
}
static bool
static bool car_destroy (void *car_);
-static void car_translate (struct ccase *input, struct ccase *output,
- void *car_);
+static struct ccase *car_translate (struct ccase *input, void *car_);
/* Creates and returns a new casereader whose cases are produced
by reading from SUBREADER and appending an additional value,
return true;
}
-
-static void
-car_translate (struct ccase *input, struct ccase *output, void *car_)
+static struct ccase *
+car_translate (struct ccase *input, void *car_)
{
struct casereader_append_rank *car = car_;
do
{
- struct ccase c;
- if ( ! casereader_peek (car->clone, car->n + ++k, &c))
+ struct ccase *c = casereader_peek (car->clone, car->n + ++k);
+ if (c == NULL)
break;
- vxx = case_data (&c, car->var)->f;
+ vxx = case_data (c, car->var)->f;
if ( vxx == value)
{
if (car->weight)
{
- double w = case_data (&c, car->weight)->f;
+ double w = case_data (c, car->weight)->f;
if ( car->err && w < 0 )
*car->err |= RANK_ERR_NEGATIVE_WEIGHT;
weight += 1.0;
car->n_common++;
}
- case_destroy (&c);
+ case_unref (c);
}
while (vxx == value);
car->mean_rank = car->cc + (weight + 1) / 2.0;
car->n++;
- case_nullify (output);
- case_move (output, input);
- case_resize (output, car->value_ofs + 1);
- case_data_rw_idx (output, car->value_ofs)->f = car->mean_rank ;
+ input = case_unshare_and_resize (input, car->value_ofs + 1);
+ case_data_rw_idx (input, car->value_ofs)->f = car->mean_rank ;
car->prev_value = value;
+ return input;
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
static void insert_shim (struct casereader *);
-/* Creates a new case in C and reads the next case from READER
- into it. The caller owns C and must destroy C when its data
- is no longer needed. Return true if successful, false when
- cases have been exhausted or upon detection of an I/O error.
- In the latter case, C is set to the null case.
+/* Reads and returns the next case from READER. The caller owns
+ the returned case and must call case_unref on it when its data
+ is no longer needed. Returns a null pointer if cases have
+ been exhausted or upon detection of an I/O error.
The case returned is effectively consumed: it can never be
read again through READER. If this is inconvenient, READER
may be cloned in advance with casereader_clone, or
casereader_peek may be used instead. */
-bool
-casereader_read (struct casereader *reader, struct ccase *c)
+struct ccase *
+casereader_read (struct casereader *reader)
{
if (reader->case_cnt != 0)
{
case_cnt after calling ->read, then this would actually
drop two cases from case_cnt instead of one, and we'd
lose the last case in the casereader. */
+ struct ccase *c;
if (reader->case_cnt != CASENUMBER_MAX)
reader->case_cnt--;
- if (reader->class->read (reader, reader->aux, c))
+ c = reader->class->read (reader, reader->aux);
+ if (c != NULL)
{
assert (case_get_value_cnt (c) >= reader->value_cnt);
- return true;
+ return c;
}
}
reader->case_cnt = 0;
- case_nullify (c);
- return false;
+ return NULL;
}
/* Destroys READER.
}
}
-/* Creates a new case in C and reads the (IDX + 1)'th case from
- READER into it. The caller owns C and must destroy C when its
- data is no longer needed. Return true if successful, false
- when cases have been exhausted or upon detection of an I/O
- error. In the latter case, C is set to the null case. */
-bool
-casereader_peek (struct casereader *reader, casenumber idx, struct ccase *c)
+/* Reads and returns the (IDX + 1)'th case from READER. The
+ caller owns the returned case and must call case_unref on it
+ when it is no longer needed. Returns a null pointer if cases
+ have been exhausted or upon detection of an I/O error. */
+struct ccase *
+casereader_peek (struct casereader *reader, casenumber idx)
{
if (idx < reader->case_cnt)
{
+ struct ccase *c;
if (reader->class->peek == NULL)
insert_shim (reader);
- if (reader->class->peek (reader, reader->aux, idx, c))
- return true;
+ c = reader->class->peek (reader, reader->aux, idx);
+ if (c != NULL)
+ return c;
else if (casereader_error (reader))
reader->case_cnt = 0;
}
if (reader->case_cnt > idx)
reader->case_cnt = idx;
- case_nullify (c);
- return false;
+ return NULL;
}
/* Returns true if no cases remain to be read from READER, or if
bool
casereader_is_empty (struct casereader *reader)
{
- struct ccase c;
- if (reader->case_cnt == 0 || !casereader_peek (reader, 0, &c))
+ if (reader->case_cnt == 0)
return true;
else
{
- case_destroy (&c);
- return false;
+ struct ccase *c = casereader_peek (reader, 0);
+ if (c == NULL)
+ return true;
+ else
+ {
+ case_unref (c);
+ return false;
+ }
}
}
if (reader->case_cnt == CASENUMBER_MAX)
{
casenumber n_cases = 0;
- struct ccase c;
+ struct ccase *c;
struct casereader *clone = casereader_clone (reader);
- for (; casereader_read (clone, &c); case_destroy (&c))
+ for (; (c = casereader_read (clone)) != NULL; case_unref (c))
n_cases++;
casereader_destroy (clone);
void
casereader_transfer (struct casereader *reader, struct casewriter *writer)
{
- struct ccase c;
+ struct ccase *c;
taint_propagate (casereader_get_taint (reader),
casewriter_get_taint (writer));
- while (casereader_read (reader, &c))
- casewriter_write (writer, &c);
+ while ((c = casereader_read (reader)) != NULL)
+ casewriter_write (writer, c);
casereader_destroy (reader);
}
}
/* struct casereader_class "read" function for random reader. */
-static bool
-random_reader_read (struct casereader *reader, void *br_, struct ccase *c)
+static struct ccase *
+random_reader_read (struct casereader *reader, void *br_)
{
struct random_reader *br = br_;
struct random_reader_shared *shared = br->shared;
-
- if (shared->class->read (reader, shared->aux,
- br->offset - shared->min_offset, c))
+ struct ccase *c = shared->class->read (reader, shared->aux,
+ br->offset - shared->min_offset);
+ if (c != NULL)
{
br->offset++;
heap_changed (shared->readers, &br->heap_node);
advance_random_reader (reader, shared);
- return true;
}
- else
- return false;
+ return c;
}
/* struct casereader_class "destroy" function for random
}
/* struct casereader_class "peek" function for random reader. */
-static bool
-random_reader_peek (struct casereader *reader, void *br_,
- casenumber idx, struct ccase *c)
+static struct ccase *
+random_reader_peek (struct casereader *reader, void *br_, casenumber idx)
{
struct random_reader *br = br_;
struct random_reader_shared *shared = br->shared;
return shared->class->read (reader, shared->aux,
- br->offset - shared->min_offset + idx, c);
+ br->offset - shared->min_offset + idx);
}
/* Casereader class for random reader. */
{
while (casewindow_get_case_cnt (b->window) < case_cnt)
{
- struct ccase tmp;
- if (!casereader_read (b->subreader, &tmp))
+ struct ccase *tmp = casereader_read (b->subreader);
+ if (tmp == NULL)
return false;
- casewindow_push_head (b->window, &tmp);
+ casewindow_push_head (b->window, tmp);
}
return true;
}
/* Reads the case at the given 0-based OFFSET from the front of
- the window into C. Returns true if successful, false if
- OFFSET is beyond the end of file or upon I/O error. */
-static bool
+ the window into C. Returns the case if successful, or a null
+ pointer if OFFSET is beyond the end of file or upon I/O error.
+ The caller must call case_unref() on the returned case when it
+ is no longer needed. */
+static struct ccase *
shim_read (struct casereader *reader UNUSED, void *b_,
- casenumber offset, struct ccase *c)
+ casenumber offset)
{
struct shim *b = b_;
- return (prime_buffer (b, offset + 1)
- && casewindow_get_case (b->window, offset, c));
+ if (!prime_buffer (b, offset + 1))
+ return NULL;
+ return casewindow_get_case (b->window, offset);
}
/* Destroys B. */
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
struct casereader;
struct casewriter;
-bool casereader_read (struct casereader *, struct ccase *);
+struct ccase *casereader_read (struct casereader *);
bool casereader_destroy (struct casereader *);
struct casereader *casereader_clone (const struct casereader *);
struct casereader *casereader_rename (struct casereader *);
void casereader_swap (struct casereader *, struct casereader *);
-bool casereader_peek (struct casereader *, casenumber, struct ccase *)
- WARN_UNUSED_RESULT;
+struct ccase *casereader_peek (struct casereader *, casenumber);
bool casereader_is_empty (struct casereader *);
bool casereader_error (const struct casereader *);
struct casereader *
casereader_create_translator (struct casereader *, size_t output_value_cnt,
- void (*translate) (struct ccase *input,
- struct ccase *output,
- void *aux),
+ struct ccase *(*translate) (struct ccase *,
+ void *aux),
bool (*destroy) (void *aux),
void *aux);
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
void (*destroy) (void *aux);
void (*push_head) (void *aux, struct ccase *);
void (*pop_tail) (void *aux, casenumber cnt);
- bool (*get_case) (void *aux, casenumber ofs, struct ccase *);
+ struct ccase *(*get_case) (void *aux, casenumber ofs);
casenumber (*get_case_cnt) (const void *aux);
};
new = do_casewindow_create (taint_clone (old->taint), old->value_cnt, 0);
while (casewindow_get_case_cnt (old) > 0 && !casewindow_error (new))
{
- struct ccase c;
- if (!casewindow_get_case (old, 0, &c))
+ struct ccase *c = casewindow_get_case (old, 0);
+ if (c == NULL)
break;
casewindow_pop_tail (old, 1);
- casewindow_push_head (new, &c);
+ casewindow_push_head (new, c);
}
casewindow_swap (old, new);
casewindow_destroy (new);
}
}
else
- case_destroy (c);
+ case_unref (c);
}
/* Deletes CASE_CNT cases at the tail of casewindow CW. */
cw->class->pop_tail (cw->aux, case_cnt);
}
-/* Copies the case that is CASE_IDX cases away from CW's tail
- into C. Returns true if successful, false on an I/O error or
- if CW is otherwise tainted. On failure, nullifies case C. */
-bool
-casewindow_get_case (const struct casewindow *cw_, casenumber case_idx,
- struct ccase *c)
+/* Returns the case that is CASE_IDX cases away from CW's tail
+ into C, or a null pointer on an I/O error or if CW is
+ otherwise tainted. The caller must call case_unref() on the
+ returned case when it is no longer needed. */
+struct ccase *
+casewindow_get_case (const struct casewindow *cw_, casenumber case_idx)
{
struct casewindow *cw = (struct casewindow *) cw_;
assert (case_idx >= 0 && case_idx < casewindow_get_case_cnt (cw));
- if (!casewindow_error (cw))
- return cw->class->get_case (cw->aux, case_idx, c);
- else
- {
- case_nullify (c);
- return false;
- }
+ if (casewindow_error (cw))
+ return NULL;
+ return cw->class->get_case (cw->aux, case_idx);
}
/* Returns the number of cases in casewindow CW. */
struct casewindow_memory
{
struct deque deque;
- struct ccase *cases;
+ struct ccase **cases;
};
static void *
{
struct casewindow_memory *cwm = cwm_;
while (!deque_is_empty (&cwm->deque))
- case_destroy (&cwm->cases[deque_pop_front (&cwm->deque)]);
+ case_unref (cwm->cases[deque_pop_front (&cwm->deque)]);
free (cwm->cases);
free (cwm);
}
struct casewindow_memory *cwm = cwm_;
if (deque_is_full (&cwm->deque))
cwm->cases = deque_expand (&cwm->deque, cwm->cases, sizeof *cwm->cases);
- case_move (&cwm->cases[deque_push_back (&cwm->deque)], c);
+ cwm->cases[deque_push_back (&cwm->deque)] = c;
}
static void
struct casewindow_memory *cwm = cwm_;
assert (deque_count (&cwm->deque) >= case_cnt);
while (case_cnt-- > 0)
- case_destroy (&cwm->cases[deque_pop_front (&cwm->deque)]);
+ case_unref (cwm->cases[deque_pop_front (&cwm->deque)]);
}
-static bool
-casewindow_memory_get_case (void *cwm_, casenumber ofs, struct ccase *c)
+static struct ccase *
+casewindow_memory_get_case (void *cwm_, casenumber ofs)
{
struct casewindow_memory *cwm = cwm_;
- case_clone (c, &cwm->cases[deque_front (&cwm->deque, ofs)]);
- return true;
+ return case_ref (cwm->cases[deque_front (&cwm->deque, ofs)]);
}
static casenumber
cwf->head = cwf->tail = 0;
}
-static bool
-casewindow_file_get_case (void *cwf_, casenumber ofs, struct ccase *c)
+static struct ccase *
+casewindow_file_get_case (void *cwf_, casenumber ofs)
{
struct casewindow_file *cwf = cwf_;
- return case_tmpfile_get_case (cwf->file, cwf->tail + ofs, c);
+ return case_tmpfile_get_case (cwf->file, cwf->tail + ofs);
}
static casenumber
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
void casewindow_push_head (struct casewindow *, struct ccase *);
void casewindow_pop_tail (struct casewindow *, casenumber cnt);
-bool casewindow_get_case (const struct casewindow *, casenumber case_idx,
- struct ccase *);
+struct ccase *casewindow_get_case (const struct casewindow *,
+ casenumber case_idx);
size_t casewindow_get_value_cnt (const struct casewindow *);
casenumber casewindow_get_case_cnt (const struct casewindow *);
/* PSPP - a program for statistical analysis.
- Copyright (C) 2006 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
{
/* Mandatory.
- Writes case C to WRITER. Destroys C before returning.
+ Writes case C to WRITER. Ownership of C is transferred to
+ WRITER.
If an I/O error occurs, this function should call
casewriter_force_error on WRITER. Some I/O error
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
{
struct casewriter *subwriter;
- void (*translate) (struct ccase *input, struct ccase *output, void *aux);
+ struct ccase *(*translate) (struct ccase *, void *aux);
bool (*destroy) (void *aux);
void *aux;
};
static const struct casewriter_class casewriter_translator_class;
/* Creates and returns a new casewriter whose cases are passed
- through TRANSLATE, which must create case OUTPUT, with
- OUTPUT_VALUE_CNT values, and populate it based on INPUT and
- auxiliary data AUX. The translated cases are then written to
- SUBWRITER. TRANSLATE must also destroy INPUT.
+ through TRANSLATE, which must return a case with
+ OUTPUT_VALUE_CNT values, based on INPUT and auxiliary data
+ AUX. (TRANSLATE may also return a null pointer, in which case
+ no case is written to the output.) The translated cases are
+ then written to SUBWRITER.
+
+ TRANSLATE takes ownership of each case passed to it. Thus, it
+ should either unref each case and return a new case, or
+ (unshare and then) modify and return the same case.
When the translating casewriter is destroyed, DESTROY will be
called to allow any state maintained by TRANSLATE to be freed.
struct casewriter *
casewriter_create_translator (struct casewriter *subwriter,
size_t translated_value_cnt,
- void (*translate) (struct ccase *input,
- struct ccase *output,
- void *aux),
+ struct ccase *(*translate) (struct ccase *,
+ void *aux),
bool (*destroy) (void *aux),
void *aux)
{
void *ct_, struct ccase *c)
{
struct casewriter_translator *ct = ct_;
- struct ccase tmp;
-
- ct->translate (c, &tmp, ct->aux);
- casewriter_write (ct->subwriter, &tmp);
+ c = ct->translate (c, ct->aux);
+ if (c != NULL)
+ casewriter_write (ct->subwriter, c);
}
static void
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
return reader;
}
-/* Reads the case at the given 0-based OFFSET from the front of
- WINDOW into C. Returns true if successful, false if
- OFFSET is beyond the end of file or upon I/O error. */
-static bool
+/* Reads and returns the case at the given 0-based OFFSET from
+ the front of WINDOW into C. Returns a null pointer if OFFSET
+ is beyond the end of file or upon I/O error. The caller must
+ call case_unref() on the returned case when it is no longer
+ needed.*/
+static struct ccase *
casereader_window_read (struct casereader *reader UNUSED, void *window_,
- casenumber offset, struct ccase *c)
+ casenumber offset)
{
struct casewindow *window = window_;
if (offset >= casewindow_get_case_cnt (window))
- return false;
- else
- return casewindow_get_case (window, offset, c);
+ return NULL;
+ return casewindow_get_case (window, offset);
}
/* Destroys casewindow reader WINDOW. */
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
\f
struct casewriter *
casewriter_create_translator (struct casewriter *, size_t translated_value_cnt,
- void (*translate) (struct ccase *input,
- struct ccase *output,
- void *aux),
+ struct ccase *(*translate) (struct ccase *input,
+ void *aux),
bool (*destroy) (void *aux),
void *aux);
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
axis_move (ds->columns, old_start, new_start, cnt);
}
-/* Retrieves the contents of the given ROW in datasheet DS into
- newly created case C. Returns true if successful, false on
- I/O error. */
-bool
-datasheet_get_row (const struct datasheet *ds, casenumber row, struct ccase *c)
+/* Retrieves and returns the contents of the given ROW in
+ datasheet DS. The caller owns the returned case and must
+ unref it when it is no longer needed. Returns a null pointer
+ on I/O error. */
+struct ccase *
+datasheet_get_row (const struct datasheet *ds, casenumber row)
{
size_t column_cnt = datasheet_get_column_cnt (ds);
- case_create (c, column_cnt);
+ struct ccase *c = case_create (column_cnt);
if (rw_case ((struct datasheet *) ds, OP_READ,
row, 0, column_cnt, case_data_all_rw (c)))
- return true;
+ return c;
else
{
- case_destroy (c);
- return false;
+ case_unref (c);
+ return NULL;
}
}
size_t column_cnt = datasheet_get_column_cnt (ds);
bool ok = rw_case (ds, OP_WRITE, row, 0, column_cnt,
(union value *) case_data_all (c));
- case_destroy (c);
+ case_unref (c);
return ok;
}
(union value *) value);
}
-/* Inserts the CNT cases at C, which are destroyed, into
- datasheet DS just before row BEFORE. Returns true if
- successful, false on I/O error. On failure, datasheet DS is
- not modified. */
+/* Inserts the CNT cases at C into datasheet DS just before row
+ BEFORE. Returns true if successful, false on I/O error. On
+ failure, datasheet DS is not modified.
+
+ Regardless of success, this function unrefs all of the cases
+ in C. */
bool
datasheet_insert_rows (struct datasheet *ds,
- casenumber before, struct ccase c[],
+ casenumber before, struct ccase *c[],
casenumber cnt)
{
casenumber added = 0;
/* Initialize the new rows. */
for (i = 0; i < phy_cnt; i++)
- if (!datasheet_put_row (ds, before + i, &c[i]))
+ if (!datasheet_put_row (ds, before + i, c[i]))
{
while (++i < cnt)
- case_destroy (&c[i]);
+ case_unref (c[i]);
datasheet_delete_rows (ds, before - added, phy_cnt + added);
return false;
}
}
/* "read" function for the datasheet random casereader. */
-static bool
+static struct ccase *
datasheet_reader_read (struct casereader *reader UNUSED, void *ds_,
- casenumber case_idx, struct ccase *c)
+ casenumber case_idx)
{
struct datasheet *ds = ds_;
- if (case_idx >= datasheet_get_row_cnt (ds))
- return false;
- else if (datasheet_get_row (ds, case_idx, c))
- return true;
- else
+ if (case_idx < datasheet_get_row_cnt (ds))
{
- taint_set_taint (ds->taint);
- return false;
+ struct ccase *c = datasheet_get_row (ds, case_idx);
+ if (c == NULL)
+ taint_set_taint (ds->taint);
+ return c;
}
+ else
+ return NULL;
}
/* "destroy" function for the datasheet random casereader. */
return sparse_cases_read (source->data, row, column, values, value_cnt);
else
{
- struct ccase c;
- bool ok;
-
- assert (source->backing != NULL);
- ok = casereader_peek (source->backing, row, &c);
+ struct ccase *c = casereader_peek (source->backing, row);
+ bool ok = c != NULL;
if (ok)
{
- case_copy_out (&c, column, values, value_cnt);
- case_destroy (&c);
+ case_copy_out (c, column, values, value_cnt);
+ case_unref (c);
}
return ok;
}
ok = sparse_cases_write (source->data, row, column, values, value_cnt);
else
{
- struct ccase c;
+ struct ccase *c;
+
if (row < source->backing_rows)
- ok = casereader_peek (source->backing, row, &c);
+ c = case_unshare (casereader_peek (source->backing, row));
else
{
/* It's not one of the backed rows. Ideally, this
levels, so that we in fact usually write the full
contents of new, unbacked rows in multiple calls to
this function. Make this work. */
- case_create (&c, column_cnt);
- ok = true;
+ c = case_create (column_cnt);
}
+ ok = c != NULL;
+
if (ok)
{
- case_copy_in (&c, column, values, value_cnt);
+ case_copy_in (c, column, values, value_cnt);
ok = sparse_cases_write (source->data, row, 0,
- case_data_all (&c), column_cnt);
- case_destroy (&c);
+ case_data_all (c), column_cnt);
+ case_unref (c);
}
}
return ok;
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* Rows. */
casenumber datasheet_get_row_cnt (const struct datasheet *);
bool datasheet_insert_rows (struct datasheet *,
- casenumber before, struct ccase[],
+ casenumber before, struct ccase *[],
casenumber cnt);
void datasheet_delete_rows (struct datasheet *,
casenumber first, casenumber cnt);
size_t cnt);
/* Data. */
-bool datasheet_get_row (const struct datasheet *, casenumber, struct ccase *);
+struct ccase *datasheet_get_row (const struct datasheet *, casenumber);
bool datasheet_put_row (struct datasheet *, casenumber, struct ccase *);
bool datasheet_get_value (const struct datasheet *, casenumber, size_t column,
union value *, int width);
hash ^= hsh_hash_string (identity->name);
return hash;
}
+
+
+
+#ifdef WINDOWS32
+
+/* Apparently windoze users like to see output dumped into their home directory,
+ not the current directory (!) */
+const char *
+default_output_path (void)
+{
+ static const char *home_dir = NULL;
+
+ /* Windows NT defines HOMEDRIVE and HOMEPATH. But give preference
+ to HOME, because the user can change HOME. */
+ if (home_dir == NULL)
+ {
+ const char *home_drive = getenv ("HOMEDRIVE");
+ const char *home_path = getenv ("HOMEPATH");
+
+ if (home_drive != NULL && home_path != NULL)
+ home_dir = xasprintf ("%s%s%c",
+ home_drive, home_path, DIRECTORY_SEPARATOR);
+ else
+ home_dir = "c:/users/default/"; /* poor default */
+ }
+ return home_dir;
+}
+
+#else
+
+/* ... whereas the rest of the world just likes it to be
+ put "here" for easy access. */
+const char *
+default_output_path (void)
+{
+ static char current_dir[] = "";
+
+ return current_dir;
+}
+
+#endif
+
const struct file_identity *);
unsigned int fn_hash_identity (const struct file_identity *);
+const char * default_output_path (void);
+
#endif /* file-name.h */
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
static void gnm_file_casereader_destroy (struct casereader *, void *);
-static bool gnm_file_casereader_read (struct casereader *, void *,
- struct ccase *);
+static struct ccase *gnm_file_casereader_read (struct casereader *, void *);
static const struct casereader_class gnm_file_casereader_class =
{
size_t value_cnt;
struct dictionary *dict;
- struct ccase first_case;
+ struct ccase *first_case;
bool used_first_case;
};
xmlFreeTextReader (r->xtr);
if ( ! r->used_first_case )
- case_destroy (&r->first_case);
+ case_unref (r->first_case);
free (r);
}
goto error;
}
- case_create (&r->first_case, r->value_cnt);
- memset (case_data_rw_idx (&r->first_case, 0)->s,
+ r->first_case = case_create (r->value_cnt);
+ memset (case_data_rw_idx (r->first_case, 0)->s,
' ', MAX_SHORT_STRING * r->value_cnt);
for ( i = 0 ; i < n_var_specs ; ++i )
{
const struct variable *var = dict_get_var (r->dict, i);
- convert_xml_string_to_value (&r->first_case, var,
+ convert_xml_string_to_value (r->first_case, var,
var_spec[i].first_value);
}
};
-/* Reads one case from READER's file into C. Returns true only
- if successful. */
-static bool
-gnm_file_casereader_read (struct casereader *reader UNUSED, void *r_,
- struct ccase *c)
+/* Reads and returns one case from READER's file. Returns a null
+ pointer on failure. */
+static struct ccase *
+gnm_file_casereader_read (struct casereader *reader UNUSED, void *r_)
{
+ struct ccase *c;
int ret = 0;
struct gnumeric_reader *r = r_;
if ( !r->used_first_case )
{
- *c = r->first_case;
r->used_first_case = true;
- return true;
+ return r->first_case;
}
- case_create (c, r->value_cnt);
+ c = case_create (r->value_cnt);
memset (case_data_rw_idx (c, 0)->s, ' ', MAX_SHORT_STRING * r->value_cnt);
}
- return (ret == 1);
+ if (ret == 1)
+ return c;
+ else
+ {
+ case_unref (c);
+ return NULL;
+ }
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
casereader_destroy (subreader);
}
-static bool
-lazy_casereader_read (struct casereader *reader, void *lc_,
- struct ccase *c)
+static struct ccase *
+lazy_casereader_read (struct casereader *reader, void *lc_)
{
struct lazy_casereader *lc = lc_;
instantiate_lazy_casereader (reader, lc);
- return casereader_read (reader, c);
+ return casereader_read (reader);
}
static void
return casereader_clone (reader);
}
-static bool
-lazy_casereader_peek (struct casereader *reader, void *lc_,
- casenumber idx, struct ccase *c)
+static struct ccase *
+lazy_casereader_peek (struct casereader *reader, void *lc_, casenumber idx)
{
struct lazy_casereader *lc = lc_;
instantiate_lazy_casereader (reader, lc);
- return casereader_peek (reader, idx, c);
+ return casereader_peek (reader, idx);
}
static const struct casereader_class lazy_casereader_class =
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
}
}
-/* Reads one case from portable file R into C. */
-static bool
-por_file_casereader_read (struct casereader *reader, void *r_, struct ccase *c)
+/* Reads and returns one case from portable file R. Returns a
+ null pointer on failure. */
+static struct ccase *
+por_file_casereader_read (struct casereader *reader, void *r_)
{
struct pfm_reader *r = r_;
+ struct ccase *volatile c;
size_t i;
size_t idx;
- case_create (c, casereader_get_value_cnt (reader));
+ c = case_create (casereader_get_value_cnt (reader));
setjmp (r->bail_out);
if (!r->ok)
{
casereader_force_error (reader);
- case_destroy (c);
- return false;
+ case_unref (c);
+ return NULL;
}
/* Check for end of file. */
if (r->cc == 'Z')
{
- case_destroy (c);
- return false;
+ case_unref (c);
+ return NULL;
}
idx = 0;
}
}
- return true;
+ return c;
}
/* Returns true if FILE is an SPSS portable file,
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
struct dictionary;
struct file_handle;
-struct ccase;
struct casereader *pfm_open_reader (struct file_handle *,
struct dictionary **,
struct pfm_read_info *);
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
else
casewriter_force_error (writer);
- case_destroy (c);
+ case_unref (c);
}
static void
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
struct file_handle;
struct dictionary;
-struct ccase;
struct casewriter *pfm_open_writer (struct file_handle *, struct dictionary *,
struct pfm_write_options);
struct pfm_write_options pfm_writer_default_options (void);
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* Cases just before ("lagging") the current one. */
int n_lag; /* Number of cases to lag. */
struct deque lag; /* Deque of lagged cases. */
- struct ccase *lag_cases; /* Lagged cases managed by deque. */
+ struct ccase **lag_cases; /* Lagged cases managed by deque. */
/* Procedure data. */
enum
}
/* "read" function for procedure casereader. */
-static bool
-proc_casereader_read (struct casereader *reader UNUSED, void *ds_,
- struct ccase *c)
+static struct ccase *
+proc_casereader_read (struct casereader *reader UNUSED, void *ds_)
{
struct dataset *ds = ds_;
enum trns_result retval = TRNS_DROP_CASE;
+ struct ccase *c;
assert (ds->proc_state == PROC_OPEN);
- for (;;)
+ for (; ; case_unref (c))
{
casenumber case_nr;
if (retval == TRNS_ERROR)
ds->ok = false;
if (!ds->ok)
- return false;
+ return NULL;
/* Read a case from source. */
- if (!casereader_read (ds->source, c))
- return false;
- case_resize (c, dict_get_next_value_idx (ds->dict));
+ c = casereader_read (ds->source);
+ if (c == NULL)
+ return NULL;
+ c = case_unshare_and_resize (c, dict_get_next_value_idx (ds->dict));
caseinit_init_vars (ds->caseinit, c);
/* Execute permanent transformations. */
case_nr = ds->cases_written + 1;
retval = trns_chain_execute (ds->permanent_trns_chain, TRNS_CONTINUE,
- c, case_nr);
+ &c, case_nr);
caseinit_update_left_vars (ds->caseinit, c);
if (retval != TRNS_CONTINUE)
- {
- case_destroy (c);
- continue;
- }
+ continue;
/* Write case to collection of lagged cases. */
if (ds->n_lag > 0)
{
while (deque_count (&ds->lag) >= ds->n_lag)
- case_destroy (&ds->lag_cases[deque_pop_back (&ds->lag)]);
- case_clone (&ds->lag_cases[deque_push_front (&ds->lag)], c);
+ case_unref (ds->lag_cases[deque_pop_back (&ds->lag)]);
+ ds->lag_cases[deque_push_front (&ds->lag)] = case_ref (c);
}
/* Write case to replacement active file. */
ds->cases_written++;
if (ds->sink != NULL)
- {
- struct ccase tmp;
- if (ds->compactor != NULL)
- case_map_execute (ds->compactor, c, &tmp);
- else
- case_clone (&tmp, c);
- casewriter_write (ds->sink, &tmp);
- }
+ casewriter_write (ds->sink,
+ case_map_execute (ds->compactor, case_ref (c)));
/* Execute temporary transformations. */
if (ds->temporary_trns_chain != NULL)
{
retval = trns_chain_execute (ds->temporary_trns_chain, TRNS_CONTINUE,
- c, ds->cases_written);
+ &c, ds->cases_written);
if (retval != TRNS_CONTINUE)
- {
- case_destroy (c);
- continue;
- }
+ continue;
}
- return true;
+ return c;
}
}
proc_casereader_destroy (struct casereader *reader, void *ds_)
{
struct dataset *ds = ds_;
- struct ccase c;
+ struct ccase *c;
/* Make sure transformations happen for every input case, in
case they have side effects, and ensure that the replacement
active file gets all the cases it should. */
- while (casereader_read (reader, &c))
- case_destroy (&c);
+ while ((c = casereader_read (reader)) != NULL)
+ case_unref (c);
ds->proc_state = PROC_CLOSED;
ds->ok = casereader_destroy (ds->source) && ds->ok;
/* Free memory for lagged cases. */
while (!deque_is_empty (&ds->lag))
- case_destroy (&ds->lag_cases[deque_pop_back (&ds->lag)]);
+ case_unref (ds->lag_cases[deque_pop_back (&ds->lag)]);
free (ds->lag_cases);
/* Dictionary from before TEMPORARY becomes permanent. */
\f
/* Returns a pointer to the lagged case from N_BEFORE cases before the
current one, or NULL if there haven't been that many cases yet. */
-struct ccase *
+const struct ccase *
lagged_case (const struct dataset *ds, int n_before)
{
assert (n_before >= 1);
assert (n_before <= ds->n_lag);
if (n_before <= deque_count (&ds->lag))
- return &ds->lag_cases[deque_front (&ds->lag, n_before - 1)];
+ return ds->lag_cases[deque_front (&ds->lag, n_before - 1)];
else
return NULL;
}
*CASES_REMAINING. */
static int
case_limit_trns_proc (void *cases_remaining_,
- struct ccase *c UNUSED, casenumber case_nr UNUSED)
+ struct ccase **c UNUSED, casenumber case_nr UNUSED)
{
size_t *cases_remaining = cases_remaining_;
if (*cases_remaining > 0)
/* FILTER transformation. */
static int
filter_trns_proc (void *filter_var_,
- struct ccase *c UNUSED, casenumber case_nr UNUSED)
+ struct ccase **c UNUSED, casenumber case_nr UNUSED)
{
struct variable *filter_var = filter_var_;
- double f = case_num (c, filter_var);
+ double f = case_num (*c, filter_var);
return (f != 0.0 && !var_is_num_missing (filter_var, f, MV_ANY)
? TRNS_CONTINUE : TRNS_DROP_CASE);
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
const struct casereader *dataset_source (const struct dataset *ds);
-struct ccase *lagged_case (const struct dataset *ds, int n_before);
+const struct ccase *lagged_case (const struct dataset *ds, int n_before);
void dataset_need_lag (struct dataset *ds, int n_before);
#endif /* procedure.h */
/* PSPP - a program for statistical analysis.
- Copyright (C) 2008 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
static void psql_casereader_destroy (struct casereader *reader UNUSED, void *r_);
-static bool psql_casereader_read (struct casereader *, void *,
- struct ccase *);
+static struct ccase *psql_casereader_read (struct casereader *, void *);
static const struct casereader_class psql_casereader_class =
{
};
-static bool set_value (struct psql_reader *r,
- struct ccase *cc);
+static struct ccase *set_value (struct psql_reader *r);
-static bool
-psql_casereader_read (struct casereader *reader UNUSED, void *r_,
- struct ccase *cc)
+static struct ccase *
+psql_casereader_read (struct casereader *reader UNUSED, void *r_)
{
struct psql_reader *r = r_;
return false;
}
- return set_value (r, cc);
+ return set_value (r);
}
-static bool
-set_value (struct psql_reader *r,
- struct ccase *c)
+static struct ccase *
+set_value (struct psql_reader *r)
{
- int i;
+ struct ccase *c;
int n_vars;
+ int i;
assert (r->res);
n_vars = PQnfields (r->res);
if ( r->tuple >= PQntuples (r->res))
- return false;
+ return NULL;
- case_create (c, r->value_cnt);
+ c = case_create (r->value_cnt);
memset (case_data_rw_idx (c, 0)->s, ' ', MAX_SHORT_STRING * r->value_cnt);
r->tuple++;
- return true;
+ return c;
}
#endif
/* PSPP - a program for statistical analysis.
- Copyright (C) 2006 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
struct dictionary;
struct file_handle;
-struct ccase;
struct casereader *scratch_reader_open (struct file_handle *,
struct dictionary **);
/* PSPP - a program for statistical analysis.
- Copyright (C) 2006 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
struct ccase *c)
{
struct scratch_writer *writer = writer_;
- struct ccase tmp;
- if (writer->compactor)
- {
- case_map_execute (writer->compactor, c, &tmp);
- case_destroy (c);
- }
- else
- case_move (&tmp, c);
- casewriter_write (writer->subwriter, &tmp);
+ casewriter_write (writer->subwriter,
+ case_map_execute (writer->compactor, c));
}
/* Closes WRITER. */
/* PSPP - a program for statistical analysis.
- Copyright (C) 2006 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
struct dictionary;
struct file_handle;
-struct ccase;
struct casewriter *scratch_writer_open (struct file_handle *,
const struct dictionary *);
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include <stdlib.h>
#include <string.h>
+#include <data/case.h>
#include <data/settings.h>
#include <data/case-tmpfile.h>
#include <libpspp/assertion.h>
sc->column_cnt = column_cnt;
sc->default_columns = NULL;
sc->max_memory_cases = settings_get_workspace_cases (column_cnt);
- sc->memory = sparse_array_create (sizeof (struct ccase));
+ sc->memory = sparse_array_create (sizeof (struct ccase *));
sc->disk = NULL;
sc->disk_cases = NULL;
return sc;
if (old->memory != NULL)
{
unsigned long int idx;
- struct ccase *c;
+ struct ccase **cp;
- new->memory = sparse_array_create (sizeof (struct ccase));
- for (c = sparse_array_scan (old->memory, NULL, &idx); c != NULL;
- c = sparse_array_scan (old->memory, &idx, &idx))
- case_clone (sparse_array_insert (new->memory, idx), c);
+ new->memory = sparse_array_create (sizeof (struct ccase *));
+ for (cp = sparse_array_scan (old->memory, NULL, &idx); cp != NULL;
+ cp = sparse_array_scan (old->memory, &idx, &idx))
+ {
+ struct ccase **ncp = sparse_array_insert (new->memory, idx);
+ *ncp = case_ref (*cp);
+ }
}
else
new->memory = NULL;
unsigned long int start = range_set_node_get_start (node);
unsigned long int end = range_set_node_get_end (node);
unsigned long int idx;
- struct ccase c;
-
- for (idx = start; idx < end; idx++)
- if (!case_tmpfile_get_case (old->disk, idx, &c)
- || !case_tmpfile_put_case (new->disk, idx, &c))
- {
- sparse_cases_destroy (new);
- return NULL;
- }
+
+ for (idx = start; idx < end; idx++)
+ {
+ struct ccase *c = case_tmpfile_get_case (old->disk, idx);
+ if (c == NULL || !case_tmpfile_put_case (new->disk, idx, c))
+ {
+ sparse_cases_destroy (new);
+ return NULL;
+ }
+ }
}
}
else
if (sc->memory != NULL)
{
unsigned long int idx;
- struct ccase *c;
- for (c = sparse_array_scan (sc->memory, NULL, &idx); c != NULL;
- c = sparse_array_scan (sc->memory, &idx, &idx))
- case_destroy (c);
+ struct ccase **cp;
+ for (cp = sparse_array_scan (sc->memory, NULL, &idx); cp != NULL;
+ cp = sparse_array_scan (sc->memory, &idx, &idx))
+ case_unref (*cp);
sparse_array_destroy (sc->memory);
}
free (sc->default_columns);
dump_sparse_cases_to_disk (struct sparse_cases *sc)
{
unsigned long int idx;
- struct ccase *c;
+ struct ccase **cp;
assert (sc->memory != NULL);
assert (sc->disk == NULL);
sc->disk = case_tmpfile_create (sc->column_cnt);
sc->disk_cases = range_set_create ();
- for (c = sparse_array_scan (sc->memory, NULL, &idx); c != NULL;
- c = sparse_array_scan (sc->memory, &idx, &idx))
+ for (cp = sparse_array_scan (sc->memory, NULL, &idx); cp != NULL;
+ cp = sparse_array_scan (sc->memory, &idx, &idx))
{
- if (!case_tmpfile_put_case (sc->disk, idx, c))
+ if (!case_tmpfile_put_case (sc->disk, idx, *cp))
{
case_tmpfile_destroy (sc->disk);
sc->disk = NULL;
if (sparse_cases_contains_row (sc, row))
{
- struct ccase c;
+ struct ccase *c;
if (sc->memory != NULL)
- case_clone (&c, sparse_array_get (sc->memory, row));
- else if (!case_tmpfile_get_case (sc->disk, row, &c))
- return false;
- case_copy_out (&c, column, values, value_cnt);
- case_destroy (&c);
+ {
+ struct ccase **cp = sparse_array_get (sc->memory, row);
+ c = case_ref (*cp);
+ }
+ else
+ {
+ c = case_tmpfile_get_case (sc->disk, row);
+ if (c == NULL)
+ return false;
+ }
+ case_copy_out (c, column, values, value_cnt);
+ case_unref (c);
}
else
{
write_disk_case (struct sparse_cases *sc, casenumber row, size_t column,
const union value values[], size_t value_cnt)
{
- struct ccase c;
+ struct ccase *c;
bool ok;
/* Get current case data. */
if (column == 0 && value_cnt == sc->column_cnt)
- case_create (&c, sc->column_cnt);
- else if (!case_tmpfile_get_case (sc->disk, row, &c))
- return false;
+ c = case_create (sc->column_cnt);
+ else
+ {
+ c = case_tmpfile_get_case (sc->disk, row);
+ if (c == NULL)
+ return false;
+ }
/* Copy in new data. */
- case_copy_in (&c, column, values, value_cnt);
+ case_copy_in (c, column, values, value_cnt);
/* Write new case. */
- ok = case_tmpfile_put_case (sc->disk, row, &c);
+ ok = case_tmpfile_put_case (sc->disk, row, c);
if (ok)
range_set_insert (sc->disk_cases, row, 1);
{
if (sc->memory != NULL)
{
- struct ccase *c = sparse_array_get (sc->memory, row);
- if (c == NULL)
+ struct ccase *c, **cp;
+ cp = sparse_array_get (sc->memory, row);
+ if (cp != NULL)
+ c = *cp = case_unshare (*cp);
+ else
{
if (sparse_array_count (sc->memory) >= sc->max_memory_cases)
{
return write_disk_case (sc, row, column, values, value_cnt);
}
- c = sparse_array_insert (sc->memory, row);
- case_create (c, sc->column_cnt);
+ cp = sparse_array_insert (sc->memory, row);
+ c = *cp = case_create (sc->column_cnt);
if (sc->default_columns != NULL
&& (column != 0 || value_cnt != sc->column_cnt))
case_copy_in (c, 0, sc->default_columns, sc->column_cnt);
/* Set individual rows. */
if (sc->memory != NULL)
{
- struct ccase *c;
+ struct ccase **cp;
unsigned long int idx;
- for (c = sparse_array_scan (sc->memory, NULL, &idx); c != NULL;
- c = sparse_array_scan (sc->memory, &idx, &idx))
- case_copy_in (c, start_column, values, value_cnt);
+ for (cp = sparse_array_scan (sc->memory, NULL, &idx); cp != NULL;
+ cp = sparse_array_scan (sc->memory, &idx, &idx))
+ {
+ *cp = case_unshare (*cp);
+ case_copy_in (*cp, start_column, values, value_cnt);
+ }
}
else
{
/* PSPP - a program for statistical analysis.
- Copyright (C) 2008 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* Copies the fields in SRC represented by SRC_SC into the
corresponding fields in DST respresented by DST_SC. SRC_SC
and DST_SC must be conformable (as tested by
- subcase_conformable()). */
+ subcase_conformable()).
+
+ DST must not be shared. */
void
subcase_copy (const struct subcase *src_sc, const struct ccase *src,
const struct subcase *dst_sc, struct ccase *dst)
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
static bool read_whole_strings (struct sfm_reader *, char *, size_t);
static bool skip_whole_strings (struct sfm_reader *, size_t);
-/* Reads one case from READER's file into C. Returns true only
- if successful. */
-static bool
-sys_file_casereader_read (struct casereader *reader, void *r_,
- struct ccase *c)
+/* Reads and returns one case from READER's file. Returns a null
+ pointer if not successful. */
+static struct ccase *
+sys_file_casereader_read (struct casereader *reader, void *r_)
{
struct sfm_reader *r = r_;
+ struct ccase *volatile c;
int i;
if (r->error)
- return false;
+ return NULL;
- case_create (c, r->value_cnt);
+ c = case_create (r->value_cnt);
if (setjmp (r->bail_out))
{
casereader_force_error (reader);
- case_destroy (c);
- return false;
+ case_unref (c);
+ return NULL;
}
for (i = 0; i < r->sfm_var_cnt; i++)
partial_record (r);
}
}
- return true;
+ return c;
eof:
- case_destroy (c);
+ case_unref (c);
if (i != 0)
partial_record (r);
if (r->case_cnt != -1)
read_error (reader, r);
- return false;
+ return NULL;
}
/* Issues an error that R ends in a partial record. */
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
struct dictionary;
struct file_handle;
-struct ccase;
struct casereader *sfm_open_reader (struct file_handle *,
struct dictionary **,
struct sfm_read_info *);
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
static void write_spaces (struct sfm_writer *, size_t);
static void write_value (struct sfm_writer *, const union value *, int width);
-static void write_case_uncompressed (struct sfm_writer *, struct ccase *);
-static void write_case_compressed (struct sfm_writer *, struct ccase *);
+static void write_case_uncompressed (struct sfm_writer *,
+ const struct ccase *);
+static void write_case_compressed (struct sfm_writer *, const struct ccase *);
static void flush_compressed (struct sfm_writer *);
static void put_cmp_opcode (struct sfm_writer *, uint8_t);
static void put_cmp_number (struct sfm_writer *, double);
if (ferror (w->file))
{
casewriter_force_error (writer);
- case_destroy (c);
+ case_unref (c);
return;
}
else
write_case_compressed (w, c);
- case_destroy (c);
+ case_unref (c);
}
/* Destroys system file writer W. */
\f
/* Writes case C to system file W, without compressing it. */
static void
-write_case_uncompressed (struct sfm_writer *w, struct ccase *c)
+write_case_uncompressed (struct sfm_writer *w, const struct ccase *c)
{
size_t i;
/* Writes case C to system file W, with compression. */
static void
-write_case_compressed (struct sfm_writer *w, struct ccase *c)
+write_case_compressed (struct sfm_writer *w, const struct ccase *c)
{
size_t i;
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
struct file_handle;
struct dictionary;
-struct ccase;
struct casewriter *sfm_open_writer (struct file_handle *, struct dictionary *,
struct sfm_write_options);
struct sfm_write_options sfm_writer_default_options (void);
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
return chain->trns_cnt;
}
-/* Executes the given CHAIN of transformations on C,
+/* Executes the given CHAIN of transformations on *C,
passing CASE_NR as the case number.
+ *C may be replaced by a new case.
Returns the result code that caused the transformations to
terminate, or TRNS_CONTINUE if the transformations finished
due to "falling off the end" of the set of transformations. */
enum trns_result
trns_chain_execute (const struct trns_chain *chain, enum trns_result start,
- struct ccase *c, casenumber case_nr)
+ struct ccase **c, casenumber case_nr)
{
size_t i;
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
struct ccase;
typedef void trns_finalize_func (void *);
-typedef int trns_proc_func (void *, struct ccase *, casenumber);
+typedef int trns_proc_func (void *, struct ccase **, casenumber);
typedef bool trns_free_func (void *);
\f
/* Transformation chains. */
void trns_chain_append (struct trns_chain *, trns_finalize_func *,
trns_proc_func *, trns_free_func *, void *);
size_t trns_chain_next (struct trns_chain *);
-enum trns_result trns_chain_execute (const struct trns_chain *, enum trns_result,
- struct ccase *, casenumber case_nr);
+enum trns_result trns_chain_execute (const struct trns_chain *,
+ enum trns_result, struct ccase **,
+ casenumber case_nr);
void trns_chain_splice (struct trns_chain *, struct trns_chain *);
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
return new_var;
}
-/* Create a variable to be used for internal calculations only */
+/* Create a variable to be used for internal calculations only.
+ The variable is assigned a unique dictionary index and a case
+ index of CASE_IDX. */
struct variable *
var_create_internal (int case_idx)
{
struct variable *v = var_create ("$internal", 0);
-
struct vardict_info vdi;
+ static int counter = INT_MAX / 2;
vdi.dict = NULL;
- vdi.dict_index = 0;
vdi.case_index = case_idx;
+ vdi.dict_index = counter++;
+ if (counter == INT_MAX)
+ counter = INT_MAX / 2;
var_set_vardict (v, &vdi);
src_language_liblanguage_la_LIBADD = \
- lib/misc/libmisc.la \
src/output/charts/libcharts.la
src_language_liblanguage_la_SOURCES = \
DEF_CMD (S_DATA, 0, "AGGREGATE", cmd_aggregate)
DEF_CMD (S_DATA, 0, "AUTORECODE", cmd_autorecode)
DEF_CMD (S_DATA, F_KEEP_FINAL_TOKEN, "BEGIN DATA", cmd_begin_data)
-DEF_CMD (S_DATA, 0, "CORRELATIONS", cmd_correlations)
DEF_CMD (S_DATA, 0, "COUNT", cmd_count)
DEF_CMD (S_DATA, 0, "CROSSTABS", cmd_crosstabs)
DEF_CMD (S_DATA, 0, "DELETE VARIABLES", cmd_delete_variables)
DEF_CMD (S_DATA, 0, "MODIFY VARS", cmd_modify_vars)
DEF_CMD (S_DATA, 0, "NPAR TESTS", cmd_npar_tests)
DEF_CMD (S_DATA, 0, "ONEWAY", cmd_oneway)
-DEF_CMD (S_DATA, 0, "PEARSON CORRELATIONS", cmd_correlations)
DEF_CMD (S_DATA, 0, "RANK", cmd_rank)
DEF_CMD (S_DATA, 0, "REGRESSION", cmd_regression)
DEF_CMD (S_DATA, 0, "RELIABILITY", cmd_reliability)
UNIMPL_CMD ("CLEAR TRANSFORMATIONS", "Clears transformations from active file")
UNIMPL_CMD ("CLUSTER", "Hierachial clustering")
UNIMPL_CMD ("CONJOINT", "Analyse full concept data")
+UNIMPL_CMD ("CORRELATIONS", "Correlation coefficients")
UNIMPL_CMD ("CORRESPONDENCE", "Show correspondence")
UNIMPL_CMD ("COXREG", "Cox proportional hazards regression")
UNIMPL_CMD ("CREATE", "Create time series data")
UNIMPL_CMD ("OVERALS", "Nonlinear canonical correlation")
UNIMPL_CMD ("PACF", "Partial autocorrelation")
UNIMPL_CMD ("PARTIAL CORR", "Partial correlation")
+UNIMPL_CMD ("PEARSON CORRELATIONS", "Correlation coefficients")
UNIMPL_CMD ("PLANCARDS", "Conjoint analysis planning")
UNIMPL_CMD ("PLUM", "Estimate ordinal regression models")
UNIMPL_CMD ("POINT", "Marker in keyed file")
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Checks each clause and jumps to the appropriate
transformation. */
static int
-do_if_trns_proc (void *do_if_, struct ccase *c, casenumber case_num UNUSED)
+do_if_trns_proc (void *do_if_, struct ccase **c, casenumber case_num UNUSED)
{
struct do_if_trns *do_if = do_if_;
struct clause *clause;
{
if (clause->condition != NULL)
{
- double boolean = expr_evaluate_num (clause->condition, c, case_num);
+ double boolean = expr_evaluate_num (clause->condition, *c, case_num);
if (boolean == 1.0)
return clause->target_index;
else if (boolean == SYSMIS)
/* Breaks out of a DO IF construct. */
static int
-break_trns_proc (void *do_if_, struct ccase *c UNUSED, casenumber case_num UNUSED)
+break_trns_proc (void *do_if_, struct ccase **c UNUSED,
+ casenumber case_num UNUSED)
{
struct do_if_trns *do_if = do_if_;
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* Sets up LOOP for the first pass. */
static int
-loop_trns_proc (void *loop_, struct ccase *c, casenumber case_num)
+loop_trns_proc (void *loop_, struct ccase **c, casenumber case_num)
{
struct loop_trns *loop = loop_;
if (loop->index_var != NULL)
{
/* Evaluate loop index expressions. */
- loop->cur = expr_evaluate_num (loop->first_expr, c, case_num);
+ loop->cur = expr_evaluate_num (loop->first_expr, *c, case_num);
if (loop->by_expr != NULL)
- loop->by = expr_evaluate_num (loop->by_expr, c, case_num);
- loop->last = expr_evaluate_num (loop->last_expr, c, case_num);
+ loop->by = expr_evaluate_num (loop->by_expr, *c, case_num);
+ loop->last = expr_evaluate_num (loop->last_expr, *c, case_num);
/* Even if the loop is never entered, set the index
variable to the initial value. */
- case_data_rw (c, loop->index_var)->f = loop->cur;
+ *c = case_unshare (*c);
+ case_data_rw (*c, loop->index_var)->f = loop->cur;
/* Throw out pathological cases. */
if (!isfinite (loop->cur) || !isfinite (loop->by)
/* Check condition. */
if (loop->loop_condition != NULL
- && expr_evaluate_num (loop->loop_condition, c, case_num) != 1.0)
+ && expr_evaluate_num (loop->loop_condition, *c, case_num) != 1.0)
goto zero_pass;
return loop->past_LOOP_index;
/* Finishes a pass through the loop and starts the next. */
static int
-end_loop_trns_proc (void *loop_, struct ccase *c, casenumber case_num UNUSED)
+end_loop_trns_proc (void *loop_, struct ccase **c, casenumber case_num UNUSED)
{
struct loop_trns *loop = loop_;
if (loop->end_loop_condition != NULL
- && expr_evaluate_num (loop->end_loop_condition, c, case_num) != 0.0)
+ && expr_evaluate_num (loop->end_loop_condition, *c, case_num) != 0.0)
goto break_out;
/* MXLOOPS limiter. */
if ((loop->by > 0.0 && loop->cur > loop->last)
|| (loop->by < 0.0 && loop->cur < loop->last))
goto break_out;
- case_data_rw (c, loop->index_var)->f = loop->cur;
+ *c = case_unshare (*c);
+ case_data_rw (*c, loop->index_var)->f = loop->cur;
}
if (loop->loop_condition != NULL
- && expr_evaluate_num (loop->loop_condition, c, case_num) != 1.0)
+ && expr_evaluate_num (loop->loop_condition, *c, case_num) != 1.0)
goto break_out;
return loop->past_LOOP_index;
/* Executes BREAK. */
static int
-break_trns_proc (void *loop_, struct ccase *c UNUSED, casenumber case_num UNUSED)
+break_trns_proc (void *loop_, struct ccase **c UNUSED,
+ casenumber case_num UNUSED)
{
struct loop_trns *loop = loop_;
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
struct file_handle *handle; /* Input file handle. */
struct dictionary *dict; /* Input file dictionary. */
struct casereader *reader; /* Input data source. */
- struct ccase data; /* The current input case. */
+ struct ccase *data; /* The current input case. */
bool is_minimal; /* Does 'data' have minimum BY values across
all input files? */
bool is_sorted; /* Is file presorted on the BY variables? */
members used. */
struct variable *first; /* Variable specified on FIRST (if any). */
struct variable *last; /* Variable specified on LAST (if any). */
- struct ccase buffered_case; /* Case ready for output except that we don't
- know the value for the LAST variable yet. */
+ struct ccase *buffered_case; /* Case ready for output except that we don't
+ know the value for the LAST var yet. */
union value *prev_BY; /* Values of BY vars in buffered_case. */
};
subcase_init_empty (&proc.by_vars);
proc.first = NULL;
proc.last = NULL;
- case_nullify (&proc.buffered_case);
+ proc.buffered_case = NULL;
proc.prev_BY = NULL;
dict_set_case_limit (proc.dict, dict_get_case_limit (dataset_dict (ds)));
file->handle = NULL;
file->dict = NULL;
file->reader = NULL;
- case_nullify (&file->data);
+ file->data = NULL;
file->is_sorted = true;
file->in_name[0] = '\0';
file->in_var = NULL;
if (!file->is_sorted)
file->reader = sort_execute (file->reader, &file->by_vars);
taint_propagate (casereader_get_taint (file->reader), taint);
- casereader_read (file->reader, &file->data);
+ file->data = casereader_read (file->reader);
if (file->type == COMB_FILE)
case_matcher_add_input (proc.matcher, &file->by_vars,
&file->data, &file->is_minimal);
fh_unref (file->handle);
dict_destroy (file->dict);
casereader_destroy (file->reader);
- case_destroy (&file->data);
+ case_unref (file->data);
}
free (proc->files);
proc->files = NULL;
casewriter_destroy (proc->output);
case_matcher_destroy (proc->matcher);
subcase_destroy (&proc->by_vars);
- case_destroy (&proc->buffered_case);
+ case_unref (proc->buffered_case);
free (proc->prev_BY);
}
\f
static bool scan_table (struct comb_file *, union value by[]);
-static void create_output_case (const struct comb_proc *, struct ccase *);
+static struct ccase *create_output_case (const struct comb_proc *);
static void apply_case (const struct comb_file *, struct ccase *);
static void apply_file_case_and_advance (struct comb_file *, struct ccase *,
union value by[]);
while (case_matcher_match (proc->matcher, &by))
{
- struct ccase output;
size_t i;
for (i = 0; i < proc->n_files; i++)
struct comb_file *file = &proc->files[i];
while (file->is_minimal)
{
- create_output_case (proc, &output);
- apply_file_case_and_advance (file, &output, by);
- output_case (proc, &output, by);
+ struct ccase *output = create_output_case (proc);
+ apply_file_case_and_advance (file, output, by);
+ output_case (proc, output, by);
}
}
}
while (case_matcher_match (proc->matcher, &by))
{
- struct ccase output;
+ struct ccase *output;
size_t i;
- create_output_case (proc, &output);
+ output = create_output_case (proc);
for (i = proc->n_files; i-- > 0; )
{
struct comb_file *file = &proc->files[i];
if (file->type == COMB_FILE)
{
if (file->is_minimal)
- apply_file_case_and_advance (file, &output, NULL);
+ apply_file_case_and_advance (file, output, NULL);
}
else
{
if (scan_table (file, by))
- apply_case (file, &output);
+ apply_case (file, output);
}
}
- output_case (proc, &output, by);
+ output_case (proc, output, by);
}
output_buffered_case (proc);
}
while (case_matcher_match (proc->matcher, &by))
{
struct comb_file *first, *file;
- struct ccase output;
+ struct ccase *output;
/* Find first nonnull case in array and make an output case
from it. */
- create_output_case (proc, &output);
+ output = create_output_case (proc);
for (first = &proc->files[0]; ; first++)
if (first->is_minimal)
break;
- apply_file_case_and_advance (first, &output, by);
+ apply_file_case_and_advance (first, output, by);
/* Read additional cases and update the output case from
them. (Don't update the output case from any duplicate
file < &proc->files[proc->n_files]; file++)
{
while (file->is_minimal)
- apply_file_case_and_advance (file, &output, by);
+ apply_file_case_and_advance (file, output, by);
}
- casewriter_write (proc->output, &output);
+ casewriter_write (proc->output, output);
/* Write duplicate cases in the master file directly to the
output. */
n_duplicates++;
while (first->is_minimal)
{
- create_output_case (proc, &output);
- apply_file_case_and_advance (first, &output, by);
- casewriter_write (proc->output, &output);
+ output = create_output_case (proc);
+ apply_file_case_and_advance (first, output, by);
+ casewriter_write (proc->output, output);
}
}
}
static bool
scan_table (struct comb_file *file, union value by[])
{
- while (!case_is_null (&file->data))
+ while (file->data != NULL)
{
- int cmp = subcase_compare_3way_xc (&file->by_vars, by, &file->data);
+ int cmp = subcase_compare_3way_xc (&file->by_vars, by, file->data);
if (cmp > 0)
{
- case_destroy (&file->data);
- casereader_read (file->reader, &file->data);
+ case_unref (file->data);
+ file->data = casereader_read (file->reader);
}
else
return cmp == 0;
return false;
}
-/* Creates OUTPUT as an output case for PROC, by initializing each of
- its values to system-missing or blanks, except that the values
- of IN variables are set to 0. */
-static void
-create_output_case (const struct comb_proc *proc, struct ccase *output)
+/* Creates and returns an output case for PROC, initializing each
+ of its values to system-missing or blanks, except that the
+ values of IN variables are set to 0. */
+static struct ccase *
+create_output_case (const struct comb_proc *proc)
{
size_t n_vars = dict_get_var_cnt (proc->dict);
+ struct ccase *output;
size_t i;
- case_create (output, dict_get_next_value_idx (proc->dict));
+ output = case_create (dict_get_next_value_idx (proc->dict));
for (i = 0; i < n_vars; i++)
{
struct variable *v = dict_get_var (proc->dict, i);
if (file->in_var != NULL)
case_data_rw (output, file->in_var)->f = false;
}
+ return output;
}
/* Copies the data from FILE's case into output case OUTPUT.
static void
apply_case (const struct comb_file *file, struct ccase *output)
{
- subcase_copy (&file->src, &file->data, &file->dst, output);
+ subcase_copy (&file->src, file->data, &file->dst, output);
if (file->in_var != NULL)
case_data_rw (output, file->in_var)->f = true;
}
union value by[])
{
apply_case (file, output);
- case_destroy (&file->data);
- casereader_read (file->reader, &file->data);
+ case_unref (file->data);
+ file->data = casereader_read (file->reader);
if (by)
- file->is_minimal = (!case_is_null (&file->data)
- && subcase_equal_cx (&file->by_vars, &file->data, by));
+ file->is_minimal = (file->data != NULL
+ && subcase_equal_cx (&file->by_vars, file->data, by));
}
/* Writes OUTPUT, whose BY values has been extracted into BY, to
{
new_BY = !subcase_equal_xx (&proc->by_vars, proc->prev_BY, by);
if (proc->last != NULL)
- case_data_rw (&proc->buffered_case, proc->last)->f = new_BY;
- casewriter_write (proc->output, &proc->buffered_case);
+ case_data_rw (proc->buffered_case, proc->last)->f = new_BY;
+ casewriter_write (proc->output, proc->buffered_case);
}
else
new_BY = true;
- case_move (&proc->buffered_case, output);
+ proc->buffered_case = output;
if (proc->first != NULL)
- case_data_rw (&proc->buffered_case, proc->first)->f = new_BY;
+ case_data_rw (proc->buffered_case, proc->first)->f = new_BY;
if (new_BY)
{
if (proc->prev_BY != NULL)
{
if (proc->last != NULL)
- case_data_rw (&proc->buffered_case, proc->last)->f = 1.0;
- casewriter_write (proc->output, &proc->buffered_case);
- case_nullify (&proc->buffered_case);
+ case_data_rw (proc->buffered_case, proc->last)->f = 1.0;
+ casewriter_write (proc->output, proc->buffered_case);
+ proc->buffered_case = NULL;
}
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
return true;
}
-/* Handle DATA LIST transformation TRNS, parsing data into C. */
+/* Handle DATA LIST transformation TRNS, parsing data into *C. */
static int
-data_list_trns_proc (void *trns_, struct ccase *c, casenumber case_num UNUSED)
+data_list_trns_proc (void *trns_, struct ccase **c, casenumber case_num UNUSED)
{
struct data_list_trns *trns = trns_;
int retval;
- if (data_parser_parse (trns->parser, trns->reader, c))
+ *c = case_unshare (*c);
+ if (data_parser_parse (trns->parser, trns->reader, *c))
retval = TRNS_CONTINUE;
else if (dfm_reader_error (trns->reader) || dfm_eof (trns->reader) > 1)
{
/* If there was an END subcommand handle it. */
if (trns->end != NULL)
{
- double *end = &case_data_rw (c, trns->end)->f;
+ double *end = &case_data_rw (*c, trns->end)->f;
if (retval == TRNS_END_FILE)
{
*end = 1.0;
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
static bool parse_fixed (const struct data_parser *,
struct dfm_reader *, struct ccase *);
-/* Reads a case from DFM into C, parsing it with PARSER.
- Returns true if successful, false at end of file or on I/O error. */
+/* Reads a case from DFM into C, parsing it with PARSER. Returns
+ true if successful, false at end of file or on I/O error.
+
+ Case C must not be shared. */
bool
data_parser_parse (struct data_parser *parser, struct dfm_reader *reader,
struct ccase *c)
{
bool retval;
+ assert (!case_is_shared (c));
assert (data_parser_any_fields (parser));
/* Skip the requested number of records before reading the
proc_set_active_file (ds, casereader, dict);
}
-static bool
-data_parser_casereader_read (struct casereader *reader UNUSED, void *r_,
- struct ccase *c)
+static struct ccase *
+data_parser_casereader_read (struct casereader *reader UNUSED, void *r_)
{
struct data_parser_casereader *r = r_;
- bool ok;
-
- case_create (c, r->value_cnt);
- ok = data_parser_parse (r->parser, r->reader, c);
- if (!ok)
- case_destroy (c);
- return ok;
+ struct ccase *c = case_create (r->value_cnt);
+ if (data_parser_parse (r->parser, r->reader, c))
+ return c;
+ else
+ {
+ case_unref (c);
+ return NULL;
+ }
}
static void
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
|| state >= 0);
}
-/* Reads one case into C.
- Returns true if successful, false at end of file or if an
+/* Reads and returns one case.
+ Returns the case if successful, null at end of file or if an
I/O error occurred. */
-static bool
-input_program_casereader_read (struct casereader *reader UNUSED, void *inp_,
- struct ccase *c)
+static struct ccase *
+input_program_casereader_read (struct casereader *reader UNUSED, void *inp_)
{
struct input_program_pgm *inp = inp_;
-
- case_create (c, inp->value_cnt);
+ struct ccase *c = case_create (inp->value_cnt);
do
{
assert (is_valid_state (inp->restart));
if (inp->restart == TRNS_ERROR || inp->restart == TRNS_END_FILE)
{
- case_destroy (c);
- return false;
+ case_unref (c);
+ return NULL;
}
+ c = case_unshare (c);
caseinit_init_vars (inp->init, c);
inp->restart = trns_chain_execute (inp->trns_chain, inp->restart,
- c, inp->case_nr);
+ &c, inp->case_nr);
assert (is_valid_state (inp->restart));
caseinit_update_left_vars (inp->init, c);
}
while (inp->restart < 0);
- return true;
+ return c;
}
static void
/* Outputs the current case */
int
-end_case_trns_proc (void *inp_, struct ccase *c UNUSED,
+end_case_trns_proc (void *inp_, struct ccase **c UNUSED,
casenumber case_nr UNUSED)
{
struct input_program_pgm *inp = inp_;
/* Executes a REREAD transformation. */
static int
-reread_trns_proc (void *t_, struct ccase *c, casenumber case_num)
+reread_trns_proc (void *t_, struct ccase **c, casenumber case_num)
{
struct reread_trns *t = t_;
dfm_reread_record (t->reader, 1);
else
{
- double column = expr_evaluate_num (t->column, c, case_num);
+ double column = expr_evaluate_num (t->column, *c, case_num);
if (!isfinite (column) || column < 1)
{
msg (SE, _("REREAD: Column numbers must be positive finite "
/* Executes an END FILE transformation. */
static int
-end_file_trns_proc (void *trns_ UNUSED, struct ccase *c UNUSED,
+end_file_trns_proc (void *trns_ UNUSED, struct ccase **c UNUSED,
casenumber case_num UNUSED)
{
return TRNS_END_FILE;
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
static void write_line (struct outp_driver *d, const char *s);
/* Other functions. */
-static void list_case (struct ccase *, casenumber case_idx,
+static void list_case (const struct ccase *, casenumber case_idx,
const struct dataset *);
static void determine_layout (void);
static void clean_up (void);
casegrouper_get_next_group (grouper, &group);
casereader_destroy (group))
{
- struct ccase c;
+ struct ccase *c;
write_all_headers (group, ds);
- for (; casereader_read (group, &c); case_destroy (&c))
+ for (; (c = casereader_read (group)) != NULL; case_unref (c))
{
case_idx++;
if (case_idx >= cmd.first && case_idx <= cmd.last
&& (case_idx - cmd.first) % cmd.step == 0)
- list_case (&c, case_idx, ds);
+ list_case (c, case_idx, ds);
}
}
ok = casegrouper_destroy (grouper);
write_all_headers (struct casereader *input, const struct dataset *ds)
{
struct outp_driver *d;
- struct ccase c;
+ struct ccase *c;
- if (!casereader_peek (input, 0, &c))
+ c = casereader_peek (input, 0);
+ if (c == NULL)
return;
- output_split_file_values (ds, &c);
- case_destroy (&c);
+ output_split_file_values (ds, c);
+ case_unref (c);
for (d = outp_drivers (NULL); d; d = outp_drivers (d))
{
/* Writes case C to output. */
static void
-list_case (struct ccase *c, casenumber case_idx, const struct dataset *ds)
+list_case (const struct ccase *c, casenumber case_idx,
+ const struct dataset *ds)
{
struct dictionary *dict = dataset_dict (ds);
struct outp_driver *d;
/* PSPP - a program for statistical analysis.
- Copyright (C) 2006 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* Executes a PRINT SPACE transformation. */
static int
-print_space_trns_proc (void *t_, struct ccase *c,
+print_space_trns_proc (void *t_, struct ccase **c,
casenumber case_num UNUSED)
{
struct print_space_trns *trns = t_;
n = 1;
if (trns->expr)
{
- double f = expr_evaluate_num (trns->expr, c, case_num);
+ double f = expr_evaluate_num (trns->expr, *c, case_num);
if (f == SYSMIS)
msg (SW, _("The expression on PRINT SPACE evaluated to the "
"system-missing value."));
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* Performs the transformation inside print_trns T on case C. */
static int
-print_trns_proc (void *trns_, struct ccase *c, casenumber case_num UNUSED)
+print_trns_proc (void *trns_, struct ccase **c, casenumber case_num UNUSED)
{
struct print_trns *trns = trns_;
bool eject = trns->eject;
ds_set_length (&trns->line, spec->first_column, encoded_space);
if (spec->type == PRT_VAR)
{
- const union value *input = case_data (c, spec->var);
+ const union value *input = case_data (*c, spec->var);
char *output = ds_put_uninit (&trns->line, spec->format.w);
if (!spec->sysmis_as_spaces || input->f != SYSMIS)
data_out_legacy (input, trns->encoding, &spec->format, output);
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
return NULL;
}
-/* Writes case C to the system file specified on XSAVE or XEXPORT. */
+/* Writes case *C to the system file specified on XSAVE or XEXPORT. */
static int
-output_trns_proc (void *trns_, struct ccase *c, casenumber case_num UNUSED)
+output_trns_proc (void *trns_, struct ccase **c, casenumber case_num UNUSED)
{
struct output_trns *t = trns_;
- struct ccase tmp;
- case_clone (&tmp, c);
- casewriter_write (t->writer, &tmp);
+ casewriter_write (t->writer, case_ref (*c));
return TRNS_CONTINUE;
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
}
if (c == NULL)
- {
- c = xmalloc (sizeof *c);
- case_create (c, dict_get_next_value_idx (d));
- }
+ c = case_create (dict_get_next_value_idx (d));
else
- case_resize (c, dict_get_next_value_idx (d));
+ c = case_resize (c, dict_get_next_value_idx (d));
if (lex_is_number (lexer))
case_data_rw (c, v)->f = lex_tokval (lexer);
if (ds)
destroy_dataset (ds);
- if (c != NULL)
- {
- case_destroy (c);
- free (c);
- }
+ case_unref (c);
return retval;
}
// -*- c -*-
//
// PSPP - a program for statistical analysis.
-// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+// Copyright (C) 2005, 2006, 2009 Free Software Foundation, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
no_opt perm_only function LAG (num_var v, pos_int n_before)
dataset ds;
{
- struct ccase *c = lagged_case (ds, n_before);
+ const struct ccase *c = lagged_case (ds, n_before);
if (c != NULL)
{
double x = case_num (c, v);
no_opt perm_only function LAG (num_var v)
dataset ds;
{
- struct ccase *c = lagged_case (ds, 1);
+ const struct ccase *c = lagged_case (ds, 1);
if (c != NULL)
{
double x = case_num (c, v);
expression e;
dataset ds;
{
- struct ccase *c = lagged_case (ds, n_before);
+ const struct ccase *c = lagged_case (ds, n_before);
if (c != NULL)
return copy_string (e, case_str (c, v), var_get_width (v));
else
expression e;
dataset ds;
{
- struct ccase *c = lagged_case (ds, 1);
+ const struct ccase *c = lagged_case (ds, 1);
if (c != NULL)
return copy_string (e, case_str (c, v), var_get_width (v));
else
#include <config.h>
#include "lexer.h"
#include <libpspp/message.h>
-#include <ctype.h>
+#include <c-ctype.h>
+#include <c-strtod.h>
#include <errno.h>
#include <limits.h>
#include <math.h>
for (;;)
{
/* Skip whitespace. */
- while (isspace ((unsigned char) *lexer->prog))
+ while (c_isspace ((unsigned char) *lexer->prog))
lexer->prog++;
if (*lexer->prog)
if (*lexer->prog == '-')
{
ds_put_char (&lexer->tokstr, *lexer->prog++);
- while (isspace ((unsigned char) *lexer->prog))
+ while (c_isspace ((unsigned char) *lexer->prog))
lexer->prog++;
- if (!isdigit ((unsigned char) *lexer->prog) && *lexer->prog != '.')
+ if (!c_isdigit ((unsigned char) *lexer->prog) && *lexer->prog != '.')
{
lexer->token = '-';
break;
lexer->token = T_POS_NUM;
/* Parse the number, copying it into tokstr. */
- while (isdigit ((unsigned char) *lexer->prog))
+ while (c_isdigit ((unsigned char) *lexer->prog))
ds_put_char (&lexer->tokstr, *lexer->prog++);
if (*lexer->prog == '.')
{
ds_put_char (&lexer->tokstr, *lexer->prog++);
- while (isdigit ((unsigned char) *lexer->prog))
+ while (c_isdigit ((unsigned char) *lexer->prog))
ds_put_char (&lexer->tokstr, *lexer->prog++);
}
if (*lexer->prog == 'e' || *lexer->prog == 'E')
ds_put_char (&lexer->tokstr, *lexer->prog++);
if (*lexer->prog == '+' || *lexer->prog == '-')
ds_put_char (&lexer->tokstr, *lexer->prog++);
- while (isdigit ((unsigned char) *lexer->prog))
+ while (c_isdigit ((unsigned char) *lexer->prog))
ds_put_char (&lexer->tokstr, *lexer->prog++);
}
/* Parse as floating point. */
- lexer->tokval = strtod (ds_cstr (&lexer->tokstr), &tail);
+ lexer->tokval = c_strtod (ds_cstr (&lexer->tokstr), &tail);
if (*tail)
{
msg (SE, _("%s does not form a valid number."),
}
else
{
- if (isgraph ((unsigned char) *lexer->prog))
+ if (c_isgraph ((unsigned char) *lexer->prog))
msg (SE, _("Bad character in input: `%c'."), *lexer->prog++);
else
msg (SE, _("Bad character in input: `\\%o'."), *lexer->prog++);
for (;;)
{
- while (isspace ((unsigned char) *lexer->prog))
+ while (c_isspace ((unsigned char) *lexer->prog))
lexer->prog++;
if (*lexer->prog)
break;
if (syntax == GETL_BATCH)
{
int first = ds_first (line);
- *line_starts_command = !isspace (first);
+ *line_starts_command = !c_isspace (first);
if (first == '+' || first == '-')
*ds_data (line) = ' ';
}
char *sp, *dp;
for (sp = ds_cstr (&lexer->tokstr); sp < ds_end (&lexer->tokstr); sp++)
- if (!isprint ((unsigned char) *sp))
+ if (!c_isprint ((unsigned char) *sp))
{
hexstring = 1;
break;
break;
for (;;)
{
- while (isspace ((unsigned char) *lexer->prog))
+ while (c_isspace ((unsigned char) *lexer->prog))
lexer->prog++;
if (*lexer->prog)
break;
break;
for (;;)
{
- while (isspace ((unsigned char) *lexer->prog))
+ while (c_isspace ((unsigned char) *lexer->prog))
lexer->prog++;
if (*lexer->prog)
break;
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2008 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2008, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
struct subcase sort; /* Sort criteria (break variables). */
const struct variable **break_vars; /* Break variables. */
size_t break_var_cnt; /* Number of break variables. */
- struct ccase break_case; /* Last values of break variables. */
+ struct ccase *break_case; /* Last values of break variables. */
enum missing_treatment missing; /* How to treat missing values. */
struct agr_var *agr_vars; /* First aggregate variable. */
memset(&agr, 0 , sizeof (agr));
agr.missing = ITEMWISE;
- case_nullify (&agr.break_case);
+ agr.break_case = NULL;
agr.dict = dict_create ();
agr.src_dict = dict;
casegrouper_get_next_group (grouper, &group);
casereader_destroy (group))
{
- struct ccase c;
-
- if (!casereader_peek (group, 0, &c))
+ struct ccase *c = casereader_peek (group, 0);
+ if (c == NULL)
{
casereader_destroy (group);
continue;
}
- initialize_aggregate_info (&agr, &c);
- case_destroy (&c);
+ initialize_aggregate_info (&agr, c);
+ case_unref (c);
- for (; casereader_read (group, &c); case_destroy (&c))
- accumulate_aggregate_info (&agr, &c);
+ for (; (c = casereader_read (group)) != NULL; case_unref (c))
+ accumulate_aggregate_info (&agr, c);
dump_aggregate_info (&agr, output);
}
if (!casegrouper_destroy (grouper))
subcase_destroy (&agr->sort);
free (agr->break_vars);
- case_destroy (&agr->break_case);
+ case_unref (agr->break_case);
for (iter = agr->agr_vars; iter; iter = next)
{
next = iter->next;
case MEDIAN:
{
double wv ;
- struct ccase cout;
- case_create (&cout, 2);
+ struct ccase *cout = case_create (2);
- case_data_rw (&cout, iter->subject)->f =
- case_data (input, iter->src)->f;
+ case_data_rw (cout, iter->subject)->f
+ = case_data (input, iter->src)->f;
wv = dict_get_case_weight (agr->src_dict, input, NULL);
- case_data_rw (&cout, iter->weight)->f = wv;
+ case_data_rw (cout, iter->weight)->f = wv;
iter->cc += wv;
- casewriter_write (iter->writer, &cout);
- case_destroy (&cout);
+ casewriter_write (iter->writer, cout);
}
break;
case SD:
static void
dump_aggregate_info (struct agr_proc *agr, struct casewriter *output)
{
- struct ccase c;
-
- case_create (&c, dict_get_next_value_idx (agr->dict));
+ struct ccase *c = case_create (dict_get_next_value_idx (agr->dict));
{
int value_idx = 0;
{
const struct variable *v = agr->break_vars[i];
size_t value_cnt = var_get_value_cnt (v);
- memcpy (case_data_rw_idx (&c, value_idx),
- case_data (&agr->break_case, v),
+ memcpy (case_data_rw_idx (c, value_idx),
+ case_data (agr->break_case, v),
sizeof (union value) * value_cnt);
value_idx += value_cnt;
}
for (i = agr->agr_vars; i; i = i->next)
{
- union value *v = case_data_rw (&c, i->dest);
+ union value *v = case_data_rw (c, i->dest);
if (agr->missing == COLUMNWISE && i->saw_missing
}
}
- casewriter_write (output, &c);
+ casewriter_write (output, c);
}
/* Resets the state for all the aggregate functions. */
{
struct agr_var *iter;
- case_destroy (&agr->break_case);
- case_clone (&agr->break_case, input);
+ case_unref (agr->break_case);
+ agr->break_case = case_ref (input);
for (iter = agr->agr_vars; iter; iter = iter->next)
{
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
{
struct autorecode_pgm arc;
struct casereader *input;
- struct ccase c;
+ struct ccase *c;
size_t dst_cnt;
size_t i;
bool ok;
}
input = proc_open (ds);
- for (; casereader_read (input, &c); case_destroy (&c))
+ for (; (c = casereader_read (input)) != NULL; case_unref (c))
for (i = 0; i < arc.var_cnt; i++)
{
union arc_value v, *vp, **vpp;
if (var_is_numeric (arc.src_vars[i]))
- v.f = case_num (&c, arc.src_vars[i]);
+ v.f = case_num (c, arc.src_vars[i]);
else
- v.c = (char *) case_str (&c, arc.src_vars[i]);
+ v.c = (char *) case_str (c, arc.src_vars[i]);
vpp = (union arc_value **) hsh_probe (arc.src_values[i], &v);
if (*vpp == NULL)
/* Executes an AUTORECODE transformation. */
static int
-autorecode_trns_proc (void *trns_, struct ccase *c, casenumber case_idx UNUSED)
+autorecode_trns_proc (void *trns_, struct ccase **c,
+ casenumber case_idx UNUSED)
{
struct autorecode_trns *trns = trns_;
size_t i;
+ *c = case_unshare (*c);
for (i = 0; i < trns->spec_cnt; i++)
{
struct arc_spec *spec = &trns->specs[i];
union arc_value v;
if (var_is_numeric (spec->src))
- v.f = case_num (c, spec->src);
+ v.f = case_num (*c, spec->src);
else
- v.c = (char *) case_str (c, spec->src);
+ v.c = (char *) case_str (*c, spec->src);
item = hsh_force_find (spec->items, &v);
- case_data_rw (c, spec->dest)->f = item->to;
+ case_data_rw (*c, spec->dest)->f = item->to;
}
return TRNS_CONTINUE;
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 2006 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
bool warn = true;
const struct one_sample_test *ost = (const struct one_sample_test *) bst;
- struct ccase c;
+ struct ccase *c;
- while (casereader_read(input, &c))
+ while ((c = casereader_read(input)) != NULL)
{
int v;
- double w = dict_get_case_weight (dict, &c, &warn);
+ double w = dict_get_case_weight (dict, c, &warn);
for (v = 0 ; v < ost->n_vars ; ++v )
{
const struct variable *var = ost->vars[v];
- const union value *value = case_data (&c, var);
+ const union value *value = case_data (c, var);
int width = var_get_width (var);
if (var_is_value_missing (var, value, exclude))
- break;
+ continue;
if ( NULL == cat1[v].value )
{
msg (ME, _("Variable %s is not dichotomous"), var_get_name (var));
}
- case_destroy (&c);
+ case_unref (c);
}
return casereader_destroy (input);
}
if ( bst->category1 != SYSMIS )
{
+ int i;
union value v;
v.f = bst->category1;
- cat1->value = value_dup (&v, 0);
+ for (i = 0; i < ost->n_vars; i++)
+ cat1[i].value = value_dup (&v, 0);
}
if ( bst->category2 != SYSMIS )
{
+ int i;
union value v;
v.f = bst->category2;
- cat2->value = value_dup (&v, 0);
+ for (i = 0; i < ost->n_vars; i++)
+ cat2[i].value = value_dup (&v, 0);
}
if (do_binomial (dataset_dict(ds), input, bst, cat1, cat2, exclude))
/* PSPP - a program for statistical analysis.
- Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
{
bool warn = true;
float i_d;
- struct ccase c;
+ struct ccase *c;
struct hsh_table *freq_hash =
hsh_create (4, compare_freq, hash_freq,
hsh_insert (freq_hash, fr);
}
- while (casereader_read (input, &c))
+ while ((c = casereader_read (input)) != NULL)
{
union value obs_value;
struct freq **existing_fr;
struct freq *fr = xmalloc(sizeof (*fr));
- fr->value = case_data (&c, var);
+ fr->value = case_data (c, var);
- fr->count = dict_get_case_weight (dict, &c, &warn);
+ fr->count = dict_get_case_weight (dict, c, &warn);
obs_value.f = trunc (fr->value->f);
if ( obs_value.f < lo || obs_value.f > hi)
{
free (fr);
- case_destroy (&c);
+ case_unref (c);
continue;
}
(*existing_fr)->count += fr->count;
free (fr);
- case_destroy (&c);
+ case_unref (c);
}
if (casereader_destroy (input))
return freq_hash;
const struct variable *var)
{
bool warn = true;
- struct ccase c;
+ struct ccase *c;
struct hsh_table *freq_hash =
hsh_create (4, compare_freq, hash_freq,
free_freq_mutable_hash,
(void *) var);
- for (; casereader_read (input, &c); case_destroy (&c))
+ for (; (c = casereader_read (input)) != NULL; case_unref (c))
{
struct freq **existing_fr;
struct freq *fr = xmalloc(sizeof (*fr));
- fr->value = case_data (&c, var);
+ fr->value = case_data (c, var);
- fr->count = dict_get_case_weight (dict, &c, &warn);
+ fr->count = dict_get_case_weight (dict, c, &warn);
existing_fr = (struct freq **) hsh_probe (freq_hash, fr);
if ( *existing_fr)
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
static int internal_cmd_crosstabs (struct lexer *lexer, struct dataset *ds);
static void precalc (struct casereader *, const struct dataset *);
-static void calc_general (struct ccase *, const struct dataset *);
-static void calc_integer (struct ccase *, const struct dataset *);
+static void calc_general (const struct ccase *, const struct dataset *);
+static void calc_integer (const struct ccase *, const struct dataset *);
static void postcalc (void);
static void submit (struct tab_table *);
grouper = casegrouper_create_splits (input, dataset_dict (ds));
while (casegrouper_get_next_group (grouper, &group))
{
- struct ccase c;
+ struct ccase *c;
precalc (group, ds);
- for (; casereader_read (group, &c); case_destroy (&c))
+ for (; (c = casereader_read (group)) != NULL; case_unref (c))
{
if (mode == GENERAL)
- calc_general (&c, ds);
+ calc_general (c, ds);
else
- calc_integer (&c, ds);
+ calc_integer (c, ds);
}
casereader_destroy (group);
static void
precalc (struct casereader *input, const struct dataset *ds)
{
- struct ccase c;
+ struct ccase *c;
- if (casereader_peek (input, 0, &c))
+ c = casereader_peek (input, 0);
+ if (c != NULL)
{
- output_split_file_values (ds, &c);
- case_destroy (&c);
+ output_split_file_values (ds, c);
+ case_unref (c);
}
if (mode == GENERAL)
/* Form crosstabulations for general mode. */
static void
-calc_general (struct ccase *c, const struct dataset *ds)
+calc_general (const struct ccase *c, const struct dataset *ds)
{
/* Missing values to exclude. */
enum mv_class exclude = (cmd.miss == CRS_TABLE ? MV_ANY
}
static void
-calc_integer (struct ccase *c, const struct dataset *ds)
+calc_integer (const struct ccase *c, const struct dataset *ds)
{
bool bad_warn = true;
if (mode == GENERAL)
{
- int width = var_get_width (v);
+ int width = MIN (var_get_width (v), MAX_SHORT_STRING);
int i;
*values = xnmalloc (entry_cnt, sizeof **values);
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
(either system or user-missing values that weren't included).
*/
static int
-descriptives_trns_proc (void *trns_, struct ccase * c,
+descriptives_trns_proc (void *trns_, struct ccase **c,
casenumber case_idx UNUSED)
{
struct dsc_trns *t = trns_;
assert(t->vars);
for (vars = t->vars; vars < t->vars + t->var_cnt; vars++)
{
- double score = case_num (c, *vars);
+ double score = case_num (*c, *vars);
if (var_is_num_missing (*vars, score, t->exclude))
{
all_sysmis = 1;
}
}
+ *c = case_unshare (*c);
for (z = t->z_scores; z < t->z_scores + t->z_score_cnt; z++)
{
- double input = case_num (c, z->src_var);
- double *output = &case_data_rw (c, z->z_var)->f;
+ double input = case_num (*c, z->src_var);
+ double *output = &case_data_rw (*c, z->z_var)->f;
if (z->mean == SYSMIS || z->std_dev == SYSMIS || all_sysmis
|| var_is_num_missing (z->src_var, input, t->exclude))
struct dataset *ds)
{
struct casereader *pass1, *pass2;
- struct ccase c;
+ struct ccase *c;
size_t i;
- if (!casereader_peek (group, 0, &c))
+ c = casereader_peek (group, 0);
+ if (c == NULL)
{
casereader_destroy (group);
return;
}
- output_split_file_values (ds, &c);
- case_destroy (&c);
+ output_split_file_values (ds, c);
+ case_unref (c);
group = casereader_create_filter_weight (group, dataset_dict (ds),
NULL, NULL);
dsc->valid = 0.;
/* First pass to handle most of the work. */
- for (; casereader_read (pass1, &c); case_destroy (&c))
+ for (; (c = casereader_read (pass1)) != NULL; case_unref (c))
{
- double weight = dict_get_case_weight (dataset_dict (ds), &c, NULL);
+ double weight = dict_get_case_weight (dataset_dict (ds), c, NULL);
/* Check for missing values. */
- if (listwise_missing (dsc, &c))
+ if (listwise_missing (dsc, c))
{
dsc->missing_listwise += weight;
if (dsc->missing_type == DSC_LISTWISE)
for (i = 0; i < dsc->var_cnt; i++)
{
struct dsc_var *dv = &dsc->vars[i];
- double x = case_num (&c, dv->v);
+ double x = case_num (c, dv->v);
if (var_is_num_missing (dv->v, x, dsc->exclude))
{
/* Second pass for higher-order moments. */
if (dsc->max_moment > MOMENT_MEAN)
{
- for (; casereader_read (pass2, &c); case_destroy (&c))
+ for (; (c = casereader_read (pass2)) != NULL; case_unref (c))
{
- double weight = dict_get_case_weight (dataset_dict (ds), &c, NULL);
+ double weight = dict_get_case_weight (dataset_dict (ds), c, NULL);
/* Check for missing values. */
- if (dsc->missing_type == DSC_LISTWISE && listwise_missing (dsc, &c))
+ if (dsc->missing_type == DSC_LISTWISE && listwise_missing (dsc, c))
continue;
for (i = 0; i < dsc->var_cnt; i++)
{
struct dsc_var *dv = &dsc->vars[i];
- double x = case_num (&c, dv->v);
+ double x = case_num (c, dv->v);
if (var_is_num_missing (dv->v, x, dsc->exclude))
continue;
/* PSPP - a program for statistical analysis.
- Copyright (C) 2004, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2008, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* Sum of all weights, including those for missing values */
double n;
+ /* Sum of weights of non_missing values */
+ double n_valid;
+
double mean;
double variance;
chart_write_yscale (dnp_chart, np->dns_min, np->dns_max, 5);
{
- struct ccase c;
struct casereader *reader = casewriter_make_reader (np->writer);
- while (casereader_read (reader, &c))
+ struct ccase *c;
+ while ((c = casereader_read (reader)) != NULL)
{
- chart_datum (np_chart, 0, case_data_idx (&c, NP_IDX_Y)->f, case_data_idx (&c, NP_IDX_NS)->f);
- chart_datum (dnp_chart, 0, case_data_idx (&c, NP_IDX_Y)->f, case_data_idx (&c, NP_IDX_DNS)->f);
+ chart_datum (np_chart, 0, case_data_idx (c, NP_IDX_Y)->f, case_data_idx (c, NP_IDX_NS)->f);
+ chart_datum (dnp_chart, 0, case_data_idx (c, NP_IDX_Y)->f, case_data_idx (c, NP_IDX_DNS)->f);
- case_destroy (&c);
+ case_unref (c);
}
casereader_destroy (reader);
}
examine_group (struct cmd_examine *cmd, struct casereader *reader, int level,
const struct dictionary *dict, struct xfactor *factor)
{
- struct ccase c;
+ struct ccase *c;
const struct variable *wv = dict_get_weight (dict);
int v;
int n_extrema = 1;
n_extrema = cmd->st_n;
- if (casereader_peek (reader, 0, &c))
+ c = casereader_peek (reader, 0);
+ if (c != NULL)
{
if ( level > 0)
{
result->value[0] =
- value_dup (case_data (&c, factor->indep_var[0]),
+ value_dup (case_data (c, factor->indep_var[0]),
var_get_width (factor->indep_var[0]));
if ( level > 1)
result->value[1] =
- value_dup (case_data (&c, factor->indep_var[1]),
+ value_dup (case_data (c, factor->indep_var[1]),
var_get_width (factor->indep_var[1]));
}
- case_destroy (&c);
+ case_unref (c);
}
for (v = 0; v < n_dependent_vars; ++v)
/* Sort or just iterate, whilst calculating moments etc */
- while (casereader_read (input, &c))
+ while ((c = casereader_read (input)) != NULL)
{
const casenumber loc =
- case_data_idx (&c, casereader_get_value_cnt (reader) - 1)->f;
+ case_data_idx (c, casereader_get_value_cnt (reader) - 1)->f;
- const double weight = wv ? case_data (&c, wv)->f : 1.0;
+ const double weight = wv ? case_data (c, wv)->f : 1.0;
+ const union value *value = case_data (c, dependent_vars[v]);
if (weight != SYSMIS)
minimize (&result->metrics[v].cmin, weight);
moments1_add (result->metrics[v].moments,
- case_data (&c, dependent_vars[v])->f,
+ value->f,
weight);
result->metrics[v].n += weight;
+ if ( ! var_is_value_missing (dependent_vars[v], value, MV_ANY) )
+ result->metrics[v].n_valid += weight;
+
extrema_add (result->metrics[v].maxima,
- case_data (&c, dependent_vars[v])->f,
+ value->f,
weight,
loc);
extrema_add (result->metrics[v].minima,
- case_data (&c, dependent_vars[v])->f,
+ value->f,
weight,
loc);
- casewriter_write (writer, &c);
+ casewriter_write (writer, c);
}
casereader_destroy (input);
result->metrics[v].up_reader = casewriter_make_reader (writer);
for (i = 0 ; i < metric->n_ptiles; ++i)
{
metric->ptl[i] = (struct percentile *)
- percentile_create (percentile_list.data[i] / 100.0, metric->n);
+ percentile_create (percentile_list.data[i] / 100.0, metric->n_valid);
if ( percentile_list.data[i] == 25)
metric->quartiles[0] = metric->ptl[i];
/* FIXME: Do this in the above loop */
if ( cmd->a_plot[XMN_PLT_HISTOGRAM] )
{
- struct ccase c;
+ struct ccase *c;
struct casereader *input = casereader_clone (reader);
for (v = 0; v < n_dependent_vars; ++v)
metric->histogram = histogram_create (10, min->value, max->value);
}
- while (casereader_read (input, &c))
+ while ((c = casereader_read (input)) != NULL)
{
- const double weight = wv ? case_data (&c, wv)->f : 1.0;
+ const double weight = wv ? case_data (c, wv)->f : 1.0;
for (v = 0; v < n_dependent_vars; ++v)
{
struct factor_metrics *metric = &result->metrics[v];
if ( metric->histogram)
histogram_add ((struct histogram *) metric->histogram,
- case_data (&c, dependent_vars[v])->f, weight);
+ case_data (c, dependent_vars[v])->f, weight);
}
- case_destroy (&c);
+ case_unref (c);
}
casereader_destroy (input);
}
{
struct ll *ll;
const struct dictionary *dict = dataset_dict (ds);
- struct ccase c;
+ struct ccase *c;
struct casereader *level0 = casereader_clone (input);
- if (!casereader_peek (input, 0, &c))
+ c = casereader_peek (input, 0);
+ if (c == NULL)
{
casereader_destroy (input);
return;
}
- output_split_file_values (ds, &c);
- case_destroy (&c);
+ output_split_file_values (ds, c);
+ case_unref (c);
ll_init (&level0_factor.result_list);
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
struct flip_pgm *flip;
struct casereader *input, *reader;
union value *output_buf;
- struct ccase c;
+ struct ccase *c;
size_t i;
bool ok;
proc_discard_output (ds);
input = proc_open (ds);
- while (casereader_read (input, &c))
+ while ((c = casereader_read (input)) != NULL)
{
- write_flip_case (flip, &c);
- case_destroy (&c);
+ write_flip_case (flip, c);
+ case_unref (c);
}
ok = casereader_destroy (input);
ok = proc_commit (ds) && ok;
return true;
}
-/* Reads one case into C.
- Returns true if successful, false at end of file or if an
- I/O error occurred. */
-static bool
-flip_casereader_read (struct casereader *reader UNUSED, void *flip_,
- struct ccase *c)
+/* Reads and returns one case.
+ Returns a null pointer at end of file or if an I/O error occurred. */
+static struct ccase *
+flip_casereader_read (struct casereader *reader UNUSED, void *flip_)
{
struct flip_pgm *flip = flip_;
+ struct ccase *c;
size_t i;
if (flip->error || flip->cases_read >= flip->var_cnt)
- return false;
+ return NULL;
- case_create (c, flip->case_cnt);
+ c = case_create (flip->case_cnt);
for (i = 0; i < flip->case_cnt; i++)
{
double in;
if (fread (&in, sizeof in, 1, flip->file) != 1)
{
- case_destroy (c);
+ case_unref (c);
if (ferror (flip->file))
msg (SE, _("Error reading FLIP temporary file: %s."),
strerror (errno));
else
NOT_REACHED ();
flip->error = true;
- return false;
+ return NULL;
}
case_data_rw_idx (c, i)->f = in;
}
flip->cases_read++;
- return true;
+ return c;
}
/* Destroys the source.
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
for (; casegrouper_get_next_group (grouper, &group);
casereader_destroy (group))
{
- struct ccase c;
+ struct ccase *c;
precalc (group, ds);
- for (; casereader_read (group, &c); case_destroy (&c))
- calc (&c, ds);
+ for (; (c = casereader_read (group)) != NULL; case_unref (c))
+ calc (c, ds);
postcalc ();
}
ok = casegrouper_destroy (grouper);
static void
precalc (struct casereader *input, struct dataset *ds)
{
- struct ccase c;
+ struct ccase *c;
size_t i;
- if (casereader_peek (input, 0, &c))
+ c = casereader_peek (input, 0);
+ if (c != NULL)
{
- output_split_file_values (ds, &c);
- case_destroy (&c);
+ output_split_file_values (ds, c);
+ case_unref (c);
}
pool_destroy (data_pool);
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
int n_indep = 0;
pspp_linreg_cache *model = NULL;
pspp_linreg_opts lopts;
- struct ccase c;
+ struct ccase *c;
size_t i;
size_t n_all_vars;
size_t n_data; /* Number of valid cases. */
struct casereader *reader;
struct covariance_matrix *cov;
- if (!casereader_peek (input, 0, &c))
+ c = casereader_peek (input, 0);
+ if (c == NULL)
{
casereader_destroy (input);
return true;
}
- output_split_file_values (ds, &c);
- case_destroy (&c);
+ output_split_file_values (ds, c);
+ case_unref (c);
if (!v_dependent)
{
cov = covariance_matrix_init (n_all_vars, all_vars, ONE_PASS, PAIRWISE, MV_ANY);
reader = casereader_create_counter (reader, &row, -1);
- for (; casereader_read (reader, &c); case_destroy (&c))
+ for (; (c = casereader_read (reader)) != NULL; case_unref (c))
{
/*
Accumulate the covariance matrix.
*/
- covariance_matrix_accumulate (cov, &c);
+ covariance_matrix_accumulate (cov, c, NULL, 0);
n_data++;
}
covariance_matrix_compute (cov);
/* PSPP - a program for statistical analysis.
- Copyright (C) 2006 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
double maximum = -DBL_MAX;
double var;
struct moments1 *moments = moments1_create (MOMENT_VARIANCE);
- struct ccase c;
+ struct ccase *c;
const struct variable *v = *vv++;
struct casereader *pass;
&v, 1,
filter, NULL, NULL);
pass = casereader_create_filter_weight (pass, dict, NULL, NULL);
- while (casereader_read(pass, &c))
+ while ((c = casereader_read (pass)) != NULL)
{
- double val = case_num (&c, v);
- double w = dict_get_case_weight (dict, &c, NULL);
+ double val = case_num (c, v);
+ double w = dict_get_case_weight (dict, c, NULL);
minimum = MIN (minimum, val);
maximum = MAX (maximum, val);
moments1_add (moments, val, w);
- case_destroy (&c);
+ case_unref (c);
}
casereader_destroy (pass);
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
struct dictionary *dict = dataset_dict (ds);
enum mv_class exclude;
struct casereader *reader;
- struct ccase c;
+ struct ccase *c;
- if (!casereader_peek (input, 0, &c))
+ c = casereader_peek (input, 0);
+ if (c == NULL)
{
casereader_destroy (input);
return;
}
- output_split_file_values (ds, &c);
- case_destroy (&c);
+ output_split_file_values (ds, c);
+ case_unref (c);
taint = taint_clone (casereader_get_taint (input));
input = casereader_create_filter_weight (input, dict, NULL, NULL);
reader = casereader_clone (input);
- for (; casereader_read (reader, &c); case_destroy (&c))
+ for (; (c = casereader_read (reader)) != NULL; case_unref (c))
{
size_t i;
- const double weight = dict_get_case_weight (dict, &c, NULL);
+ const double weight = dict_get_case_weight (dict, c, NULL);
- const union value *indep_val = case_data (&c, indep_var);
+ const union value *indep_val = case_data (c, indep_var);
void **p = hsh_probe (global_group_hash, indep_val);
if (*p == NULL)
*p = value_dup (indep_val, var_get_width (indep_var));
{
const struct variable *v = vars[i];
- const union value *val = case_data (&c, v);
+ const union value *val = case_data (c, v);
struct group_proc *gp = group_proc_get (vars[i]);
struct hsh_table *group_hash = gp->group_hash;
/* PSPP - a program for statistical analysis.
- Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
{
struct casereader *pass1, *pass2, *pass2_1;
struct casegrouper *tie_grouper;
- struct ccase c;
+ struct ccase *c;
double w = 0.0;
double cc = 0.0;
int tie_group = 1;
casereader_split (input, &pass1, &pass2);
/* Pass 1: Get total group weight. */
- for (; casereader_read (pass1, &c); case_destroy (&c))
- w += dict_get_case_weight (dict, &c, NULL);
+ for (; (c = casereader_read (pass1)) != NULL; case_unref (c))
+ w += dict_get_case_weight (dict, c, NULL);
casereader_destroy (pass1);
/* Pass 2: Do ranking. */
casewriter_get_taint (output));
/* Pass 2.1: Sum up weight for tied cases. */
- for (; casereader_read (pass2_1, &c); case_destroy (&c))
- tw += dict_get_case_weight (dict, &c, NULL);
+ for (; (c = casereader_read (pass2_1)) != NULL; case_unref (c))
+ tw += dict_get_case_weight (dict, c, NULL);
cc += tw;
casereader_destroy (pass2_1);
/* Pass 2.2: Rank tied cases. */
- while (casereader_read (pass2_2, &c))
+ while ((c = casereader_read (pass2_2)) != NULL)
{
+ c = case_unshare (c);
for (i = 0; i < n_rank_specs; ++i)
{
const struct variable *dst_var = rs[i].destvars[dest_idx];
- double *dst_value = &case_data_rw (&c, dst_var)->f;
+ double *dst_value = &case_data_rw (c, dst_var)->f;
*dst_value = rank_func[rs[i].rfunc] (tw, cc, cc_1, tie_group, w);
}
- casewriter_write (output, &c);
+ casewriter_write (output, c);
}
casereader_destroy (pass2_2);
/* Transformation function to enumerate all the cases */
static int
-create_resort_key (void *key_var_, struct ccase *cc, casenumber case_num)
+create_resort_key (void *key_var_, struct ccase **cc, casenumber case_num)
{
struct variable *key_var = key_var_;
- case_data_rw(cc, key_var)->f = case_num;
+ *cc = case_unshare (*cc);
+ case_data_rw (*cc, key_var)->f = case_num;
return TRNS_CONTINUE;
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Gets the predicted values.
*/
static int
-regression_trns_pred_proc (void *t_, struct ccase *c,
+regression_trns_pred_proc (void *t_, struct ccase **c,
casenumber case_idx UNUSED)
{
size_t i;
n_vals = (*model->get_vars) (model, vars);
vals = xnmalloc (n_vals, sizeof (*vals));
- output = case_data_rw (c, model->pred);
- assert (output != NULL);
+ *c = case_unshare (*c);
+ output = case_data_rw (*c, model->pred);
for (i = 0; i < n_vals; i++)
{
- vals[i] = case_data (c, vars[i]);
+ vals[i] = case_data (*c, vars[i]);
}
output->f = (*model->predict) ((const struct variable **) vars,
vals, model, n_vals);
Gets the residuals.
*/
static int
-regression_trns_resid_proc (void *t_, struct ccase *c,
+regression_trns_resid_proc (void *t_, struct ccase **c,
casenumber case_idx UNUSED)
{
size_t i;
n_vals = (*model->get_vars) (model, vars);
vals = xnmalloc (n_vals, sizeof (*vals));
- output = case_data_rw (c, model->resid);
+ *c = case_unshare (*c);
+ output = case_data_rw (*c, model->resid);
assert (output != NULL);
for (i = 0; i < n_vals; i++)
{
- vals[i] = case_data (c, vars[i]);
+ vals[i] = case_data (*c, vars[i]);
}
- obs = case_data (c, model->depvar);
+ obs = case_data (*c, model->depvar);
output->f = (*model->residual) ((const struct variable **) vars,
vals, obs, model, n_vals);
free (vals);
for (lc = models; lc < models + cmd.n_dependent; lc++)
{
- assert (*lc != NULL);
- assert ((*lc)->depvar != NULL);
- if (cmd.a_save[REGRESSION_SV_RESID])
- {
- reg_save_var (ds, "RES", regression_trns_resid_proc, *lc,
- &(*lc)->resid, n_trns);
- }
- if (cmd.a_save[REGRESSION_SV_PRED])
+ if (*lc != NULL)
{
- reg_save_var (ds, "PRED", regression_trns_pred_proc, *lc,
- &(*lc)->pred, n_trns);
+ if ((*lc)->depvar != NULL)
+ {
+ if (cmd.a_save[REGRESSION_SV_RESID])
+ {
+ reg_save_var (ds, "RES", regression_trns_resid_proc, *lc,
+ &(*lc)->resid, n_trns);
+ }
+ if (cmd.a_save[REGRESSION_SV_PRED])
+ {
+ reg_save_var (ds, "PRED", regression_trns_pred_proc, *lc,
+ &(*lc)->pred, n_trns);
+ }
+ }
}
}
}
struct moments_var *mom)
{
int n_data;
- struct ccase c;
+ struct ccase *c;
size_t i;
assert (vars != NULL);
cat_stored_values_create (vars[i]);
n_data = 0;
- for (; casereader_read (input, &c); case_destroy (&c))
+ for (; (c = casereader_read (input)) != NULL; case_unref (c))
{
/*
The second condition ensures the program will run even if
*/
for (i = 0; i < n_vars; i++)
{
- const union value *val = case_data (&c, vars[i]);
+ const union value *val = case_data (c, vars[i]);
if (var_is_alpha (vars[i]))
cat_value_update (vars[i], val);
else
size_t i;
int n_indep = 0;
int k;
- struct ccase c;
+ struct ccase *c;
const struct variable **indep_vars;
struct design_matrix *X;
struct moments_var *mom;
assert (models != NULL);
- if (!casereader_peek (input, 0, &c))
+ c = casereader_peek (input, 0);
+ if (c == NULL)
{
casereader_destroy (input);
return true;
}
- output_split_file_values (ds, &c);
- case_destroy (&c);
+ output_split_file_values (ds, c);
+ case_unref (c);
if (!v_variables)
{
const struct variable *dep_var;
struct casereader *reader;
casenumber row;
- struct ccase c;
+ struct ccase *c;
size_t n_data; /* Number of valid cases. */
dep_var = cmd->v_dependent[k];
The second pass fills the design matrix.
*/
reader = casereader_create_counter (reader, &row, -1);
- for (; casereader_read (reader, &c); case_destroy (&c))
+ for (; (c = casereader_read (reader)) != NULL; case_unref (c))
{
for (i = 0; i < n_indep; ++i)
{
const struct variable *v = indep_vars[i];
- const union value *val = case_data (&c, v);
+ const union value *val = case_data (c, v);
if (var_is_alpha (v))
design_matrix_set_categorical (X, row, v, val);
else
design_matrix_set_numeric (X, row, v, val);
}
- gsl_vector_set (Y, row, case_num (&c, dep_var));
+ gsl_vector_set (Y, row, case_num (c, dep_var));
}
/*
Now that we know the number of coefficients, allocate space
/* PSPP - a program for statistical analysis.
- Copyright (C) 2008 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
{
int i;
int si;
- struct ccase c;
+ struct ccase *c;
casenumber n_missing ;
casenumber n_valid = 0;
s, NULL);
}
- for (; casereader_read (input, &c); case_destroy (&c))
+ for (; (c = casereader_read (input)) != NULL; case_unref (c))
{
double weight = 1.0;
n_valid ++;
struct cronbach *s = &rel->sc[si];
for (i = 0 ; i < s->n_items ; ++i )
- moments1_add (s->m[i], case_data (&c, s->items[i])->f, weight);
+ moments1_add (s->m[i], case_data (c, s->items[i])->f, weight);
- moments1_add (s->total, case_data_idx (&c, s->totals_idx)->f, weight);
+ moments1_add (s->total, case_data_idx (c, s->totals_idx)->f, weight);
}
}
casereader_destroy (input);
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
struct casereader *pass1, *pass2, *pass3;
struct taint *taint;
- struct ccase c;
+ struct ccase *c;
enum mv_class exclude = cmd->miss != TTS_INCLUDE ? MV_ANY : MV_SYSTEM;
- if (!casereader_peek (input, 0, &c))
+ c = casereader_peek (input, 0);
+ if (c == NULL)
{
casereader_destroy (input);
return;
}
- output_split_file_values (ds, &c);
- case_destroy (&c);
+ output_split_file_values (ds, c);
+ case_unref (c);
if ( cmd->miss == TTS_LISTWISE )
input = casereader_create_filter_missing (input,
casereader_split (input, &pass1, &pass2);
common_precalc (cmd);
- for (; casereader_read (pass1, &c); case_destroy (&c))
- common_calc (dict, &c, cmd, exclude);
+ for (; (c = casereader_read (pass1)) != NULL; case_unref (c))
+ common_calc (dict, c, cmd, exclude);
casereader_destroy (pass1);
common_postcalc (cmd);
{
case T_1_SAMPLE:
one_sample_precalc (cmd);
- for (; casereader_read (pass2, &c); case_destroy (&c))
- one_sample_calc (dict, &c, cmd, exclude);
+ for (; (c = casereader_read (pass2)) != NULL; case_unref (c))
+ one_sample_calc (dict, c, cmd, exclude);
one_sample_postcalc (cmd);
break;
case T_PAIRED:
paired_precalc (cmd);
- for (; casereader_read (pass2, &c); case_destroy (&c))
- paired_calc (dict, &c, cmd, exclude);
+ for (; (c = casereader_read (pass2)) != NULL; case_unref (c))
+ paired_calc (dict, c, cmd, exclude);
paired_postcalc (cmd);
break;
case T_IND_SAMPLES:
pass3 = casereader_clone (pass2);
group_precalc (cmd);
- for (; casereader_read (pass2, &c); case_destroy (&c))
- group_calc (dict, &c, cmd, exclude);
+ for (; (c = casereader_read (pass2)) != NULL; case_unref (c))
+ group_calc (dict, c, cmd, exclude);
group_postcalc (cmd);
levene (dict, pass3, indep_var, cmd->n_variables, cmd->v_variables,
/* Pspp - a program for statistical analysis.
- Copyright (C) 2008 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include <output/table.h>
#include <data/procedure.h>
#include <data/dictionary.h>
-#include <misc/wx-mp-sr.h>
+#include <math/wilcoxon-sig.h>
#include <gsl/gsl_cdf.h>
#include <unistd.h>
#include <signal.h>
#include <libpspp/assertion.h>
-static double timed_wilcoxon_significance (double w, long int n, double timer);
-
-
static double
append_difference (const struct ccase *c, casenumber n UNUSED, void *aux)
{
{
struct casereader *r = casereader_clone (input);
struct casewriter *writer;
- struct ccase c;
+ struct ccase *c;
struct subcase ordering;
variable_pair *vp = &t2s->pairs[i];
writer = sort_create_writer (&ordering, reader_width);
subcase_destroy (&ordering);
- while (casereader_read (r, &c))
+ for (; (c = casereader_read (r)) != NULL; case_unref (c))
{
- struct ccase output;
- double d = append_difference (&c, 0, vp);
-
- case_create (&output, reader_width);
+ struct ccase *output = case_create (reader_width);
+ double d = append_difference (c, 0, vp);
if (d > 0)
{
- case_data_rw (&output, ws[i].sign)->f = 1.0;
+ case_data_rw (output, ws[i].sign)->f = 1.0;
}
else if (d < 0)
{
- case_data_rw (&output, ws[i].sign)->f = -1.0;
+ case_data_rw (output, ws[i].sign)->f = -1.0;
}
else
{
double w = 1.0;
if (weight)
- w = case_data (&c, weight)->f;
+ w = case_data (c, weight)->f;
/* Central point values should be dropped */
ws[i].n_zeros += w;
- case_destroy (&c);
- continue;
+ continue;
}
- case_data_rw (&output, ws[i].absdiff)->f = fabs (d);
+ case_data_rw (output, ws[i].absdiff)->f = fabs (d);
if (weight)
- case_data_rw (&output, weightx)->f = case_data (&c, weight)->f;
+ case_data_rw (output, weightx)->f = case_data (c, weight)->f;
- casewriter_write (writer, &output);
- case_destroy (&c);
+ casewriter_write (writer, output);
}
casereader_destroy (r);
ws[i].reader = casewriter_make_reader (writer);
for (i = 0 ; i < t2s->n_pairs; ++i )
{
struct casereader *rr ;
- struct ccase c;
+ struct ccase *c;
enum rank_error err = 0;
rr = casereader_create_append_rank (ws[i].reader, ws[i].absdiff,
distinct_callback, &ws[i]
);
- while (casereader_read (rr, &c))
+ for (; (c = casereader_read (rr)) != NULL; case_unref (c))
{
- double sign = case_data (&c, ws[i].sign)->f;
- double rank = case_data_idx (&c, weight ? 3 : 2)->f;
+ double sign = case_data (c, ws[i].sign)->f;
+ double rank = case_data_idx (c, weight ? 3 : 2)->f;
double w = 1.0;
if (weight)
- w = case_data (&c, weightx)->f;
+ w = case_data (c, weightx)->f;
if ( sign > 0 )
{
}
else
NOT_REACHED ();
-
- case_destroy (&c);
}
casereader_destroy (rr);
show_tests_box (const struct wilcoxon_state *ws,
const struct two_sample_test *t2s,
bool exact,
- double timer
+ double timer UNUSED
)
{
size_t i;
if (exact)
{
- double p =
- timed_wilcoxon_significance (ws[i].positives.sum,
- n,
- timer );
-
- if ( p == SYSMIS)
+ double p = LevelOfSignificanceWXMPSR (ws[i].positives.sum, n);
+ if (p < 0)
{
- msg (MW, _("Exact significance was not calculated after %.2f minutes. Skipping test."), timer);
+ msg (MW, ("Too many pairs to calculate exact significance."));
}
else
{
tab_submit (table);
}
-
-\f
-
-#include <setjmp.h>
-
-static sigjmp_buf env;
-
-static void
-give_up_callback (int signal UNUSED)
-{
- siglongjmp (env, 1);
-}
-
-static double
-timed_wilcoxon_significance (double w, long int n, double timer)
-{
- double p = SYSMIS;
-
- sigset_t set;
-
- struct sigaction timeout_action;
- struct sigaction old_action;
-
- if (timer <= 0 )
- return LevelOfSignificanceWXMPSR (w, n);
-
- sigemptyset (&set);
-
- timeout_action.sa_mask = set;
- timeout_action.sa_flags = 0;
-
- timeout_action.sa_handler = give_up_callback;
-
- if ( 0 == sigsetjmp (env, 1))
- {
- sigaction (SIGALRM, &timeout_action, &old_action);
- alarm (timer * 60.0);
-
- p = LevelOfSignificanceWXMPSR (w, n);
- }
-
- sigaction (SIGALRM, &old_action, NULL);
-
- return p;
-}
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
casereader_get_value_cnt (reader), column_cnt);
else
{
- struct ccase c;
+ struct ccase *c;
size_t row;
for (row = 0; row < row_cnt; row++)
{
size_t col;
- if (!casereader_read (reader, &c))
+ c = casereader_read (reader);
+ if (c == NULL)
{
mc_error (mc, "casereader_read failed reading row %zu of %zu "
"(%zu columns)", row, row_cnt, column_cnt);
}
for (col = 0; col < column_cnt; col++)
- if (case_num_idx (&c, col) != array[row][col])
+ if (case_num_idx (c, col) != array[row][col])
mc_error (mc, "element %zu,%zu (of %zu,%zu) differs: "
"%g != %g",
row, col, row_cnt, column_cnt,
- case_num_idx (&c, col), array[row][col]);
+ case_num_idx (c, col), array[row][col]);
- case_destroy (&c);
+ case_unref (c);
}
- if (casereader_read (reader, &c))
+ c = casereader_read (reader);
+ if (c != NULL)
mc_error (mc, "casereader has extra cases (expected %zu)", row_cnt);
}
}
writer = mem_writer_create (params->backing_cols);
for (row = 0; row < params->backing_rows; row++)
{
- struct ccase c;
+ struct ccase *c;
int col;
- case_create (&c, params->backing_cols);
+ c = case_create (params->backing_cols);
for (col = 0; col < params->backing_cols; col++)
{
double value = params->next_value++;
data[row][col] = value;
- case_data_rw_idx (&c, col)->f = value;
+ case_data_rw_idx (c, col)->f = value;
}
- casewriter_write (writer, &c);
+ casewriter_write (writer, c);
}
reader = casewriter_make_reader (writer);
assert (reader != NULL);
if (mc_include_state (mc))
{
struct datasheet *ds;
- struct ccase c[MAX_ROWS];
+ struct ccase *c[MAX_ROWS];
size_t i, j;
clone_model (ods, odata, &ds, data);
for (i = 0; i < cnt; i++)
{
- case_create (&c[i], column_cnt);
+ c[i] = case_create (column_cnt);
for (j = 0; j < column_cnt; j++)
- case_data_rw_idx (&c[i], j)->f = params->next_value++;
+ case_data_rw_idx (c[i], j)->f = params->next_value++;
}
insert_range (data, row_cnt, sizeof data[pos], pos, cnt);
for (i = 0; i < cnt; i++)
for (j = 0; j < column_cnt; j++)
- data[i + pos][j] = case_num_idx (&c[i], j);
+ data[i + pos][j] = case_num_idx (c[i], j);
if (!datasheet_insert_rows (ds, pos, c, cnt))
mc_error (mc, "datasheet_insert_rows failed");
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* Rows. */
casenumber datasheet_get_row_cnt (const struct datasheet *);
bool datasheet_insert_rows (struct datasheet *,
- casenumber before, struct ccase[],
+ casenumber before, struct ccase *rows[],
casenumber cnt);
void datasheet_delete_rows (struct datasheet *,
casenumber first, casenumber cnt);
size_t cnt);
/* Data. */
-bool datasheet_get_row (const struct datasheet *, casenumber, struct ccase *);
+struct ccase *datasheet_get_row (const struct datasheet *, casenumber);
bool datasheet_put_row (struct datasheet *, casenumber, struct ccase *);
bool datasheet_get_value (const struct datasheet *, casenumber, size_t column,
union value *, int width);
#include <config.h>
#include <ctype.h>
+#include <errno.h>
#include <stdlib.h>
+#include <string.h>
#include <language/command.h>
#include <libpspp/message.h>
#include <libpspp/getl.h>
}
*filename = relative_filename;
+ if (*filename == NULL)
+ {
+ msg (SE, _("Unable to open `%s': %s."),
+ relative_filename, strerror (errno));
+ free (relative_filename);
+ return CMD_FAILURE;
+ }
return CMD_SUCCESS;
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* Handle COMPUTE or IF with numeric target variable. */
static int
-compute_num (void *compute_, struct ccase *c, casenumber case_num)
+compute_num (void *compute_, struct ccase **c, casenumber case_num)
{
struct compute_trns *compute = compute_;
if (compute->test == NULL
- || expr_evaluate_num (compute->test, c, case_num) == 1.0)
- case_data_rw (c, compute->variable)->f
- = expr_evaluate_num (compute->rvalue, c, case_num);
+ || expr_evaluate_num (compute->test, *c, case_num) == 1.0)
+ {
+ *c = case_unshare (*c);
+ case_data_rw (*c, compute->variable)->f
+ = expr_evaluate_num (compute->rvalue, *c, case_num);
+ }
return TRNS_CONTINUE;
}
/* Handle COMPUTE or IF with numeric vector element target
variable. */
static int
-compute_num_vec (void *compute_, struct ccase *c, casenumber case_num)
+compute_num_vec (void *compute_, struct ccase **c, casenumber case_num)
{
struct compute_trns *compute = compute_;
if (compute->test == NULL
- || expr_evaluate_num (compute->test, c, case_num) == 1.0)
+ || expr_evaluate_num (compute->test, *c, case_num) == 1.0)
{
double index; /* Index into the vector. */
int rindx; /* Rounded index value. */
- index = expr_evaluate_num (compute->element, c, case_num);
+ index = expr_evaluate_num (compute->element, *c, case_num);
rindx = floor (index + EPSILON);
if (index == SYSMIS
|| rindx < 1 || rindx > vector_get_var_cnt (compute->vector))
index, vector_get_name (compute->vector));
return TRNS_CONTINUE;
}
- case_data_rw (c, vector_get_var (compute->vector, rindx - 1))->f
- = expr_evaluate_num (compute->rvalue, c, case_num);
+
+ *c = case_unshare (*c);
+ case_data_rw (*c, vector_get_var (compute->vector, rindx - 1))->f
+ = expr_evaluate_num (compute->rvalue, *c, case_num);
}
return TRNS_CONTINUE;
/* Handle COMPUTE or IF with string target variable. */
static int
-compute_str (void *compute_, struct ccase *c, casenumber case_num)
+compute_str (void *compute_, struct ccase **c, casenumber case_num)
{
struct compute_trns *compute = compute_;
if (compute->test == NULL
- || expr_evaluate_num (compute->test, c, case_num) == 1.0)
- expr_evaluate_str (compute->rvalue, c, case_num,
- case_data_rw (c, compute->variable)->s, compute->width);
+ || expr_evaluate_num (compute->test, *c, case_num) == 1.0)
+ {
+ *c = case_unshare (*c);
+ expr_evaluate_str (compute->rvalue, *c, case_num,
+ case_data_rw (*c, compute->variable)->s,
+ compute->width);
+ }
return TRNS_CONTINUE;
}
/* Handle COMPUTE or IF with string vector element target
variable. */
static int
-compute_str_vec (void *compute_, struct ccase *c, casenumber case_num)
+compute_str_vec (void *compute_, struct ccase **c, casenumber case_num)
{
struct compute_trns *compute = compute_;
if (compute->test == NULL
- || expr_evaluate_num (compute->test, c, case_num) == 1.0)
+ || expr_evaluate_num (compute->test, *c, case_num) == 1.0)
{
double index; /* Index into the vector. */
int rindx; /* Rounded index value. */
struct variable *vr; /* Variable reference by indexed vector. */
- index = expr_evaluate_num (compute->element, c, case_num);
+ index = expr_evaluate_num (compute->element, *c, case_num);
rindx = floor (index + EPSILON);
if (index == SYSMIS)
{
}
vr = vector_get_var (compute->vector, rindx - 1);
- expr_evaluate_str (compute->rvalue, c, case_num,
- case_data_rw (c, vr)->s,
+ *c = case_unshare (*c);
+ expr_evaluate_str (compute->rvalue, *c, case_num,
+ case_data_rw (*c, vr)->s,
var_get_width (vr));
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* Transformation. */
/* Counts the number of values in case C matching CRIT. */
-static inline int
-count_numeric (struct criteria *crit, struct ccase *c)
+static int
+count_numeric (struct criteria *crit, const struct ccase *c)
{
int counter = 0;
size_t i;
}
/* Counts the number of values in case C matching CRIT. */
-static inline int
-count_string (struct criteria *crit, struct ccase *c)
+static int
+count_string (struct criteria *crit, const struct ccase *c)
{
int counter = 0;
size_t i;
/* Performs the COUNT transformation T on case C. */
static int
-count_trns_proc (void *trns_, struct ccase *c,
+count_trns_proc (void *trns_, struct ccase **c,
casenumber case_num UNUSED)
{
struct count_trns *trns = trns_;
struct dst_var *dv;
+ *c = case_unshare (*c);
for (dv = trns->dst_vars; dv; dv = dv->next)
{
struct criteria *crit;
counter = 0;
for (crit = dv->crit; crit; crit = crit->next)
if (var_is_numeric (crit->vars[0]))
- counter += count_numeric (crit, c);
+ counter += count_numeric (crit, *c);
else
- counter += count_string (crit, c);
- case_data_rw (c, dv->var)->f = counter;
+ counter += count_string (crit, *c);
+ case_data_rw (*c, dv->var)->f = counter;
}
return TRNS_CONTINUE;
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include <language/command.h>
#include <language/lexer/lexer.h>
-static int trns_fail (void *x, struct ccase *c, casenumber n);
+static int trns_fail (void *x, struct ccase **c, casenumber n);
\f
/* A transformation which is guaranteed to fail. */
static int
-trns_fail (void *x UNUSED, struct ccase *c UNUSED,
+trns_fail (void *x UNUSED, struct ccase **c UNUSED,
casenumber n UNUSED)
{
return TRNS_ERROR;
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* Performs RECODE transformation. */
static int
-recode_trns_proc (void *trns_, struct ccase *c, casenumber case_idx UNUSED)
+recode_trns_proc (void *trns_, struct ccase **c, casenumber case_idx UNUSED)
{
struct recode_trns *trns = trns_;
size_t i;
+ *c = case_unshare (*c);
for (i = 0; i < trns->var_cnt; i++)
{
const struct variable *src_var = trns->src_vars[i];
const struct variable *dst_var = trns->dst_vars[i];
- const union value *src_data = case_data (c, src_var);
- union value *dst_data = case_data_rw (c, dst_var);
+ const union value *src_data = case_data (*c, src_var);
+ union value *dst_data = case_data_rw (*c, dst_var);
const struct map_out *out;
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* Executes a SAMPLE transformation. */
static int
-sample_trns_proc (void *t_, struct ccase *c UNUSED,
+sample_trns_proc (void *t_, struct ccase **c UNUSED,
casenumber case_num UNUSED)
{
struct sample_trns *t = t_;
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* Performs the SELECT IF transformation T on case C. */
static int
-select_if_proc (void *t_, struct ccase *c,
+select_if_proc (void *t_, struct ccase **c,
casenumber case_num)
{
struct select_if_trns *t = t_;
- return (expr_evaluate_num (t->e, c, case_num) == 1.0
+ return (expr_evaluate_num (t->e, *c, case_num) == 1.0
? TRNS_CONTINUE : TRNS_DROP_CASE);
}
nodist_src_libpspp_libpspp_la_SOURCES = src/libpspp/version.c
-src/libpspp/version.c: $(top_srcdir)/AUTHORS
+src/libpspp/version.c: $(top_srcdir)/AUTHORS Makefile
@$(MKDIR_P) src/libpspp
echo "/* -*- mode: c; buffer-read-only: t -*-" > $@
- echo " Generated by src/libpspp/automake.mk --- Do not edit. */">> $@
+ echo " Generated by src/libpspp/automake.mk --- Do not edit.">> $@
+ echo "" >> $@
+ echo " The following line is for the benefit of the perl module" >>$@
+ echo "\$$VERSION='"@VERSION@"';" >> $@
+ echo "*/" >> $@
echo "#include \"version.h\"" >> $@
echo "const char bare_version[] = \"@VERSION@\";" >> $@
echo "const char version[] = \"GNU @PACKAGE@ @VERSION@\";" >> $@
void
msg_emit (struct msg *m)
{
- get_msg_location (s_stream, &m->where);
+ if ( s_stream )
+ get_msg_location (s_stream, &m->where);
+
if (!messages_disabled)
- msg_handler (m);
+ msg_handler (m);
free (m->text);
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
return st->ss.string;
}
-/* Appends to ST a newline-terminated line read from STREAM, but
- no more than MAX_LENGTH characters.
- Newline is the last character of ST on return, if encountering
- a newline was the reason for terminating.
- Returns true if at least one character was read from STREAM
- and appended to ST, false if no characters at all were read
- before an I/O error or end of file was encountered (or
- MAX_LENGTH was 0). */
+/* Reads characters from STREAM and appends them to ST, stopping
+ after MAX_LENGTH characters, after appending a newline, or
+ after an I/O error or end of file was encountered, whichever
+ comes first. Returns true if at least one character was added
+ to ST, false if no characters were read before an I/O error or
+ end of file (or if MAX_LENGTH was 0).
+
+ This function accepts LF, CR LF, and CR sequences as new-line,
+ and translates each of them to a single '\n' new-line
+ character in ST. */
bool
ds_read_line (struct string *st, FILE *stream, size_t max_length)
{
- if (!st->ss.length && max_length == SIZE_MAX)
- {
- size_t capacity = st->capacity ? st->capacity + 1 : 0;
- ssize_t n = getline (&st->ss.string, &capacity, stream);
- if (capacity)
- st->capacity = capacity - 1;
- if (n > 0)
- {
- st->ss.length = n;
- return true;
- }
- else
- return false;
- }
- else
+ size_t length;
+
+ for (length = 0; length < max_length; length++)
{
- size_t length;
+ int c = getc (stream);
+ if (c == EOF)
+ break;
- for (length = 0; length < max_length; length++)
+ if (c == '\r')
{
- int c = getc (stream);
- if (c == EOF)
- break;
-
- ds_put_char (st, c);
- if (c == '\n')
- return true;
+ c = getc (stream);
+ if (c != '\n')
+ {
+ ungetc (c, stream);
+ c = '\n';
+ }
}
-
- return length > 0;
+ ds_put_char (st, c);
+ if (c == '\n')
+ return true;
}
+
+ return length > 0;
}
/* Removes a comment introduced by `#' from ST,
src/math/statistic.h \
src/math/sort.c src/math/sort.h \
src/math/trimmed-mean.c src/math/trimmed-mean.h \
- src/math/tukey-hinges.c src/math/tukey-hinges.h
+ src/math/tukey-hinges.c src/math/tukey-hinges.h \
+ src/math/wilcoxon-sig.c src/math/wilcoxon-sig.h
int n_pass;
int missing_handling;
enum mv_class missing_value;
- void (*accumulate) (struct covariance_matrix *, const struct ccase *);
+ void (*accumulate) (struct covariance_matrix *, const struct ccase *,
+ const struct interaction_variable **, size_t);
void (*update_moments) (struct covariance_matrix *, size_t, double);
};
+
+
static struct hsh_table *covariance_hsh_create (size_t);
static hsh_hash_func covariance_accumulator_hash;
static unsigned int hash_numeric_alpha (const struct variable *,
value
*);
static void covariance_accumulate_listwise (struct covariance_matrix *,
- const struct ccase *);
+ const struct ccase *,
+ const struct interaction_variable **,
+ size_t);
static void covariance_accumulate_pairwise (struct covariance_matrix *,
- const struct ccase *);
+ const struct ccase *,
+ const struct interaction_variable **,
+ size_t);
struct covariance_matrix *
covariance_matrix_init (size_t n_variables,
col += i;
y = -1.0 * cat_get_category_count (i, v) / ssize;
tmp_val = cat_subscript_to_value (i, v);
- if (compare_values_short (tmp_val, val1, v))
+ if (!compare_values_short (tmp_val, val1, v))
{
y += -1.0;
}
row += i;
x = -1.0 * cat_get_category_count (i, v1) / ssize;
tmp_val = cat_subscript_to_value (i, v1);
- if (compare_values_short (tmp_val, val1, v1))
+ if (!compare_values_short (tmp_val, val1, v1))
{
x += 1.0;
}
}
if (var_is_numeric (v1) && var_is_alpha (v2))
{
- if (compare_values_short (val2, c->val2, v2))
+ if (!compare_values_short (val2, c->val2, v2))
{
return 0;
}
}
if (var_is_alpha (v1) && var_is_numeric (v2))
{
- if (compare_values_short (val1, c->val1, v1))
+ if (!compare_values_short (val1, c->val1, v1))
{
return 0;
}
}
if (var_is_alpha (v1) && var_is_alpha (v2))
{
- if (compare_values_short (val1, c->val1, v1))
+ if (!compare_values_short (val1, c->val1, v1))
{
- if (compare_values_short (val2, c->val2, v2))
+ if (!compare_values_short (val2, c->val2, v2))
{
return 0;
}
return 0.0;
}
static double
-update_sum (const struct variable *var, const union value *val)
+update_sum (const struct variable *var, const union value *val, double weight)
{
assert (var != NULL);
assert (val != NULL);
if (var_is_alpha (var))
{
- return 1.0;
+ return weight;
}
return val->f;
}
return cov->v_variables;
}
+
static void
update_hash_entry (struct hsh_table *c,
const struct variable *v1,
const struct variable *v2,
- const union value *val1, const union value *val2)
+ const union value *val1, const union value *val2,
+ const struct interaction_value *i_val1,
+ const struct interaction_value *i_val2)
{
struct covariance_accumulator *ca;
struct covariance_accumulator *new_entry;
+ double iv_f1;
+ double iv_f2;
-
+ iv_f1 = interaction_value_get_nonzero_entry (i_val1);
+ iv_f2 = interaction_value_get_nonzero_entry (i_val2);
ca = get_new_covariance_accumulator (v1, v2, val1, val2);
ca->dot_product = update_product (ca->v1, ca->v2, ca->val1, ca->val2);
- ca->sum1 = update_sum (ca->v1, ca->val1);
- ca->sum2 = update_sum (ca->v2, ca->val2);
+ ca->dot_product *= iv_f1 * iv_f2;
+ ca->sum1 = update_sum (ca->v1, ca->val1, iv_f1);
+ ca->sum2 = update_sum (ca->v2, ca->val2, iv_f2);
ca->ssize = 1.0;
new_entry = hsh_insert (c, ca);
if (new_entry != NULL)
*/
static void
covariance_accumulate_pairwise (struct covariance_matrix *cov,
- const struct ccase *ccase)
+ const struct ccase *ccase,
+ const struct interaction_variable **i_var,
+ size_t n_intr)
{
size_t i;
size_t j;
const union value *val1;
const union value *val2;
const struct variable **v_variables;
+ struct interaction_value *i_val1 = NULL;
+ struct interaction_value *i_val2 = NULL;
assert (cov != NULL);
assert (ccase != NULL);
for (i = 0; i < cov->n_variables; ++i)
{
- val1 = case_data (ccase, v_variables[i]);
+ if (is_interaction (v_variables[i], i_var, n_intr))
+ {
+ i_val1 = interaction_case_data (ccase, v_variables[i], i_var, n_intr);
+ val1 = interaction_value_get (i_val1);
+ }
+ else
+ {
+ val1 = case_data (ccase, v_variables[i]);
+ }
if (!var_is_value_missing (v_variables[i], val1, cov->missing_value))
{
cat_value_update (v_variables[i], val1);
- if (var_is_alpha (v_variables[i]))
+ if (var_is_numeric (v_variables[i]))
cov->update_moments (cov, i, val1->f);
for (j = i; j < cov->n_variables; j++)
{
- val2 = case_data (ccase, v_variables[j]);
+ if (is_interaction (v_variables[j], i_var, n_intr))
+ {
+ i_val2 = interaction_case_data (ccase, v_variables[j], i_var, n_intr);
+ val2 = interaction_value_get (i_val2);
+ }
+ else
+ {
+ val2 = case_data (ccase, v_variables[j]);
+ }
if (!var_is_value_missing
(v_variables[j], val2, cov->missing_value))
{
update_hash_entry (cov->ca, v_variables[i], v_variables[j],
- val1, val2);
+ val1, val2, i_val1, i_val2);
if (j != i)
update_hash_entry (cov->ca, v_variables[j],
- v_variables[i], val2, val1);
+ v_variables[i], val2, val1, i_val2, i_val1);
}
}
}
*/
static void
covariance_accumulate_listwise (struct covariance_matrix *cov,
- const struct ccase *ccase)
+ const struct ccase *ccase,
+ const struct interaction_variable **i_var,
+ size_t n_intr)
{
size_t i;
size_t j;
const union value *val1;
const union value *val2;
const struct variable **v_variables;
+ struct interaction_value *i_val1 = NULL;
+ struct interaction_value *i_val2 = NULL;
assert (cov != NULL);
assert (ccase != NULL);
for (i = 0; i < cov->n_variables; ++i)
{
- val1 = case_data (ccase, v_variables[i]);
+ if (is_interaction (v_variables[i], i_var, n_intr))
+ {
+ i_val1 = interaction_case_data (ccase, v_variables[i], i_var, n_intr);
+ val1 = interaction_value_get (i_val1);
+ }
+ else
+ {
+ val1 = case_data (ccase, v_variables[i]);
+ }
cat_value_update (v_variables[i], val1);
- if (var_is_alpha (v_variables[i]))
+ if (var_is_numeric (v_variables[i]))
cov->update_moments (cov, i, val1->f);
for (j = i; j < cov->n_variables; j++)
{
- val2 = case_data (ccase, v_variables[j]);
+ if (is_interaction (v_variables[j], i_var, n_intr))
+ {
+ i_val2 = interaction_case_data (ccase, v_variables[j], i_var, n_intr);
+ val2 = interaction_value_get (i_val2);
+ }
+ else
+ {
+ val2 = case_data (ccase, v_variables[j]);
+ }
update_hash_entry (cov->ca, v_variables[i], v_variables[j],
- val1, val2);
+ val1, val2, i_val1, i_val2);
if (j != i)
update_hash_entry (cov->ca, v_variables[j], v_variables[i],
- val2, val1);
+ val2, val1, i_val2, i_val1);
}
}
}
Call this function during the data pass. Each case will be added to
a hash containing all values of the covariance matrix. After the
data have been passed, call covariance_matrix_compute to put the
- values in the struct covariance_matrix.
+ values in the struct covariance_matrix.
*/
void
covariance_matrix_accumulate (struct covariance_matrix *cov,
- const struct ccase *ccase)
+ const struct ccase *ccase, void **aux, size_t n_intr)
{
- cov->accumulate (cov, ccase);
+ cov->accumulate (cov, ccase, (const struct interaction_variable **) aux, n_intr);
}
static void
{
i = 0;
tmp_val = cat_subscript_to_value (i, v1);
- while (!compare_values_short (tmp_val, val1, v1))
+ while (compare_values_short (tmp_val, val1, v1))
{
i++;
tmp_val = cat_subscript_to_value (i, v1);
col = design_matrix_var_to_column (cov, v2);
i = 0;
tmp_val = cat_subscript_to_value (i, v1);
- while (!compare_values_short (tmp_val, val1, v1))
+ while (compare_values_short (tmp_val, val1, v1))
{
i++;
tmp_val = cat_subscript_to_value (i, v1);
#define COVARIANCE_MATRIX_H
#include <math/design-matrix.h>
+#include <math/interaction.h>
struct moments1;
struct ccase;
int, int, enum mv_class);
void covariance_matrix_free (struct covariance_matrix *);
void covariance_matrix_accumulate (struct covariance_matrix *,
- const struct ccase *);
+ const struct ccase *, void **, size_t);
struct design_matrix *covariance_to_design (const struct covariance_matrix *);
#endif
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
OBS_VALS member. If there are K categorical variables, each with
N_1, N_2, ..., N_K categories, then the interaction will have
N_1 * N_2 * N_3 *...* N_K - 1 entries.
+
+ When using these functions, make sure the orders of variables and
+ values match when appropriate.
*/
#include <config.h>
#include <assert.h>
#include <gsl/gsl_math.h>
#include <gsl/gsl_vector.h>
-#include <data/category.h>
+#include <data/value.h>
#include <data/variable.h>
-#include "interaction.h"
+#include <math/interaction.h>
+#include <string.h>
+#include <xalloc.h>
-#include "xalloc.h"
+struct interaction_variable
+{
+ int n_vars;
+ const struct variable **members;
+ struct variable *intr;
+ size_t n_alpha;
+};
+
+struct interaction_value
+{
+ const struct interaction_variable *intr;
+ union value *val; /* Concatenation of the string values in this
+ interaction's value, or the product of a bunch
+ of numeric values for a purely numeric
+ interaction.
+ */
+ double f; /* Product of the numerical values in this interaction's value. */
+};
/*
- Convert a list of values to a binary vector. The order of VALS must
- correspond to the order of V.
+ An interaction_variable has type alpha if any of members have type
+ alpha. Otherwise, its type is numeric.
*/
-gsl_vector *
-get_interaction (union value **vals, const struct variable **v, size_t n_vars)
+struct interaction_variable *
+interaction_variable_create (const struct variable **vars, int n_vars)
{
- gsl_vector *result = NULL;
- size_t *subs = NULL;
- size_t length = 1;
+ struct interaction_variable *result = NULL;
size_t i;
- size_t j;
- double tmp = 1.0;
- assert (n_vars > 0);
- for (i = 0; i < n_vars; i++)
+ if (n_vars > 0)
{
- if (var_is_alpha (v[i]))
+ result = xmalloc (sizeof (*result));
+ result->n_alpha = 0;
+ result->members = xnmalloc (n_vars, sizeof (*result->members));
+ result->intr = var_create_internal (0);
+ result->n_vars = n_vars;
+ for (i = 0; i < n_vars; i++)
{
- length *= cat_get_n_categories (v[i]);
+ result->members[i] = vars[i];
+ if (var_is_alpha (vars[i]))
+ {
+ result->n_alpha++;
+ }
}
- else
+ }
+ /*
+ VAR_SET_WIDTH sets the type of the variable.
+ */
+ var_set_width (result->intr, MAX_SHORT_STRING * result->n_alpha + 1);
+
+ return result;
+}
+void interaction_variable_destroy (struct interaction_variable *iv)
+{
+ var_destroy (iv->intr);
+ free (iv->members);
+ free (iv);
+}
+
+/*
+ Get one of the member variables.
+ */
+const struct variable *
+interaction_variable_get_member (const struct interaction_variable *iv, size_t i)
+{
+ return iv->members[i];
+}
+
+size_t
+interaction_get_n_vars (const struct interaction_variable *iv)
+{
+ return (iv == NULL) ? 0 : iv->n_vars;
+}
+
+size_t
+interaction_get_n_alpha (const struct interaction_variable *iv)
+{
+ return iv->n_alpha;
+}
+
+size_t
+interaction_get_n_numeric (const struct interaction_variable *iv)
+{
+ return (interaction_get_n_vars (iv) - interaction_get_n_alpha (iv));
+}
+
+/*
+ Get the interaction varibale itself.
+ */
+const struct variable *
+interaction_variable_get_var (const struct interaction_variable *iv)
+{
+ return iv->intr;
+}
+/*
+ Given list of values, compute the value of the corresponding
+ interaction. This "value" is not stored as the typical vector of
+ 0's and one double, but rather the string values are concatenated to
+ make one big string value, and the numerical values are multiplied
+ together to give the non-zero entry of the corresponding vector.
+ */
+struct interaction_value *
+interaction_value_create (const struct interaction_variable *var, const union value **vals)
+{
+ struct interaction_value *result = NULL;
+ const struct variable *member;
+ size_t i;
+ size_t n_vars;
+
+ if (var != NULL)
+ {
+ result = xmalloc (sizeof (*result));
+ result->intr = var;
+ n_vars = interaction_get_n_vars (var);
+ result->val = value_create (n_vars * MAX_SHORT_STRING + 1);
+ result->f = 1.0;
+ for (i = 0; i < n_vars; i++)
+ {
+ member = interaction_variable_get_member (var, i);
+
+ if (var_is_value_missing (member, vals[i], MV_ANY))
+ {
+ value_set_missing (result->val, MAX_SHORT_STRING);
+ result->f = SYSMIS;
+ break;
+ }
+ else
+ {
+ if (var_is_alpha (var->members[i]))
+ {
+ strncat (result->val->s, vals[i]->s, MAX_SHORT_STRING);
+ }
+ else if (var_is_numeric (var->members[i]))
+ {
+ result->f *= vals[i]->f;
+ }
+ }
+ }
+ if (interaction_get_n_alpha (var) == 0)
{
- length = (length > 0) ? length : 1;
+ /*
+ If there are no categorical variables, then the
+ interaction consists of only numeric data. In this case,
+ code that uses this interaction_value will see the union
+ member as the numeric value. If we were to store that
+ numeric value in result->f as well, the calling code may
+ inadvertently square this value by multiplying by
+ result->val->f. Such multiplication would be correct for an
+ interaction consisting of both categorical and numeric
+ data, but a mistake for purely numerical interactions. To
+ avoid the error, we set result->f to 1.0 for numeric
+ interactions.
+ */
+ result->val->f = result->f;
+ result->f = 1.0;
}
}
- if (length > 0)
+ return result;
+}
+
+union value *
+interaction_value_get (const struct interaction_value *val)
+{
+ return val->val;
+}
+
+/*
+ Returns the numeric value of the non-zero entry for the vector
+ corresponding to this interaction. Do not use this function to get
+ the numeric value of a purley numeric interaction. Instead, use the
+ union value * returned by interaction_value_get.
+ */
+double
+interaction_value_get_nonzero_entry (const struct interaction_value *val)
+{
+ if (val != NULL)
+ return val->f;
+ return 1.0;
+}
+
+void
+interaction_value_destroy (struct interaction_value *val)
+{
+ if (val != NULL)
{
- length--;
+ free (val->val);
+ free (val);
}
+}
- result = gsl_vector_calloc (length);
- subs = xnmalloc (n_vars, sizeof (*subs));
- for (j = 0; j < n_vars; j++)
+/*
+ Return a value from a variable that is an interaction.
+ */
+struct interaction_value *
+interaction_case_data (const struct ccase *ccase, const struct variable *var,
+ const struct interaction_variable **intr_vars, size_t n_intr)
+{
+ size_t i;
+ size_t n_vars;
+ const struct interaction_variable *iv;
+ const struct variable *intr;
+ const struct variable *member;
+ const union value **vals = NULL;
+
+ for (i = 0; i < n_intr; i++)
{
- if (var_is_alpha (v[j]))
+ iv = intr_vars[i];
+ intr = interaction_variable_get_var (iv);
+ if (var_get_dict_index (intr) == var_get_dict_index (var))
{
- subs[j] = cat_value_find (v[j], vals[j]);
+ break;
}
}
- j = subs[0];
- for (i = 1; i < n_vars; i++)
+ n_vars = interaction_get_n_vars (iv);
+ vals = xnmalloc (n_vars, sizeof (*vals));
+ for (i = 0; i < n_vars; i++)
{
- j = j * cat_get_n_categories (v[i]) + subs[i];
+ member = interaction_variable_get_member (iv, i);
+ vals[i] = case_data (ccase, member);
}
- gsl_vector_set (result, j, 1.0);
- /*
- If any of the variables are numeric, the interaction of that
- variable with another is just a scalar product.
- */
- for (i = 1; i < n_vars; i++)
+ return interaction_value_create (iv, vals);
+}
+
+bool
+is_interaction (const struct variable *var, const struct interaction_variable **iv, size_t n_intr)
+{
+ size_t i;
+ const struct variable *intr;
+
+ for (i = 0; i < n_intr; i++)
{
- if (var_is_numeric (v[i]))
+ intr = interaction_variable_get_var (iv[i]);
+ if (var_get_dict_index (intr) == var_get_dict_index (var))
{
- tmp *= vals[i]->f;
+ return true;
}
}
- if (fabs (tmp - 1.0) > GSL_DBL_EPSILON)
- {
- gsl_vector_set (result, j, tmp);
- }
- free (subs);
-
- return result;
+ return false;
}
+
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
-gsl_vector *
-get_interaction (union value **, const struct variable **, size_t);
+#ifndef INTERACTION_H
+#define INTERACTION_H
+#include <data/case.h>
+
+struct interaction_variable;
+struct interaction_value;
+
+struct interaction_variable * interaction_variable_create (const struct variable **, int);
+void interaction_variable_destroy (struct interaction_variable *);
+struct interaction_value * interaction_value_create (const struct interaction_variable *, const union value **);
+void interaction_value_destroy (struct interaction_value *);
+size_t interaction_variable_get_n_vars (const struct interaction_variable *);
+double interaction_value_get_nonzero_entry (const struct interaction_value *);
+union value * interaction_value_get (const struct interaction_value *);
+const struct variable * interaction_variable_get_var (const struct interaction_variable *);
+size_t interaction_get_n_numeric (const struct interaction_variable *);
+size_t interaction_get_n_alpha (const struct interaction_variable *);
+size_t interaction_get_n_vars (const struct interaction_variable *);
+const struct variable * interaction_variable_get_member (const struct interaction_variable *, size_t);
+bool is_interaction (const struct variable *, const struct interaction_variable **, size_t);
+struct interaction_value *
+interaction_case_data (const struct ccase *, const struct variable *,
+ const struct interaction_variable **, size_t);
+double interaction_value_get_nonzero_entry (const struct interaction_value *);
+#endif
/* PSPP - a program for statistical analysis.
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
enum mv_class exclude)
{
struct casereader *pass1, *pass2;
- struct ccase c;
+ struct ccase *c;
struct levene_info l;
l.n_dep = n_dep;
casereader_split (reader, &pass1, &pass2);
levene_precalc (&l);
- for (; casereader_read (pass1, &c); case_destroy (&c))
- levene_calc (dict, &c, &l);
+ for (; (c = casereader_read (pass1)) != NULL; case_unref (c))
+ levene_calc (dict, c, &l);
casereader_destroy (pass1);
levene_postcalc (&l);
levene2_precalc(&l);
- for (; casereader_read (pass2, &c); case_destroy (&c))
- levene2_calc (dict, &c, &l);
+ for (; (c = casereader_read (pass2)) != NULL; case_unref (c))
+ levene2_calc (dict, c, &l);
casereader_destroy (pass2);
levene2_postcalc (&l);
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
struct merge_input
{
struct casereader *reader;
- struct ccase c;
+ struct ccase *c;
};
struct merge
{
struct merge_input *i = &m->inputs[idx];
- if (casereader_read (i->reader, &i->c))
+ i->c = casereader_read (i->reader);
+ if (i->c)
return true;
else
{
min = 0;
for (i = 1; i < m->input_cnt; i++)
- if (subcase_compare_3way (&m->ordering, &m->inputs[i].c,
- &m->ordering, &m->inputs[min].c) < 0)
+ if (subcase_compare_3way (&m->ordering, m->inputs[i].c,
+ &m->ordering, m->inputs[min].c) < 0)
min = i;
- casewriter_write (w, &m->inputs[min].c);
+ casewriter_write (w, m->inputs[min].c);
read_input_case (m, min);
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 2008 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
acc (struct statistic *s, const struct ccase *cx UNUSED,
double c, double cc, double y)
{
- struct ccase cp;
+ struct ccase *cp;
struct np *np = (struct np *) s;
double rank = np->prev_cc + (c + 1) / 2.0;
maximize (&np->y_max, y);
minimize (&np->y_min, y);
- case_create (&cp, n_NP_IDX);
-
- case_data_rw_idx (&cp, NP_IDX_Y)->f = y;
- case_data_rw_idx (&cp, NP_IDX_NS)->f = ns;
- case_data_rw_idx (&cp, NP_IDX_DNS)->f = dns;
-
- casewriter_write (np->writer, &cp);
+ cp = case_create (n_NP_IDX);
+ case_data_rw_idx (cp, NP_IDX_Y)->f = y;
+ case_data_rw_idx (cp, NP_IDX_NS)->f = ns;
+ case_data_rw_idx (cp, NP_IDX_DNS)->f = dns;
+ casewriter_write (np->writer, cp);
np->prev_cc = cc;
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 2008 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
const struct variable *var,
enum mv_class exclude)
{
- struct ccase cx;
- struct ccase prev_cx;
+ struct ccase *cx;
+ struct ccase *prev_cx = NULL;
double prev_value = -DBL_MAX;
double cc_i = 0;
double c_i = 0;
- case_nullify (&prev_cx);
-
- for (; casereader_read (reader, &cx); case_destroy (&cx))
+ for (; (cx = casereader_read (reader)) != NULL; case_unref (cx))
{
- const double weight = wv ? case_data (&cx, wv)->f : 1.0;
- const double this_value = case_data (&cx, var)->f;
+ const double weight = wv ? case_data (cx, wv)->f : 1.0;
+ const double this_value = case_data (cx, var)->f;
/* The casereader MUST be sorted */
assert (this_value >= prev_value);
- if ( var_is_value_missing (var, case_data (&cx, var), exclude))
+ if ( var_is_value_missing (var, case_data (cx, var), exclude))
continue;
- case_destroy (&prev_cx);
+ case_unref (prev_cx);
if ( prev_value == -DBL_MAX || prev_value == this_value)
c_i += weight;
if ( prev_value > -DBL_MAX && this_value > prev_value)
{
- update_k_values (&prev_cx, prev_value, c_i, cc_i, os, nos);
+ update_k_values (prev_cx, prev_value, c_i, cc_i, os, nos);
c_i = weight;
}
cc_i += weight;
prev_value = this_value;
- case_clone (&prev_cx, &cx);
+ prev_cx = case_ref (cx);
}
- update_k_values (&prev_cx, prev_value, c_i, cc_i, os, nos);
- case_destroy (&prev_cx);
+ update_k_values (prev_cx, prev_value, c_i, cc_i, os, nos);
+ case_unref (prev_cx);
casereader_destroy (reader);
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
struct casewriter *run;
casenumber run_id;
- struct ccase run_end;
+ struct ccase *run_end;
};
static struct casewriter_class sort_casewriter_class;
static bool pqueue_is_full (const struct pqueue *);
static bool pqueue_is_empty (const struct pqueue *);
static void pqueue_push (struct pqueue *, struct ccase *, casenumber);
-static void pqueue_pop (struct pqueue *, struct ccase *, casenumber *);
+static struct ccase *pqueue_pop (struct pqueue *, casenumber *);
static void output_record (struct sort_writer *);
sort->pqueue = pqueue_create (ordering, value_cnt);
sort->run = NULL;
sort->run_id = 0;
- case_nullify (&sort->run_end);
+ sort->run_end = NULL;
return casewriter_create (value_cnt, &sort_casewriter_class, sort);
}
if (pqueue_is_full (sort->pqueue))
output_record (sort);
- next_run = (case_is_null (&sort->run_end)
+ next_run = (sort->run_end == NULL
|| subcase_compare_3way (&sort->ordering, c,
- &sort->ordering, &sort->run_end) < 0);
+ &sort->ordering, sort->run_end) < 0);
pqueue_push (sort->pqueue, c, sort->run_id + (next_run ? 1 : 0));
}
merge_destroy (sort->merge);
pqueue_destroy (sort->pqueue);
casewriter_destroy (sort->run);
- case_destroy (&sort->run_end);
+ case_unref (sort->run_end);
free (sort);
}
static void
output_record (struct sort_writer *sort)
{
- struct ccase min_case;
+ struct ccase *min_case;
casenumber min_run_id;
- pqueue_pop (sort->pqueue, &min_case, &min_run_id);
+ min_case = pqueue_pop (sort->pqueue, &min_run_id);
#if 0
- printf ("\toutput: %f to run %d\n", case_num_idx (&min_case, 0), min_run_id);
+ printf ("\toutput: %f to run %d\n", case_num_idx (min_case, 0), min_run_id);
#endif
if (sort->run_id != min_run_id && sort->run != NULL)
sort->run_id = min_run_id;
}
- case_destroy (&sort->run_end);
- case_clone (&sort->run_end, &min_case);
-
- casewriter_write (sort->run, &min_case);
+ case_unref (sort->run_end);
+ sort->run_end = case_ref (min_case);
+ casewriter_write (sort->run, min_case);
}
static struct casewriter_class sort_casewriter_class =
struct pqueue_record
{
casenumber id;
- struct ccase c;
+ struct ccase *c;
casenumber idx;
};
{
while (!pqueue_is_empty (pq))
{
- struct ccase c;
casenumber id;
- pqueue_pop (pq, &c, &id);
- case_destroy (&c);
+ struct ccase *c = pqueue_pop (pq, &id);
+ case_unref (c);
}
subcase_destroy (&pq->ordering);
free (pq->records);
r = &pq->records[pq->record_cnt++];
r->id = id;
- case_move (&r->c, c);
+ r->c = c;
r->idx = pq->idx++;
push_heap (pq->records, pq->record_cnt, sizeof *pq->records,
compare_pqueue_records_minheap, pq);
}
-static void
-pqueue_pop (struct pqueue *pq, struct ccase *c, casenumber *id)
+static struct ccase *
+pqueue_pop (struct pqueue *pq, casenumber *id)
{
struct pqueue_record *r;
r = &pq->records[pq->record_cnt];
*id = r->id;
- case_move (c, &r->c);
+ return r->c;
}
/* Compares record-run tuples A and B on id, then on case data,
const struct pqueue *pq = pq_;
int result = a->id < b->id ? -1 : a->id > b->id;
if (result == 0)
- result = subcase_compare_3way (&pq->ordering, &a->c,
- &pq->ordering, &b->c);
+ result = subcase_compare_3way (&pq->ordering, a->c, &pq->ordering, b->c);
if (result == 0)
result = a->idx < b->idx ? -1 : a->idx > b->idx;
return -result;
--- /dev/null
+/* PSPP - a program for statistical analysis.
+ Copyright (C) 2009 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* Thanks to Rob van Son for writing the original version of this
+ file. This version has been completely rewritten; only the
+ name of the function has been retained. In the process of
+ rewriting, it was sped up from O(2**N) to O(N**3). */
+
+#include <config.h>
+#include "wilcoxon-sig.h"
+#include <assert.h>
+#include <limits.h>
+#include <math.h>
+#include <stdlib.h>
+#include "xalloc.h"
+
+/* For integers N and W, with 0 <= N < CHAR_BIT*sizeof(long),
+ calculates and returns the value of the function S(N,W),
+ defined as the number of subsets of 1, 2, 3, ..., N that sum
+ to at least W. There are 2**N subsets of N items, so S(N,W)
+ is in the range 0...2**N.
+
+ There are a few trivial cases:
+
+ * For W <= 0, S(N,W) = 2**N.
+
+ * For W > N*(N+1)/2, S(N,W) = 0.
+
+ * S(1,1) = 1.
+
+ Notably, these trivial cases include all values of W for N = 1.
+
+ Now consider the remaining, nontrivial cases, that is, N > 1 and
+ 1 <= W <= N*(N+1)/2. In this case, apply the following identity:
+
+ S(N,W) = S(N-1, W) + S(N-1, W-N).
+
+ The first term on the right hand is the number of subsets that do
+ not include N that sum to at least W; the second term is the
+ number of subsets that do include N that sum to at least W.
+
+ Then we repeatedly apply the identity to the result, reducing the
+ value of N by 1 each time until we reach N=1. Some expansions
+ yield trivial cases, e.g. if W - N <= 0 (in which case we add a
+ 2**N term to the final result) or if W is greater than the new N.
+
+ Here is an example:
+
+ S(7,7) = S(6,7) + S(6,0)
+ = S(6,7) + 64
+
+ = (S(5,7) + S(5,1)) + 64
+
+ = (S(4,7) + S(4,2)) + (S(4,1) + S(4,0)) + 64
+ = S(4,7) + S(4,2) + S(4,1) + 80
+
+ = (S(3,7) + S(3,3)) + (S(3,2) + S(3,2)) + (S(3,1) + S(3,0)) + 80
+ = S(3,3) + 2*S(3,2) + S(3,1) + 88
+
+ = (S(2,3) + S(2,0)) + 2*(S(2,2) + S(2,0)) + (S(2,1) + S(2,0)) + 88
+ = S(2,3) + 2*S(2,2) + S(2,1) + 104
+
+ = (S(1,3) + S(1,1)) + 2*(S(1,2) + S(1,0)) + (S(1,1) + S(2,0)) + 104
+ = 2*S(1,1) + 112
+
+ = 114
+
+ This function runs in O(N*W) = O(N**3) time. It seems very
+ likely that it can be made to run in O(N**2) time or perhaps
+ even better, but N is, practically speaking, quite small.
+ Plus, the return value may be as large as N**2, so N must not
+ be larger than 31 on 32-bit systems anyhow, and even 63**3 is
+ only 250,047.
+*/
+static unsigned long int
+count_sums_to_W (unsigned long int n, unsigned long int w)
+{
+ /* The array contain ints even though everything else is long,
+ but no element in the array can have a value bigger than N,
+ and using int will save some memory on 64-bit systems. */
+ unsigned long int total;
+ unsigned long int max;
+ int *array;
+
+ assert (n < CHAR_BIT * sizeof (unsigned long int));
+ if (n == 0)
+ return 0;
+ else if (w <= 0)
+ return 1 << n;
+ else if (w > n * (n + 1) / 2)
+ return 0;
+ else if (n == 1)
+ return 1;
+
+ array = xcalloc (sizeof *array, w + 1);
+ array[w] = 1;
+
+ max = w;
+ total = 0;
+ for (; n > 1; n--)
+ {
+ unsigned long int max_sum = n * (n + 1) / 2;
+ int i;
+
+ if (max_sum < max)
+ max = max_sum;
+
+ for (i = 1; i <= max; i++)
+ if (array[i] != 0)
+ {
+ int new_w = i - n;
+ if (new_w <= 0)
+ total += array[i] * (1 << (n - 1));
+ else
+ array[new_w] += array[i];
+ }
+ }
+ total += array[1];
+ free (array);
+ return total;
+}
+
+/* Returns the exact, two-tailed level of significance for the
+ Wilcoxon Matched-Pairs Signed-Ranks test, given sum of ranks
+ of positive (or negative samples) W and sample size N.
+
+ Returns -1 if the exact significance level cannot be
+ calculated because W is out of the supported range. */
+double
+LevelOfSignificanceWXMPSR (double w, long int n)
+{
+ unsigned long int max_w;
+
+ /* Limit N to valid range that won't cause integer overflow. */
+ if (n < 0 || n >= CHAR_BIT * sizeof (unsigned long int))
+ return -1;
+
+ max_w = n * (n + 1) / 2;
+ if (w < max_w / 2)
+ w = max_w - w;
+
+ return count_sums_to_W (n, ceil (w)) / (double) (1 << n) * 2;
+}
--- /dev/null
+#ifndef WX_MP_SR
+#define WX_MP_SR 1
+
+double LevelOfSignificanceWXMPSR(double w, long int n);
+
+#endif
#include <stdio.h>
#include <stdlib.h>
+#include <data/file-name.h>
#include <libpspp/str.h>
#include "fwriteerror.h"
if (journal_file == NULL)
{
if (journal_file_name == NULL)
- journal_file_name = xstrdup ("pspp.jnl");
+ {
+ const char *output_path = default_output_path ();
+ journal_file_name = xasprintf ("%s%s", output_path, "pspp.jnl");
+ }
journal_file = fopen (journal_file_name, "w");
if (journal_file == NULL)
{
src_ui_gui_psppire_LDFLAGS = \
+ $(PSPPIRE_LDFLAGS) \
$(PG_LDFLAGS)
src/libpspp-core.la \
$(GTK_LIBS) \
$(GLADE_LIBS) \
- @LIBINTL@
+ @LIBINTL@ \
+ $(LIB_CLOSE)
src_ui_gui_psppiredir = $(pkgdatadir)
nodist_src_ui_gui_psppire_DATA = \
- $(top_srcdir)/src/ui/gui/crosstabs.ui \
- $(top_srcdir)/src/ui/gui/examine.ui \
- $(top_srcdir)/src/ui/gui/frequencies.ui \
- $(top_srcdir)/src/ui/gui/message-dialog.ui \
- $(top_srcdir)/src/ui/gui/psppire.ui \
- $(top_srcdir)/src/ui/gui/oneway.ui \
- $(top_srcdir)/src/ui/gui/rank.ui \
- $(top_srcdir)/src/ui/gui/recode.ui \
- $(top_srcdir)/src/ui/gui/regression.ui \
- $(top_srcdir)/src/ui/gui/t-test.ui
+ $(top_builddir)/src/ui/gui/crosstabs.ui \
+ $(top_builddir)/src/ui/gui/examine.ui \
+ $(top_builddir)/src/ui/gui/frequencies.ui \
+ $(top_builddir)/src/ui/gui/message-dialog.ui \
+ $(top_builddir)/src/ui/gui/psppire.ui \
+ $(top_builddir)/src/ui/gui/oneway.ui \
+ $(top_builddir)/src/ui/gui/rank.ui \
+ $(top_builddir)/src/ui/gui/recode.ui \
+ $(top_builddir)/src/ui/gui/regression.ui \
+ $(top_builddir)/src/ui/gui/t-test.ui
EXTRA_DIST += \
$(top_srcdir)/src/ui/gui/crosstabs.glade \
src/ui/gui/marshaller-list
BUILT_SOURCES += src/ui/gui/psppire-marshal.c src/ui/gui/psppire-marshal.h
-CLEANFILES += src/ui/gui/psppire-marshal.c src/ui/gui/psppire-marshal.h
+CLEANFILES += src/ui/gui/psppire-marshal.c src/ui/gui/psppire-marshal.h \
+ $(nodist_src_ui_gui_psppire_DATA)
\ No newline at end of file
/* PSPPIRE - a graphical user interface for PSPP.
- Copyright (C) 2008 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
writer = autopaging_writer_create (dict_get_next_value_idx (clip_dict));
for (i = range.row0; i <= range.rowi ; ++i )
{
- struct ccase old;
-
- if (psppire_data_store_get_case (ds, i, &old))
- {
- struct ccase new;
-
- case_map_execute (map, &old, &new);
- case_destroy (&old);
- casewriter_write (writer, &new);
- }
+ struct ccase *old = psppire_data_store_get_case (ds, i);
+ if (old != NULL)
+ casewriter_write (writer, case_map_execute (map, old));
else
casewriter_force_error (writer);
}
for (r = 0 ; r < case_cnt ; ++r )
{
int c;
- struct ccase cc;
- if ( ! casereader_peek (clip_datasheet, r, &cc))
+ struct ccase *cc;
+
+ cc = casereader_peek (clip_datasheet, r);
+ if (cc == NULL)
{
g_warning ("Clipboard seems to have inexplicably shrunk");
break;
for (c = 0 ; c < var_cnt ; ++c)
{
const struct variable *v = dict_get_var (clip_dict, c);
- data_out_g_string (string, v, &cc);
+ data_out_g_string (string, v, cc);
if ( c < val_cnt - 1 )
g_string_append (string, "\t");
}
if ( r < case_cnt)
g_string_append (string, "\n");
- case_destroy (&cc);
+ case_unref (cc);
}
return string;
for (r = 0 ; r < case_cnt ; ++r )
{
int c;
- struct ccase cc;
- if ( ! casereader_peek (clip_datasheet, r, &cc))
+ struct ccase *cc = casereader_peek (clip_datasheet, r);
+ if (cc == NULL)
{
g_warning ("Clipboard seems to have inexplicably shrunk");
break;
{
const struct variable *v = dict_get_var (clip_dict, c);
g_string_append (string, "<td>");
- data_out_g_string (string, v, &cc);
+ data_out_g_string (string, v, cc);
g_string_append (string, "</td>\n");
}
g_string_append (string, "</tr>\n");
- case_destroy (&cc);
+ case_unref (cc);
}
g_string_append (string, "</table>\n");
/* PSPPIRE - a graphical user interface for PSPP.
- Copyright (C) 2006, 2008 Free Software Foundation
+ Copyright (C) 2006, 2008, 2009 Free Software Foundation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
{
gboolean result;
gint val_cnt, v;
- struct ccase cc;
+ struct ccase *cc;
g_return_val_if_fail (ds, FALSE);
val_cnt = datasheet_get_column_cnt (ds->datasheet) ;
g_return_val_if_fail (posn <= psppire_data_store_get_case_count (ds), FALSE);
- case_create (&cc, val_cnt);
+ cc = case_create (val_cnt);
- memset ( case_data_rw_idx (&cc, 0), 0, val_cnt * MAX_SHORT_STRING);
+ memset ( case_data_rw_idx (cc, 0), 0, val_cnt * MAX_SHORT_STRING);
for (v = 0 ; v < psppire_dict_get_var_cnt (ds->dict) ; ++v)
{
if ( var_is_alpha (pv))
continue;
- case_data_rw (&cc, pv)->f = SYSMIS;
+ case_data_rw (cc, pv)->f = SYSMIS;
}
- result = psppire_data_store_insert_case (ds, &cc, posn);
+ result = psppire_data_store_insert_case (ds, cc, posn);
- case_destroy (&cc);
+ case_unref (cc);
return result;
}
\f
-/* Fills C with the CASENUMth case.
- Returns true on success, false otherwise.
+/* Returns the CASENUMth case, or a null pointer on failure.
*/
-gboolean
+struct ccase *
psppire_data_store_get_case (const PsppireDataStore *ds,
- casenumber casenum,
- struct ccase *c)
+ casenumber casenum)
{
g_return_val_if_fail (ds, FALSE);
g_return_val_if_fail (ds->datasheet, FALSE);
- return datasheet_get_row (ds->datasheet, casenum, c);
+ return datasheet_get_row (ds->datasheet, casenum);
}
struct ccase *cc,
casenumber posn)
{
- struct ccase tmp;
bool result ;
g_return_val_if_fail (ds, FALSE);
g_return_val_if_fail (ds->datasheet, FALSE);
- case_clone (&tmp, cc);
- result = datasheet_insert_rows (ds->datasheet, posn, &tmp, 1);
+ case_ref (cc);
+ result = datasheet_insert_rows (ds->datasheet, posn, &cc, 1);
if ( result )
{
/* PSPPIRE - a graphical user interface for PSPP.
- Copyright (C) 2006 Free Software Foundation
+ Copyright (C) 2006, 2009 Free Software Foundation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
\f
-gboolean psppire_data_store_get_case (const PsppireDataStore *ds,
- casenumber casenum,
- struct ccase *c);
+struct ccase *psppire_data_store_get_case (const PsppireDataStore *ds,
+ casenumber casenum);
#include "psppire-dialog.h"
#include "psppire-buttonbox.h"
#include "psppire-selector.h"
+#include <string.h>
static void psppire_dialog_class_init (PsppireDialogClass *);
static void psppire_dialog_init (PsppireDialog *);
{
PsppireDialog *dialog = PSPPIRE_DIALOG (buildable);
- if ( 0 == g_strcmp0 (childname, "hbox"))
+ if ( 0 == strcmp (childname, "hbox"))
return G_OBJECT (dialog->box);
return NULL;
/* PSPPIRE - a graphical user interface for PSPP.
- Copyright (C) 2004, 2005, 2006 Free Software Foundation
+ Copyright (C) 2004, 2005, 2006, 2009 Free Software Foundation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include <assert.h>
#include <libintl.h>
#include <gsl/gsl_errno.h>
-#include <signal.h>
#include <argp.h>
#include <ui/command-line.h>
#define _(msgid) gettext (msgid)
#define N_(msgid) msgid
+
+const char * output_file_name (void);
+
+
void
initialize (struct command_line_processor *clp, int argc, char **argv)
{
create_icon_factory ();
- outp_configure_driver_line (
- ss_cstr ("gui:ascii:screen:squeeze=on headers=off top-margin=0 "
- "bottom-margin=0 paginate=off length=auto width=auto "
- "emphasis=none "
- "output-file=\"" OUTPUT_FILE_NAME "\" append=yes"));
+ {
+ const char *filename = output_file_name ();
+
+ struct string config_string;
+
+ ds_init_empty (&config_string);
+
+ ds_put_format (&config_string,
+ "gui:ascii:screen:squeeze=on headers=off top-margin=0 "
+ "bottom-margin=0 paginate=off length=auto width=auto "
+ "emphasis=none "
+ "output-file=\"%s\" append=yes", filename);
+
+ outp_configure_driver_line (ds_ss (&config_string));
+
+ unlink (filename);
- unlink (OUTPUT_FILE_NAME);
+ ds_destroy (&config_string);
+ }
journal_enable ();
textdomain (PACKAGE);
- /* Ignore alarm clock signals */
- signal (SIGALRM, SIG_IGN);
-
the_data_window = psppire_data_window_new ();
command_line_processor_replace_aux (clp, &post_init_argp, the_source_stream);
const struct argp non_option_argp = {NULL, parse_non_options, 0, 0, 0, 0, 0};
+
+
+const char *
+output_file_name (void)
+{
+ const char *dir = default_output_path ();
+ static char *filename = NULL;
+
+ if ( NULL == filename )
+ filename = xasprintf ("%s%s", dir, OUTPUT_FILE_NAME);
+
+
+ return filename;
+}
src/libpspp-core.la \
$(NCURSES_LIBS) \
$(LIBICONV) \
- @LIBINTL@ @LIBREADLINE@
+ @LIBINTL@ @LIBREADLINE@ \
+ $(LIB_CLOSE)
-src_ui_terminal_pspp_LDFLAGS = $(PG_LDFLAGS)
+src_ui_terminal_pspp_LDFLAGS = $(PSPP_LDFLAGS) $(PG_LDFLAGS)
if RELOCATABLE_VIA_LD
src_ui_terminal_pspp_LDFLAGS += `$(RELOCATABLE_LDFLAGS) $(bindir)`
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2007, 2009 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
signal (SIGABRT, bug_handler);
signal (SIGSEGV, bug_handler);
signal (SIGFPE, bug_handler);
- signal (SIGALRM, SIG_IGN);
at_fatal_signal (clean_up);
i18n_init ();
tests/command/input-program.sh \
tests/command/insert.sh \
tests/command/lag.sh \
+ tests/command/line-ends.sh \
tests/command/list.sh \
tests/command/loop.sh \
tests/command/longvars.sh \
src/libpspp/pool.c \
src/libpspp/pool.h \
tests/libpspp/heap-test.c
-tests_libpspp_heap_test_LDADD = gl/libgl.la @LIBINTL@
+tests_libpspp_heap_test_LDADD = gl/libgl.la @LIBINTL@ @LIB_CLOSE@
tests_libpspp_heap_test_CPPFLAGS = $(AM_CPPFLAGS) -DASSERT_LEVEL=10
tests_libpspp_hmap_test_SOURCES = \
src/libpspp/range-set.c \
src/libpspp/range-set.h \
tests/libpspp/range-set-test.c
-tests_libpspp_range_set_test_LDADD = gl/libgl.la @LIBINTL@
+tests_libpspp_range_set_test_LDADD = gl/libgl.la @LIBINTL@ @LIB_CLOSE@
tests_libpspp_range_set_test_CPPFLAGS = $(AM_CPPFLAGS) -DASSERT_LEVEL=10
tests_libpspp_str_test_SOURCES = \
tests/libpspp/str-test.c
-tests_libpspp_str_test_LDADD = src/libpspp/libpspp.la gl/libgl.la @LIBINTL@
+tests_libpspp_str_test_LDADD = src/libpspp/libpspp.la gl/libgl.la @LIBINTL@ @LIB_CLOSE@
tests_libpspp_tower_test_SOURCES = \
src/libpspp/abt.c \
src/libpspp/tower.c \
src/libpspp/tower.h \
tests/libpspp/tower-test.c
-tests_libpspp_tower_test_LDADD = gl/libgl.la @LIBINTL@
+tests_libpspp_tower_test_LDADD = gl/libgl.la @LIBINTL@ @LIB_CLOSE@
tests_libpspp_tower_test_CPPFLAGS = $(AM_CPPFLAGS) -DASSERT_LEVEL=10
tests_libpspp_sparse_array_test_SOURCES = \
src/libpspp/pool.c \
src/libpspp/pool.h \
tests/libpspp/sparse-array-test.c
-tests_libpspp_sparse_array_test_LDADD = gl/libgl.la @LIBINTL@
+tests_libpspp_sparse_array_test_LDADD = gl/libgl.la @LIBINTL@ @LIB_CLOSE@
tests_libpspp_sparse_array_test_CPPFLAGS = $(AM_CPPFLAGS) -DASSERT_LEVEL=10
tests_formats_inexactify_SOURCES = tests/formats/inexactify.c
src/libpspp/integer-format.c \
src/libpspp/float-format.c \
tests/dissect-sysfile.c
-tests_dissect_sysfile_LDADD = gl/libgl.la @LIBINTL@
+tests_dissect_sysfile_LDADD = gl/libgl.la @LIBINTL@ @LIB_CLOSE@
tests_dissect_sysfile_CPPFLAGS = $(AM_CPPFLAGS) -DINSTALLDIR=\"$(bindir)\"
EXTRA_DIST += \
cd $TEMPDIR
-activity="create program"
+activity="create program 1"
cat > $TESTFILE << EOF
DATA LIST LIST /x * y *.
BEGIN DATA.
if [ $? -ne 0 ] ; then no_result ; fi
-activity="run program"
+activity="run program 1"
$SUPERVISOR $PSPP --testing-mode -o raw-ascii $TESTFILE
if [ $? -ne 0 ] ; then no_result ; fi
EOF
if [ $? -ne 0 ] ; then fail ; fi
+
+#Make sure this doesn't interfere with percentiles operation.
+
+activity="create program 2"
+cat > $TESTFILE << EOF
+DATA LIST LIST /X *.
+BEGIN DATA.
+99
+99
+5.00
+END DATA.
+
+MISSING VALUE X (99).
+
+EXAMINE /x
+ /PERCENTILES=HAVERAGE.
+
+
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+
+activity="run program 2"
+$SUPERVISOR $PSPP --testing-mode -o raw-ascii $TESTFILE
+if [ $? -ne 0 ] ; then fail ; fi
+
+
pass;
EOF
if [ $? -ne 0 ] ; then fail ; fi
+# Test for regression against bug #24569 in which PSPP crashed
+# upon attempt to insert a nonexistent file.
+activity="create wrapper 9"
+cat <<EOF > $TESTFILE
+INSERT
+ FILE='$TEMPDIR/nonexistent'
+ ERROR=CONTINUE.
+ .
+
+LIST.
+
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+#This command should fail
+activity="run program 7"
+$SUPERVISOR $PSPP --testing-mode -o raw-ascii $TESTFILE > /dev/null
+if [ $? -eq 0 ] ; then no_result ; fi
+
pass;
--- /dev/null
+#!/bin/sh
+
+# This program tests that DATA LIST can be used to read input files
+# with varying line ends (LF only, CR LF, CR only).
+
+TEMPDIR=/tmp/pspp-tst-$$
+TESTFILE=$TEMPDIR/`basename $0`.sps
+
+# ensure that top_builddir are absolute
+if [ -z "$top_builddir" ] ; then top_builddir=. ; fi
+if [ -z "$top_srcdir" ] ; then top_srcdir=. ; fi
+top_builddir=`cd $top_builddir; pwd`
+PSPP=$top_builddir/src/ui/terminal/pspp
+
+# ensure that top_srcdir is absolute
+top_srcdir=`cd $top_srcdir; pwd`
+
+STAT_CONFIG_PATH=$top_srcdir/config
+export STAT_CONFIG_PATH
+
+
+cleanup()
+{
+ if [ x"$PSPP_TEST_NO_CLEANUP" != x ] ; then
+ echo "NOT cleaning $TEMPDIR"
+ return ;
+ fi
+ cd /
+ rm -rf $TEMPDIR
+}
+
+
+fail()
+{
+ echo $activity
+ echo FAILED
+ cleanup;
+ exit 1;
+}
+
+
+no_result()
+{
+ echo $activity
+ echo NO RESULT;
+ cleanup;
+ exit 2;
+}
+
+pass()
+{
+ cleanup;
+ exit 0;
+}
+
+mkdir -p $TEMPDIR
+
+cd $TEMPDIR
+
+# Create command file.
+activity="create program"
+cat > $TESTFILE << EOF
+data list list notable file='input.txt'/a b c.
+list.
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+
+activity="create input.txt"
+printf '1 2 3\n4 5 6\r\n7 8 9\r10 11 12\n13 14 15 \r\n16 17 18\r' > input.txt
+if [ $? -ne 0 ] ; then no_result ; fi
+
+
+# Make sure that input.txt actually received the data that we expect.
+# It might not have, if we're running on a system that translates \n
+# into some other sequence.
+activity="check input.txt"
+cksum input.txt > input.cksum
+diff input.cksum - <<EOF
+4116052799 48 input.txt
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+
+activity="run program"
+$SUPERVISOR $PSPP --testing-mode $TESTFILE
+if [ $? -ne 0 ] ; then fail ; fi
+
+
+activity="compare output"
+perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
+diff -b $TEMPDIR/pspp.list - << EOF
+ a b c
+-------- -------- --------
+ 1.00 2.00 3.00
+ 4.00 5.00 6.00
+ 7.00 8.00 9.00
+ 10.00 11.00 12.00
+ 13.00 14.00 15.00
+ 16.00 17.00 18.00
+EOF
+if [ $? -ne 0 ] ; then fail ; fi
+
+pass;