gethostname getline getlogin_r getopt gettext memchr memcmp memmem \
memmove memset progname readlink restrict snprintf stat-macros stdbool \
stpcpy strcase strcspn strerror strftime strstr strtod strtok_r strtol \
-strtoul vsnprintf xalloc xalloc-die xreadlink
+strtoul vsnprintf xalloc xalloc-die xreadlink xvasprintf
all: po/POTFILES.in
test -d m4 || mkdir m4
Data are the focus of the PSPP language.
Each datum belongs to a @dfn{case} (also called an @dfn{observation}).
-Each case represents an individual or `experimental unit'.
+Each case represents an individual or ``experimental unit''.
For example, in the results of a survey, the names of the respondents,
-their sex, age @i{etc}. and their responses are all data and the data
+their sex, age, etc.@: and their responses are all data and the data
pertaining to single respondent is a case.
This chapter examines
the PSPP commands for defining variables and reading and writing data.
-@quotation
-@strong{Please note:} Data is not actually read until a procedure is
-executed. These commands tell PSPP how to read data, but they
-do not @emph{cause} PSPP to read data.
+@quotation Note
+These commands tell PSPP how to read data, but the data will not
+actually be read until a procedure is executed.
@end quotation
@menu
* BEGIN DATA:: Embed data within a syntax file.
* CLEAR TRANSFORMATIONS:: Clear pending transformations.
+* CLOSE FILE HANDLE:: Close a file handle.
* DATA LIST:: Fundamental data reading command.
* END CASE:: Output the current case.
* END FILE:: Terminate the current input program.
-* FILE HANDLE:: Support for fixed-length records.
+* FILE HANDLE:: Support for special file formats.
* INPUT PROGRAM:: Support for complex input programs.
* LIST:: List cases in the active file.
* MATRIX DATA:: Read matrices in text format.
* WRITE:: Display values in write formats.
@end menu
-@node BEGIN DATA, CLEAR TRANSFORMATIONS, Data Input and Output, Data Input and Output
+@node BEGIN DATA
@section BEGIN DATA
@vindex BEGIN DATA
@vindex END DATA
END DATA.
@end example
-@node CLEAR TRANSFORMATIONS, DATA LIST, BEGIN DATA, Data Input and Output
+@node CLEAR TRANSFORMATIONS
@section CLEAR TRANSFORMATIONS
@vindex CLEAR TRANSFORMATIONS
transformations. It does not cancel the current input program. It is
valid only when PSPP is interactive, not in syntax files.
-@node DATA LIST, END CASE, CLEAR TRANSFORMATIONS, Data Input and Output
+@node CLOSE FILE HANDLE
+@section CLOSE FILE HANDLE
+
+@display
+CLOSE FILE HANDLE handle_name.
+@end display
+
+@cmd{CLOSE FILE HANDLE} disassociates the name of a file handle with a
+given file. The only specification is the name of the handle to close.
+Afterward
+@cmd{FILE HANDLE}.
+
+If the file handle name refers to a scratch file, then the storage
+associated with the scratch file in memory or on disk will be freed.
+If the scratch file is in use, e.g.@: it has been specified on a
+@cmd{GET} command whose execution has not completed, then freeing is
+delayed until it is no longer in use.
+
+The file named INLINE, which represents data entered between @cmd{BEGIN
+DATA} and @cmd{END DATA}, cannot be closed. Attempts to close it with
+@cmd{CLOSE FILE HANDLE} have no effect.
+
+@cmd{CLOSE FILE HANDLE} is a PSPP extension.
+
+@node DATA LIST
@section DATA LIST
@vindex DATA LIST
@cindex reading data from a file
* DATA LIST LIST:: Each case must be on a single line.
@end menu
-@node DATA LIST FIXED, DATA LIST FREE, DATA LIST, DATA LIST
+@node DATA LIST FIXED
@subsection DATA LIST FIXED
@vindex DATA LIST FIXED
@cindex reading fixed-format data
The FILE subcommand must be used if input is to be taken from an
external file. It may be used to specify a filename as a string or a
-file handle (@pxref{FILE HANDLE}). If the FILE subcommand is not used,
+file handle (@pxref{File Handles}). If the FILE subcommand is not used,
then input is assumed to be specified within the command file using
@cmd{BEGIN DATA}@dots{}@cmd{END DATA} (@pxref{BEGIN DATA}).
* DATA LIST FIXED Examples:: Examples of DATA LIST FIXED.
@end menu
-@node DATA LIST FIXED Examples, , DATA LIST FIXED, DATA LIST FIXED
+@node DATA LIST FIXED Examples
@unnumberedsubsubsec Examples
@enumerate
@end enumerate
-@node DATA LIST FREE, DATA LIST LIST, DATA LIST FIXED, DATA LIST
+@node DATA LIST FREE
@subsection DATA LIST FREE
@vindex DATA LIST FREE
Specified field widths are ignored on input, although all normal limits
on field width apply, but they are honored on output.
-@node DATA LIST LIST, , DATA LIST FREE, DATA LIST
+@node DATA LIST LIST
@subsection DATA LIST LIST
@vindex DATA LIST LIST
record. If more or fewer fields are found on an input line than
expected, an appropriate diagnostic is issued.
-@node END CASE, END FILE, DATA LIST, Data Input and Output
+@node END CASE
@section END CASE
@vindex END CASE
@cmd{END CASE} is used only within @cmd{INPUT PROGRAM} to output the
current case. @xref{INPUT PROGRAM}, for details.
-@node END FILE, FILE HANDLE, END CASE, Data Input and Output
+@node END FILE
@section END FILE
@vindex END FILE
@cmd{END FILE} is used only within @cmd{INPUT PROGRAM} to terminate
the current input program. @xref{INPUT PROGRAM}.
-@node FILE HANDLE, INPUT PROGRAM, END FILE, Data Input and Output
+@node FILE HANDLE
@section FILE HANDLE
@vindex FILE HANDLE
@display
-FILE HANDLE handle_name
- /NAME='filename'
- /MODE=@{CHARACTER,IMAGE@}
- /LRECL=rec_len
- /TABWIDTH=tab_width
+For text files:
+ FILE HANDLE handle_name
+ /NAME='filename'
+ [/MODE=CHARACTER]
+ /TABWIDTH=tab_width
+
+For binary files with fixed-length records:
+ FILE HANDLE handle_name
+ /NAME='filename'
+ /MODE=IMAGE
+ [/LRECL=rec_len]
+
+To explicitly declare a scratch handle:
+ FILE HANDLE handle_name
+ /MODE=SCRATCH
@end display
Use @cmd{FILE HANDLE} to associate a file handle name with a file and
its attributes, so that later commands can refer to the file by its
-handle name. Because names of text files can be specified directly on
-commands that access files, @cmd{FILE HANDLE} is only needed when a
+handle name. Names of text files can be specified directly on
+commands that access files, so that @cmd{FILE HANDLE} is only needed when a
file is not an ordinary file containing lines of text. However,
@cmd{FILE HANDLE} may be used even for text files, and it may be
easier to specify a file's name once and later refer to it by an
abstract handle.
-Specify the file handle name as an identifier. Any given identifier may
-only appear once in a PSPP run. File handles may not be reassigned to a
-different file. The file handle name must immediately follow the @cmd{FILE
-HANDLE} command name.
-
-The NAME subcommand specifies the name of the file associated with the
-handle. It is the only required subcommand.
+Specify the file handle name as the identifier immediately following the
+@cmd{FILE HANDLE} command name. The identifier INLINE is reserved for
+representing data embedded in the syntax file (@pxref{BEGIN DATA}) The
+file handle name must not already have been used in a previous
+invocation of @cmd{FILE HANDLE}, unless it has been closed by an
+intervening command (@pxref{CLOSE FILE HANDLE}).
MODE specifies a file mode. In CHARACTER mode, the default, the data
-file is opened in ANSI C text mode, so that local end of line
-conventions are followed, and each text line is read as one record.
+file is read as a text file, according to the local system's
+conventions, and each text line is read as one record.
In CHARACTER mode, most input programs will expand tabs to spaces
(@cmd{DATA LIST FREE} with explicitly specified delimiters is an
exception). By default, each tab is 4 characters wide, but an
alternate width may be specified on TABWIDTH. A tab width of 0
suppresses tab expansion entirely.
-By contrast, in IMAGE mode, the data file is opened in ANSI C binary
-mode and records are a fixed length. In IMAGE mode, LRECL specifies
-the record length in bytes, with a default of 1024. Tab characters
-are never expanded to spaces in binary mode.
+In IMAGE mode, the data file is opened in ANSI C binary mode and records
+are fixed in length. In IMAGE mode, LRECL specifies the record length in
+bytes, with a default of 1024. Tab characters are never expanded to
+spaces in binary mode.
+
+The NAME subcommand specifies the name of the file associated with the
+handle. It is required in CHARACTER and IMAGE modes.
+
+The SCRATCH mode designates the file handle as a scratch file handle.
+Its use is usually unnecessary because file handle names that begin with
+@samp{#} are assumed to refer to scratch files. @pxref{File Handles},
+for more information.
-@node INPUT PROGRAM, LIST, FILE HANDLE, Data Input and Output
+@node INPUT PROGRAM
@section INPUT PROGRAM
@vindex INPUT PROGRAM
The above example causes an active file to be created consisting of 50
random variates between 0 and 10.
-@node LIST, MATRIX DATA, INPUT PROGRAM, Data Input and Output
+@node LIST
@section LIST
@vindex LIST
@cmd{LIST} is a procedure. It causes the data to be read.
-@node MATRIX DATA, NEW FILE, LIST, Data Input and Output
+@node MATRIX DATA
@section MATRIX DATA
@vindex MATRIX DATA
should specify VARIABLES first.
Specify the file to read on FILE, either as a file name string or a file
-handle (@pxref{FILE HANDLE}). If FILE is not specified then matrix data
+handle (@pxref{File Handles}). If FILE is not specified then matrix data
must immediately follow @cmd{MATRIX DATA} with a @cmd{BEGIN
DATA}@dots{}@cmd{END DATA}
construct (@pxref{BEGIN DATA}).
accepting or producing related data, so these semantics aren't
documented. Later, they'll be described here in detail.
-@node NEW FILE, PRINT, MATRIX DATA, Data Input and Output
+@node NEW FILE
@section NEW FILE
@vindex NEW FILE
@cmd{NEW FILE} command clears the current active file.
-@node PRINT, PRINT EJECT, NEW FILE, Data Input and Output
+@node PRINT
@section PRINT
@vindex PRINT
All @cmd{PRINT} subcommands are optional.
The OUTFILE subcommand specifies the file to receive the output. The
-file may be a file name as a string or a file handle (@pxref{FILE
-HANDLE}). If OUTFILE is not present then output will be sent to PSPP's
+file may be a file name as a string or a file handle (@pxref{File
+Handles}). If OUTFILE is not present then output will be sent to PSPP's
output listing file.
The RECORDS subcommand specifies the number of lines to be output. The
truncated to that length, although additional text being added will
again extend the line to that length.
-@node PRINT EJECT, PRINT SPACE, PRINT, Data Input and Output
+@node PRINT EJECT
@section PRINT EJECT
@vindex PRINT EJECT
@xref{PRINT}, for more information on syntax and usage.
-@node PRINT SPACE, REREAD, PRINT EJECT, Data Input and Output
+@node PRINT SPACE
@section PRINT SPACE
@vindex PRINT SPACE
@cmd{PRINT SPACE} prints one or more blank lines to an output file.
The OUTFILE subcommand is optional. It may be used to direct output to
-a file specified by file name as a string or file handle (@pxref{FILE
-HANDLE}). If OUTFILE is not specified then output will be directed to
+a file specified by file name as a string or file handle (@pxref{File
+Handles}). If OUTFILE is not specified then output will be directed to
the listing file.
n_lines is also optional. If present, it is an expression
(@pxref{Expressions}) specifying the number of blank lines to be
printed. The expression must evaluate to a nonnegative value.
-@node REREAD, REPEATING DATA, PRINT SPACE, Data Input and Output
+@node REREAD
@section REREAD
@vindex REREAD
for further processing.
The FILE subcommand, which is optional, is used to specify the file to
-have its line re-read. The file must be specified in the form of a file
-handle (@pxref{FILE HANDLE}). If FILE is not specified then the last
+have its line re-read. The file must be specified as the name of a file
+handle (@pxref{File Handles}). If FILE is not specified then the last
file specified on @cmd{DATA LIST} will be assumed (last file specified
lexically, not in terms of flow-of-control).
Issuing @code{REREAD} multiple times will not back up in the data
file. Instead, it will re-read the same line multiple times.
-@node REPEATING DATA, WRITE, REREAD, Data Input and Output
+@node REPEATING DATA
@section REPEATING DATA
@vindex REPEATING DATA
All other subcommands are optional.
FILE specifies the file to read, either a file name as a string or a
-file handle (@pxref{FILE HANDLE}). If FILE is not present then the
+file handle (@pxref{File Handles}). If FILE is not present then the
default is the last file handle used on @cmd{DATA LIST} (lexically, not in
terms of flow of control).
structure (@pxref{LOOP}). Use @cmd{DATA LIST} before, not after,
@cmd{REPEATING DATA}.
-@node WRITE, , REPEATING DATA, Data Input and Output
+@node WRITE
@section WRITE
@vindex WRITE
@vindex APPLY DICTIONARY
@display
-APPLY DICTIONARY FROM='filename'.
+APPLY DICTIONARY FROM=@{'filename',file_handle@}.
@end display
@cmd{APPLY DICTIONARY} applies the variable labels, value labels,
-and missing values from variables in a system file to corresponding
+and missing values taken from a file to corresponding
variables in the active file. In some cases it also updates the
weighting variable.
-Specify a system file with a file name string or as a file handle
-(@pxref{FILE HANDLE}). The dictionary in the system file will be read,
-but it will not replace the active file dictionary. The system file's
-data will not be read.
+Specify a system file, portable file, or scratch file with a file name
+string or as a file handle (@pxref{File Handles}). The dictionary in the
+file will be read, but it will not replace the active file dictionary.
+The file's data will not be read.
Only variables with names that exist in both the active file and the
system file are considered. Variables with the same name but different
@end display
The @cmd{EXPORT} procedure writes the active file dictionary and data to a
-specified portable file.
+specified portable file or scratch file.
-By default, cases excluded with FILTER are written to the portable
+By default, cases excluded with FILTER are written to the
file. These can be excluded by specifying DELETE on the UNSELECTED
subcommand. Specifying RETAIN makes the default explicit.
precision to write. DIGITS applies only to non-integers.
The OUTFILE subcommand, which is the only required subcommand, specifies
-the portable file to be written as a file name string or a file handle
-(@pxref{FILE HANDLE}).
+the portable file or scratch file to be written as a file name string or
+a file handle (@pxref{File Handles}).
DROP, KEEP, and RENAME follow the same format as the SAVE procedure
(@pxref{SAVE}).
@display
GET
- /FILE='filename'
+ /FILE=@{'filename',file_handle@}
/DROP=var_list
/KEEP=var_list
/RENAME=(src_names=target_names)@dots{}
@end display
@cmd{GET} clears the current dictionary and active file and
-replaces them with the dictionary and data from a specified system file.
+replaces them with the dictionary and data from a specified file.
The FILE subcommand is the only required subcommand. Specify the system
-file to be read as a string file name or a file handle (@pxref{FILE
-HANDLE}).
+file, portable file, or scratch file to be read as a string file name or
+a file handle (@pxref{File Handles}).
-By default, all the variables in a system file are read. The DROP
+By default, all the variables in a file are read. The DROP
subcommand can be used to specify a list of variables that are not to be
read. By contrast, the KEEP subcommand can be used to specify variable
that are to be read, with all other variables not read.
-Normally variables in a system file retain the names that they were
+Normally variables in a file retain the names that they were
saved under. Use the RENAME subcommand to change these names. Specify,
within parentheses, a list of variable names followed by an equals sign
(@samp{=}) and the names that they should be renamed to. Multiple
once. For instance, @samp{/RENAME=A=B}. This alternate syntax is
deprecated.
-DROP, KEEP, and RENAME are performed in left-to-right order. They
-each may be present any number of times. @cmd{GET} never modifies a
-system file on disk. Only the active file read from the system file
+DROP, KEEP, and RENAME are executed in left-to-right order.
+Each may be present any number of times. @cmd{GET} never modifies a
+file on disk. Only the active file read from the file
is affected by these subcommands.
@cmd{GET} does not cause the data to be read, only the dictionary. The data
is read later, when a procedure is executed.
+Use of @cmd{GET} to read a portable file or scratch file is a PSPP
+extension.
+
@node IMPORT
@section IMPORT
@vindex IMPORT
The @cmd{IMPORT} transformation clears the active file dictionary and
data and
-replaces them with a dictionary and data from a portable file on disk.
+replaces them with a dictionary and data from a system, portable file,
+or scratch file.
The FILE subcommand, which is the only required subcommand, specifies
the portable file to be read as a file name string or a file handle
-(@pxref{FILE HANDLE}).
+(@pxref{File Handles}).
The TYPE subcommand is currently not used.
@cmd{IMPORT} does not cause the data to be read, only the dictionary. The
data is read later, when a procedure is executed.
+Use of @cmd{IMPORT} to read a system file or scratch file is a PSPP
+extension.
+
@node MATCH FILES
@section MATCH FILES
@vindex MATCH FILES
/MAP
@end display
-@cmd{MATCH FILES} merges one or more system files, optionally
+@cmd{MATCH FILES} merges one or more system, portable, or scratch files,
+optionally
including the active file. Records with the same values for BY
variables are combined into a single record. Records with different
-values are output in order. Thus, multiple sorted system files are
-combined into a single sorted system file based on the value of the BY
+values are output in order. Thus, multiple sorted files are
+combined into a single sorted file based on the value of the BY
variables. The results of the merge become the new active file.
The BY subcommand specifies a list of variables that are used to match
-records from each of the system files. Variables specified must exist
+records from each of the files. Variables specified must exist
in all the files specified on FILE and TABLE. BY should usually be
specified. If TABLE or IN is used then BY is required.
-Specify FILE with a system file as a file name string or file handle
-(@pxref{FILE HANDLE}), or with an asterisk (@samp{*}) to
+Specify FILE with a system, portable, or scratch file as a file name
+string or file handle
+(@pxref{File Handles}), or with an asterisk (@samp{*}) to
indicate the current active file. The files specified on FILE are
merged together based on the BY variables, or combined case-by-case if
BY is not specified. Normally at least two FILE subcommands should be
specified.
-Specify TABLE with a system file to use it as a @dfn{table
+Specify TABLE with a file to use it as a @dfn{table
lookup file}. Records in table lookup files are not used up after
they've been used once. This means that data in table lookup files can
correspond to any number of records in FILE files. Table lookup files
@cmd{MATCH FILES} may not be specified following @cmd{TEMPORARY}
(@pxref{TEMPORARY}) if the active file is used as an input source.
+Use of portable or scratch files on @cmd{MATCH FILES} is a PSPP
+extension.
+
@node SAVE
@section SAVE
@vindex SAVE
@display
SAVE
- /OUTFILE='filename'
+ /OUTFILE=@{'filename',file_handle@}
/UNSELECTED=@{RETAIN,DELETE@}
/@{COMPRESSED,UNCOMPRESSED@}
/PERMISSIONS=@{WRITEABLE,READONLY@}
The @cmd{SAVE} procedure causes the dictionary and data in the active
file to
-be written to a system file.
+be written to a system file or scratch file.
-OUTFILE is the only required subcommand. Specify the system
-file to be written as a string file name or a file handle (@pxref{FILE
-HANDLE}).
+OUTFILE is the only required subcommand. Specify the system file or
+scratch file to be written as a string file name or a file handle
+(@pxref{File Handles}).
By default, cases excluded with FILTER are written to the system file.
These can be excluded by specifying DELETE on the UNSELECTED
@end display
The @cmd{XSAVE} transformation writes the active file dictionary and
-data to a system file stored on disk. It is similar to the @cmd{SAVE}
+data to a system file or scratch file. It is similar to the @cmd{SAVE}
procedure, with two differences:
@itemize
* Missing Observations:: Handling missing observations.
* Variables:: The unit of data storage.
* Files:: Files used by PSPP.
+* File Handles:: How files are named.
* BNF:: How command syntax is described.
@end menu
to copy its value into an ordinary variable, then use that ordinary
variable in the analysis.
-@node Files, BNF, Variables, Language
+@node Files
@section Files Used by PSPP
PSPP makes use of many files each time it runs. Some of these it
@itemx syntax file
These names (synonyms) refer to the file that contains instructions
that tell PSPP what to do. The syntax file's name is specified on
-the PSPP command line. Syntax files can also be pulled in with
+the PSPP command line. Syntax files can also be read with
@cmd{INCLUDE} (@pxref{INCLUDE}).
@cindex file, data
@cindex data file
@item data file
-Data files contain raw data in ASCII format suitable for being read in
-by @cmd{DATA LIST}. Data can be embedded in the syntax
-file with @cmd{BEGIN DATA} and @cmd{END DATA}: this makes the
-syntax file a data file too.
+Data files contain raw data in text or binary format. Data can also
+be embedded in a syntax file with @cmd{BEGIN DATA} and @cmd{END DATA}.
@cindex file, output
@cindex output file
@cindex active file
@cindex file, active
@item active file
-The active file is the ``file'' on which all PSPP procedures
-are performed. The active file contains variable definitions and
-cases. The active file is not necessarily a disk file: it is stored
-in memory if there is room.
+The active file is the ``file'' on which all PSPP procedures are
+performed. The active file consists of a dictionary and a set of cases.
+The active file is not necessarily a disk file: it is stored in memory
+if there is room.
+
+@cindex system file
+@cindex file, system
+@item system file
+System files are binary files that store a dictionary and a set of
+cases. @cmd{GET} and @cmd{SAVE} read and write system files.
+
+@cindex portable file
+@cindex file, portable
+@item portable file
+Portable files are files in a text-based format that store a dictionary
+and a set of cases. @cmd{IMPORT} and @cmd{EXPORT} read and write
+portable files.
+
+@cindex scratch file
+@cindex file, scratch
+@item scratch file
+Scratch files consist of a dictionary and cases and may be stored in
+memory or on disk. Most procedures that act on a system file or
+portable file can use a scratch file instead. The contents of scratch
+files persist within a single PSPP session only. @cmd{GET} and
+@cmd{SAVE} can be used to read and write scratch files. Scratch files
+are a PSPP extension.
@end table
-@node BNF, , Files, Language
+@node File Handles
+@section File Handles
+@cindex file handles
+
+A @dfn{file handle} is a reference to a data file, system file, portable
+file, or scratch file. Most often, a file handle is specified as the
+name of a file as a string, that is, enclosed within @samp{'} or
+@samp{"}.
+
+PSPP also supports declaring named file handles with the @cmd{FILE
+HANDLE} command. This command associates an identifier of your choice
+(the file handle's name) with a file. Later, the file handle name can
+be substituted for the name of the file. When PSPP syntax accesses a
+file multiple times, declaring a named file handle simplifies updating
+the syntax later to use a different file. Use of @cmd{FILE HANDLE} is
+also required to read data files in binary formats. @xref{FILE HANDLE},
+for more information.
+
+PSPP assumes that a file handle name that begins with @samp{#} refers to
+a scratch file, unless the name has already been declared on @cmd{FILE
+HANDLE} to refer to another kind of file. A scratch file is similar to
+a system file, except that it persists only for the duration of a given
+PSPP session. Most commands that read or write a system or portable
+file, such as @cmd{GET} and @cmd{SAVE}, also accept scratch file
+handles. Scratch file handles may also be declared explicitly with
+@cmd{FILE HANDLE}. Scratch files are a PSPP extension.
+
+In some circumstances, PSPP must distinguish whether a file handle
+refers to a system file or a portable file. When this is necessary to
+read a file, e.g.@: as an input file for @cmd{GET} or @cmd{MATCH FILES},
+PSPP uses the file's contents to decide. In the context of writing a
+file, e.g.@: as an output file for @cmd{SAVE} or @cmd{AGGREGATE}, PSPP
+decides based on the file's name: if it ends in @samp{.por} (with any
+capitalization), then PSPP writes a portable file; otherwise, PSPP
+writes a system file.
+
+INLINE is reserved as a file handle name. It refers to the ``data
+file'' embedded into the syntax file between @cmd{BEGIN DATA} and
+@cmd{END DATA}. @xref{BEGIN DATA}, for more information.
+
+The file to which a file handle refers may be reassigned on a later
+@cmd{FILE HANDLE} command if it is first closed using @cmd{CLOSE FILE
+HANDLE}. The @cmd{CLOSE FILE HANDLE} command is also useful to free the
+storage associated with a scratch file. @xref{CLOSE FILE HANDLE}, for
+more information.
+
+@node BNF
@section Backus-Naur Form
@cindex BNF
@cindex Backus-Naur Form
@display
AGGREGATE
- OUTFILE=@{*,'filename'@}
+ OUTFILE=@{*,'filename',file_handle@}
/PRESORTED
/DOCUMENT
/MISSING=COLUMNWISE
for summarizing case contents.
The OUTFILE subcommand is required and must appear first. Specify a
-system file by file name string or file handle (@pxref{FILE HANDLE}).
+system file, portable file, or scratch file by file name or file
+handle (@pxref{File Handles}).
The aggregated cases are written to this file. If @samp{*} is
-specified, then the aggregated cases replace the active file.
+specified, then the aggregated cases replace the active file. Use of
+OUTFILE to write a portable file or scratch file is a PSPP extension.
By default, the active file will be sorted based on the break variables
before aggregation takes place. If the active file is already sorted
msgstr ""
"Project-Id-Version: PSPP 0.3.1\n"
"Report-Msgid-Bugs-To: pspp-dev@gnu.org\n"
-"POT-Creation-Date: 2006-01-24 17:40+0800\n"
+"POT-Creation-Date: 2006-01-28 17:20-0800\n"
"PO-Revision-Date: 2004-01-23 13:04+0800\n"
"Last-Translator: John Darrington <john@darrington.wattle.id.au>\n"
"Language-Team: John Darrington <john@darrington.wattle.id.au>\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n!=1);\n"
-#: src/aggregate.c:199
+#: src/aggregate.c:200
msgid "while expecting COLUMNWISE"
msgstr ""
-#: src/aggregate.c:228
+#: src/aggregate.c:229
msgid "expecting BREAK"
msgstr ""
-#: src/aggregate.c:233
+#: src/aggregate.c:234
msgid ""
"When PRESORTED is specified, specifying sorting directions with (A) or (D) "
"has no effect. Output data will be sorted the same way as the input data."
"contains the aggregate variables and the break variables."
msgstr ""
+#: src/any-reader.c:74
+#, c-format
+msgid "An error occurred while opening \"%s\": %s."
+msgstr ""
+
+#: src/any-reader.c:129
+#, c-format
+msgid "\"%s\" is not a system or portable file."
+msgstr ""
+
+#: src/any-reader.c:135 src/any-writer.c:80
+msgid "The inline file is not allowed here."
+msgstr ""
+
#: src/apply-dict.c:71
#, c-format
msgid "Variable %s is %s in target file, but %s in source file."
msgstr ""
#: src/apply-dict.c:74 src/apply-dict.c:75 src/format.c:198 src/recode.c:464
-#: src/recode.c:465 src/sfm-read.c:1014 src/sfm-read.c:1159
-#: src/sfm-read.c:1160 src/vars-atr.c:40 src/vars-atr.c:48
+#: src/recode.c:465 src/sfm-read.c:1016 src/sfm-read.c:1161
+#: src/sfm-read.c:1162 src/vars-atr.c:40 src/vars-atr.c:48
msgid "string"
msgstr ""
#: src/apply-dict.c:74 src/apply-dict.c:75 src/format.c:198 src/recode.c:464
-#: src/recode.c:465 src/sfm-read.c:1014 src/sfm-read.c:1159
-#: src/sfm-read.c:1160 src/vars-atr.c:40
+#: src/recode.c:465 src/sfm-read.c:1016 src/sfm-read.c:1161
+#: src/sfm-read.c:1162 src/vars-atr.c:40
msgid "numeric"
msgstr ""
msgid "Source variable count (%u) does not match target variable count (%u)."
msgstr ""
-#: src/autorecode.c:142 src/command.c:797 src/file-handle.q:83 src/lexer.c:440
-#: src/matrix-data.c:532 src/print.c:335 src/print.c:1044 src/sel-if.c:57
+#: src/autorecode.c:142 src/command.c:797 src/lexer.c:440
+#: src/matrix-data.c:532 src/print.c:335 src/print.c:1046 src/sel-if.c:57
#: src/sel-if.c:134 src/vector.c:197
msgid "expecting end of command"
msgstr ""
#: src/crosstabs.q:1109 src/crosstabs.q:1136 src/crosstabs.q:1156
#: src/crosstabs.q:1178 src/examine.q:1131 src/frequencies.q:1142
-#: src/frequencies.q:1263 src/sysfile-info.c:518 src/vfm.c:840
+#: src/frequencies.q:1263 src/sysfile-info.c:518 src/vfm.c:845
msgid "Value"
msgstr ""
msgid "Field too long (%d characters). Truncated after character %d."
msgstr ""
-#: src/data-list.c:142
-msgid ""
-"DATA LIST may not use a different file from that specified on its "
-"surrounding FILE TYPE."
+#: src/data-list.c:144
+msgid "DATA LIST must use the same file as the enclosing FILE TYPE."
msgstr ""
-#: src/data-list.c:161
+#: src/data-list.c:163
msgid "The END subcommand may only be specified once."
msgstr ""
-#: src/data-list.c:196
+#: src/data-list.c:198
msgid "Only one of FIXED, FREE, or LIST may be specified."
msgstr ""
-#: src/data-list.c:346 src/print.c:296
+#: src/data-list.c:348 src/print.c:296
#, c-format
msgid ""
"The record number specified, %ld, is before the previous record, %d. Data "
"fields must be listed in order of increasing record number."
msgstr ""
-#: src/data-list.c:375 src/data-list.c:1735
+#: src/data-list.c:377 src/data-list.c:1727
msgid ""
"SPSS-like or FORTRAN-like format specification expected after variable names."
msgstr ""
-#: src/data-list.c:386
+#: src/data-list.c:388
msgid "At least one variable must be specified."
msgstr ""
-#: src/data-list.c:391 src/print.c:328
+#: src/data-list.c:393 src/print.c:328
msgid ""
"Variables are specified on records that should not exist according to "
"RECORDS subcommand."
msgstr ""
-#: src/data-list.c:424 src/data-list.c:438 src/print.c:520 src/print.c:533
+#: src/data-list.c:426 src/data-list.c:440 src/print.c:520 src/print.c:533
msgid "Column positions for fields must be positive."
msgstr ""
-#: src/data-list.c:443
+#: src/data-list.c:445
msgid "The ending column for a field must be greater than the starting column."
msgstr ""
-#: src/data-list.c:457
+#: src/data-list.c:459
#, c-format
msgid "The %d columns %d-%d can't be evenly divided into %d fields."
msgstr ""
-#: src/data-list.c:477 src/print.c:561
+#: src/data-list.c:479 src/print.c:561
msgid "A format specifier on this line has extra characters on the end."
msgstr ""
-#: src/data-list.c:492 src/print.c:577
+#: src/data-list.c:494 src/print.c:577
msgid "The value for number of decimal places must be at least 1."
msgstr ""
-#: src/data-list.c:506 src/print.c:590
+#: src/data-list.c:508 src/print.c:590
#, c-format
msgid "Input format %s doesn't accept decimal places."
msgstr ""
-#: src/data-list.c:553 src/data-list.c:649 src/data-list.c:863
+#: src/data-list.c:555 src/data-list.c:651 src/data-list.c:859
#, c-format
msgid "%s is a duplicate variable name."
msgstr ""
-#: src/data-list.c:558
+#: src/data-list.c:560
#, c-format
msgid "There is already a variable %s of a different type."
msgstr ""
-#: src/data-list.c:565
+#: src/data-list.c:567
#, c-format
msgid "There is already a string variable %s of a different width."
msgstr ""
-#: src/data-list.c:640
+#: src/data-list.c:642
msgid ""
"The number of format specifications exceeds the given number of variable "
"names."
msgstr ""
-#: src/data-list.c:753 src/print.c:766
+#: src/data-list.c:755 src/print.c:766
msgid ""
"There aren't enough format specifications to match the number of variable "
"names given."
msgstr ""
-#: src/data-list.c:780 src/data-list.c:904 src/descript.c:882 src/print.c:797
-#: src/sysfile-info.c:139 src/sysfile-info.c:373 src/vfm.c:839
+#: src/data-list.c:782 src/data-list.c:900 src/descript.c:882 src/print.c:797
+#: src/sysfile-info.c:139 src/sysfile-info.c:373 src/vfm.c:844
msgid "Variable"
msgstr ""
-#: src/data-list.c:781 src/print.c:798
+#: src/data-list.c:783 src/print.c:798
msgid "Record"
msgstr ""
-#: src/data-list.c:782 src/print.c:799
+#: src/data-list.c:784 src/print.c:799
msgid "Columns"
msgstr ""
-#: src/data-list.c:783 src/data-list.c:905 src/print.c:800
+#: src/data-list.c:785 src/data-list.c:901 src/print.c:800
msgid "Format"
msgstr ""
-#: src/data-list.c:799
+#: src/data-list.c:800
#, c-format
-msgid "Reading %d record from file %s."
-msgid_plural "Reading %d records from file %s."
+msgid "Reading %d record from %s."
+msgid_plural "Reading %d records from %s."
msgstr[0] ""
msgstr[1] ""
-#: src/data-list.c:803
+#: src/data-list.c:916
#, c-format
-msgid "Reading %d record from the command file."
-msgid_plural "Reading %d records from the command file."
-msgstr[0] ""
-msgstr[1] ""
-
-#: src/data-list.c:921
-#, c-format
-msgid "Reading free-form data from file %s."
-msgstr ""
-
-#: src/data-list.c:924
-msgid "Reading free-form data from the command file."
+msgid "Reading free-form data from %s."
msgstr ""
-#: src/data-list.c:975
+#: src/data-list.c:967
#, c-format
msgid "Quoted string missing terminating `%c'."
msgstr ""
-#: src/data-list.c:1084
+#: src/data-list.c:1076
#, c-format
msgid "Partial case of %d of %d records discarded."
msgstr ""
-#: src/data-list.c:1138
+#: src/data-list.c:1130
#, c-format
msgid "Partial case discarded. The first variable missing was %s."
msgstr ""
-#: src/data-list.c:1182
+#: src/data-list.c:1174
#, 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/data-list.c:1259
+#: src/data-list.c:1251
msgid "Attempt to read past end of file."
msgstr ""
-#: src/data-list.c:1398
+#: src/data-list.c:1390
msgid ""
"REPEATING DATA must use the same file as its corresponding DATA LIST or FILE "
"TYPE."
msgstr ""
-#: src/data-list.c:1408 src/data-list.c:1442 src/data-list.c:1455
-#: src/data-list.c:1468 src/data-list.c:1502
+#: src/data-list.c:1400 src/data-list.c:1434 src/data-list.c:1447
+#: src/data-list.c:1460 src/data-list.c:1494
#, c-format
msgid "%s subcommand given multiple times."
msgstr ""
-#: src/data-list.c:1431
+#: src/data-list.c:1423
#, c-format
msgid "STARTS beginning column (%d) exceeds STARTS ending column (%d)."
msgstr ""
-#: src/data-list.c:1488
+#: src/data-list.c:1480
#, c-format
msgid "CONTINUED beginning column (%d) exceeds CONTINUED ending column (%d)."
msgstr ""
-#: src/data-list.c:1511
+#: src/data-list.c:1503
#, c-format
msgid "ID beginning column (%ld) must be positive."
msgstr ""
-#: src/data-list.c:1526
+#: src/data-list.c:1518
#, c-format
msgid "ID ending column (%ld) must be positive."
msgstr ""
-#: src/data-list.c:1532
+#: src/data-list.c:1524
#, c-format
msgid "ID ending column (%ld) cannot be less than ID beginning column (%d)."
msgstr ""
-#: src/data-list.c:1572
+#: src/data-list.c:1564
msgid "Missing required specification STARTS."
msgstr ""
-#: src/data-list.c:1574
+#: src/data-list.c:1566
msgid "Missing required specification OCCURS."
msgstr ""
-#: src/data-list.c:1581
+#: src/data-list.c:1573
msgid "ID specified without CONTINUED."
msgstr ""
-#: src/data-list.c:1592
+#: src/data-list.c:1584
#, c-format
msgid ""
"STARTS beginning column (%d) exceeds default STARTS ending column taken from "
"file's record width (%d)."
msgstr ""
-#: src/data-list.c:1605
+#: src/data-list.c:1597
#, c-format
msgid ""
"CONTINUED beginning column (%d) exceeds default CONTINUED ending column "
"taken from file's record width (%d)."
msgstr ""
-#: src/data-list.c:1684
+#: src/data-list.c:1676
msgid "String variable not allowed here."
msgstr ""
-#: src/data-list.c:1694
+#: src/data-list.c:1686
#, c-format
msgid "%s (%d) must be at least 1."
msgstr ""
-#: src/data-list.c:1700
+#: src/data-list.c:1692
#, c-format
msgid "Variable or integer expected for %s."
msgstr ""
-#: src/data-list.c:1825
+#: src/data-list.c:1817
#, c-format
msgid "Encountered mismatched record ID \"%s\" expecting \"%s\"."
msgstr ""
-#: src/data-list.c:1857
+#: src/data-list.c:1849
#, c-format
msgid ""
"Variable %s starting in column %d extends beyond physical record length of %"
"d."
msgstr ""
-#: src/data-list.c:1924
+#: src/data-list.c:1916
#, c-format
msgid "Invalid value %d for OCCURS."
msgstr ""
-#: src/data-list.c:1930
+#: src/data-list.c:1922
#, c-format
msgid "Beginning column for STARTS (%d) must be at least 1."
msgstr ""
-#: src/data-list.c:1938
+#: src/data-list.c:1930
#, c-format
msgid "Ending column for STARTS (%d) is less than beginning column (%d)."
msgstr ""
-#: src/data-list.c:1946
+#: src/data-list.c:1938
#, c-format
msgid "Invalid value %d for LENGTH."
msgstr ""
-#: src/data-list.c:1953
+#: src/data-list.c:1945
#, c-format
msgid "Beginning column for CONTINUED (%d) must be at least 1."
msgstr ""
-#: src/data-list.c:1961
+#: src/data-list.c:1953
#, c-format
msgid "Ending column for CONTINUED (%d) is less than beginning column (%d)."
msgstr ""
-#: src/data-list.c:1993
+#: src/data-list.c:1985
#, c-format
msgid ""
"Number of repetitions specified on OCCURS (%d) exceed number of repetitions "
"available in space on STARTS (%d), and CONTINUED not specified."
msgstr ""
-#: src/data-list.c:2011
+#: src/data-list.c:2003
#, c-format
msgid "Unexpected end of file with %d repetitions remaining out of %d."
msgstr ""
msgid "Valid cases = %g; cases with missing value(s) = %g."
msgstr ""
-#: src/dfm-read.c:158
+#: src/dfm-read.c:136
#, c-format
msgid "Could not open \"%s\" for reading as a data file: %s."
msgstr ""
-#: src/dfm-read.c:191 src/dfm-read.c:209
+#: src/dfm-read.c:168 src/dfm-read.c:186
msgid "BEGIN DATA expected."
msgstr ""
-#: src/dfm-read.c:218
+#: src/dfm-read.c:195
msgid ""
"Unexpected end-of-file while reading data in BEGIN DATA. This probably "
"indicates a missing or misformatted END DATA command. END DATA must appear "
"by itself on a single line with exactly one space between words."
msgstr ""
-#: src/dfm-read.c:251 src/dfm-read.c:271
+#: src/dfm-read.c:227 src/dfm-read.c:247
#, c-format
msgid "Error reading file %s: %s."
msgstr ""
-#: src/dfm-read.c:274
+#: src/dfm-read.c:250
#, c-format
msgid "%s: Partial record at end of file."
msgstr ""
-#: src/dfm-read.c:317
+#: src/dfm-read.c:299
#, c-format
msgid "Attempt to read beyond end-of-file on file %s."
msgstr ""
-#: src/dfm-read.c:320
+#: src/dfm-read.c:302
msgid "Attempt to read beyond END DATA."
msgstr ""
-#: src/dfm-read.c:467
+#: src/dfm-read.c:446
msgid ""
"This command is not valid here since the current input program does not "
"access the inline file."
msgid "%s is a PSPP extension."
msgstr ""
-#: src/file-handle-def.c:229
+#: src/file-handle-def.c:303
#, c-format
-msgid "Can't open %s as a %s because it is already open as a %s"
+msgid "Can't open %s as a %s because it is already open as a %s."
msgstr ""
-#: src/file-handle-def.c:236
+#: src/file-handle-def.c:310
#, c-format
-msgid "Can't open %s as a %s for %s because it is already open for %s"
+msgid "Can't open %s as a %s for %s because it is already open for %s."
msgstr ""
-#: src/file-handle-def.c:244
+#: src/file-handle-def.c:318
#, c-format
-msgid "Can't re-open %s as a %s for %s"
+msgid "Can't re-open %s as a %s for %s."
msgstr ""
-#: src/file-handle.q:68
+#: src/file-handle.q:69
#, c-format
msgid ""
-"File handle %s already refers to file %s. File handles cannot be redefined "
-"within a session."
+"File handle %s is already defined. Use CLOSE FILE HANDLE before redefining "
+"a file handle."
msgstr ""
-#: src/file-handle.q:89
-msgid "The FILE HANDLE required subcommand NAME is not present."
-msgstr ""
-
-#: src/file-handle.q:104
+#: src/file-handle.q:101
#, c-format
msgid ""
"Fixed-length records were specified on /RECFORM, but record length was not "
"specified on /LRECL. Assuming %d-character records."
msgstr ""
-#: src/file-handle.q:109
+#: src/file-handle.q:106
#, c-format
msgid ""
"Record length (%ld) must be at least one byte. Assuming %d-character "
"records."
msgstr ""
-#: src/file-handle.q:139
-msgid "expecting a file name or handle name"
+#: src/file-handle.q:152
+msgid "file"
msgstr ""
-#: src/filename.c:227
-#, c-format
-msgid "Searching for `%s'..."
+#: src/file-handle.q:154
+msgid "inline file"
msgstr ""
-#: src/filename.c:235 src/filename.c:267
-msgid "Search unsuccessful!"
+#: src/file-handle.q:156
+msgid "scratch file"
msgstr ""
-#: src/filename.c:260
-#, c-format
-msgid "Found `%s'."
+#: src/file-handle.q:177
+msgid "expecting a file name or handle name"
msgstr ""
-#: src/filename.c:665
+#: src/file-handle.q:204
#, c-format
-msgid "Not opening pipe file `%s' because SAFER option set."
+msgid "Handle for %s not allowed here."
msgstr ""
#: src/file-type.c:133
msgid "Unknown record type %g."
msgstr ""
+#: src/filename.c:227
+#, c-format
+msgid "Searching for `%s'..."
+msgstr ""
+
+#: src/filename.c:235 src/filename.c:267
+msgid "Search unsuccessful!"
+msgstr ""
+
+#: src/filename.c:260
+#, c-format
+msgid "Found `%s'."
+msgstr ""
+
+#: src/filename.c:677
+#, c-format
+msgid "Not opening pipe file `%s' because SAFER option set."
+msgstr ""
+
#: src/flip.c:88
msgid ""
"FLIP ignores TEMPORARY. Temporary transformations will be made permanent."
msgid "Unexpected end of file reading FLIP temporary file."
msgstr ""
+#: src/format-prs.c:66
+msgid "X and T format specifiers not allowed here."
+msgstr ""
+
+#: src/format-prs.c:74
+#, c-format
+msgid "%.*s is not a valid data format."
+msgstr ""
+
+#: src/format-prs.c:115
+msgid "Format specifier expected."
+msgstr ""
+
+#: src/format-prs.c:127
+#, c-format
+msgid "Data format %s does not specify a width."
+msgstr ""
+
+#: src/format-prs.c:145
+#, c-format
+msgid "Data format %s is not valid."
+msgstr ""
+
#: src/format.c:73
#, c-format
msgid "Format specifies a bad type (%d)"
msgid "%s variables are not compatible with %s format %s."
msgstr ""
-#: src/format.c:197 src/pfm-read.c:476 src/sfm-read.c:1012 src/sfm-read.c:1021
+#: src/format.c:197 src/pfm-read.c:476 src/sfm-read.c:1014 src/sfm-read.c:1023
msgid "String"
msgstr ""
-#: src/format.c:197 src/pfm-read.c:476 src/sfm-read.c:1012 src/sfm-read.c:1021
+#: src/format.c:197 src/pfm-read.c:476 src/sfm-read.c:1014 src/sfm-read.c:1023
msgid "Numeric"
msgstr ""
msgid "String variable with width %d not compatible with format %s."
msgstr ""
-#: src/format-prs.c:66
-msgid "X and T format specifiers not allowed here."
-msgstr ""
-
-#: src/format-prs.c:74
-#, c-format
-msgid "%.*s is not a valid data format."
-msgstr ""
-
-#: src/format-prs.c:115
-msgid "Format specifier expected."
-msgstr ""
-
-#: src/format-prs.c:127
-#, c-format
-msgid "Data format %s does not specify a width."
-msgstr ""
-
-#: src/format-prs.c:145
-#, c-format
-msgid "Data format %s is not valid."
-msgstr ""
-
#: src/formats.c:89
msgid "`(' expected after variable list"
msgstr ""
msgid "No valid data for variable %s; statistics not displayed."
msgstr ""
-#: src/get.c:306 src/get.c:320 src/get.c:345
+#: src/get.c:108
+msgid "expecting COMM or TAPE"
+msgstr ""
+
+#: src/get.c:343 src/get.c:357 src/get.c:382
#, c-format
msgid "expecting %s or %s"
msgstr ""
-#: src/get.c:552 src/print.c:179
+#: src/get.c:586 src/print.c:179
msgid "expecting a valid subcommand"
msgstr ""
-#: src/get.c:585
+#: src/get.c:619
#, c-format
msgid ""
"Cannot rename %s as %s because there already exists a variable named %s. To "
"as \"/RENAME (A=B)(B=C)(C=A)\", or equivalently, \"/RENAME (A B C=B C A)\"."
msgstr ""
-#: src/get.c:610
+#: src/get.c:644
msgid "`=' expected after variable list."
msgstr ""
-#: src/get.c:617
+#: src/get.c:651
#, c-format
msgid ""
"Number of variables on left side of `=' (%d) does not match number of "
"variables on right side (%d), in parenthesized group %d of RENAME subcommand."
msgstr ""
-#: src/get.c:630
+#: src/get.c:664
#, c-format
msgid "Requested renaming duplicates variable name %s."
msgstr ""
-#: src/get.c:660
+#: src/get.c:694
msgid "Cannot DROP all variables from dictionary."
msgstr ""
-#: src/get.c:835
+#: src/get.c:869
msgid "The active file may not be specified more than once."
msgstr ""
-#: src/get.c:844
+#: src/get.c:878
msgid "Cannot specify the active file since no active file has been defined."
msgstr ""
-#: src/get.c:852
+#: src/get.c:886
msgid ""
"MATCH FILES may not be used after TEMPORARY when the active file is an input "
"source. Temporary transformations will be made permanent."
msgstr ""
-#: src/get.c:890
+#: src/get.c:924
msgid "Multiple IN subcommands for a single FILE or TABLE."
msgstr ""
-#: src/get.c:910
+#: src/get.c:944
msgid "BY may appear at most once."
msgstr ""
-#: src/get.c:930
+#: src/get.c:964
#, c-format
msgid "File %s lacks BY variable %s."
msgstr ""
-#: src/get.c:944
+#: src/get.c:978
msgid "FIRST may appear at most once."
msgstr ""
-#: src/get.c:958
+#: src/get.c:992
msgid "LAST may appear at most once."
msgstr ""
-#: src/get.c:999
+#: src/get.c:1033
msgid "BY is required when TABLE is specified."
msgstr ""
-#: src/get.c:1004
+#: src/get.c:1038
msgid "BY is required when IN is specified."
msgstr ""
-#: src/get.c:1032
+#: src/get.c:1066
#, c-format
msgid "IN variable name %s duplicates an existing variable name."
msgstr ""
-#: src/get.c:1461
+#: src/get.c:1495
#, c-format
msgid ""
"Variable %s in file %s (%s) has different type or width from the same "
"variable in earlier file (%s)."
msgstr ""
-#: src/get.c:1545
-msgid "expecting COMM or TAPE"
-msgstr ""
-
#: src/getl.c:139
#, c-format
msgid "Can't find `%s' in include file search path."
msgid "Cannot change mode of %s: %s"
msgstr ""
-#: src/pfm-read.c:87
+#: src/pfm-read.c:97
#, c-format
msgid "portable file %s corrupt at offset %ld: "
msgstr ""
-#: src/pfm-read.c:114
+#: src/pfm-read.c:124
msgid "unexpected end of file"
msgstr ""
-#: src/pfm-read.c:172
+#: src/pfm-read.c:182
#, c-format
msgid ""
"An error occurred while opening \"%s\" for reading as a portable file: %s."
msgstr ""
-#: src/pfm-read.c:190
+#: src/pfm-read.c:200
msgid "Data record expected."
msgstr ""
-#: src/pfm-read.c:298
+#: src/pfm-read.c:308
msgid "Missing numeric terminator."
msgstr ""
-#: src/pfm-read.c:321
+#: src/pfm-read.c:331
msgid "Invalid integer."
msgstr ""
-#: src/pfm-read.c:332
+#: src/pfm-read.c:342
#, c-format
msgid "Bad string length %d."
msgstr ""
msgid "Bad time string length %d."
msgstr ""
-#: src/pfm-read.c:468 src/sfm-read.c:1004
+#: src/pfm-read.c:468 src/sfm-read.c:1006
#, c-format
msgid "%s: Bad format specifier byte (%d)."
msgstr ""
-#: src/pfm-read.c:475 src/sfm-read.c:1020
+#: src/pfm-read.c:475 src/sfm-read.c:1022
#, c-format
msgid "%s variable %s has invalid format specifier %s."
msgstr ""
msgid "%s: Writing portable file: %s."
msgstr ""
-#: src/pfm-write.c:468
+#: src/pfm-write.c:466
#, c-format
msgid "%s: Closing portable file: %s."
msgstr ""
#: src/print.c:839
#, c-format
-msgid "Writing %d record(s) to file %s."
-msgstr ""
+msgid "Writing %d record to %s."
+msgid_plural "Writing %d records to %s."
+msgstr[0] ""
+msgstr[1] ""
-#: src/print.c:842
+#: src/print.c:843
#, c-format
-msgid "Writing %d record(s) to the listing file."
-msgstr ""
+msgid "Writing %d record."
+msgid_plural "Writing %d records."
+msgstr[0] ""
+msgstr[1] ""
-#: src/print.c:1082
+#: src/print.c:1084
msgid "The expression on PRINT SPACE evaluated to the system-missing value."
msgstr ""
-#: src/print.c:1085
+#: src/print.c:1087
#, c-format
msgid "The expression on PRINT SPACE evaluated to %g."
msgstr ""
msgid "Cannot sample %d observations from a population of %d."
msgstr ""
+#: src/scratch-reader.c:59
+#, c-format
+msgid ""
+"Scratch file handle %s has not yet been written, using SAVE or another "
+"procedure, so it cannot yet be used for reading."
+msgstr ""
+
#: src/sel-if.c:103
msgid "The filter variable must be numeric."
msgstr ""
msgid "corrupt system file: "
msgstr ""
-#: src/sfm-read.c:151 src/sfm-write.c:931
+#: src/sfm-read.c:149 src/sfm-write.c:929
#, c-format
msgid "%s: Closing system file: %s."
msgstr ""
-#: src/sfm-read.c:237
+#: src/sfm-read.c:239
#, c-format
msgid ""
"An error occurred while opening \"%s\" for reading as a system file: %s."
msgstr ""
-#: src/sfm-read.c:255
+#: src/sfm-read.c:257
#, c-format
msgid ""
"%s: Index of weighting variable (%d) is not between 0 and number of elements "
"per case (%d)."
msgstr ""
-#: src/sfm-read.c:264
+#: src/sfm-read.c:266
#, c-format
msgid ""
"%s: Weighting variable may not be a continuation of a long string variable."
msgstr ""
-#: src/sfm-read.c:267
+#: src/sfm-read.c:269
#, c-format
msgid "%s: Weighting variable may not be a string variable."
msgstr ""
-#: src/sfm-read.c:292
+#: src/sfm-read.c:294
#, c-format
msgid ""
"%s: Orphaned variable index record (type 4). Type 4 records must always "
"immediately follow type 3 records."
msgstr ""
-#: src/sfm-read.c:350
+#: src/sfm-read.c:352
#, c-format
msgid "%s: Invalid subrecord length. Record: 7; Subrecord: 11"
msgstr ""
-#: src/sfm-read.c:404
+#: src/sfm-read.c:406
#, c-format
msgid "%s: Trailing garbage in long variable name map."
msgstr ""
-#: src/sfm-read.c:411
+#: src/sfm-read.c:413
#, c-format
msgid "%s: Long variable mapping to invalid variable name `%s'."
msgstr ""
-#: src/sfm-read.c:421
+#: src/sfm-read.c:423
#, c-format
msgid "%s: Long variable mapping for nonexistent variable %s."
msgstr ""
-#: src/sfm-read.c:431
+#: src/sfm-read.c:433
#, c-format
msgid "%s: Duplicate long variable name `%s' within system file."
msgstr ""
-#: src/sfm-read.c:459
+#: src/sfm-read.c:461
#, c-format
msgid "%s: Unrecognized record type 7, subtype %d encountered in system file."
msgstr ""
-#: src/sfm-read.c:484
+#: src/sfm-read.c:486
#, c-format
msgid "%s: Unrecognized record type %d."
msgstr ""
-#: src/sfm-read.c:516
+#: src/sfm-read.c:518
#, c-format
msgid ""
"%s: Bad size (%d) or count (%d) field on record type 7, subtype 3.\tExpected "
"size %d, count 8."
msgstr ""
-#: src/sfm-read.c:527
+#: src/sfm-read.c:529
#, c-format
msgid ""
"%s: Floating-point representation in system file is not IEEE-754. PSPP "
"cannot convert between floating-point formats."
msgstr ""
-#: src/sfm-read.c:543
+#: src/sfm-read.c:545
#, c-format
msgid ""
"%s: File-indicated endianness (%s) does not match endianness intuited from "
"file header (%s)."
msgstr ""
-#: src/sfm-read.c:546 src/sfm-read.c:547
+#: src/sfm-read.c:548 src/sfm-read.c:549
msgid "big-endian"
msgstr ""
-#: src/sfm-read.c:546 src/sfm-read.c:547
+#: src/sfm-read.c:548 src/sfm-read.c:549
msgid "little-endian"
msgstr ""
-#: src/sfm-read.c:548
+#: src/sfm-read.c:550
msgid "unknown"
msgstr ""
-#: src/sfm-read.c:552
+#: src/sfm-read.c:554
#, c-format
msgid "%s: File-indicated character representation code (%s) is not ASCII."
msgstr ""
-#: src/sfm-read.c:556
+#: src/sfm-read.c:558
msgid "DEC Kanji"
msgstr ""
-#: src/sfm-read.c:556 src/sysfile-info.c:119
+#: src/sfm-read.c:558 src/sysfile-info.c:119
msgid "Unknown"
msgstr ""
-#: src/sfm-read.c:572
+#: src/sfm-read.c:574
#, c-format
msgid ""
"%s: Bad size (%d) or count (%d) field on record type 7, subtype 4.\tExpected "
"size %d, count 8."
msgstr ""
-#: src/sfm-read.c:587
+#: src/sfm-read.c:589
#, c-format
msgid ""
"%s: File-indicated value is different from internal value for at least one "
"%g; LOWEST: %g, %g."
msgstr ""
-#: src/sfm-read.c:614
+#: src/sfm-read.c:616
#, c-format
msgid ""
"%s: Bad magic. Proper system files begin with the four characters `$FL2'. "
"This file will not be read."
msgstr ""
-#: src/sfm-read.c:656
+#: src/sfm-read.c:658
#, c-format
msgid ""
"%s: File layout code has unexpected value %d. Value should be 2, in big-"
"endian or little-endian format."
msgstr ""
-#: src/sfm-read.c:684
+#: src/sfm-read.c:686
#, c-format
msgid "%s: Number of cases in file (%ld) is not between -1 and %d."
msgstr ""
-#: src/sfm-read.c:689
+#: src/sfm-read.c:691
#, c-format
msgid "%s: Compression bias (%g) is not the usual value of 100."
msgstr ""
-#: src/sfm-read.c:812
+#: src/sfm-read.c:814
#, c-format
msgid ""
"%s: position %d: String variable does not have proper number of continuation "
"records."
msgstr ""
-#: src/sfm-read.c:823
+#: src/sfm-read.c:825
#, c-format
msgid "%s: position %d: Superfluous long string continuation record."
msgstr ""
-#: src/sfm-read.c:829
+#: src/sfm-read.c:831
#, c-format
msgid "%s: position %d: Bad variable type code %d."
msgstr ""
-#: src/sfm-read.c:832
+#: src/sfm-read.c:834
#, c-format
msgid "%s: position %d: Variable label indicator field is not 0 or 1."
msgstr ""
-#: src/sfm-read.c:836
+#: src/sfm-read.c:838
#, c-format
msgid ""
"%s: position %d: Missing value indicator field is not -3, -2, 0, 1, 2, or 3."
msgstr ""
-#: src/sfm-read.c:842
+#: src/sfm-read.c:844
#, c-format
msgid "%s: position %d: Variable name begins with invalid character."
msgstr ""
-#: src/sfm-read.c:846
+#: src/sfm-read.c:848
#, c-format
msgid "%s: position %d: Variable name begins with lowercase letter %c."
msgstr ""
-#: src/sfm-read.c:850
+#: src/sfm-read.c:852
#, c-format
msgid ""
"%s: position %d: Variable name begins with octothorpe (`#'). Scratch "
"variables should not appear in system files."
msgstr ""
-#: src/sfm-read.c:865
+#: src/sfm-read.c:867
#, c-format
msgid "%s: position %d: Variable name character %d is lowercase letter %c."
msgstr ""
-#: src/sfm-read.c:874
+#: src/sfm-read.c:876
#, c-format
msgid ""
"%s: position %d: character `\\%03o' (%c) is not valid in a variable name."
msgstr ""
-#: src/sfm-read.c:881
+#: src/sfm-read.c:883
#, c-format
msgid "%s: Invalid variable name `%s' within system file."
msgstr ""
-#: src/sfm-read.c:888
+#: src/sfm-read.c:890
#, c-format
msgid "%s: Duplicate variable name `%s' within system file."
msgstr ""
-#: src/sfm-read.c:911
+#: src/sfm-read.c:913
#, c-format
msgid "%s: Variable %s indicates variable label of invalid length %d."
msgstr ""
-#: src/sfm-read.c:932
+#: src/sfm-read.c:934
#, c-format
msgid "%s: Long string variable %s may not have missing values."
msgstr ""
-#: src/sfm-read.c:953
+#: src/sfm-read.c:955
#, c-format
msgid ""
"%s: String variable %s may not have missing values specified as a range."
msgstr ""
-#: src/sfm-read.c:980
+#: src/sfm-read.c:982
#, c-format
msgid "%s: Long string continuation records omitted at end of dictionary."
msgstr ""
-#: src/sfm-read.c:985
+#: src/sfm-read.c:987
#, c-format
msgid ""
"%s: System file header indicates %d variable positions but %d were read from "
"file."
msgstr ""
-#: src/sfm-read.c:1010
+#: src/sfm-read.c:1012
#, c-format
msgid "%s: %s variable %s has %s format specifier %s."
msgstr ""
-#: src/sfm-read.c:1063
+#: src/sfm-read.c:1065
#, c-format
msgid "%s: Invalid number of labels: %d. Ignoring labels."
msgstr ""
-#: src/sfm-read.c:1105
+#: src/sfm-read.c:1107
#, c-format
msgid ""
"%s: Variable index record (type 4) does not immediately follow value label "
"record (type 3) as it should."
msgstr ""
-#: src/sfm-read.c:1116
+#: src/sfm-read.c:1118
#, c-format
msgid ""
"%s: Number of variables associated with a value label (%d) is not between 1 "
"and the number of variables (%d)."
msgstr ""
-#: src/sfm-read.c:1132
+#: src/sfm-read.c:1134
#, c-format
msgid ""
"%s: Variable index associated with value label (%d) is not between 1 and the "
"number of values (%d)."
msgstr ""
-#: src/sfm-read.c:1139
+#: src/sfm-read.c:1141
#, c-format
msgid ""
"%s: Variable index associated with value label (%d) refers to a continuation "
"of a string variable, not to an actual variable."
msgstr ""
-#: src/sfm-read.c:1144
+#: src/sfm-read.c:1146
#, c-format
msgid "%s: Value labels are not allowed on long string variables (%s)."
msgstr ""
-#: src/sfm-read.c:1155
+#: src/sfm-read.c:1157
#, c-format
msgid ""
"%s: Variables associated with value label are not all of identical type. "
"Variable %s has %s type, but variable %s has %s type."
msgstr ""
-#: src/sfm-read.c:1196
+#: src/sfm-read.c:1198
#, c-format
msgid "%s: File contains duplicate label for value %g for variable %s."
msgstr ""
-#: src/sfm-read.c:1200
+#: src/sfm-read.c:1202
#, c-format
msgid "%s: File contains duplicate label for value `%.*s' for variable %s."
msgstr ""
-#: src/sfm-read.c:1242 src/sfm-read.c:1519
+#: src/sfm-read.c:1244 src/sfm-read.c:1521
#, c-format
msgid "%s: Reading system file: %s."
msgstr ""
-#: src/sfm-read.c:1245 src/sfm-read.c:1360 src/sfm-read.c:1402
+#: src/sfm-read.c:1247 src/sfm-read.c:1362 src/sfm-read.c:1404
#, c-format
msgid "%s: Unexpected end of file."
msgstr ""
-#: src/sfm-read.c:1260
+#: src/sfm-read.c:1262
#, c-format
msgid "%s: Seeking system file: %s."
msgstr ""
-#: src/sfm-read.c:1275
+#: src/sfm-read.c:1277
#, c-format
msgid "%s: System file contains multiple type 6 (document) records."
msgstr ""
-#: src/sfm-read.c:1281
+#: src/sfm-read.c:1283
#, c-format
msgid "%s: Number of document lines (%ld) must be greater than 0."
msgstr ""
-#: src/sfm-read.c:1313
+#: src/sfm-read.c:1315
#, c-format
msgid "%s: Error reading file: %s."
msgstr ""
-#: src/sfm-read.c:1350
+#: src/sfm-read.c:1352
#, c-format
msgid "%s: Compressed data is corrupted. Data ends in partial case."
msgstr ""
-#: src/sfm-read.c:1522
+#: src/sfm-read.c:1524
#, c-format
msgid "%s: Partial record at end of system file."
msgstr ""
msgid "%s: Writing system file: %s."
msgstr ""
+#: src/sort-prs.c:94
+msgid "`A' or `D' expected inside parentheses."
+msgstr ""
+
+#: src/sort-prs.c:99
+msgid "`)' expected."
+msgstr ""
+
#: src/sort.c:85
msgid "Buffer limit must be at least 2."
msgstr ""
"each. (PSPP workspace is currently restricted to a maximum of %d KB.)"
msgstr ""
-#: src/sort-prs.c:94
-msgid "`A' or `D' expected inside parentheses."
-msgstr ""
-
-#: src/sort-prs.c:99
-msgid "`)' expected."
-msgstr ""
-
#: src/sysfile-info.c:100
msgid "File:"
msgstr ""
msgid "Documents in the active file:"
msgstr ""
-#: src/sysfile-info.c:380 src/sysfile-info.c:519 src/vfm.c:841
+#: src/sysfile-info.c:380 src/sysfile-info.c:519 src/vfm.c:846
msgid "Label"
msgstr ""
msgid "Vector"
msgstr ""
-#: src/tab.c:258
-#, c-format
-msgid "bad vline: x=%d+%d=%d y=(%d+%d=%d,%d+%d=%d) in table size (%d,%d)\n"
-msgstr ""
-
-#: src/tab.c:333
-#, c-format
-msgid ""
-"bad box: (%d+%d=%d,%d+%d=%d)-(%d+%d=%d,%d+%d=%d) in table size (%d,%d)\n"
-msgstr ""
-
-#: src/temporary.c:49
-msgid "This command is not valid inside DO IF or LOOP."
-msgstr ""
-
-#: src/temporary.c:56
-msgid ""
-"This command may only appear once between procedures and procedure-like "
-"commands."
-msgstr ""
-
-#: src/title.c:60
-#, c-format
-msgid "%s before: %s\n"
-msgstr ""
-
-#: src/title.c:60
-msgid "<none>"
-msgstr ""
-
-#: src/title.c:72
-#, c-format
-msgid "%s: `.' expected after string."
-msgstr ""
-
-#: src/title.c:88
-#, c-format
-msgid "%s after: %s\n"
-msgstr ""
-
-#: src/title.c:143
-#, c-format
-msgid "Document entered %s by %s:"
-msgstr ""
-
#: src/t-test.q:270
msgid "TESTVAL, GROUPS and PAIRS subcommands are mutually exclusive."
msgstr ""
msgid "%s & %s"
msgstr ""
+#: src/tab.c:258
+#, c-format
+msgid "bad vline: x=%d+%d=%d y=(%d+%d=%d,%d+%d=%d) in table size (%d,%d)\n"
+msgstr ""
+
+#: src/tab.c:333
+#, c-format
+msgid ""
+"bad box: (%d+%d=%d,%d+%d=%d)-(%d+%d=%d,%d+%d=%d) in table size (%d,%d)\n"
+msgstr ""
+
+#: src/temporary.c:49
+msgid "This command is not valid inside DO IF or LOOP."
+msgstr ""
+
+#: src/temporary.c:56
+msgid ""
+"This command may only appear once between procedures and procedure-like "
+"commands."
+msgstr ""
+
+#: src/title.c:60
+#, c-format
+msgid "%s before: %s\n"
+msgstr ""
+
+#: src/title.c:60
+msgid "<none>"
+msgstr ""
+
+#: src/title.c:72
+#, c-format
+msgid "%s: `.' expected after string."
+msgstr ""
+
+#: src/title.c:88
+#, c-format
+msgid "%s after: %s\n"
+msgstr ""
+
+#: src/title.c:143
+#, c-format
+msgid "Document entered %s by %s:"
+msgstr ""
+
#: src/val-labs.c:121
#, c-format
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: pspp-dev@gnu.org\n"
-"POT-Creation-Date: 2006-01-24 17:40+0800\n"
+"POT-Creation-Date: 2006-01-28 17:20-0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
-#: src/aggregate.c:199
+#: src/aggregate.c:200
msgid "while expecting COLUMNWISE"
msgstr ""
-#: src/aggregate.c:228
+#: src/aggregate.c:229
msgid "expecting BREAK"
msgstr ""
-#: src/aggregate.c:233
+#: src/aggregate.c:234
msgid ""
"When PRESORTED is specified, specifying sorting directions with (A) or (D) "
"has no effect. Output data will be sorted the same way as the input data."
"contains the aggregate variables and the break variables."
msgstr ""
+#: src/any-reader.c:74
+#, c-format
+msgid "An error occurred while opening \"%s\": %s."
+msgstr ""
+
+#: src/any-reader.c:129
+#, c-format
+msgid "\"%s\" is not a system or portable file."
+msgstr ""
+
+#: src/any-reader.c:135 src/any-writer.c:80
+msgid "The inline file is not allowed here."
+msgstr ""
+
#: src/apply-dict.c:71
#, c-format
msgid "Variable %s is %s in target file, but %s in source file."
msgstr ""
#: src/apply-dict.c:74 src/apply-dict.c:75 src/format.c:198 src/recode.c:464
-#: src/recode.c:465 src/sfm-read.c:1014 src/sfm-read.c:1159
-#: src/sfm-read.c:1160 src/vars-atr.c:40 src/vars-atr.c:48
+#: src/recode.c:465 src/sfm-read.c:1016 src/sfm-read.c:1161
+#: src/sfm-read.c:1162 src/vars-atr.c:40 src/vars-atr.c:48
msgid "string"
msgstr ""
#: src/apply-dict.c:74 src/apply-dict.c:75 src/format.c:198 src/recode.c:464
-#: src/recode.c:465 src/sfm-read.c:1014 src/sfm-read.c:1159
-#: src/sfm-read.c:1160 src/vars-atr.c:40
+#: src/recode.c:465 src/sfm-read.c:1016 src/sfm-read.c:1161
+#: src/sfm-read.c:1162 src/vars-atr.c:40
msgid "numeric"
msgstr ""
msgid "Source variable count (%u) does not match target variable count (%u)."
msgstr ""
-#: src/autorecode.c:142 src/command.c:797 src/file-handle.q:83 src/lexer.c:440
-#: src/matrix-data.c:532 src/print.c:335 src/print.c:1044 src/sel-if.c:57
+#: src/autorecode.c:142 src/command.c:797 src/lexer.c:440
+#: src/matrix-data.c:532 src/print.c:335 src/print.c:1046 src/sel-if.c:57
#: src/sel-if.c:134 src/vector.c:197
msgid "expecting end of command"
msgstr ""
#: src/crosstabs.q:1109 src/crosstabs.q:1136 src/crosstabs.q:1156
#: src/crosstabs.q:1178 src/examine.q:1131 src/frequencies.q:1142
-#: src/frequencies.q:1263 src/sysfile-info.c:518 src/vfm.c:840
+#: src/frequencies.q:1263 src/sysfile-info.c:518 src/vfm.c:845
msgid "Value"
msgstr ""
msgid "Field too long (%d characters). Truncated after character %d."
msgstr ""
-#: src/data-list.c:142
-msgid ""
-"DATA LIST may not use a different file from that specified on its "
-"surrounding FILE TYPE."
+#: src/data-list.c:144
+msgid "DATA LIST must use the same file as the enclosing FILE TYPE."
msgstr ""
-#: src/data-list.c:161
+#: src/data-list.c:163
msgid "The END subcommand may only be specified once."
msgstr ""
-#: src/data-list.c:196
+#: src/data-list.c:198
msgid "Only one of FIXED, FREE, or LIST may be specified."
msgstr ""
-#: src/data-list.c:346 src/print.c:296
+#: src/data-list.c:348 src/print.c:296
#, c-format
msgid ""
"The record number specified, %ld, is before the previous record, %d. Data "
"fields must be listed in order of increasing record number."
msgstr ""
-#: src/data-list.c:375 src/data-list.c:1735
+#: src/data-list.c:377 src/data-list.c:1727
msgid ""
"SPSS-like or FORTRAN-like format specification expected after variable names."
msgstr ""
-#: src/data-list.c:386
+#: src/data-list.c:388
msgid "At least one variable must be specified."
msgstr ""
-#: src/data-list.c:391 src/print.c:328
+#: src/data-list.c:393 src/print.c:328
msgid ""
"Variables are specified on records that should not exist according to "
"RECORDS subcommand."
msgstr ""
-#: src/data-list.c:424 src/data-list.c:438 src/print.c:520 src/print.c:533
+#: src/data-list.c:426 src/data-list.c:440 src/print.c:520 src/print.c:533
msgid "Column positions for fields must be positive."
msgstr ""
-#: src/data-list.c:443
+#: src/data-list.c:445
msgid "The ending column for a field must be greater than the starting column."
msgstr ""
-#: src/data-list.c:457
+#: src/data-list.c:459
#, c-format
msgid "The %d columns %d-%d can't be evenly divided into %d fields."
msgstr ""
-#: src/data-list.c:477 src/print.c:561
+#: src/data-list.c:479 src/print.c:561
msgid "A format specifier on this line has extra characters on the end."
msgstr ""
-#: src/data-list.c:492 src/print.c:577
+#: src/data-list.c:494 src/print.c:577
msgid "The value for number of decimal places must be at least 1."
msgstr ""
-#: src/data-list.c:506 src/print.c:590
+#: src/data-list.c:508 src/print.c:590
#, c-format
msgid "Input format %s doesn't accept decimal places."
msgstr ""
-#: src/data-list.c:553 src/data-list.c:649 src/data-list.c:863
+#: src/data-list.c:555 src/data-list.c:651 src/data-list.c:859
#, c-format
msgid "%s is a duplicate variable name."
msgstr ""
-#: src/data-list.c:558
+#: src/data-list.c:560
#, c-format
msgid "There is already a variable %s of a different type."
msgstr ""
-#: src/data-list.c:565
+#: src/data-list.c:567
#, c-format
msgid "There is already a string variable %s of a different width."
msgstr ""
-#: src/data-list.c:640
+#: src/data-list.c:642
msgid ""
"The number of format specifications exceeds the given number of variable "
"names."
msgstr ""
-#: src/data-list.c:753 src/print.c:766
+#: src/data-list.c:755 src/print.c:766
msgid ""
"There aren't enough format specifications to match the number of variable "
"names given."
msgstr ""
-#: src/data-list.c:780 src/data-list.c:904 src/descript.c:882 src/print.c:797
-#: src/sysfile-info.c:139 src/sysfile-info.c:373 src/vfm.c:839
+#: src/data-list.c:782 src/data-list.c:900 src/descript.c:882 src/print.c:797
+#: src/sysfile-info.c:139 src/sysfile-info.c:373 src/vfm.c:844
msgid "Variable"
msgstr ""
-#: src/data-list.c:781 src/print.c:798
+#: src/data-list.c:783 src/print.c:798
msgid "Record"
msgstr ""
-#: src/data-list.c:782 src/print.c:799
+#: src/data-list.c:784 src/print.c:799
msgid "Columns"
msgstr ""
-#: src/data-list.c:783 src/data-list.c:905 src/print.c:800
+#: src/data-list.c:785 src/data-list.c:901 src/print.c:800
msgid "Format"
msgstr ""
-#: src/data-list.c:799
+#: src/data-list.c:800
#, c-format
-msgid "Reading %d record from file %s."
-msgid_plural "Reading %d records from file %s."
+msgid "Reading %d record from %s."
+msgid_plural "Reading %d records from %s."
msgstr[0] ""
msgstr[1] ""
-#: src/data-list.c:803
+#: src/data-list.c:916
#, c-format
-msgid "Reading %d record from the command file."
-msgid_plural "Reading %d records from the command file."
-msgstr[0] ""
-msgstr[1] ""
-
-#: src/data-list.c:921
-#, c-format
-msgid "Reading free-form data from file %s."
-msgstr ""
-
-#: src/data-list.c:924
-msgid "Reading free-form data from the command file."
+msgid "Reading free-form data from %s."
msgstr ""
-#: src/data-list.c:975
+#: src/data-list.c:967
#, c-format
msgid "Quoted string missing terminating `%c'."
msgstr ""
-#: src/data-list.c:1084
+#: src/data-list.c:1076
#, c-format
msgid "Partial case of %d of %d records discarded."
msgstr ""
-#: src/data-list.c:1138
+#: src/data-list.c:1130
#, c-format
msgid "Partial case discarded. The first variable missing was %s."
msgstr ""
-#: src/data-list.c:1182
+#: src/data-list.c:1174
#, 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/data-list.c:1259
+#: src/data-list.c:1251
msgid "Attempt to read past end of file."
msgstr ""
-#: src/data-list.c:1398
+#: src/data-list.c:1390
msgid ""
"REPEATING DATA must use the same file as its corresponding DATA LIST or FILE "
"TYPE."
msgstr ""
-#: src/data-list.c:1408 src/data-list.c:1442 src/data-list.c:1455
-#: src/data-list.c:1468 src/data-list.c:1502
+#: src/data-list.c:1400 src/data-list.c:1434 src/data-list.c:1447
+#: src/data-list.c:1460 src/data-list.c:1494
#, c-format
msgid "%s subcommand given multiple times."
msgstr ""
-#: src/data-list.c:1431
+#: src/data-list.c:1423
#, c-format
msgid "STARTS beginning column (%d) exceeds STARTS ending column (%d)."
msgstr ""
-#: src/data-list.c:1488
+#: src/data-list.c:1480
#, c-format
msgid "CONTINUED beginning column (%d) exceeds CONTINUED ending column (%d)."
msgstr ""
-#: src/data-list.c:1511
+#: src/data-list.c:1503
#, c-format
msgid "ID beginning column (%ld) must be positive."
msgstr ""
-#: src/data-list.c:1526
+#: src/data-list.c:1518
#, c-format
msgid "ID ending column (%ld) must be positive."
msgstr ""
-#: src/data-list.c:1532
+#: src/data-list.c:1524
#, c-format
msgid "ID ending column (%ld) cannot be less than ID beginning column (%d)."
msgstr ""
-#: src/data-list.c:1572
+#: src/data-list.c:1564
msgid "Missing required specification STARTS."
msgstr ""
-#: src/data-list.c:1574
+#: src/data-list.c:1566
msgid "Missing required specification OCCURS."
msgstr ""
-#: src/data-list.c:1581
+#: src/data-list.c:1573
msgid "ID specified without CONTINUED."
msgstr ""
-#: src/data-list.c:1592
+#: src/data-list.c:1584
#, c-format
msgid ""
"STARTS beginning column (%d) exceeds default STARTS ending column taken from "
"file's record width (%d)."
msgstr ""
-#: src/data-list.c:1605
+#: src/data-list.c:1597
#, c-format
msgid ""
"CONTINUED beginning column (%d) exceeds default CONTINUED ending column "
"taken from file's record width (%d)."
msgstr ""
-#: src/data-list.c:1684
+#: src/data-list.c:1676
msgid "String variable not allowed here."
msgstr ""
-#: src/data-list.c:1694
+#: src/data-list.c:1686
#, c-format
msgid "%s (%d) must be at least 1."
msgstr ""
-#: src/data-list.c:1700
+#: src/data-list.c:1692
#, c-format
msgid "Variable or integer expected for %s."
msgstr ""
-#: src/data-list.c:1825
+#: src/data-list.c:1817
#, c-format
msgid "Encountered mismatched record ID \"%s\" expecting \"%s\"."
msgstr ""
-#: src/data-list.c:1857
+#: src/data-list.c:1849
#, c-format
msgid ""
"Variable %s starting in column %d extends beyond physical record length of %"
"d."
msgstr ""
-#: src/data-list.c:1924
+#: src/data-list.c:1916
#, c-format
msgid "Invalid value %d for OCCURS."
msgstr ""
-#: src/data-list.c:1930
+#: src/data-list.c:1922
#, c-format
msgid "Beginning column for STARTS (%d) must be at least 1."
msgstr ""
-#: src/data-list.c:1938
+#: src/data-list.c:1930
#, c-format
msgid "Ending column for STARTS (%d) is less than beginning column (%d)."
msgstr ""
-#: src/data-list.c:1946
+#: src/data-list.c:1938
#, c-format
msgid "Invalid value %d for LENGTH."
msgstr ""
-#: src/data-list.c:1953
+#: src/data-list.c:1945
#, c-format
msgid "Beginning column for CONTINUED (%d) must be at least 1."
msgstr ""
-#: src/data-list.c:1961
+#: src/data-list.c:1953
#, c-format
msgid "Ending column for CONTINUED (%d) is less than beginning column (%d)."
msgstr ""
-#: src/data-list.c:1993
+#: src/data-list.c:1985
#, c-format
msgid ""
"Number of repetitions specified on OCCURS (%d) exceed number of repetitions "
"available in space on STARTS (%d), and CONTINUED not specified."
msgstr ""
-#: src/data-list.c:2011
+#: src/data-list.c:2003
#, c-format
msgid "Unexpected end of file with %d repetitions remaining out of %d."
msgstr ""
msgid "Valid cases = %g; cases with missing value(s) = %g."
msgstr ""
-#: src/dfm-read.c:158
+#: src/dfm-read.c:136
#, c-format
msgid "Could not open \"%s\" for reading as a data file: %s."
msgstr ""
-#: src/dfm-read.c:191 src/dfm-read.c:209
+#: src/dfm-read.c:168 src/dfm-read.c:186
msgid "BEGIN DATA expected."
msgstr ""
-#: src/dfm-read.c:218
+#: src/dfm-read.c:195
msgid ""
"Unexpected end-of-file while reading data in BEGIN DATA. This probably "
"indicates a missing or misformatted END DATA command. END DATA must appear "
"by itself on a single line with exactly one space between words."
msgstr ""
-#: src/dfm-read.c:251 src/dfm-read.c:271
+#: src/dfm-read.c:227 src/dfm-read.c:247
#, c-format
msgid "Error reading file %s: %s."
msgstr ""
-#: src/dfm-read.c:274
+#: src/dfm-read.c:250
#, c-format
msgid "%s: Partial record at end of file."
msgstr ""
-#: src/dfm-read.c:317
+#: src/dfm-read.c:299
#, c-format
msgid "Attempt to read beyond end-of-file on file %s."
msgstr ""
-#: src/dfm-read.c:320
+#: src/dfm-read.c:302
msgid "Attempt to read beyond END DATA."
msgstr ""
-#: src/dfm-read.c:467
+#: src/dfm-read.c:446
msgid ""
"This command is not valid here since the current input program does not "
"access the inline file."
msgid "%s is a PSPP extension."
msgstr ""
-#: src/file-handle-def.c:229
+#: src/file-handle-def.c:303
#, c-format
-msgid "Can't open %s as a %s because it is already open as a %s"
+msgid "Can't open %s as a %s because it is already open as a %s."
msgstr ""
-#: src/file-handle-def.c:236
+#: src/file-handle-def.c:310
#, c-format
-msgid "Can't open %s as a %s for %s because it is already open for %s"
+msgid "Can't open %s as a %s for %s because it is already open for %s."
msgstr ""
-#: src/file-handle-def.c:244
+#: src/file-handle-def.c:318
#, c-format
-msgid "Can't re-open %s as a %s for %s"
+msgid "Can't re-open %s as a %s for %s."
msgstr ""
-#: src/file-handle.q:68
+#: src/file-handle.q:69
#, c-format
msgid ""
-"File handle %s already refers to file %s. File handles cannot be redefined "
-"within a session."
+"File handle %s is already defined. Use CLOSE FILE HANDLE before redefining "
+"a file handle."
msgstr ""
-#: src/file-handle.q:89
-msgid "The FILE HANDLE required subcommand NAME is not present."
-msgstr ""
-
-#: src/file-handle.q:104
+#: src/file-handle.q:101
#, c-format
msgid ""
"Fixed-length records were specified on /RECFORM, but record length was not "
"specified on /LRECL. Assuming %d-character records."
msgstr ""
-#: src/file-handle.q:109
+#: src/file-handle.q:106
#, c-format
msgid ""
"Record length (%ld) must be at least one byte. Assuming %d-character "
"records."
msgstr ""
-#: src/file-handle.q:139
-msgid "expecting a file name or handle name"
+#: src/file-handle.q:152
+msgid "file"
msgstr ""
-#: src/filename.c:227
-#, c-format
-msgid "Searching for `%s'..."
+#: src/file-handle.q:154
+msgid "inline file"
msgstr ""
-#: src/filename.c:235 src/filename.c:267
-msgid "Search unsuccessful!"
+#: src/file-handle.q:156
+msgid "scratch file"
msgstr ""
-#: src/filename.c:260
-#, c-format
-msgid "Found `%s'."
+#: src/file-handle.q:177
+msgid "expecting a file name or handle name"
msgstr ""
-#: src/filename.c:665
+#: src/file-handle.q:204
#, c-format
-msgid "Not opening pipe file `%s' because SAFER option set."
+msgid "Handle for %s not allowed here."
msgstr ""
#: src/file-type.c:133
msgid "Unknown record type %g."
msgstr ""
+#: src/filename.c:227
+#, c-format
+msgid "Searching for `%s'..."
+msgstr ""
+
+#: src/filename.c:235 src/filename.c:267
+msgid "Search unsuccessful!"
+msgstr ""
+
+#: src/filename.c:260
+#, c-format
+msgid "Found `%s'."
+msgstr ""
+
+#: src/filename.c:677
+#, c-format
+msgid "Not opening pipe file `%s' because SAFER option set."
+msgstr ""
+
#: src/flip.c:88
msgid ""
"FLIP ignores TEMPORARY. Temporary transformations will be made permanent."
msgid "Unexpected end of file reading FLIP temporary file."
msgstr ""
+#: src/format-prs.c:66
+msgid "X and T format specifiers not allowed here."
+msgstr ""
+
+#: src/format-prs.c:74
+#, c-format
+msgid "%.*s is not a valid data format."
+msgstr ""
+
+#: src/format-prs.c:115
+msgid "Format specifier expected."
+msgstr ""
+
+#: src/format-prs.c:127
+#, c-format
+msgid "Data format %s does not specify a width."
+msgstr ""
+
+#: src/format-prs.c:145
+#, c-format
+msgid "Data format %s is not valid."
+msgstr ""
+
#: src/format.c:73
#, c-format
msgid "Format specifies a bad type (%d)"
msgid "%s variables are not compatible with %s format %s."
msgstr ""
-#: src/format.c:197 src/pfm-read.c:476 src/sfm-read.c:1012 src/sfm-read.c:1021
+#: src/format.c:197 src/pfm-read.c:476 src/sfm-read.c:1014 src/sfm-read.c:1023
msgid "String"
msgstr ""
-#: src/format.c:197 src/pfm-read.c:476 src/sfm-read.c:1012 src/sfm-read.c:1021
+#: src/format.c:197 src/pfm-read.c:476 src/sfm-read.c:1014 src/sfm-read.c:1023
msgid "Numeric"
msgstr ""
msgid "String variable with width %d not compatible with format %s."
msgstr ""
-#: src/format-prs.c:66
-msgid "X and T format specifiers not allowed here."
-msgstr ""
-
-#: src/format-prs.c:74
-#, c-format
-msgid "%.*s is not a valid data format."
-msgstr ""
-
-#: src/format-prs.c:115
-msgid "Format specifier expected."
-msgstr ""
-
-#: src/format-prs.c:127
-#, c-format
-msgid "Data format %s does not specify a width."
-msgstr ""
-
-#: src/format-prs.c:145
-#, c-format
-msgid "Data format %s is not valid."
-msgstr ""
-
#: src/formats.c:89
msgid "`(' expected after variable list"
msgstr ""
msgid "No valid data for variable %s; statistics not displayed."
msgstr ""
-#: src/get.c:306 src/get.c:320 src/get.c:345
+#: src/get.c:108
+msgid "expecting COMM or TAPE"
+msgstr ""
+
+#: src/get.c:343 src/get.c:357 src/get.c:382
#, c-format
msgid "expecting %s or %s"
msgstr ""
-#: src/get.c:552 src/print.c:179
+#: src/get.c:586 src/print.c:179
msgid "expecting a valid subcommand"
msgstr ""
-#: src/get.c:585
+#: src/get.c:619
#, c-format
msgid ""
"Cannot rename %s as %s because there already exists a variable named %s. To "
"as \"/RENAME (A=B)(B=C)(C=A)\", or equivalently, \"/RENAME (A B C=B C A)\"."
msgstr ""
-#: src/get.c:610
+#: src/get.c:644
msgid "`=' expected after variable list."
msgstr ""
-#: src/get.c:617
+#: src/get.c:651
#, c-format
msgid ""
"Number of variables on left side of `=' (%d) does not match number of "
"variables on right side (%d), in parenthesized group %d of RENAME subcommand."
msgstr ""
-#: src/get.c:630
+#: src/get.c:664
#, c-format
msgid "Requested renaming duplicates variable name %s."
msgstr ""
-#: src/get.c:660
+#: src/get.c:694
msgid "Cannot DROP all variables from dictionary."
msgstr ""
-#: src/get.c:835
+#: src/get.c:869
msgid "The active file may not be specified more than once."
msgstr ""
-#: src/get.c:844
+#: src/get.c:878
msgid "Cannot specify the active file since no active file has been defined."
msgstr ""
-#: src/get.c:852
+#: src/get.c:886
msgid ""
"MATCH FILES may not be used after TEMPORARY when the active file is an input "
"source. Temporary transformations will be made permanent."
msgstr ""
-#: src/get.c:890
+#: src/get.c:924
msgid "Multiple IN subcommands for a single FILE or TABLE."
msgstr ""
-#: src/get.c:910
+#: src/get.c:944
msgid "BY may appear at most once."
msgstr ""
-#: src/get.c:930
+#: src/get.c:964
#, c-format
msgid "File %s lacks BY variable %s."
msgstr ""
-#: src/get.c:944
+#: src/get.c:978
msgid "FIRST may appear at most once."
msgstr ""
-#: src/get.c:958
+#: src/get.c:992
msgid "LAST may appear at most once."
msgstr ""
-#: src/get.c:999
+#: src/get.c:1033
msgid "BY is required when TABLE is specified."
msgstr ""
-#: src/get.c:1004
+#: src/get.c:1038
msgid "BY is required when IN is specified."
msgstr ""
-#: src/get.c:1032
+#: src/get.c:1066
#, c-format
msgid "IN variable name %s duplicates an existing variable name."
msgstr ""
-#: src/get.c:1461
+#: src/get.c:1495
#, c-format
msgid ""
"Variable %s in file %s (%s) has different type or width from the same "
"variable in earlier file (%s)."
msgstr ""
-#: src/get.c:1545
-msgid "expecting COMM or TAPE"
-msgstr ""
-
#: src/getl.c:139
#, c-format
msgid "Can't find `%s' in include file search path."
msgid "Cannot change mode of %s: %s"
msgstr ""
-#: src/pfm-read.c:87
+#: src/pfm-read.c:97
#, c-format
msgid "portable file %s corrupt at offset %ld: "
msgstr ""
-#: src/pfm-read.c:114
+#: src/pfm-read.c:124
msgid "unexpected end of file"
msgstr ""
-#: src/pfm-read.c:172
+#: src/pfm-read.c:182
#, c-format
msgid ""
"An error occurred while opening \"%s\" for reading as a portable file: %s."
msgstr ""
-#: src/pfm-read.c:190
+#: src/pfm-read.c:200
msgid "Data record expected."
msgstr ""
-#: src/pfm-read.c:298
+#: src/pfm-read.c:308
msgid "Missing numeric terminator."
msgstr ""
-#: src/pfm-read.c:321
+#: src/pfm-read.c:331
msgid "Invalid integer."
msgstr ""
-#: src/pfm-read.c:332
+#: src/pfm-read.c:342
#, c-format
msgid "Bad string length %d."
msgstr ""
msgid "Bad time string length %d."
msgstr ""
-#: src/pfm-read.c:468 src/sfm-read.c:1004
+#: src/pfm-read.c:468 src/sfm-read.c:1006
#, c-format
msgid "%s: Bad format specifier byte (%d)."
msgstr ""
-#: src/pfm-read.c:475 src/sfm-read.c:1020
+#: src/pfm-read.c:475 src/sfm-read.c:1022
#, c-format
msgid "%s variable %s has invalid format specifier %s."
msgstr ""
msgid "%s: Writing portable file: %s."
msgstr ""
-#: src/pfm-write.c:468
+#: src/pfm-write.c:466
#, c-format
msgid "%s: Closing portable file: %s."
msgstr ""
#: src/print.c:839
#, c-format
-msgid "Writing %d record(s) to file %s."
-msgstr ""
+msgid "Writing %d record to %s."
+msgid_plural "Writing %d records to %s."
+msgstr[0] ""
+msgstr[1] ""
-#: src/print.c:842
+#: src/print.c:843
#, c-format
-msgid "Writing %d record(s) to the listing file."
-msgstr ""
+msgid "Writing %d record."
+msgid_plural "Writing %d records."
+msgstr[0] ""
+msgstr[1] ""
-#: src/print.c:1082
+#: src/print.c:1084
msgid "The expression on PRINT SPACE evaluated to the system-missing value."
msgstr ""
-#: src/print.c:1085
+#: src/print.c:1087
#, c-format
msgid "The expression on PRINT SPACE evaluated to %g."
msgstr ""
msgid "Cannot sample %d observations from a population of %d."
msgstr ""
+#: src/scratch-reader.c:59
+#, c-format
+msgid ""
+"Scratch file handle %s has not yet been written, using SAVE or another "
+"procedure, so it cannot yet be used for reading."
+msgstr ""
+
#: src/sel-if.c:103
msgid "The filter variable must be numeric."
msgstr ""
msgid "corrupt system file: "
msgstr ""
-#: src/sfm-read.c:151 src/sfm-write.c:931
+#: src/sfm-read.c:149 src/sfm-write.c:929
#, c-format
msgid "%s: Closing system file: %s."
msgstr ""
-#: src/sfm-read.c:237
+#: src/sfm-read.c:239
#, c-format
msgid ""
"An error occurred while opening \"%s\" for reading as a system file: %s."
msgstr ""
-#: src/sfm-read.c:255
+#: src/sfm-read.c:257
#, c-format
msgid ""
"%s: Index of weighting variable (%d) is not between 0 and number of elements "
"per case (%d)."
msgstr ""
-#: src/sfm-read.c:264
+#: src/sfm-read.c:266
#, c-format
msgid ""
"%s: Weighting variable may not be a continuation of a long string variable."
msgstr ""
-#: src/sfm-read.c:267
+#: src/sfm-read.c:269
#, c-format
msgid "%s: Weighting variable may not be a string variable."
msgstr ""
-#: src/sfm-read.c:292
+#: src/sfm-read.c:294
#, c-format
msgid ""
"%s: Orphaned variable index record (type 4). Type 4 records must always "
"immediately follow type 3 records."
msgstr ""
-#: src/sfm-read.c:350
+#: src/sfm-read.c:352
#, c-format
msgid "%s: Invalid subrecord length. Record: 7; Subrecord: 11"
msgstr ""
-#: src/sfm-read.c:404
+#: src/sfm-read.c:406
#, c-format
msgid "%s: Trailing garbage in long variable name map."
msgstr ""
-#: src/sfm-read.c:411
+#: src/sfm-read.c:413
#, c-format
msgid "%s: Long variable mapping to invalid variable name `%s'."
msgstr ""
-#: src/sfm-read.c:421
+#: src/sfm-read.c:423
#, c-format
msgid "%s: Long variable mapping for nonexistent variable %s."
msgstr ""
-#: src/sfm-read.c:431
+#: src/sfm-read.c:433
#, c-format
msgid "%s: Duplicate long variable name `%s' within system file."
msgstr ""
-#: src/sfm-read.c:459
+#: src/sfm-read.c:461
#, c-format
msgid "%s: Unrecognized record type 7, subtype %d encountered in system file."
msgstr ""
-#: src/sfm-read.c:484
+#: src/sfm-read.c:486
#, c-format
msgid "%s: Unrecognized record type %d."
msgstr ""
-#: src/sfm-read.c:516
+#: src/sfm-read.c:518
#, c-format
msgid ""
"%s: Bad size (%d) or count (%d) field on record type 7, subtype 3.\tExpected "
"size %d, count 8."
msgstr ""
-#: src/sfm-read.c:527
+#: src/sfm-read.c:529
#, c-format
msgid ""
"%s: Floating-point representation in system file is not IEEE-754. PSPP "
"cannot convert between floating-point formats."
msgstr ""
-#: src/sfm-read.c:543
+#: src/sfm-read.c:545
#, c-format
msgid ""
"%s: File-indicated endianness (%s) does not match endianness intuited from "
"file header (%s)."
msgstr ""
-#: src/sfm-read.c:546 src/sfm-read.c:547
+#: src/sfm-read.c:548 src/sfm-read.c:549
msgid "big-endian"
msgstr ""
-#: src/sfm-read.c:546 src/sfm-read.c:547
+#: src/sfm-read.c:548 src/sfm-read.c:549
msgid "little-endian"
msgstr ""
-#: src/sfm-read.c:548
+#: src/sfm-read.c:550
msgid "unknown"
msgstr ""
-#: src/sfm-read.c:552
+#: src/sfm-read.c:554
#, c-format
msgid "%s: File-indicated character representation code (%s) is not ASCII."
msgstr ""
-#: src/sfm-read.c:556
+#: src/sfm-read.c:558
msgid "DEC Kanji"
msgstr ""
-#: src/sfm-read.c:556 src/sysfile-info.c:119
+#: src/sfm-read.c:558 src/sysfile-info.c:119
msgid "Unknown"
msgstr ""
-#: src/sfm-read.c:572
+#: src/sfm-read.c:574
#, c-format
msgid ""
"%s: Bad size (%d) or count (%d) field on record type 7, subtype 4.\tExpected "
"size %d, count 8."
msgstr ""
-#: src/sfm-read.c:587
+#: src/sfm-read.c:589
#, c-format
msgid ""
"%s: File-indicated value is different from internal value for at least one "
"%g; LOWEST: %g, %g."
msgstr ""
-#: src/sfm-read.c:614
+#: src/sfm-read.c:616
#, c-format
msgid ""
"%s: Bad magic. Proper system files begin with the four characters `$FL2'. "
"This file will not be read."
msgstr ""
-#: src/sfm-read.c:656
+#: src/sfm-read.c:658
#, c-format
msgid ""
"%s: File layout code has unexpected value %d. Value should be 2, in big-"
"endian or little-endian format."
msgstr ""
-#: src/sfm-read.c:684
+#: src/sfm-read.c:686
#, c-format
msgid "%s: Number of cases in file (%ld) is not between -1 and %d."
msgstr ""
-#: src/sfm-read.c:689
+#: src/sfm-read.c:691
#, c-format
msgid "%s: Compression bias (%g) is not the usual value of 100."
msgstr ""
-#: src/sfm-read.c:812
+#: src/sfm-read.c:814
#, c-format
msgid ""
"%s: position %d: String variable does not have proper number of continuation "
"records."
msgstr ""
-#: src/sfm-read.c:823
+#: src/sfm-read.c:825
#, c-format
msgid "%s: position %d: Superfluous long string continuation record."
msgstr ""
-#: src/sfm-read.c:829
+#: src/sfm-read.c:831
#, c-format
msgid "%s: position %d: Bad variable type code %d."
msgstr ""
-#: src/sfm-read.c:832
+#: src/sfm-read.c:834
#, c-format
msgid "%s: position %d: Variable label indicator field is not 0 or 1."
msgstr ""
-#: src/sfm-read.c:836
+#: src/sfm-read.c:838
#, c-format
msgid ""
"%s: position %d: Missing value indicator field is not -3, -2, 0, 1, 2, or 3."
msgstr ""
-#: src/sfm-read.c:842
+#: src/sfm-read.c:844
#, c-format
msgid "%s: position %d: Variable name begins with invalid character."
msgstr ""
-#: src/sfm-read.c:846
+#: src/sfm-read.c:848
#, c-format
msgid "%s: position %d: Variable name begins with lowercase letter %c."
msgstr ""
-#: src/sfm-read.c:850
+#: src/sfm-read.c:852
#, c-format
msgid ""
"%s: position %d: Variable name begins with octothorpe (`#'). Scratch "
"variables should not appear in system files."
msgstr ""
-#: src/sfm-read.c:865
+#: src/sfm-read.c:867
#, c-format
msgid "%s: position %d: Variable name character %d is lowercase letter %c."
msgstr ""
-#: src/sfm-read.c:874
+#: src/sfm-read.c:876
#, c-format
msgid ""
"%s: position %d: character `\\%03o' (%c) is not valid in a variable name."
msgstr ""
-#: src/sfm-read.c:881
+#: src/sfm-read.c:883
#, c-format
msgid "%s: Invalid variable name `%s' within system file."
msgstr ""
-#: src/sfm-read.c:888
+#: src/sfm-read.c:890
#, c-format
msgid "%s: Duplicate variable name `%s' within system file."
msgstr ""
-#: src/sfm-read.c:911
+#: src/sfm-read.c:913
#, c-format
msgid "%s: Variable %s indicates variable label of invalid length %d."
msgstr ""
-#: src/sfm-read.c:932
+#: src/sfm-read.c:934
#, c-format
msgid "%s: Long string variable %s may not have missing values."
msgstr ""
-#: src/sfm-read.c:953
+#: src/sfm-read.c:955
#, c-format
msgid ""
"%s: String variable %s may not have missing values specified as a range."
msgstr ""
-#: src/sfm-read.c:980
+#: src/sfm-read.c:982
#, c-format
msgid "%s: Long string continuation records omitted at end of dictionary."
msgstr ""
-#: src/sfm-read.c:985
+#: src/sfm-read.c:987
#, c-format
msgid ""
"%s: System file header indicates %d variable positions but %d were read from "
"file."
msgstr ""
-#: src/sfm-read.c:1010
+#: src/sfm-read.c:1012
#, c-format
msgid "%s: %s variable %s has %s format specifier %s."
msgstr ""
-#: src/sfm-read.c:1063
+#: src/sfm-read.c:1065
#, c-format
msgid "%s: Invalid number of labels: %d. Ignoring labels."
msgstr ""
-#: src/sfm-read.c:1105
+#: src/sfm-read.c:1107
#, c-format
msgid ""
"%s: Variable index record (type 4) does not immediately follow value label "
"record (type 3) as it should."
msgstr ""
-#: src/sfm-read.c:1116
+#: src/sfm-read.c:1118
#, c-format
msgid ""
"%s: Number of variables associated with a value label (%d) is not between 1 "
"and the number of variables (%d)."
msgstr ""
-#: src/sfm-read.c:1132
+#: src/sfm-read.c:1134
#, c-format
msgid ""
"%s: Variable index associated with value label (%d) is not between 1 and the "
"number of values (%d)."
msgstr ""
-#: src/sfm-read.c:1139
+#: src/sfm-read.c:1141
#, c-format
msgid ""
"%s: Variable index associated with value label (%d) refers to a continuation "
"of a string variable, not to an actual variable."
msgstr ""
-#: src/sfm-read.c:1144
+#: src/sfm-read.c:1146
#, c-format
msgid "%s: Value labels are not allowed on long string variables (%s)."
msgstr ""
-#: src/sfm-read.c:1155
+#: src/sfm-read.c:1157
#, c-format
msgid ""
"%s: Variables associated with value label are not all of identical type. "
"Variable %s has %s type, but variable %s has %s type."
msgstr ""
-#: src/sfm-read.c:1196
+#: src/sfm-read.c:1198
#, c-format
msgid "%s: File contains duplicate label for value %g for variable %s."
msgstr ""
-#: src/sfm-read.c:1200
+#: src/sfm-read.c:1202
#, c-format
msgid "%s: File contains duplicate label for value `%.*s' for variable %s."
msgstr ""
-#: src/sfm-read.c:1242 src/sfm-read.c:1519
+#: src/sfm-read.c:1244 src/sfm-read.c:1521
#, c-format
msgid "%s: Reading system file: %s."
msgstr ""
-#: src/sfm-read.c:1245 src/sfm-read.c:1360 src/sfm-read.c:1402
+#: src/sfm-read.c:1247 src/sfm-read.c:1362 src/sfm-read.c:1404
#, c-format
msgid "%s: Unexpected end of file."
msgstr ""
-#: src/sfm-read.c:1260
+#: src/sfm-read.c:1262
#, c-format
msgid "%s: Seeking system file: %s."
msgstr ""
-#: src/sfm-read.c:1275
+#: src/sfm-read.c:1277
#, c-format
msgid "%s: System file contains multiple type 6 (document) records."
msgstr ""
-#: src/sfm-read.c:1281
+#: src/sfm-read.c:1283
#, c-format
msgid "%s: Number of document lines (%ld) must be greater than 0."
msgstr ""
-#: src/sfm-read.c:1313
+#: src/sfm-read.c:1315
#, c-format
msgid "%s: Error reading file: %s."
msgstr ""
-#: src/sfm-read.c:1350
+#: src/sfm-read.c:1352
#, c-format
msgid "%s: Compressed data is corrupted. Data ends in partial case."
msgstr ""
-#: src/sfm-read.c:1522
+#: src/sfm-read.c:1524
#, c-format
msgid "%s: Partial record at end of system file."
msgstr ""
msgid "%s: Writing system file: %s."
msgstr ""
+#: src/sort-prs.c:94
+msgid "`A' or `D' expected inside parentheses."
+msgstr ""
+
+#: src/sort-prs.c:99
+msgid "`)' expected."
+msgstr ""
+
#: src/sort.c:85
msgid "Buffer limit must be at least 2."
msgstr ""
"each. (PSPP workspace is currently restricted to a maximum of %d KB.)"
msgstr ""
-#: src/sort-prs.c:94
-msgid "`A' or `D' expected inside parentheses."
-msgstr ""
-
-#: src/sort-prs.c:99
-msgid "`)' expected."
-msgstr ""
-
#: src/sysfile-info.c:100
msgid "File:"
msgstr ""
msgid "Documents in the active file:"
msgstr ""
-#: src/sysfile-info.c:380 src/sysfile-info.c:519 src/vfm.c:841
+#: src/sysfile-info.c:380 src/sysfile-info.c:519 src/vfm.c:846
msgid "Label"
msgstr ""
msgid "Vector"
msgstr ""
-#: src/tab.c:258
-#, c-format
-msgid "bad vline: x=%d+%d=%d y=(%d+%d=%d,%d+%d=%d) in table size (%d,%d)\n"
-msgstr ""
-
-#: src/tab.c:333
-#, c-format
-msgid ""
-"bad box: (%d+%d=%d,%d+%d=%d)-(%d+%d=%d,%d+%d=%d) in table size (%d,%d)\n"
-msgstr ""
-
-#: src/temporary.c:49
-msgid "This command is not valid inside DO IF or LOOP."
-msgstr ""
-
-#: src/temporary.c:56
-msgid ""
-"This command may only appear once between procedures and procedure-like "
-"commands."
-msgstr ""
-
-#: src/title.c:60
-#, c-format
-msgid "%s before: %s\n"
-msgstr ""
-
-#: src/title.c:60
-msgid "<none>"
-msgstr ""
-
-#: src/title.c:72
-#, c-format
-msgid "%s: `.' expected after string."
-msgstr ""
-
-#: src/title.c:88
-#, c-format
-msgid "%s after: %s\n"
-msgstr ""
-
-#: src/title.c:143
-#, c-format
-msgid "Document entered %s by %s:"
-msgstr ""
-
#: src/t-test.q:270
msgid "TESTVAL, GROUPS and PAIRS subcommands are mutually exclusive."
msgstr ""
msgid "%s & %s"
msgstr ""
+#: src/tab.c:258
+#, c-format
+msgid "bad vline: x=%d+%d=%d y=(%d+%d=%d,%d+%d=%d) in table size (%d,%d)\n"
+msgstr ""
+
+#: src/tab.c:333
+#, c-format
+msgid ""
+"bad box: (%d+%d=%d,%d+%d=%d)-(%d+%d=%d,%d+%d=%d) in table size (%d,%d)\n"
+msgstr ""
+
+#: src/temporary.c:49
+msgid "This command is not valid inside DO IF or LOOP."
+msgstr ""
+
+#: src/temporary.c:56
+msgid ""
+"This command may only appear once between procedures and procedure-like "
+"commands."
+msgstr ""
+
+#: src/title.c:60
+#, c-format
+msgid "%s before: %s\n"
+msgstr ""
+
+#: src/title.c:60
+msgid "<none>"
+msgstr ""
+
+#: src/title.c:72
+#, c-format
+msgid "%s: `.' expected after string."
+msgstr ""
+
+#: src/title.c:88
+#, c-format
+msgid "%s after: %s\n"
+msgstr ""
+
+#: src/title.c:143
+#, c-format
+msgid "Document entered %s by %s:"
+msgstr ""
+
#: src/val-labs.c:121
#, c-format
msgid ""
+Sat Jan 28 17:45:36 2006 Ben Pfaff <blp@gnu.org>
+
+ Cleaner (faster?) way to compact cases.
+
+ * dictionary.c: (dict_compact_case) Removed.
+ (dict_needs_compaction) New function.
+ (struct copy_map) New structure.
+ (struct dict_compactor) New structure.
+ (dict_make_compactor) New function.
+ (dict_compactor_compact) New function.
+ (dict_compactor_destroy) New function.
+
+Sat Jan 28 17:24:22 2006 Ben Pfaff <blp@gnu.org>
+
+ Cleanups.
+
+ * data-list.c: Make data_list_source_class static.
+ (dump_fixed_table) Use fh_get_name() to describe source of data.
+ (dump_free_table) Ditto.
+ (cmd_repeating_data) Eliminate special cases for inline file.
+
+ * dictionary.c: (dict_contains_var) Change return value from int to
+ bool.
+ (dict_rename_vars) Ditto.
+ (dict_create_vector) Ditto.
+
+Sat Jan 28 17:20:50 2006 Ben Pfaff <blp@gnu.org>
+
+ Add scratch file handles.
+
+ Now a file handle can refer to a disk file, to an in-memory
+ structure, or to the "inline" file, instead of just to a disk
+ file. The introduction of new categories means that special cases
+ for the inline file in a few places could be eliminated, but it
+ also means that code that assumed that a handle refers to a file
+ has to check for that.
+
+ Also, now file handles can be freed, so code now must be sure not
+ to access a handle after closing it (with fh_close()).
+
+ * Makefile.am: Add any-reader.c, any-reader.h, any-writer.c,
+ any-writer.h, scratch-handle.c, scratch-handle.h,
+ scratch-reader.c, scratch-reader.h, scratch-writer.c,
+ scratch-writer.h to pspp_SOURCES.
+
+ * any-reader.c: New file.
+
+ * any-reader.h: New file.
+
+ * any-writer.c: New file.
+
+ * any-writer.h: New file.
+
+ * scratch-handle.c: New file.
+
+ * scratch-handle.h: New file.
+
+ * scratch-reader.c: New file.
+
+ * scratch-reader.h: New file.
+
+ * scratch-writer.c: New file.
+
+ * scratch-writer.h: New file.
+
+ * aggregate.c: Use an any_writer instead of an sfm_writer, to add
+ flexibility.
+
+ * apply-dict.c: Use an any_reader instead of an sfm_reader, to add
+ flexibility.
+
+ * command.def: Add CLOSE FILE HANDLE command.
+
+ * dfm-reader.c: Now fewer special cases for inline file.
+ (static var inline_open_cnt) Removed.
+ (static var inline_file) Removed.
+ (dfm_close_reader) Eliminate a special case for inline file.
+ Reorganize to avoid access-after-free.
+ (dfm_open_reader) Eliminate a special case for inline file.
+ (read_inline_record) Use bool instead of int. No need to
+ increment line number.
+ (read_file_record) Use bool instead of int.
+ (read_record) Check whether file handle is inline file, instead of
+ for null pointer.
+ (dfm_eof) Ditto.
+ (dfm_expand_tabs) Ditto.
+ (dfm_push) Ditto.
+ (dfm_pop) Ditto.
+ (cmd_begin_data) Fix inaccurate check for whether the inline file
+ is in use--now we can tell by checking whether the inline file's
+ open count is positive.
+
+ * file-handle-def.c: (struct file_handle) Reorder members. Add
+ `deleted' member. Add `referent' member. Add `sh' member.
+ (static var default_handle) New variable.
+ (static var inline_file) New variable.
+ (fh_init) Initialize inline file.
+ (free_handle) New function.
+ (fh_done) Rewrite.
+ (fh_from_name) Don't return deleted handles.
+ (fh_from_filename) Ditto.
+ (fh_create) Removed.
+ (create_handle) New function.
+ (fh_create_file) New function.
+ (fh_create_scratch) New function.
+ (fh_inline_file) New function.
+ (fh_free) Rewrite.
+ (fh_open) Now requires a referent type mask and verifies it. All
+ references updated.
+ (fh_close) If open_cnt goes to 0 on a deleted handle, free it.
+ (fh_is_open) New function.
+ (fh_get_referent) New function.
+ (fh_get_filename) Limit to handles that refer to files.
+ (fh_get_mode) Ditto.
+ (fh_get_record_width) Limit to handles that refer to files or the
+ inline file.
+ (fh_get_tab_width) Ditto.
+ (fh_get_scratch_handle) New function.
+ (fh_set_scratch_handle) New function.
+ (fh_get_default_handle) New function.
+ (fh_set_default_handle) New function.
+
+ * file-handle.h: (enum fh_referent) New type.
+ (enum fh_mode) Rename MODE_TEXT to FH_MODE_TEXT, MODE_BINARY to
+ FH_MODE_BINARY, and update all usages.
+
+ * file-handle.q: Add "scratch" as a possible mode.
+ (cmd_file_handle) Mention CLOSE FILE HANDLE in error message.
+ Use lex_end_of_command(), lex_sbc_missing(). Support creating
+ scratch handles.
+ (cmd_close_file_handle) New function.
+ (referent_name) New function.
+ (fh_parse) Now takes a referent type mask to specify handles that
+ can be accepted. Updated all references.
+
+ * filename.c: (fn_extension) New function.
+
+ * get.c: Use any_reader and any_writer and thereby merge code that
+ has been duplicated for each kind of file. Also, we had something
+ here called `any_writer' before, so its name had to be changed to
+ `case_writer'.
+ (enum operation) Removed, because unused.
+ (struct get_pgm) Removed.
+ (get_pgm_free) Removed.
+ (get_source_destroy) Removed.
+ (get_source_read) Removed.
+ (global var get_source_class) Removed.
+ (static var case_reader_source_class) Removed.
+ (enum reader_command) New enum.
+ (struct case_reader_pgm) New struct.
+ (parse_read_command) New function.
+ (case_reader_pgm_free) New function.
+ (case_reader_source_destroy) New function.
+ (case_Reader_source_Read) New function.
+ (cmd_get) Rewrote as a call to parse_read_command().
+ (cmd_import) Ditto.
+ (struct any_writer) Rename to case_writer. Drop `writer_type',
+ `writer' members in favor of an `any_writer' member named
+ `writer'.
+ (any_writer_destroy) Rename case_writer_destroy. Use
+ any_writer_close().
+ (parse_write_command) Allow scratch files. Use any_writer.
+ (any_writer_write_case) Rename case_writer_write_case(). Use
+ any_writer_write().
+` (struct mtf_file) Use any_reader.
+ (cmd_match_files) Allow scratch files. Use any_reader.
+ (mtf_free_file) Use any_reader_close().
+ (mtf_read_nonactive_records) Use any_reader_read().
+ (mtf_processing) Use any_reader_read().
+ (struct import_pgm) Removed.
+ (import_pgm_free) Removed.
+ (import_source_destroy) Removed.
+ (import_source_read) Removed.
+ (global var import_source_class) Removed.
+
+ * glob.c: (global var default_handle) Removed. Replaced all
+ references by fh_get_default_handle() or fh_set_default_handle().
+
+ * pfm-read.c: (static var portable_to_local) Moved from inside
+ read_header() to top level.
+ (pfm_detect) New function.
+
+ * pfm-write.c: (pfm_write_case) Make case argument const.
+ Reorganize to avoid access-after-free.
+
+ * print.c: (dump_table) Use fh_get_name() to describe source of
+ data.
+
+ * sfm-read.c: (sfm_close_reader) Reorganize to avoid
+ access-after-free.
+ (sfm_detect) New function.
+
+ * str.c: (str_lowercase) New function.
+
+ * vfm.c: Use new compaction interface.
+ (static var compaction_necessary) Removed.
+ (static var compactor) New variable.
+ (open_active_file) Initialize compactor.
+ (write_case) Use compactor.
+ (close_active_file) Free compactor.
+
Wed Jan 11 19:28:39 2006 Ben Pfaff <blp@gnu.org>
- Clean up file handle code in preparation to add temporary file
+ Clean up file handle code in preparation to add scratch file
handles.
* file-handle-def.c: Lots of formatting cleanup. Added function
algorithm.h \
alloc.c \
alloc.h \
+ any-reader.c \
+ any-reader.h \
+ any-writer.c \
+ any-writer.h \
apply-dict.c \
ascii.c \
autorecode.c \
tab.c \
tab.h \
temporary.c \
+ scratch-handle.c \
+ scratch-handle.h \
+ scratch-reader.c \
+ scratch-reader.h \
+ scratch-writer.c \
+ scratch-writer.h \
mkfile.c \
mkfile.h \
title.c \
#include "error.h"
#include <stdlib.h>
#include "alloc.h"
+#include "any-writer.h"
#include "case.h"
#include "casefile.h"
#include "command.h"
struct agr_proc
{
/* We have either an output file or a sink. */
- struct sfm_writer *writer; /* Output file, or null if none. */
+ struct any_writer *writer; /* Output file, or null if none. */
struct case_sink *sink; /* Sink, or null if none. */
/* Break variables. */
lex_match ('=');
if (!lex_match ('*'))
{
- out_file = fh_parse ();
+ out_file = fh_parse (FH_REF_FILE | FH_REF_SCRATCH);
if (out_file == NULL)
goto error;
}
}
else
{
- agr.writer = sfm_open_writer (out_file, agr.dict,
- sfm_writer_default_options ());
+ agr.writer = any_writer_open (out_file, agr.dict);
if (agr.writer == NULL)
goto error;
while (casereader_read_xfer (reader, &c))
{
if (aggregate_single_case (&agr, &c, &agr.agr_case))
- sfm_write_case (agr.writer, &agr.agr_case);
+ any_writer_write (agr.writer, &agr.agr_case);
case_destroy (&c);
}
casereader_destroy (reader);
if (agr.case_cnt > 0)
{
dump_aggregate_info (&agr, &agr.agr_case);
- sfm_write_case (agr.writer, &agr.agr_case);
+ any_writer_write (agr.writer, &agr.agr_case);
}
}
{
struct agr_var *iter, *next;
- sfm_close_writer (agr->writer);
+ any_writer_close (agr->writer);
if (agr->sort != NULL)
sort_destroy_criteria (agr->sort);
free (agr->break_vars);
struct agr_proc *agr = agr_;
if (aggregate_single_case (agr, c, &agr->agr_case))
- sfm_write_case (agr->writer, &agr->agr_case);
+ any_writer_write (agr->writer, &agr->agr_case);
return 1;
}
--- /dev/null
+/* PSPP - computes sample statistics.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+ Written by Ben Pfaff <blp@gnu.org>.
+
+ 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 <config.h>
+#include "any-reader.h"
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "error.h"
+#include "file-handle-def.h"
+#include "filename.h"
+#include "pfm-read.h"
+#include "sfm-read.h"
+#include "str.h"
+#include "scratch-reader.h"
+#include "xalloc.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+/* Type of file backing an any_reader. */
+enum any_reader_type
+ {
+ SYSTEM_FILE, /* System file. */
+ PORTABLE_FILE, /* Portable file. */
+ SCRATCH_FILE /* Scratch file. */
+ };
+
+/* Reader for any type of case-structured file. */
+struct any_reader
+ {
+ enum any_reader_type type; /* Type of file. */
+ void *private; /* Private data. */
+ };
+
+/* Result of type detection. */
+enum detect_result
+ {
+ YES, /* It is this type. */
+ NO, /* It is not this type. */
+ IO_ERROR /* File couldn't be opened. */
+ };
+
+/* Tries to detect whether HANDLE represents a given type of
+ file, by opening the file and passing it to DETECT, and
+ returns a detect_result. */
+static enum detect_result
+try_detect (struct file_handle *handle, bool (*detect) (FILE *))
+{
+ FILE *file;
+ bool is_type;
+
+ file = fn_open (fh_get_filename (handle), "rb");
+ if (file == NULL)
+ {
+ msg (ME, _("An error occurred while opening \"%s\": %s."),
+ fh_get_filename (handle), strerror (errno));
+ return IO_ERROR;
+ }
+
+ is_type = detect (file);
+
+ fn_close (fh_get_filename (handle), file);
+
+ return is_type ? YES : NO;
+}
+
+/* If PRIVATE is non-null, creates and returns a new any_reader,
+ initializing its fields to TYPE and PRIVATE. If PRIVATE is a
+ null pointer, just returns a null pointer. */
+static struct any_reader *
+make_any_reader (enum any_reader_type type, void *private)
+{
+ if (private != NULL)
+ {
+ struct any_reader *reader = xmalloc (sizeof *reader);
+ reader->type = type;
+ reader->private = private;
+ return reader;
+ }
+ else
+ return NULL;
+}
+
+/* Creates an any_reader for HANDLE. On success, returns the new
+ any_reader and stores the file's dictionary into *DICT. On
+ failure, returns a null pointer. */
+struct any_reader *
+any_reader_open (struct file_handle *handle, struct dictionary **dict)
+{
+ switch (fh_get_referent (handle))
+ {
+ case FH_REF_FILE:
+ {
+ enum detect_result result;
+
+ result = try_detect (handle, sfm_detect);
+ if (result == IO_ERROR)
+ return NULL;
+ else if (result == YES)
+ return make_any_reader (SYSTEM_FILE,
+ sfm_open_reader (handle, dict, NULL));
+
+ result = try_detect (handle, pfm_detect);
+ if (result == IO_ERROR)
+ return NULL;
+ else if (result == YES)
+ return make_any_reader (PORTABLE_FILE,
+ pfm_open_reader (handle, dict, NULL));
+
+ msg (SE, _("\"%s\" is not a system or portable file."),
+ fh_get_filename (handle));
+ return NULL;
+ }
+
+ case FH_REF_INLINE:
+ msg (SE, _("The inline file is not allowed here."));
+ return NULL;
+
+ case FH_REF_SCRATCH:
+ return make_any_reader (SCRATCH_FILE,
+ scratch_reader_open (handle, dict));
+ }
+ abort ();
+}
+
+/* Reads a single case from READER into C.
+ Returns true if successful, false at end of file or on error. */
+bool
+any_reader_read (struct any_reader *reader, struct ccase *c)
+{
+ switch (reader->type)
+ {
+ case SYSTEM_FILE:
+ return sfm_read_case (reader->private, c);
+
+ case PORTABLE_FILE:
+ return pfm_read_case (reader->private, c);
+
+ case SCRATCH_FILE:
+ return scratch_reader_read_case (reader->private, c);
+ }
+ abort ();
+}
+
+/* Closes READER. */
+void
+any_reader_close (struct any_reader *reader)
+{
+ if (reader == NULL)
+ return;
+
+ switch (reader->type)
+ {
+ case SYSTEM_FILE:
+ sfm_close_reader (reader->private);
+ break;
+
+ case PORTABLE_FILE:
+ pfm_close_reader (reader->private);
+ break;
+
+ case SCRATCH_FILE:
+ scratch_reader_close (reader->private);
+ break;
+
+ default:
+ abort ();
+ }
+}
--- /dev/null
+/* PSPP - computes sample statistics.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+ Written by Ben Pfaff <blp@gnu.org>.
+
+ 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. */
+
+#ifndef ANY_READER_H
+#define ANY_READER_H 1
+
+#include <stdbool.h>
+
+struct file_handle;
+struct dictionary;
+struct ccase;
+struct any_reader *any_reader_open (struct file_handle *,
+ struct dictionary **);
+bool any_reader_read (struct any_reader *, struct ccase *);
+void any_reader_close (struct any_reader *);
+
+#endif /* any-reader.h */
--- /dev/null
+/* PSPP - computes sample statistics.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+ Written by Ben Pfaff <blp@gnu.org>.
+
+ 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 <config.h>
+#include "any-writer.h"
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "error.h"
+#include "file-handle-def.h"
+#include "filename.h"
+#include "pfm-write.h"
+#include "sfm-write.h"
+#include "str.h"
+#include "scratch-writer.h"
+#include "xalloc.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+/* Type of file backing an any_writer. */
+enum any_writer_type
+ {
+ SYSTEM_FILE, /* System file. */
+ PORTABLE_FILE, /* Portable file. */
+ SCRATCH_FILE /* Scratch file. */
+ };
+
+/* Writer for any type of case-structured file. */
+struct any_writer
+ {
+ enum any_writer_type type; /* Type of file. */
+ void *private; /* Private data. */
+ };
+
+/* Creates and returns a writer for HANDLE with the given DICT. */
+struct any_writer *
+any_writer_open (struct file_handle *handle, struct dictionary *dict)
+{
+ switch (fh_get_referent (handle))
+ {
+ case FH_REF_FILE:
+ {
+ struct any_writer *writer;
+ char *extension;
+
+ extension = fn_extension (fh_get_filename (handle));
+ str_lowercase (extension);
+
+ if (!strcmp (extension, ".por"))
+ writer = any_writer_from_pfm_writer (
+ pfm_open_writer (handle, dict, pfm_writer_default_options ()));
+ else
+ writer = any_writer_from_sfm_writer (
+ sfm_open_writer (handle, dict, sfm_writer_default_options ()));
+ free (extension);
+
+ return writer;
+ }
+
+ case FH_REF_INLINE:
+ msg (ME, _("The inline file is not allowed here."));
+ return NULL;
+
+ case FH_REF_SCRATCH:
+ return any_writer_from_scratch_writer (scratch_writer_open (handle,
+ dict));
+ }
+
+ abort ();
+}
+
+/* If PRIVATE is non-null, creates and returns a new any_writer,
+ initializing its fields to TYPE and PRIVATE. If PRIVATE is a
+ null pointer, just returns a null pointer. */
+static struct any_writer *
+make_any_writer (enum any_writer_type type, void *private)
+{
+ if (private != NULL)
+ {
+ struct any_writer *writer = xmalloc (sizeof *writer);
+ writer->type = type;
+ writer->private = private;
+ return writer;
+ }
+ else
+ return NULL;
+}
+
+/* If SFM_WRITER is non-null, encapsulates SFM_WRITER in an
+ any_writer and returns it. If SFM_WRITER is null, just
+ returns a null pointer.
+
+ Useful when you need to pass options to sfm_open_writer().
+ Typical usage:
+ any_writer_from_sfm_writer (sfm_open_writer (fh, dict, opts))
+ If you don't need to pass options, then any_writer_open() by
+ itself is easier and more straightforward. */
+struct any_writer *
+any_writer_from_sfm_writer (struct sfm_writer *sfm_writer)
+{
+ return make_any_writer (SYSTEM_FILE, sfm_writer);
+}
+
+/* If PFM_WRITER is non-null, encapsulates PFM_WRITER in an
+ any_writer and returns it. If PFM_WRITER is null, just
+ returns a null pointer.
+
+ Useful when you need to pass options to pfm_open_writer().
+ Typical usage:
+ any_writer_from_pfm_writer (pfm_open_writer (fh, dict, opts))
+ If you don't need to pass options, then any_writer_open() by
+ itself is easier and more straightforward. */
+struct any_writer *
+any_writer_from_pfm_writer (struct pfm_writer *pfm_writer)
+{
+ return make_any_writer (PORTABLE_FILE, pfm_writer);
+}
+
+/* If SCRATCH_WRITER is non-null, encapsulates SCRATCH_WRITER in
+ an any_writer and returns it. If SCRATCH_WRITER is null, just
+ returns a null pointer.
+
+ Not particularly useful. Included just for consistency. */
+struct any_writer *
+any_writer_from_scratch_writer (struct scratch_writer *scratch_writer)
+{
+ return make_any_writer (SCRATCH_FILE, scratch_writer);
+}
+
+/* Writes cases C to WRITER.
+ Returns true if successful, false on failure. */
+bool
+any_writer_write (struct any_writer *writer, const struct ccase *c)
+{
+ switch (writer->type)
+ {
+ case SYSTEM_FILE:
+ return sfm_write_case (writer->private, c);
+
+ case PORTABLE_FILE:
+ return pfm_write_case (writer->private, c);
+
+ case SCRATCH_FILE:
+ scratch_writer_write_case (writer->private, c);
+ return true;
+ }
+ abort ();
+}
+
+/* Closes WRITER. */
+void
+any_writer_close (struct any_writer *writer)
+{
+ if (writer == NULL)
+ return;
+
+ switch (writer->type)
+ {
+ case SYSTEM_FILE:
+ sfm_close_writer (writer->private);
+ break;
+
+ case PORTABLE_FILE:
+ pfm_close_writer (writer->private);
+ break;
+
+ case SCRATCH_FILE:
+ scratch_writer_close (writer->private);
+ break;
+
+ default:
+ abort ();
+ }
+}
--- /dev/null
+/* PSPP - computes sample statistics.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+ Written by Ben Pfaff <blp@gnu.org>.
+
+ 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. */
+
+#ifndef ANY_WRITER_H
+#define ANY_WRITER_H 1
+
+#include <stdbool.h>
+
+struct file_handle;
+struct dictionary;
+struct ccase;
+struct sfm_writer;
+struct pfm_writer;
+struct scratch_writer;
+
+struct any_writer *any_writer_open (struct file_handle *, struct dictionary *);
+struct any_writer *any_writer_from_sfm_writer (struct sfm_writer *);
+struct any_writer *any_writer_from_pfm_writer (struct pfm_writer *);
+struct any_writer *any_writer_from_scratch_writer (struct scratch_writer *);
+
+bool any_writer_write (struct any_writer *, const struct ccase *);
+void any_writer_close (struct any_writer *);
+
+#endif /* any-writer.h */
#include <config.h>
#include <stdlib.h>
+#include "any-reader.h"
#include "command.h"
#include "dictionary.h"
#include "error.h"
#include "file-handle.h"
#include "hash.h"
#include "lexer.h"
-#include "sfm-read.h"
#include "str.h"
#include "value-labels.h"
#include "var.h"
cmd_apply_dictionary (void)
{
struct file_handle *handle;
- struct sfm_reader *reader;
+ struct any_reader *reader;
struct dictionary *dict;
int n_matched = 0;
lex_match_id ("FROM");
lex_match ('=');
- handle = fh_parse ();
+ handle = fh_parse (FH_REF_FILE | FH_REF_SCRATCH);
if (!handle)
return CMD_FAILURE;
- reader = sfm_open_reader (handle, &dict, NULL);
+ reader = any_reader_open (handle, &dict);
if (dict == NULL)
return CMD_FAILURE;
- sfm_close_reader (reader);
+ any_reader_close (reader);
for (i = 0; i < dict_get_var_cnt (dict); i++)
{
dict_set_weight (default_dict, new_weight);
}
- sfm_close_reader (reader);
+ any_reader_close (reader);
return lex_end_of_command ();
}
values stored.
*/
};
+
#endif
UNIMPL ("CASESTOVARS", ERRO, ERRO, ERRO, ERRO, "Restructure complex data")
UNIMPL ("CCF", ERRO, ERRO, ERRO, ERRO, "Time series cross correlation")
DEFCMD ("CLEAR TRANSFORMATIONS", ERRO, INPU, TRAN, TRAN, cmd_clear_transformations)
+DEFCMD ("CLOSE FILE HANDLE", INIT, INPU, TRAN, PROC, cmd_close_file_handle)
UNIMPL ("CLUSTER", ERRO, ERRO, ERRO, ERRO, "Hierachial clustering")
DEFCMD ("COMPUTE", ERRO, INPU, TRAN, TRAN, cmd_compute)
UNIMPL ("CONJOINT", ERRO, ERRO, ERRO, ERRO, "Analyse full concept data")
matrix_file = NULL;
else
{
- matrix_file = fh_parse ();
+ matrix_file = fh_parse (FH_REF_FILE);
if (matrix_file == NULL)
return 0;
}
/* PSPP - computes sample statistics.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
Written by Ben Pfaff <blp@gnu.org>.
This program is free software; you can redistribute it and/or
size_t delim_cnt; /* Number of delimiter, or 0 for spaces. */
};
+static const struct case_source_class data_list_source_class;
+
static int parse_fixed (struct data_list_pgm *);
static int parse_free (struct dls_var_spec **, struct dls_var_spec **);
static void dump_fixed_table (const struct dls_var_spec *,
int
cmd_data_list (void)
{
- struct data_list_pgm *dls; /* DATA LIST program under construction. */
+ struct data_list_pgm *dls;
int table = -1; /* Print table if nonzero, -1=undecided. */
- struct file_handle *fh = NULL; /* File handle of source, NULL=inline file. */
+ struct file_handle *fh = fh_inline_file ();
if (!case_source_is_complex (vfm_source))
discard_variables ();
if (lex_match_id ("FILE"))
{
lex_match ('=');
- fh = fh_parse ();
+ fh = fh_parse (FH_REF_FILE | FH_REF_INLINE);
if (fh == NULL)
goto error;
if (case_source_is_class (vfm_source, &file_type_source_class)
- && fh != default_handle)
+ && fh != fh_get_default_handle ())
{
- msg (SE, _("DATA LIST may not use a different file from "
- "that specified on its surrounding FILE TYPE."));
+ msg (SE, _("DATA LIST must use the same file "
+ "as the enclosing FILE TYPE."));
goto error;
}
}
}
dls->case_size = dict_get_case_size (default_dict);
- default_handle = fh;
+ fh_set_default_handle (fh);
if (dls->type == -1)
dls->type = DLS_FIXED;
fmt_to_string (&spec->input));
}
- if (fh != NULL)
- tab_title (t, 1, ngettext ("Reading %d record from file %s.",
- "Reading %d records from file %s.", rec_cnt),
- rec_cnt, fh_get_filename (fh));
- else
- tab_title (t, 1, ngettext ("Reading %d record from the command file.",
- "Reading %d records from the command file.",
- rec_cnt),
- rec_cnt);
+ tab_title (t, 1, ngettext ("Reading %d record from %s.",
+ "Reading %d records from %s.", rec_cnt),
+ rec_cnt, fh_get_name (fh));
tab_submit (t);
}
\f
}
}
- if (fh != NULL)
- tab_title (t, 1, _("Reading free-form data from file %s."),
- fh_get_filename (fh));
- else
- tab_title (t, 1, _("Reading free-form data from the command file."));
+ tab_title (t, 1, _("Reading free-form data from %s."), fh_get_name (fh));
tab_submit (t);
}
data_list_trns_free (source->aux);
}
-const struct case_source_class data_list_source_class =
+static const struct case_source_class data_list_source_class =
{
"DATA LIST",
NULL,
bool saw_length = false; /* Saw LENGTH subcommand? */
bool saw_continued = false; /* Saw CONTINUED subcommand? */
bool saw_id = false; /* Saw ID subcommand? */
- struct file_handle *const fh = default_handle;
+ struct file_handle *const fh = fh_get_default_handle ();
assert (case_source_is_complex (vfm_source));
rpd = xmalloc (sizeof *rpd);
- rpd->reader = dfm_open_reader (default_handle);
+ rpd->reader = dfm_open_reader (fh);
rpd->first = rpd->last = NULL;
rpd->starts_beg.num = 0;
rpd->starts_beg.var = NULL;
{
struct file_handle *file;
lex_match ('=');
- file = fh_parse ();
+ file = fh_parse (FH_REF_FILE | FH_REF_INLINE);
if (file == NULL)
goto error;
if (file != fh)
/* Calculate and check starts_end, cont_end if necessary. */
if (rpd->starts_end.num == 0 && rpd->starts_end.var == NULL)
{
- rpd->starts_end.num = fh != NULL ? fh_get_record_width (fh) : 80;
+ rpd->starts_end.num = fh_get_record_width (fh);
if (rpd->starts_beg.num != 0
&& rpd->starts_beg.num > rpd->starts_end.num)
{
}
if (rpd->cont_end.num == 0 && rpd->cont_end.var == NULL)
{
- rpd->cont_end.num = fh != NULL ? fh_get_record_width (fh) : 80;
+ rpd->cont_end.num = fh_get_record_width (fh);
if (rpd->cont_beg.num != 0
&& rpd->cont_beg.num > rpd->cont_end.num)
{
/* PSPP - computes sample statistics.
- Copyright (C) 1997-2004 Free Software Foundation, Inc.
+ Copyright (C) 1997-2004, 2006 Free Software Foundation, Inc.
Written by Ben Pfaff <blp@gnu.org>.
This program is free software; you can redistribute it and/or
struct dfm_reader
{
struct file_handle *fh; /* File handle. */
- struct file_ext file; /* Associated file. */
struct file_locator where; /* Current location in data file. */
struct string line; /* Current line. */
- size_t pos; /* Offset in line of current character. */
struct string scratch; /* Extra line buffer. */
enum dfm_reader_flags flags; /* Zero or more of DFM_*. */
+ struct file_ext file; /* Associated file. */
+ size_t pos; /* Offset in line of current character. */
};
-static int inline_open_cnt;
-static struct dfm_reader *inline_file;
-
static void read_record (struct dfm_reader *r);
/* Closes reader R opened by dfm_open_reader(). */
dfm_close_reader (struct dfm_reader *r)
{
int still_open;
+ bool is_inline;
if (r == NULL)
return;
- if (r->fh != NULL)
- still_open = fh_close (r->fh, "data file", "rs");
- else
- {
- assert (inline_open_cnt > 0);
- still_open = --inline_open_cnt;
-
- if (!still_open)
- {
- /* Skip any remaining data on the inline file. */
- if (r->flags & DFM_SAW_BEGIN_DATA)
- while ((r->flags & DFM_EOF) == 0)
- read_record (r);
- inline_file = NULL;
- }
- }
+ is_inline = r->fh == fh_inline_file ();
+ still_open = fh_close (r->fh, "data file", "rs");
if (still_open)
return;
- if (r->fh != NULL && r->file.file)
+ if (!is_inline)
{
fn_close_ext (&r->file);
free (r->file.filename);
r->file.filename = NULL;
}
+ else
+ {
+ /* Skip any remaining data on the inline file. */
+ if (r->flags & DFM_SAW_BEGIN_DATA)
+ while ((r->flags & DFM_EOF) == 0)
+ read_record (r);
+ }
+
ds_destroy (&r->line);
ds_destroy (&r->scratch);
free (r);
}
/* Opens the file designated by file handle FH for reading as a
- data file. Providing a null pointer for FH designates the
+ data file. Providing fh_inline_file() for FH designates the
"inline file", that is, data included inline in the command
- file between BEGIN FILE and END FILE. Returns nonzero only if
- successful. */
+ file between BEGIN FILE and END FILE. Returns a reader if
+ successful, or a null pointer otherwise. */
struct dfm_reader *
dfm_open_reader (struct file_handle *fh)
{
struct dfm_reader *r;
void **rp;
- if (fh != NULL)
- {
- rp = fh_open (fh, "data file", "rs");
- if (rp == NULL)
- return NULL;
- if (*rp != NULL)
- return *rp;
- }
- else
- {
- assert (inline_open_cnt >= 0);
- if (inline_open_cnt++ > 0)
- return inline_file;
- rp = NULL;
- }
+ rp = fh_open (fh, FH_REF_FILE | FH_REF_INLINE, "data file", "rs");
+ if (rp == NULL)
+ return NULL;
+ if (*rp != NULL)
+ return *rp;
r = xmalloc (sizeof *r);
r->fh = fh;
- if (fh != NULL)
- {
- r->where.filename = fh_get_filename (fh);
- r->where.line_number = 0;
- }
- r->file.file = NULL;
ds_init (&r->line, 64);
ds_init (&r->scratch, 0);
r->flags = DFM_ADVANCE;
-
- if (fh != NULL)
+ if (fh != fh_inline_file ())
{
+ r->where.filename = fh_get_filename (fh);
+ r->where.line_number = 0;
+ r->file.file = NULL;
r->file.filename = xstrdup (fh_get_filename (r->fh));
r->file.mode = "rb";
r->file.file = NULL;
r->file.postopen = NULL;
r->file.preclose = NULL;
if (!fn_open_ext (&r->file))
- {
- msg (ME, _("Could not open \"%s\" for reading "
- "as a data file: %s."),
+ {
+ msg (ME, _("Could not open \"%s\" for reading as a data file: %s."),
fh_get_filename (r->fh), strerror (errno));
err_cond_fail ();
fh_close (fh,"data file", "rs");
free (r);
return NULL;
- }
- *rp = r;
+ }
}
- else
- inline_file = r;
+ *rp = r;
return r;
}
-static int
+/* Reads a record from the inline file into R.
+ Returns true if successful, false on failure. */
+static bool
read_inline_record (struct dfm_reader *r)
{
if ((r->flags & DFM_SAW_BEGIN_DATA) == 0)
{
msg (SE, _("BEGIN DATA expected."));
lex_preprocess_line ();
- return 0;
+ return false;
}
getl_prompt = GETL_PRPT_DATA;
}
err_failure ();
}
- if (r->fh != NULL)
- r->where.line_number++;
-
if (ds_length (&getl_buf) >= 8
&& !strncasecmp (ds_c_str (&getl_buf), "end data", 8))
{
lex_set_prog (ds_c_str (&getl_buf) + ds_length (&getl_buf));
- return 0;
+ return false;
}
ds_replace (&r->line, ds_c_str (&getl_buf));
- return 1;
+ return true;
}
-static int
+/* Reads a record from a disk file into R.
+ Returns true if successful, false on failure. */
+static bool
read_file_record (struct dfm_reader *r)
{
- assert (r->fh != NULL);
- if (fh_get_mode (r->fh) == MODE_TEXT)
+ assert (r->fh != fh_inline_file ());
+ if (fh_get_mode (r->fh) == FH_MODE_TEXT)
{
ds_clear (&r->line);
if (!ds_gets (&r->line, r->file.file))
fh_get_name (r->fh), strerror (errno));
err_cond_fail ();
}
- return 0;
+ return false;
}
}
- else if (fh_get_mode (r->fh) == MODE_BINARY)
+ else if (fh_get_mode (r->fh) == FH_MODE_BINARY)
{
size_t record_width = fh_get_record_width (r->fh);
size_t amt;
msg (ME, _("%s: Partial record at end of file."),
fh_get_name (r->fh));
else
- return 0;
+ return false;
err_cond_fail ();
- return 0;
+ return false;
}
}
else
r->where.line_number++;
- return 1;
+ return true;
}
/* Reads a record from R, setting the current position to the
static void
read_record (struct dfm_reader *r)
{
- int success = r->fh != NULL ? read_file_record (r) : read_inline_record (r);
+ bool success;
+
+ if (fh_get_referent (r->fh) == FH_REF_FILE)
+ success = read_file_record (r);
+ else
+ success = read_inline_record (r);
+
if (success)
r->pos = 0;
else
read_record (r);
else
{
- if (r->fh != NULL)
+ if (r->fh != fh_inline_file ())
msg (SE, _("Attempt to read beyond end-of-file on file %s."),
fh_get_name (r->fh));
else
return;
r->flags |= DFM_TABS_EXPANDED;
- if (r->fh != NULL
- && (fh_get_mode (r->fh) == MODE_BINARY
+ if (r->fh != fh_inline_file ()
+ && (fh_get_mode (r->fh) == FH_MODE_BINARY
|| fh_get_tab_width (r->fh) == 0
|| memchr (ds_c_str (&r->line), '\t', ds_length (&r->line)) == NULL))
return;
/* Expand tabs from r->line into r->scratch, and figure out
new value for r->pos. */
- tab_width = r->fh != NULL ? fh_get_tab_width (r->fh) : 8;
+ tab_width = fh_get_tab_width (r->fh);
ds_clear (&r->scratch);
new_pos = 0;
for (ofs = 0; ofs < ds_length (&r->line); ofs++)
void
dfm_push (struct dfm_reader *r)
{
- if (r->fh != NULL)
+ if (r->fh != fh_inline_file ())
err_push_file_locator (&r->where);
}
void
dfm_pop (struct dfm_reader *r)
{
- if (r->fh != NULL)
+ if (r->fh != fh_inline_file ())
err_pop_file_locator (&r->where);
}
\f
{
struct dfm_reader *r;
- /* FIXME: figure out the *exact* conditions, not these really
- lenient conditions. */
- if (vfm_source == NULL
- || case_source_is_class (vfm_source, &storage_source_class))
+ if (!fh_is_open (fh_inline_file ()))
{
msg (SE, _("This command is not valid here since the current "
"input program does not access the inline file."));
}
/* Open inline file. */
- r = dfm_open_reader (NULL);
+ r = dfm_open_reader (fh_inline_file ());
r->flags |= DFM_SAW_BEGIN_DATA;
/* Input procedure reads from inline file. */
struct dfm_writer *w;
void **aux;
- aux = fh_open (fh, "data file", "ws");
+ aux = fh_open (fh, FH_REF_FILE, "data file", "ws");
if (aux == NULL)
return NULL;
if (*aux != NULL)
{
assert (w != NULL);
- if (fh_get_mode (w->fh) == MODE_BINARY
+ if (fh_get_mode (w->fh) == FH_MODE_BINARY
&& len < fh_get_record_width (w->fh))
{
size_t rec_width = fh_get_record_width (w->fh);
/* PSPP - computes sample statistics.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
Written by Ben Pfaff <blp@gnu.org>.
This program is free software; you can redistribute it and/or
#include "alloc.h"
#include "case.h"
#include "cat.h"
+#include "cat-routines.h"
#include "error.h"
#include "hash.h"
#include "misc.h"
return v;
}
-/* Returns nonzero if variable V is in dictionary D. */
-int
+/* Returns true if variable V is in dictionary D,
+ false otherwise. */
+bool
dict_contains_var (const struct dictionary *d, const struct variable *v)
{
assert (d != NULL);
/* Renames COUNT variables specified in VARS to the names given
in NEW_NAMES within dictionary D. If the renaming would
- result in a duplicate variable name, returns zero and stores a
+ result in a duplicate variable name, returns false and stores a
name that would be duplicated into *ERR_NAME (if ERR_NAME is
- non-null). Otherwise, the renaming is successful, and nonzero
+ non-null). Otherwise, the renaming is successful, and true
is returned. */
-int
+bool
dict_rename_vars (struct dictionary *d,
struct variable **vars, char **new_names,
size_t count, char **err_name)
{
char **old_names;
size_t i;
- int success = 1;
+ bool success = true;
assert (d != NULL);
assert (count == 0 || vars != NULL);
hsh_force_insert (d->name_tab, vars[i]);
}
- success = 0;
+ success = false;
goto done;
}
}
}
}
-/* Copies values from SRC, which represents a case arranged
- according to dictionary D, to DST, which represents a case
- arranged according to the dictionary that will be produced by
- dict_compact_values(D). */
-void
-dict_compact_case (const struct dictionary *d,
- struct ccase *dst, const struct ccase *src)
-{
- size_t i;
- size_t value_idx;
-
- value_idx = 0;
- for (i = 0; i < d->var_cnt; i++)
- {
- struct variable *v = d->var[i];
-
- if (dict_class_from_id (v->name) != DC_SCRATCH)
- {
- case_copy (dst, value_idx, src, v->fv, v->nv);
- value_idx += v->nv;
- }
- }
-}
-
/* Returns the number of values that would be used by a case if
dict_compact_values() were called. */
size_t
return idx_to_fv;
}
+/* Returns true if a case for dictionary D would be smaller after
+ compaction, false otherwise. Compacting a case eliminates
+ "holes" between values and after the last value. Holes are
+ created by deleting variables (or by scratch variables).
+
+ The return value may differ from whether compacting a case
+ from dictionary D would *change* the case: compaction could
+ rearrange values even if it didn't reduce space
+ requirements. */
+bool
+dict_needs_compaction (const struct dictionary *d)
+{
+ return dict_get_compacted_value_cnt (d) < dict_get_next_value_idx (d);
+}
+\f
+/* How to copy a contiguous range of values between cases. */
+struct copy_map
+ {
+ size_t src_idx; /* Starting value index in source case. */
+ size_t dst_idx; /* Starting value index in target case. */
+ size_t cnt; /* Number of values. */
+ };
+
+/* How to compact a case. */
+struct dict_compactor
+ {
+ struct copy_map *maps; /* Array of mappings. */
+ size_t map_cnt; /* Number of mappings. */
+ };
+
+/* Creates and returns a dict_compactor that can be used to
+ compact cases for dictionary D.
+
+ Compacting a case eliminates "holes" between values and after
+ the last value. Holes are created by deleting variables (or
+ by scratch variables). */
+struct dict_compactor *
+dict_make_compactor (const struct dictionary *d)
+{
+ struct dict_compactor *compactor;
+ struct copy_map *map;
+ size_t map_allocated;
+ size_t value_idx;
+ size_t i;
+
+ compactor = xmalloc (sizeof *compactor);
+ compactor->maps = NULL;
+ compactor->map_cnt = 0;
+ map_allocated = 0;
+
+ value_idx = 0;
+ map = NULL;
+ for (i = 0; i < d->var_cnt; i++)
+ {
+ struct variable *v = d->var[i];
+
+ if (dict_class_from_id (v->name) == DC_SCRATCH)
+ continue;
+ if (map != NULL && map->src_idx + map->cnt == v->fv)
+ map->cnt += v->nv;
+ else
+ {
+ if (compactor->map_cnt == map_allocated)
+ compactor->maps = x2nrealloc (compactor->maps, &map_allocated,
+ sizeof *compactor->maps);
+ map = &compactor->maps[compactor->map_cnt++];
+ map->src_idx = v->fv;
+ map->dst_idx = value_idx;
+ map->cnt = v->nv;
+ }
+ value_idx += v->nv;
+ }
+
+ return compactor;
+}
+
+/* Compacts SRC by copying it to DST according to the scheme in
+ COMPACTOR.
+
+ Compacting a case eliminates "holes" between values and after
+ the last value. Holes are created by deleting variables (or
+ by scratch variables). */
+void
+dict_compactor_compact (const struct dict_compactor *compactor,
+ struct ccase *dst, const struct ccase *src)
+{
+ size_t i;
+
+ for (i = 0; i < compactor->map_cnt; i++)
+ {
+ const struct copy_map *map = &compactor->maps[i];
+ case_copy (dst, map->dst_idx, src, map->src_idx, map->cnt);
+ }
+}
+
+/* Destroys COMPACTOR. */
+void
+dict_compactor_destroy (struct dict_compactor *compactor)
+{
+ if (compactor != NULL)
+ {
+ free (compactor->maps);
+ free (compactor);
+ }
+}
+
/* Returns the SPLIT FILE vars (see cmd_split_file()). Call
dict_get_split_cnt() to determine how many SPLIT FILE vars
there are. Returns a null pointer if and only if there are no
}
/* Creates in D a vector named NAME that contains CNT variables
- VAR (see cmd_vector()). Returns nonzero if successful, or
- zero if a vector named NAME already exists in D. */
-int
+ VAR (see cmd_vector()). Returns true if successful, or
+ false if a vector named NAME already exists in D. */
+bool
dict_create_vector (struct dictionary *d,
const char *name,
struct variable **var, size_t cnt)
assert (cnt > 0);
if (dict_lookup_vector (d, name) != NULL)
- return 0;
+ return false;
d->vector = xnrealloc (d->vector, d->vector_cnt + 1, sizeof *d->vector);
vector = d->vector[d->vector_cnt] = xmalloc (sizeof *vector);
}
vector->cnt = cnt;
- return 1;
+ return true;
}
/* Returns the vector in D with index IDX, which must be less
#ifndef DICTIONARY_H
#define DICTIONARY_H
+#include <stdbool.h>
#include <stddef.h>
/* Dictionary. */
struct variable *dict_lookup_var (const struct dictionary *, const char *);
struct variable *dict_lookup_var_assert (const struct dictionary *,
const char *);
-int dict_contains_var (const struct dictionary *, const struct variable *);
+bool dict_contains_var (const struct dictionary *, const struct variable *);
void dict_delete_var (struct dictionary *, struct variable *);
void dict_delete_vars (struct dictionary *,
struct variable *const *, size_t count);
void dict_reorder_vars (struct dictionary *,
struct variable *const *, size_t count);
void dict_rename_var (struct dictionary *, struct variable *, const char *);
-int dict_rename_vars (struct dictionary *,
- struct variable **, char **new_names,
- size_t count, char **err_name);
+bool dict_rename_vars (struct dictionary *,
+ struct variable **, char **new_names,
+ size_t count, char **err_name);
struct ccase;
struct variable *dict_get_weight (const struct dictionary *);
size_t dict_get_case_size (const struct dictionary *);
void dict_compact_values (struct dictionary *);
-void dict_compact_case (const struct dictionary *,
- struct ccase *, const struct ccase *);
size_t dict_get_compacted_value_cnt (const struct dictionary *);
int *dict_get_compacted_idx_to_fv (const struct dictionary *);
+bool dict_needs_compaction (const struct dictionary *);
+
+struct dict_compactor *dict_make_compactor (const struct dictionary *);
+void dict_compactor_compact (const struct dict_compactor *,
+ struct ccase *, const struct ccase *);
+void dict_compactor_destroy (struct dict_compactor *);
struct variable *const *dict_get_split_vars (const struct dictionary *);
size_t dict_get_split_cnt (const struct dictionary *);
const char *dict_get_documents (const struct dictionary *);
void dict_set_documents (struct dictionary *, const char *);
-int dict_create_vector (struct dictionary *,
- const char *name,
- struct variable **, size_t cnt);
+bool dict_create_vector (struct dictionary *,
+ const char *name,
+ struct variable **, size_t cnt);
const struct vector *dict_get_vector (const struct dictionary *,
size_t idx);
size_t dict_get_vector_cnt (const struct dictionary *);
#include "main.h"
#include "output.h"
#include "progname.h"
+#include "readln.h"
#include "settings.h"
#include "str.h"
#include "var.h"
/* PSPP - computes sample statistics.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
Written by Ben Pfaff <blp@gnu.org>.
This program is free software; you can redistribute it and/or
02110-1301, USA. */
#include <config.h>
-#include "file-handle.h"
#include "file-handle-def.h"
#include "error.h"
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "alloc.h"
+#include "file-handle.h"
#include "filename.h"
#include "command.h"
#include "getl.h"
#include "error.h"
#include "magic.h"
#include "var.h"
-#include "file-handle-def.h"
+#include "scratch-handle.h"
#include "gettext.h"
-
#define _(msgid) gettext (msgid)
/* (headers) */
struct file_handle
{
struct file_handle *next; /* Next in global list. */
+ int open_cnt; /* 0=not open, otherwise # of openers. */
+ bool deleted; /* Destroy handle when open_cnt goes to 0? */
+
char *name; /* File handle identifier. */
+ const char *type; /* If open, type of file. */
+ char open_mode[3]; /* "[rw][se]". */
+ void *aux; /* Aux data pointer for owner if any. */
+ enum fh_referent referent; /* What the file handle refers to. */
+
+ /* FH_REF_FILE only. */
char *filename; /* Filename as provided by user. */
struct file_identity *identity; /* For checking file identity. */
- struct file_locator where; /* Used for reporting error messages. */
enum fh_mode mode; /* File mode. */
+
+ /* FH_REF_FILE and FH_REF_INLINE only. */
size_t record_width; /* Length of fixed-format records. */
size_t tab_width; /* Tab width, 0=do not expand tabs. */
- int open_cnt; /* 0=not open, otherwise # of openers. */
- const char *type; /* If open, type of file. */
- char open_mode[3]; /* "[rw][se]". */
- void *aux; /* Aux data pointer for owner if any. */
+ /* FH_REF_SCRATCH only. */
+ struct scratch_handle *sh; /* Scratch file data. */
};
+/* List of all handles. */
static struct file_handle *file_handles;
+/* Default file handle for DATA LIST, REREAD, REPEATING DATA
+ commands. */
+static struct file_handle *default_handle;
+
+/* The "file" that reads from BEGIN DATA...END DATA. */
+static struct file_handle *inline_file;
+
+static struct file_handle *create_handle (const char *name, enum fh_referent);
+
/* File handle initialization routine. */
void
fh_init (void)
{
- /* Currently nothing to do. */
+ inline_file = create_handle ("INLINE", FH_REF_INLINE);
+ inline_file->record_width = 80;
+ inline_file->tab_width = 8;
}
-
-/* Destroy file handle.
- Normally needed only if a file_handle needs to be re-assigned.
- Otherwise, just let fh_done clean destroy the handle.
- */
-void
-fh_free(struct file_handle *fh)
+/* Free HANDLE and remove it from the global list. */
+static void
+free_handle (struct file_handle *handle)
{
- if ( !fh->name )
- return ;
-
- free (fh->name);
- fh->name = 0;
- free (fh->filename);
- fn_free_identity (fh->identity);
- free (fh);
-}
+ /* Remove handle from global list. */
+ if (file_handles == handle)
+ file_handles = handle->next;
+ else
+ {
+ struct file_handle *iter = file_handles;
+ while (iter->next != handle)
+ iter = iter->next;
+ iter->next = handle->next;
+ }
+ /* Free data. */
+ free (handle->name);
+ free (handle->filename);
+ fn_free_identity (handle->identity);
+ scratch_handle_destroy (handle->sh);
+ free (handle);
+}
/* Frees all the file handles. */
void
fh_done (void)
{
- struct file_handle *fh, *next;
-
- for (fh = file_handles; fh != NULL; fh = next)
- {
- next = fh->next;
- fh_free(fh);
- }
- file_handles = NULL;
+ while (file_handles != NULL)
+ free_handle (file_handles);
}
/* Returns the handle named HANDLE_NAME, or a null pointer if
struct file_handle *iter;
for (iter = file_handles; iter != NULL; iter = iter->next)
- if (!strcasecmp (handle_name, iter->name))
+ if (!iter->deleted && !strcasecmp (handle_name, iter->name))
return iter;
return NULL;
}
if (identity != NULL)
{
for (iter = file_handles; iter != NULL; iter = iter->next)
- if (iter->identity != NULL
+ if (!iter->deleted
+ && iter->referent == FH_REF_FILE
+ && iter->identity != NULL
&& !fn_compare_file_identities (identity, iter->identity))
{
fn_free_identity (identity);
/* Then check for a file with the same name. */
for (iter = file_handles; iter != NULL; iter = iter->next)
- if (!strcmp (filename, iter->filename))
+ if (!iter->deleted
+ && iter->referent == FH_REF_FILE && !strcmp (filename, iter->filename))
return iter;
return NULL;
}
-/* Creates and returns a new file handle with the given values
- and defaults for other values. Adds the created file handle
- to the global list. */
-struct file_handle *
-fh_create (const char *handle_name, const char *filename,
- const struct fh_properties *properties)
-{
- struct file_handle *handle;
-
- assert(filename);
- assert(handle_name);
+/* Creates a new handle with name HANDLE_NAME that refers to
+ REFERENT. Links the new handle into the global list. Returns
+ the new handle.
- /* Create and initialize file handle. */
- handle = xmalloc (sizeof *handle);
+ The new handle is not fully initialized. The caller is
+ responsible for completing its initialization. */
+static struct file_handle *
+create_handle (const char *handle_name, enum fh_referent referent)
+{
+ struct file_handle *handle = xzalloc (sizeof *handle);
handle->next = file_handles;
+ handle->open_cnt = 0;
+ handle->deleted = false;
handle->name = xstrdup (handle_name);
+ handle->type = NULL;
+ handle->aux = NULL;
+ handle->referent = referent;
+ file_handles = handle;
+ return handle;
+}
+
+/* Returns the unique handle of referent type FH_REF_INLINE,
+ which refers to the "inline file" that represents character
+ data in the command file between BEGIN DATA and END DATA. */
+struct file_handle *
+fh_inline_file (void)
+{
+ return inline_file;
+}
+
+/* Creates a new file handle named HANDLE_NAME, which must not be
+ the name of an existing file handle. The new handle is
+ associated with file FILENAME and the given PROPERTIES. */
+struct file_handle *
+fh_create_file (const char *handle_name, const char *filename,
+ const struct fh_properties *properties)
+{
+ struct file_handle *handle;
+ assert (fh_from_name (handle_name) == NULL);
+ handle = create_handle (handle_name, FH_REF_FILE);
handle->filename = xstrdup (filename);
handle->identity = fn_get_identity (filename);
- handle->where.filename = handle->filename;
- handle->where.line_number = 0;
handle->mode = properties->mode;
handle->record_width = properties->record_width;
handle->tab_width = properties->tab_width;
- handle->open_cnt = 0;
- handle->type = NULL;
- handle->aux = NULL;
- file_handles = handle;
+ return handle;
+}
+/* Creates a new file handle named HANDLE_NAME, which must not be
+ the name of an existing file handle. The new handle is
+ associated with a scratch file (initially empty). */
+struct file_handle *
+fh_create_scratch (const char *handle_name)
+{
+ struct file_handle *handle = create_handle (handle_name, FH_REF_SCRATCH);
+ handle->sh = NULL;
return handle;
}
const struct fh_properties *
fh_default_properties (void)
{
- static const struct fh_properties default_properties = {MODE_TEXT, 1024, 4};
+ static const struct fh_properties default_properties
+ = {FH_MODE_TEXT, 1024, 4};
return &default_properties;
}
+/* Deletes FH from the global list of file handles. Afterward,
+ attempts to search for it will fail. Unless the file handle
+ is currently open, it will be destroyed; otherwise, it will be
+ destroyed later when it is closed.
+ Normally needed only if a file_handle needs to be re-assigned.
+ Otherwise, just let fh_done() destroy the handle. */
+void
+fh_free (struct file_handle *handle)
+{
+ if (handle == fh_inline_file () || handle == NULL || handle->deleted)
+ return;
+ handle->deleted = true;
+
+ if (handle == default_handle)
+ default_handle = fh_inline_file ();
+
+ if (handle->open_cnt == 0)
+ free_handle (handle);
+}
+
/* Returns an English description of MODE,
which is in the format of the MODE argument to fh_open(). */
static const char *
/* Tries to open handle H with the given TYPE and MODE.
+ H's referent type must be one of the bits in MASK. The caller
+ must verify this ahead of time; we simply assert it here.
+
TYPE is the sort of file, e.g. "system file". Only one given
type of access is allowed on a given file handle at once.
If successful, a reference to TYPE is retained, so it should
modes the void * will necessarily be null only if no other
sharers are active. */
void **
-fh_open (struct file_handle *h, const char *type, const char *mode)
+fh_open (struct file_handle *h, enum fh_referent mask UNUSED,
+ const char *type, const char *mode)
{
assert (h != NULL);
+ assert ((fh_get_referent (h) & mask) != 0);
assert (type != NULL);
assert (mode != NULL);
assert (mode[0] == 'r' || mode[0] == 'w');
if (strcmp (h->type, type))
{
msg (SE, _("Can't open %s as a %s because it is "
- "already open as a %s"),
+ "already open as a %s."),
fh_get_name (h), type, h->type);
return NULL;
}
else if (strcmp (h->open_mode, mode))
{
msg (SE, _("Can't open %s as a %s for %s because it is "
- "already open for %s"),
+ "already open for %s."),
fh_get_name (h), type, mode_name (mode),
mode_name (h->open_mode));
return NULL;
}
else if (h->open_mode[1] == 'e')
{
- msg (SE, _("Can't re-open %s as a %s for %s"),
+ msg (SE, _("Can't re-open %s as a %s for %s."),
fh_get_name (h), type, mode_name (mode));
return NULL;
}
/* Closes file handle H, which must have been open for the
specified TYPE and MODE of access provided to fh_open().
Returns zero if the file is now closed, nonzero if it is still
- open due to another reference. */
+ open due to another reference.
+
+ After fh_close() returns zero for a handle, it is unsafe to
+ reference that file handle again in any way, because its
+ storage may have been freed. */
int
fh_close (struct file_handle *h, const char *type, const char *mode)
{
assert (mode != NULL);
assert (!strcmp (mode, h->open_mode));
- h->open_cnt--;
- if (h->open_cnt == 0)
+ if (--h->open_cnt == 0)
{
h->type = NULL;
h->aux = NULL;
+ if (h->deleted)
+ free_handle (h);
+ return 0;
}
- return h->open_cnt;
+ return 1;
+}
+
+/* Is the file open? BEGIN DATA...END DATA uses this to detect
+ whether the inline file is actually in use. */
+bool
+fh_is_open (const struct file_handle *handle)
+{
+ return handle->open_cnt > 0;
}
/* Returns the identifier of file HANDLE. If HANDLE was created
const char *
fh_get_name (const struct file_handle *handle)
{
- assert (handle != NULL);
return handle->name;
}
+/* Returns the type of object that HANDLE refers to. */
+enum fh_referent
+fh_get_referent (const struct file_handle *handle)
+{
+ return handle->referent;
+}
+
/* Returns the name of the file associated with HANDLE. */
const char *
fh_get_filename (const struct file_handle *handle)
{
- assert (handle != NULL);
+ assert (handle->referent == FH_REF_FILE);
return handle->filename;
}
enum fh_mode
fh_get_mode (const struct file_handle *handle)
{
- assert (handle != NULL);
+ assert (handle->referent == FH_REF_FILE);
return handle->mode;
}
size_t
fh_get_record_width (const struct file_handle *handle)
{
- assert (handle != NULL);
+ assert (handle->referent & (FH_REF_FILE | FH_REF_INLINE));
return handle->record_width;
}
/* Returns the number of characters per tab stop for HANDLE, or
zero if tabs are not to be expanded. Applicable only to
- MODE_TEXT files. */
+ FH_MODE_TEXT files. */
size_t
fh_get_tab_width (const struct file_handle *handle)
{
- assert (handle != NULL);
+ assert (handle->referent & (FH_REF_FILE | FH_REF_INLINE));
return handle->tab_width;
}
+
+/* Returns the scratch file handle associated with HANDLE.
+ Applicable to only FH_REF_SCRATCH files. */
+struct scratch_handle *
+fh_get_scratch_handle (struct file_handle *handle)
+{
+ assert (handle->referent == FH_REF_SCRATCH);
+ return handle->sh;
+}
+
+/* Sets SH to be the scratch file handle associated with HANDLE.
+ Applicable to only FH_REF_SCRATCH files. */
+void
+fh_set_scratch_handle (struct file_handle *handle, struct scratch_handle *sh)
+{
+ assert (handle->referent == FH_REF_SCRATCH);
+ handle->sh = sh;
+}
+
+/* Returns the current default handle. */
+struct file_handle *
+fh_get_default_handle (void)
+{
+ return default_handle ? default_handle : fh_inline_file ();
+}
+
+/* Sets NEW_DEFAULT_HANDLE as the default handle. */
+void
+fh_set_default_handle (struct file_handle *new_default_handle)
+{
+ assert (new_default_handle == NULL
+ || (new_default_handle->referent & (FH_REF_INLINE | FH_REF_FILE)));
+ default_handle = new_default_handle;
+}
/* PSPP - computes sample statistics.
- Copyright (C) 1997-9, 2000,2005 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2005, 2006 Free Software Foundation, Inc.
Written by Ben Pfaff <blp@gnu.org>.
This program is free software; you can redistribute it and/or
#ifndef FILE_HANDLE_DEF_H
#define FILE_HANDLE_DEF_H
-#include <config.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+/* What a file handle refers to.
+ (Ordinarily only a single value is allowed, but fh_open()
+ and fh_parse() take a mask.) */
+enum fh_referent
+ {
+ FH_REF_FILE = 001, /* Ordinary file (the most common case). */
+ FH_REF_INLINE = 002, /* The inline file. */
+ FH_REF_SCRATCH = 004 /* Temporary dataset. */
+ };
/* File modes. */
enum fh_mode
{
- MODE_TEXT, /* New-line delimited lines. */
- MODE_BINARY /* Fixed-length records. */
+ FH_MODE_TEXT, /* New-line delimited lines. */
+ FH_MODE_BINARY /* Fixed-length records. */
};
/* Properties of a file handle. */
void fh_done (void);
/* Creating file handles. */
-struct file_handle *fh_create (const char *handle_name,
- const char *filename,
- const struct fh_properties *);
-/* Destroy file handle */
-void fh_free(struct file_handle *);
-
+struct file_handle *fh_create_file (const char *handle_name,
+ const char *filename,
+ const struct fh_properties *);
+struct file_handle *fh_create_scratch (const char *handle_name);
const struct fh_properties *fh_default_properties (void);
-/* Finding file handles, based on handle name or filename. */
+/* Delete file handle from global list. */
+void fh_free (struct file_handle *);
+
+/* Finding file handles. */
struct file_handle *fh_from_name (const char *handle_name);
struct file_handle *fh_from_filename (const char *filename);
+struct file_handle *fh_inline_file (void);
-/* Querying properties of file handles. */
+/* Generic properties of file handles. */
const char *fh_get_name (const struct file_handle *);
+enum fh_referent fh_get_referent (const struct file_handle *);
+
+/* Properties of FH_REF_FILE file handles. */
const char *fh_get_filename (const struct file_handle *);
enum fh_mode fh_get_mode (const struct file_handle *) ;
+
+/* Properties of FH_REF_FILE and FH_REF_INLINE file handles. */
size_t fh_get_record_width (const struct file_handle *);
size_t fh_get_tab_width (const struct file_handle *);
+/* Properties of FH_REF_SCRATCH file handles. */
+struct scratch_handle *fh_get_scratch_handle (struct file_handle *);
+void fh_set_scratch_handle (struct file_handle *, struct scratch_handle *);
+
/* Opening and closing file handles. */
-void **fh_open (struct file_handle *, const char *type, const char *mode);
+void **fh_open (struct file_handle *, enum fh_referent mask,
+ const char *type, const char *mode);
int fh_close (struct file_handle *, const char *type, const char *mode);
+bool fh_is_open (const struct file_handle *);
+
+/* Default file handle for DATA LIST, REREAD, REPEATING DATA
+ commands. */
+struct file_handle *fh_get_default_handle (void);
+void fh_set_default_handle (struct file_handle *);
#endif
/* File handles. */
+#include <stdbool.h>
#include <stddef.h>
#include "file-handle-def.h"
-struct file_handle *fh_parse (void);
+struct file_handle *fh_parse (enum fh_referent);
#endif /* !file_handle.h */
/* PSPP - computes sample statistics.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
Written by Ben Pfaff <blp@gnu.org>.
This program is free software; you can redistribute it and/or
#include "getl.h"
#include "error.h"
#include "magic.h"
+#include "str.h"
#include "var.h"
#include "linked-list.h"
#include "file-handle-def.h"
name=string;
lrecl=integer;
tabwidth=integer "x>=0" "%s must be nonnegative";
- mode=mode:!character/image.
+ mode=mode:!character/image/scratch.
*/
/* (declarations) */
/* (functions) */
handle = fh_from_name (handle_name);
if (handle != NULL)
{
- msg (SE, _("File handle %s already refers to file %s. "
- "File handles cannot be redefined within a session."),
- handle_name, fh_get_filename(handle));
+ msg (SE, _("File handle %s is already defined. "
+ "Use CLOSE FILE HANDLE before redefining a file handle."),
+ handle_name);
return CMD_FAILURE;
}
if (!parse_file_handle (&cmd))
return CMD_FAILURE;
- if (token != '.')
- {
- lex_error (_("expecting end of command"));
- goto lossage;
- }
+ if (lex_end_of_command () != CMD_SUCCESS)
+ goto lossage;
- if (cmd.s_name == NULL)
+ if (cmd.s_name == NULL && cmd.mode != FH_SCRATCH)
{
- msg (SE, _("The FILE HANDLE required subcommand NAME "
- "is not present."));
+ lex_sbc_missing ("NAME");
goto lossage;
}
switch (cmd.mode)
{
case FH_CHARACTER:
- properties.mode = MODE_TEXT;
+ properties.mode = FH_MODE_TEXT;
if (cmd.sbc_tabwidth)
properties.tab_width = cmd.n_tabwidth[0];
break;
case FH_IMAGE:
- properties.mode = MODE_BINARY;
+ properties.mode = FH_MODE_BINARY;
if (cmd.n_lrecl[0] == NOT_LONG)
msg (SE, _("Fixed-length records were specified on /RECFORM, but "
"record length was not specified on /LRECL. "
assert (0);
}
- handle = fh_create (handle_name, cmd.s_name, &properties);
+ if (cmd.mode != FH_SCRATCH)
+ fh_create_file (handle_name, cmd.s_name, &properties);
+ else
+ fh_create_scratch (handle_name);
free_file_handle (&cmd);
return CMD_SUCCESS;
return CMD_FAILURE;
}
-/* Parses a file handle name, which may be a filename as a string or
- a file handle name as an identifier. Returns the file handle or
- NULL on failure. */
-struct file_handle *
-fh_parse (void)
+int
+cmd_close_file_handle (void)
{
struct file_handle *handle;
- if (token != T_ID && token != T_STRING)
+ if (!lex_force_id ())
+ return CMD_FAILURE;
+ handle = fh_from_name (tokid);
+ if (handle == NULL)
+ return CMD_FAILURE;
+
+ fh_free (handle);
+
+ return CMD_SUCCESS;
+}
+
+/* Returns the name for REFERENT. */
+static const char *
+referent_name (enum fh_referent referent)
+{
+ switch (referent)
{
- lex_error (_("expecting a file name or handle name"));
- return NULL;
+ case FH_REF_FILE:
+ return _("file");
+ case FH_REF_INLINE:
+ return _("inline file");
+ case FH_REF_SCRATCH:
+ return _("scratch file");
+ default:
+ abort ();
}
+}
- /* Check for named handles first, then go by filename. */
- handle = NULL;
- if (token == T_ID)
- handle = fh_from_name (tokid);
- if (handle == NULL)
- handle = fh_from_filename (ds_c_str (&tokstr));
- if (handle == NULL)
+/* Parses a file handle name, which may be a filename as a string
+ or a file handle name as an identifier. The allowed types of
+ file handle are restricted to those in REFERENT_MASK. Returns
+ the file handle when successful, a null pointer on failure. */
+struct file_handle *
+fh_parse (enum fh_referent referent_mask)
+{
+ struct file_handle *handle;
+
+ if (lex_match_id ("INLINE"))
+ handle = fh_inline_file ();
+ else
{
- char *filename = ds_c_str (&tokstr);
- char *handle_name = xmalloc (strlen (filename) + 3);
- sprintf (handle_name, "\"%s\"", filename);
- handle = fh_create (handle_name, filename, fh_default_properties ());
- free (handle_name);
+ if (token != T_ID && token != T_STRING)
+ {
+ lex_error (_("expecting a file name or handle name"));
+ return NULL;
+ }
+
+ handle = NULL;
+ if (token == T_ID)
+ handle = fh_from_name (tokid);
+ if (handle == NULL)
+ handle = fh_from_filename (ds_c_str (&tokstr));
+ if (handle == NULL)
+ {
+ if (token != T_ID || tokid[0] != '#' || get_syntax () != ENHANCED)
+ {
+ char *filename = ds_c_str (&tokstr);
+ char *handle_name = xasprintf ("\"%s\"", filename);
+ handle = fh_create_file (handle_name, filename,
+ fh_default_properties ());
+ free (handle_name);
+ }
+ else
+ handle = fh_create_scratch (tokid);
+ }
+ lex_get ();
}
- lex_get ();
+ if (!(fh_get_referent (handle) & referent_mask))
+ {
+ msg (SE, _("Handle for %s not allowed here."),
+ referent_name (fh_get_referent (handle)));
+ return NULL;
+ }
return handle;
}
cmd_file_type (void)
{
static struct file_type_pgm *fty; /* FIXME: static? WTF? */
- struct file_handle *fh = NULL;
+ struct file_handle *fh = fh_inline_file ();
/* Initialize. */
discard_variables ();
if (lex_match_id ("FILE"))
{
lex_match ('=');
- fh = fh_parse ();
+ fh = fh_parse (FH_REF_FILE | FH_REF_INLINE);
if (fh == NULL)
goto error;
}
fty->reader = dfm_open_reader (fh);
if (fty->reader == NULL)
goto error;
- default_handle = fh;
+ fh_set_default_handle (fh);
create_col_var (&fty->record);
if (fty->case_sbc.name[0])
/* PSPP - computes sample statistics.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
Written by Ben Pfaff <blp@gnu.org>.
This program is free software; you can redistribute it and/or
abort ();
}
#endif
+
+/* Returns the extension part of FILENAME as a malloc()'d string.
+ If FILENAME does not have an extension, returns an empty
+ string. */
+char *
+fn_extension (const char *filename)
+{
+ const char *extension = strrchr (filename, '.');
+ if (extension == NULL)
+ extension = "";
+ return xstrdup (extension);
+}
\f
#if unix
/* Returns the current working directory, as a malloc()'d string.
char *fn_normalize (const char *fn);
char *fn_dirname (const char *fn);
char *fn_basename (const char *fn);
+char *fn_extension (const char *fn);
char *fn_get_cwd (void);
/* PSPP - computes sample statistics.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
Written by Ben Pfaff <blp@gnu.org>.
This program is free software; you can redistribute it and/or
#include "error.h"
#include <stdlib.h>
#include "alloc.h"
+#include "any-reader.h"
+#include "any-writer.h"
#include "case.h"
#include "command.h"
#include "dictionary.h"
#include "hash.h"
#include "lexer.h"
#include "misc.h"
-#include "pfm-read.h"
#include "pfm-write.h"
#include "settings.h"
-#include "sfm-read.h"
#include "sfm-write.h"
#include "str.h"
#include "value-labels.h"
const struct ccase *, struct ccase *);
static void destroy_case_map (struct case_map *);
-/* Operation type. */
-enum operation
+static bool parse_dict_trim (struct dictionary *);
+\f
+/* Reading system and portable files. */
+
+/* Type of command. */
+enum reader_command
{
- OP_READ, /* GET or IMPORT. */
- OP_SAVE, /* SAVE or XSAVE. */
- OP_EXPORT /* EXPORT. */
+ GET_CMD,
+ IMPORT_CMD
};
-static bool parse_dict_trim (struct dictionary *);
-\f
-/* GET input program. */
-struct get_pgm
+/* Case reader input program. */
+struct case_reader_pgm
{
- struct sfm_reader *reader; /* System file reader. */
- struct case_map *map; /* Map from system file to active file dict. */
+ struct any_reader *reader; /* File reader. */
+ struct case_map *map; /* Map from file dict to active file dict. */
struct ccase bounce; /* Bounce buffer. */
};
-static void get_pgm_free (struct get_pgm *);
+static const struct case_source_class case_reader_source_class;
-/* Parses the GET command. */
-int
-cmd_get (void)
+static void case_reader_pgm_free (struct case_reader_pgm *);
+
+/* Parses a GET or IMPORT command. */
+static int
+parse_read_command (enum reader_command type)
{
- struct get_pgm *pgm = NULL;
- struct file_handle *fh;
+ struct case_reader_pgm *pgm = NULL;
+ struct file_handle *fh = NULL;
struct dictionary *dict = NULL;
- pgm = xmalloc (sizeof *pgm);
- pgm->reader = NULL;
- pgm->map = NULL;
- case_nullify (&pgm->bounce);
+ for (;;)
+ {
+ lex_match ('/');
- discard_variables ();
+ if (lex_match_id ("FILE") || token == T_STRING)
+ {
+ lex_match ('=');
- lex_match ('/');
- if (lex_match_id ("FILE"))
- lex_match ('=');
- fh = fh_parse ();
- if (fh == NULL)
- goto error;
+ fh = fh_parse (FH_REF_FILE | FH_REF_SCRATCH);
+ if (fh == NULL)
+ goto error;
+ }
+ else if (type == IMPORT_CMD && lex_match_id ("TYPE"))
+ {
+ lex_match ('=');
- pgm->reader = sfm_open_reader (fh, &dict, NULL);
+ if (lex_match_id ("COMM"))
+ type = PFM_COMM;
+ else if (lex_match_id ("TAPE"))
+ type = PFM_TAPE;
+ else
+ {
+ lex_error (_("expecting COMM or TAPE"));
+ goto error;
+ }
+ }
+ else
+ break;
+ }
+
+ if (fh == NULL)
+ {
+ lex_sbc_missing ("FILE");
+ goto error;
+ }
+
+ discard_variables ();
+
+ pgm = xmalloc (sizeof *pgm);
+ pgm->reader = any_reader_open (fh, &dict);
+ pgm->map = NULL;
+ case_nullify (&pgm->bounce);
if (pgm->reader == NULL)
goto error;
- case_create (&pgm->bounce, dict_get_next_value_idx (dict));
+ case_create (&pgm->bounce, dict_get_next_value_idx (dict));
+
start_case_map (dict);
- while (lex_match ('/'))
- if (!parse_dict_trim (dict))
- goto error;
- if (!lex_end_of_command ())
- return false;
+ while (token != '.')
+ {
+ lex_match ('/');
+ if (!parse_dict_trim (dict))
+ goto error;
+ }
- dict_compact_values (dict);
pgm->map = finish_case_map (dict);
-
+
dict_destroy (default_dict);
default_dict = dict;
- vfm_source = create_case_source (&get_source_class, pgm);
+ vfm_source = create_case_source (&case_reader_source_class, pgm);
return CMD_SUCCESS;
error:
- get_pgm_free (pgm);
- if (dict != NULL)
+ case_reader_pgm_free (pgm);
+ if (dict != NULL)
dict_destroy (dict);
return CMD_FAILURE;
}
-/* Frees a struct get_pgm. */
+/* Frees a struct case_reader_pgm. */
static void
-get_pgm_free (struct get_pgm *pgm)
+case_reader_pgm_free (struct case_reader_pgm *pgm)
{
if (pgm != NULL)
{
- sfm_close_reader (pgm->reader);
+ any_reader_close (pgm->reader);
destroy_case_map (pgm->map);
case_destroy (&pgm->bounce);
free (pgm);
}
}
-/* Clears internal state related to GET input procedure. */
+/* Clears internal state related to case reader input procedure. */
static void
-get_source_destroy (struct case_source *source)
+case_reader_source_destroy (struct case_source *source)
{
- struct get_pgm *pgm = source->aux;
- get_pgm_free (pgm);
+ struct case_reader_pgm *pgm = source->aux;
+ case_reader_pgm_free (pgm);
}
/* Reads all the cases from the data file into C and passes them
to WRITE_CASE one by one, passing WC_DATA. */
static void
-get_source_read (struct case_source *source,
- struct ccase *c,
- write_case_func *write_case, write_case_data wc_data)
+case_reader_source_read (struct case_source *source,
+ struct ccase *c,
+ write_case_func *write_case, write_case_data wc_data)
{
- struct get_pgm *pgm = source->aux;
+ struct case_reader_pgm *pgm = source->aux;
int ok;
do
{
if (pgm->map == NULL)
- ok = sfm_read_case (pgm->reader, c);
+ ok = any_reader_read (pgm->reader, c);
else
{
- ok = sfm_read_case (pgm->reader, &pgm->bounce);
+ ok = any_reader_read (pgm->reader, &pgm->bounce);
if (ok)
map_case (pgm->map, &pgm->bounce, c);
}
while (ok);
}
-const struct case_source_class get_source_class =
+static const struct case_source_class case_reader_source_class =
{
- "GET",
+ "case reader",
NULL,
- get_source_read,
- get_source_destroy,
+ case_reader_source_read,
+ case_reader_source_destroy,
};
\f
+/* GET. */
+int
+cmd_get (void)
+{
+ return parse_read_command (GET_CMD);
+}
+
+/* IMPORT. */
+int
+cmd_import (void)
+{
+ return parse_read_command (IMPORT_CMD);
+}
+\f
+/* Writing system and portable files. */
+
/* Type of output file. */
enum writer_type
{
PROC_CMD /* Procedure. */
};
-/* Portable or system file writer plus a case map. */
-struct any_writer
+/* File writer plus a case map. */
+struct case_writer
{
- enum writer_type writer_type;
- void *writer;
+ struct any_writer *writer; /* File writer. */
struct case_map *map; /* Map to output file dictionary
(null pointer for identity mapping). */
struct ccase bounce; /* Bounce buffer for mapping (if needed). */
/* Destroys AW. */
static void
-any_writer_destroy (struct any_writer *aw)
+case_writer_destroy (struct case_writer *aw)
{
if (aw != NULL)
{
- switch (aw->writer_type)
- {
- case PORFILE_WRITER:
- pfm_close_writer (aw->writer);
- break;
- case SYSFILE_WRITER:
- sfm_close_writer (aw->writer);
- break;
- }
+ any_writer_close (aw->writer);
destroy_case_map (aw->map);
case_destroy (&aw->bounce);
free (aw);
included.
On failure, returns a null pointer. */
-static struct any_writer *
+static struct case_writer *
parse_write_command (enum writer_type writer_type,
enum command_type command_type,
bool *retain_unselected)
/* Common data. */
struct file_handle *handle; /* Output file. */
struct dictionary *dict; /* Dictionary for output file. */
- struct any_writer *aw; /* Writer. */
+ struct case_writer *aw; /* Writer. */
/* Common options. */
bool print_map; /* Print map? TODO. */
handle = NULL;
dict = dict_clone (default_dict);
aw = xmalloc (sizeof *aw);
- aw->writer_type = writer_type;
aw->writer = NULL;
aw->map = NULL;
case_nullify (&aw->bounce);
lex_match ('=');
- handle = fh_parse ();
+ handle = fh_parse (FH_REF_FILE | FH_REF_SCRATCH);
if (handle == NULL)
goto error;
}
if (aw->map != NULL)
case_create (&aw->bounce, dict_get_next_value_idx (dict));
- switch (writer_type)
+ if (fh_get_referent (handle) == FH_REF_FILE)
{
- case SYSFILE_WRITER:
- aw->writer = sfm_open_writer (handle, dict, sysfile_opts);
- break;
- case PORFILE_WRITER:
- aw->writer = pfm_open_writer (handle, dict, porfile_opts);
- break;
+ switch (writer_type)
+ {
+ case SYSFILE_WRITER:
+ aw->writer = any_writer_from_sfm_writer (
+ sfm_open_writer (handle, dict, sysfile_opts));
+ break;
+ case PORFILE_WRITER:
+ aw->writer = any_writer_from_pfm_writer (
+ pfm_open_writer (handle, dict, porfile_opts));
+ break;
+ }
}
-
+ else
+ aw->writer = any_writer_open (handle, dict);
dict_destroy (dict);
return aw;
error:
- any_writer_destroy (aw);
+ case_writer_destroy (aw);
dict_destroy (dict);
return NULL;
}
/* Writes case C to writer AW. */
static void
-any_writer_write_case (struct any_writer *aw, struct ccase *c)
+case_writer_write_case (struct case_writer *aw, struct ccase *c)
{
if (aw->map != NULL)
{
map_case (aw->map, c, &aw->bounce);
c = &aw->bounce;
}
-
- switch (aw->writer_type)
- {
- case SYSFILE_WRITER:
- sfm_write_case (aw->writer, c);
- break;
- case PORFILE_WRITER:
- pfm_write_case (aw->writer, c);
- break;
- }
+ any_writer_write (aw->writer, c);
}
\f
/* SAVE and EXPORT. */
{
bool retain_unselected;
struct variable *saved_filter_variable;
- struct any_writer *aw;
+ struct case_writer *aw;
aw = parse_write_command (writer_type, PROC_CMD, &retain_unselected);
if (aw == NULL)
procedure (output_proc, aw);
dict_set_filter (default_dict, saved_filter_variable);
- any_writer_destroy (aw);
+ case_writer_destroy (aw);
return CMD_SUCCESS;
}
static int
output_proc (struct ccase *c, void *aw_)
{
- struct any_writer *aw = aw_;
- any_writer_write_case (aw, c);
+ struct case_writer *aw = aw_;
+ case_writer_write_case (aw, c);
return 0;
}
/* Transformation. */
struct output_trns
{
- struct any_writer *aw; /* Writer. */
+ struct case_writer *aw; /* Writer. */
};
static trns_proc_func output_trns_proc;
output_trns_proc (void *trns_, struct ccase *c, int case_num UNUSED)
{
struct output_trns *t = trns_;
- any_writer_write_case (t->aw, c);
+ case_writer_write_case (t->aw, c);
return -1;
}
if (t != NULL)
{
- any_writer_destroy (t->aw);
+ case_writer_destroy (t->aw);
free (t);
}
}
int type; /* One of MTF_*. */
struct variable **by; /* List of BY variables for this file. */
struct file_handle *handle; /* File handle. */
- struct sfm_reader *reader; /* System file reader. */
+ struct any_reader *reader; /* File reader. */
struct dictionary *dict; /* Dictionary from system file. */
/* IN subcommand. */
}
else
{
- file->handle = fh_parse ();
+ file->handle = fh_parse (FH_REF_FILE | FH_REF_SCRATCH);
if (file->handle == NULL)
goto error;
- file->reader = sfm_open_reader (file->handle, &file->dict, NULL);
+ file->reader = any_reader_open (file->handle, &file->dict);
if (file->reader == NULL)
goto error;
mtf_free_file (struct mtf_file *file)
{
free (file->by);
- sfm_close_reader (file->reader);
+ any_reader_close (file->reader);
if (file->dict != default_dict)
dict_destroy (file->dict);
case_destroy (&file->input);
for (iter = mtf->head; iter != NULL; iter = next)
{
next = iter->next;
- if (iter->handle && !sfm_read_case (iter->reader, &iter->input))
+ if (iter->handle && !any_reader_read (iter->reader, &iter->input))
mtf_delete_file_in_place (mtf, &iter);
}
}
{
if (iter->handle == NULL)
return 1;
- if (sfm_read_case (iter->reader, &iter->input))
+ if (any_reader_read (iter->reader, &iter->input))
continue;
mtf_delete_file_in_place (mtf, &iter);
}
{
next = iter->next_min;
if (iter->reader != NULL
- && !sfm_read_case (iter->reader, &iter->input))
+ && !any_reader_read (iter->reader, &iter->input))
mtf_delete_file_in_place (mtf, &iter);
}
}
return v->aux;
}
\f
-/* IMPORT command. */
-
-/* IMPORT input program. */
-struct import_pgm
- {
- struct pfm_reader *reader; /* Portable file reader. */
- struct case_map *map; /* Map from system file to active file dict. */
- struct ccase bounce; /* Bounce buffer. */
- };
-
-static void import_pgm_free (struct import_pgm *);
-
-/* Parses the IMPORT command. */
-int
-cmd_import (void)
-{
- struct import_pgm *pgm = NULL;
- struct file_handle *fh = NULL;
- struct dictionary *dict = NULL;
- enum pfm_type type;
-
- lex_match ('/');
- for (;;)
- {
- if (pgm == NULL && (lex_match_id ("FILE") || token == T_STRING))
- {
- lex_match ('=');
-
- fh = fh_parse ();
- if (fh == NULL)
- goto error;
- }
- else if (pgm == NULL && lex_match_id ("TYPE"))
- {
- lex_match ('=');
-
- if (lex_match_id ("COMM"))
- type = PFM_COMM;
- else if (lex_match_id ("TAPE"))
- type = PFM_TAPE;
- else
- {
- lex_error (_("expecting COMM or TAPE"));
- goto error;
- }
- }
- else
- {
- if (pgm == NULL)
- {
- if (fh == NULL)
- {
- lex_sbc_missing ("FILE");
- goto error;
- }
-
- discard_variables ();
-
- pgm = xmalloc (sizeof *pgm);
- pgm->reader = pfm_open_reader (fh, &dict, NULL);
- pgm->map = NULL;
- case_nullify (&pgm->bounce);
- if (pgm->reader == NULL)
- goto error;
-
- case_create (&pgm->bounce, dict_get_next_value_idx (dict));
-
- start_case_map (dict);
- }
-
- if (token == '.')
- break;
-
- if (!parse_dict_trim (dict))
- goto error;
- }
-
- lex_match ('/');
- }
- if (pgm == NULL)
- {
- lex_error (NULL);
- goto error;
- }
-
- pgm->map = finish_case_map (dict);
-
- dict_destroy (default_dict);
- default_dict = dict;
-
- vfm_source = create_case_source (&import_source_class, pgm);
-
- return CMD_SUCCESS;
-
- error:
- import_pgm_free (pgm);
- if (dict != NULL)
- dict_destroy (dict);
- return CMD_FAILURE;
-}
-
-/* Frees a struct import_pgm. */
-static void
-import_pgm_free (struct import_pgm *pgm)
-{
- if (pgm != NULL)
- {
- pfm_close_reader (pgm->reader);
- destroy_case_map (pgm->map);
- case_destroy (&pgm->bounce);
- free (pgm);
- }
-}
-
-/* Clears internal state related to IMPORT input procedure. */
-static void
-import_source_destroy (struct case_source *source)
-{
- struct import_pgm *pgm = source->aux;
- import_pgm_free (pgm);
-}
-
-/* Reads all the cases from the data file into C and passes them
- to WRITE_CASE one by one, passing WC_DATA. */
-static void
-import_source_read (struct case_source *source,
- struct ccase *c,
- write_case_func *write_case, write_case_data wc_data)
-{
- struct import_pgm *pgm = source->aux;
- int ok;
-
- do
- {
- if (pgm->map == NULL)
- ok = pfm_read_case (pgm->reader, c);
- else
- {
- ok = pfm_read_case (pgm->reader, &pgm->bounce);
- if (ok)
- map_case (pgm->map, &pgm->bounce, c);
- }
-
- if (ok)
- ok = write_case (wc_data);
- }
- while (ok);
-}
-
-const struct case_source_class import_source_class =
- {
- "IMPORT",
- NULL,
- import_source_read,
- import_source_destroy,
- };
\f
/* Case map.
size_t n_trns, m_trns, f_trns;
int FILTER_before_TEMPORARY;
-
-struct file_handle *default_handle;
\f
/* Functions. */
struct expression *e; /* Expression for column to set. */
struct reread_trns *t; /* Created transformation. */
- fh = default_handle;
+ fh = fh_get_default_handle ();
e = NULL;
while (token != '.')
{
else if (lex_match_id ("FILE"))
{
lex_match ('=');
- fh = fh_parse ();
+ fh = fh_parse (FH_REF_FILE | FH_REF_INLINE);
if (fh == NULL)
{
expr_free (e);
{
struct pool *pool;
struct matrix_data_pgm *mx;
- struct file_handle *fh = NULL;
+ struct file_handle *fh = fh_inline_file ();
unsigned seen = 0;
else if (lex_match_id ("FILE"))
{
lex_match ('=');
- fh = fh_parse ();
+ fh = fh_parse (FH_REF_FILE | FH_REF_INLINE);
if (fh == NULL)
goto lossage;
}
/* PSPP - computes sample statistics.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
Written by Ben Pfaff <blp@gnu.org>.
Code for parsing floating-point numbers adapted from GNU C
library.
#include "debug-print.h"
+/* portable_to_local[PORTABLE] translates the given portable
+ character into the local character set. */
+static const char portable_to_local[256] =
+ {
+ " "
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ."
+ "<(+|&[]!$*);^-/|,%_>?`:$@'=\" ~- 0123456789 -() {}\\ "
+ " "
+ };
+
/* Portable file reader. */
struct pfm_reader
{
struct pfm_reader *volatile r = NULL;
*dict = dict_create ();
- if (!fh_open (fh, "portable file", "rs"))
+ if (!fh_open (fh, FH_REF_FILE, "portable file", "rs"))
goto error;
/* Create and initialize reader. */
static void
read_header (struct pfm_reader *r)
{
- /* portable_to_local[PORTABLE] translates the given portable
- character into the local character set. */
- static const char portable_to_local[256] =
- {
- " "
- "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ."
- "<(+|&[]!$*);^-/|,%_>?`:$@'=\" ~- 0123456789 -() {}\\ "
- " "
- };
-
char *trans;
int i;
return true;
}
+
+/* Returns true if FILE is an SPSS portable file,
+ false otherwise. */
+bool
+pfm_detect (FILE *file)
+{
+ unsigned char header[464];
+ char trans[256];
+ int cooked_cnt, raw_cnt;
+ int i;
+
+ cooked_cnt = raw_cnt = 0;
+ while (cooked_cnt < sizeof header)
+ {
+ int c = getc (file);
+ if (c == EOF || raw_cnt++ > 512)
+ return false;
+ else if (c != '\n' && c != '\r')
+ header[cooked_cnt++] = c;
+ }
+
+ memset (trans, 0, 256);
+ for (i = 64; i < 256; i++)
+ {
+ unsigned char c = header[i + 200];
+ if (trans[c] == 0)
+ trans[c] = portable_to_local[i];
+ }
+
+ for (i = 0; i < 8; i++)
+ if (trans[header[i + 456]] != "SPSSPORT"[i])
+ return false;
+
+ return true;
+}
/* Portable file reading. */
#include <stdbool.h>
+#include <stdio.h>
/* Information produced by pfm_read_dictionary() that doesn't fit into
a dictionary struct. */
struct pfm_read_info *);
bool pfm_read_case (struct pfm_reader *, struct ccase *);
void pfm_close_reader (struct pfm_reader *);
+bool pfm_detect (FILE *);
#endif /* pfm-read.h */
goto open_error;
/* Open file handle. */
- if (!fh_open (fh, "portable file", "we"))
+ if (!fh_open (fh, FH_REF_FILE, "portable file", "we"))
goto error;
/* Initialize data structures. */
/* Writes case ELEM to the portable file represented by H. Returns
success. */
int
-pfm_write_case (struct pfm_writer *w, struct ccase *c)
+pfm_write_case (struct pfm_writer *w, const struct ccase *c)
{
int i;
if (w == NULL)
return;
- fh_close (w->fh, "portable file", "we");
-
if (w->file != NULL)
{
char buf[80];
fh_get_filename (w->fh), strerror (errno));
}
+ fh_close (w->fh, "portable file", "we");
+
free (w->vars);
free (w);
}
struct pfm_write_options);
struct pfm_write_options pfm_writer_default_options (void);
-int pfm_write_case (struct pfm_writer *, struct ccase *);
+int pfm_write_case (struct pfm_writer *, const struct ccase *);
void pfm_close_writer (struct pfm_writer *);
#endif /* pfm-write.h */
{
lex_match ('=');
- fh = fh_parse ();
+ fh = fh_parse (FH_REF_FILE);
if (fh == NULL)
goto error;
}
if (prt.writer == NULL)
goto error;
- if (fh_get_mode (fh) == MODE_BINARY)
+ if (fh_get_mode (fh) == FH_MODE_BINARY)
prt.options |= PRT_BINARY;
}
}
if (fh != NULL)
- tab_title (t, 1, _("Writing %d record(s) to file %s."),
- recno, fh_get_filename (fh));
+ tab_title (t, 1, ngettext ("Writing %d record to %s.",
+ "Writing %d records to %s.", recno),
+ recno, fh_get_name (fh));
else
- tab_title (t, 1, _("Writing %d record(s) to the listing file."), recno);
+ tab_title (t, 1, ngettext ("Writing %d record.",
+ "Writing %d records.", recno), recno);
tab_submit (t);
}
{
lex_match ('=');
- fh = fh_parse ();
+ fh = fh_parse (FH_REF_FILE);
if (fh == NULL)
return CMD_FAILURE;
lex_get ();
model_file = NULL;
else
{
- model_file = fh_parse ();
+ model_file = fh_parse (FH_REF_FILE);
if (model_file == NULL)
return 0;
}
--- /dev/null
+/* PSPP - computes sample statistics.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+ Written by Ben Pfaff <blp@gnu.org>.
+
+ 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 <config.h>
+#include <stdlib.h>
+#include "scratch-handle.h"
+#include "casefile.h"
+#include "dictionary.h"
+
+/* Destroys HANDLE. */
+void
+scratch_handle_destroy (struct scratch_handle *handle)
+{
+ if (handle != NULL)
+ {
+ dict_destroy (handle->dictionary);
+ casefile_destroy (handle->casefile);
+ free (handle);
+ }
+}
--- /dev/null
+/* PSPP - computes sample statistics.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+ Written by Ben Pfaff <blp@gnu.org>.
+
+ 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. */
+
+#ifndef SCRATCH_HANDLE_H
+#define SCRATCH_HANDLE_H 1
+
+#include <stdbool.h>
+
+/* A scratch file. */
+struct scratch_handle
+ {
+ struct dictionary *dictionary; /* Dictionary. */
+ struct casefile *casefile; /* Cases. */
+ };
+
+void scratch_handle_destroy (struct scratch_handle *);
+
+#endif /* scratch-handle.h */
--- /dev/null
+/* PSPP - computes sample statistics.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+ Written by Ben Pfaff <blp@gnu.org>.
+
+ 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 <config.h>
+#include "scratch-reader.h"
+#include <stdlib.h>
+#include "casefile.h"
+#include "dictionary.h"
+#include "error.h"
+#include "file-handle-def.h"
+#include "scratch-handle.h"
+#include "xalloc.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+/* A reader for a scratch file. */
+struct scratch_reader
+ {
+ struct file_handle *fh; /* Underlying file handle. */
+ struct casereader *casereader; /* Case reader. */
+ };
+
+/* Opens FH, which must have referent type FH_REF_SCRATCH, and
+ returns a scratch_reader for it, or a null pointer on
+ failure. Stores the dictionary for the scratch file into
+ *DICT.
+
+ If you use an any_reader instead, then your code can be more
+ flexible without being any harder to write. */
+struct scratch_reader *
+scratch_reader_open (struct file_handle *fh, struct dictionary **dict)
+{
+ struct scratch_handle *sh;
+ struct scratch_reader *reader;
+
+ if (!fh_open (fh, FH_REF_SCRATCH, "scratch file", "rs"))
+ return NULL;
+
+ sh = fh_get_scratch_handle (fh);
+ if (sh == NULL)
+ {
+ msg (SE, _("Scratch file handle %s has not yet been written, "
+ "using SAVE or another procedure, so it cannot yet "
+ "be used for reading."),
+ fh_get_name (fh));
+ return NULL;
+ }
+
+ *dict = dict_clone (sh->dictionary);
+ reader = xmalloc (sizeof *reader);
+ reader->fh = fh;
+ reader->casereader = casefile_get_reader (sh->casefile);
+ return reader;
+}
+
+/* Reads a case from READER into C.
+ Returns true if successful, false on error or at end of file. */
+bool
+scratch_reader_read_case (struct scratch_reader *reader, struct ccase *c)
+{
+ return casereader_read (reader->casereader, c);
+}
+
+/* Closes READER. */
+void
+scratch_reader_close (struct scratch_reader *reader)
+{
+ fh_close (reader->fh, "scratch file", "rs");
+ casereader_destroy (reader->casereader);
+ free (reader);
+}
--- /dev/null
+/* PSPP - computes sample statistics.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+ Written by Ben Pfaff <blp@gnu.org>.
+
+ 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. */
+
+#ifndef SCRATCH_READER_H
+#define SCRATCH_READER_H 1
+
+#include <stdbool.h>
+
+struct dictionary;
+struct file_handle;
+struct ccase;
+struct scratch_reader *scratch_reader_open (struct file_handle *,
+ struct dictionary **);
+bool scratch_reader_read_case (struct scratch_reader *, struct ccase *);
+void scratch_reader_close (struct scratch_reader *);
+
+#endif /* scratch-reader.h */
--- /dev/null
+/* PSPP - computes sample statistics.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+ Written by Ben Pfaff <blp@gnu.org>.
+
+ 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 <config.h>
+#include "scratch-writer.h"
+#include <stdlib.h>
+#include "case.h"
+#include "casefile.h"
+#include "dictionary.h"
+#include "file-handle-def.h"
+#include "scratch-handle.h"
+#include "xalloc.h"
+
+/* A scratch file writer. */
+struct scratch_writer
+ {
+ struct scratch_handle *handle; /* Underlying scratch handle. */
+ struct file_handle *fh; /* Underlying file handle. */
+ struct dict_compactor *compactor; /* Compacts into handle->dictionary. */
+ };
+
+/* Opens FH, which must have referent type FH_REF_SCRATCH, and
+ returns a scratch_writer for it, or a null pointer on
+ failure. Cases stored in the scratch_writer will be expected
+ to be drawn from DICTIONARY.
+
+ If you use an any_writer instead, then your code can be more
+ flexible without being any harder to write. */
+struct scratch_writer *
+scratch_writer_open (struct file_handle *fh,
+ const struct dictionary *dictionary)
+{
+ struct scratch_handle *sh;
+ struct scratch_writer *writer;
+ struct dictionary *scratch_dict;
+ struct dict_compactor *compactor;
+
+ if (!fh_open (fh, FH_REF_SCRATCH, "scratch file", "we"))
+ return NULL;
+
+ /* Destroy previous contents of handle. */
+ sh = fh_get_scratch_handle (fh);
+ if (sh != NULL)
+ scratch_handle_destroy (sh);
+
+ /* Copy the dictionary and compact if needed. */
+ scratch_dict = dict_clone (dictionary);
+ if (dict_needs_compaction (scratch_dict))
+ {
+ compactor = dict_make_compactor (scratch_dict);
+ dict_compact_values (scratch_dict);
+ }
+ else
+ compactor = NULL;
+
+ /* Create new contents. */
+ sh = xmalloc (sizeof *sh);
+ sh->dictionary = scratch_dict;
+ sh->casefile = casefile_create (dict_get_next_value_idx (sh->dictionary));
+
+ /* Create writer. */
+ writer = xmalloc (sizeof *writer);
+ writer->handle = sh;
+ writer->fh = fh;
+ writer->compactor = compactor;
+
+ fh_set_scratch_handle (fh, sh);
+ return writer;
+}
+
+/* Writes case C to WRITER. */
+void
+scratch_writer_write_case (struct scratch_writer *writer,
+ const struct ccase *c)
+{
+ struct scratch_handle *handle = writer->handle;
+ if (writer->compactor)
+ {
+ struct ccase tmp_case;
+ case_create (&tmp_case, dict_get_next_value_idx (handle->dictionary));
+ dict_compactor_compact (writer->compactor, &tmp_case, c);
+ casefile_append_xfer (handle->casefile, &tmp_case);
+ }
+ else
+ casefile_append (handle->casefile, c);
+}
+
+/* Closes WRITER. */
+void
+scratch_writer_close (struct scratch_writer *writer)
+{
+ struct scratch_handle *handle = writer->handle;
+ casefile_mode_reader (handle->casefile);
+ fh_close (writer->fh, "scratch file", "we");
+ free (writer);
+}
--- /dev/null
+/* PSPP - computes sample statistics.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+ Written by Ben Pfaff <blp@gnu.org>.
+
+ 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. */
+
+#ifndef SCRATCH_WRITER_H
+#define SCRATCH_WRITER_H 1
+
+#include <stdbool.h>
+
+struct dictionary;
+struct file_handle;
+struct ccase;
+struct scratch_writer *scratch_writer_open (struct file_handle *,
+ const struct dictionary *);
+void scratch_writer_write_case (struct scratch_writer *, const struct ccase *);
+void scratch_writer_close (struct scratch_writer *);
+
+#endif /* scratch-writer.h */
/* PSPP - computes sample statistics.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
Written by Ben Pfaff <blp@gnu.org>.
This program is free software; you can redistribute it and/or
if (r == NULL)
return;
+ if (r->file)
+ {
+ if (fn_close (fh_get_filename (r->fh), r->file) == EOF)
+ msg (ME, _("%s: Closing system file: %s."),
+ fh_get_filename (r->fh), strerror (errno));
+ r->file = NULL;
+ }
+
if (r->fh != NULL)
fh_close (r->fh, "system file", "rs");
- if ( r->file ) {
- if (fn_close (fh_get_filename (r->fh), r->file) == EOF)
- msg (ME, _("%s: Closing system file: %s."),
- fh_get_filename (r->fh), strerror (errno));
- r->file = NULL;
- }
free (r->vars);
free (r->buf);
free (r);
struct variable **var_by_idx = NULL;
*dict = dict_create ();
- if (!fh_open (fh, "system file", "rs"))
+ if (!fh_open (fh, FH_REF_FILE, "system file", "rs"))
goto error;
/* Create and initialize reader. */
return 0;
}
}
+\f
+/* Returns true if FILE is an SPSS system file,
+ false otherwise. */
+bool
+sfm_detect (FILE *file)
+{
+ struct sysfile_header hdr;
+
+ if (fread (&hdr, sizeof hdr, 1, file) != 1)
+ return false;
+ if (strncmp ("$FL2", hdr.rec_type, 4))
+ return false;
+ return true;
+}
#ifndef SFM_READ_H
#define SFM_READ_H 1
+#include <stdbool.h>
+#include <stdio.h>
+
/* Reading system files. */
/* System file info that doesn't fit in struct dictionary. */
struct sfm_read_info *);
int sfm_read_case (struct sfm_reader *, struct ccase *);
void sfm_close_reader (struct sfm_reader *);
+bool sfm_detect (FILE *);
#endif /* sfm-read.h */
goto open_error;
/* Open file handle. */
- if (!fh_open (fh, "system file", "we"))
+ if (!fh_open (fh, FH_REF_FILE, "system file", "we"))
goto error;
/* Create and initialize writer. */
if (w == NULL)
return;
- fh_close (w->fh, "system file", "we");
-
if (w->file != NULL)
{
/* Flush buffer. */
fh_get_filename (w->fh), strerror (errno));
}
+ fh_close (w->fh, "system file", "we");
+
free (w->buf);
free (w->vars);
free (w);
/* PSPP - computes sample statistics.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
Written by Ben Pfaff <blp@gnu.org>.
This program is free software; you can redistribute it and/or
for (; *s != '\0'; s++)
*s = toupper ((unsigned char) *s);
}
+
+/* Converts each character in S to lowercase. */
+void
+str_lowercase (char *s)
+{
+ for (; *s != '\0'; s++)
+ *s = tolower ((unsigned char) *s);
+}
\f
/* Initializes ST with initial contents S. */
void
#include "strstr.h"
#include "strtok_r.h"
#include "vsnprintf.h"
+#include "xvasprintf.h"
#ifndef HAVE_STRCHR
#define strchr index
void str_copy_trunc (char *, size_t, const char *);
void str_copy_buf_trunc (char *, size_t, const char *, size_t);
void str_uppercase (char *);
+void str_lowercase (char *);
\f
/* Fixed-length strings. */
struct fixed_string
lex_match_id ("FILE");
lex_match ('=');
- h = fh_parse ();
+ h = fh_parse (FH_REF_FILE);
if (!h)
return CMD_FAILURE;
\f
/* Transformation state. */
-/* Default file handle for DATA LIST, REREAD, REPEATING DATA
- commands. */
-extern struct file_handle *default_handle;
-
/* PROCESS IF expression. */
extern struct expression *process_if_expr;
\f
/* PSPP - computes sample statistics.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
Written by Ben Pfaff <blp@gnu.org>.
This program is free software; you can redistribute it and/or
#include "ctl-stack.h"
#include "error.h"
#include "expressions/public.h"
+#include "file-handle-def.h"
#include "misc.h"
#include "settings.h"
#include "som.h"
/* The replacement active file, to which cases are written. */
struct case_sink *vfm_sink;
-/* Nonzero if the case needs to have values deleted before being
- stored, zero otherwise. */
-static int compaction_necessary;
+/* The compactor used to compact a compact, if necessary;
+ otherwise a null pointer. */
+static struct dict_compactor *compactor;
/* Time at which vfm was last invoked. */
static time_t last_vfm_invocation;
}
/* Figure out compaction. */
- compaction_necessary = (dict_get_next_value_idx (temp_dict)
- != dict_get_compacted_value_cnt (temp_dict));
+ compactor = (dict_needs_compaction (temp_dict)
+ ? dict_make_compactor (temp_dict)
+ : NULL);
/* Prepare sink. */
if (vfm_sink == NULL)
/* Write case to replacement active file. */
if (vfm_sink->class->write != NULL)
{
- if (compaction_necessary)
+ if (compactor != NULL)
{
- dict_compact_case (temp_dict, &wc_data->sink_case,
- &wc_data->trns_case);
+ dict_compactor_compact (compactor, &wc_data->sink_case,
+ &wc_data->trns_case);
vfm_sink->class->write (vfm_sink, &wc_data->sink_case);
}
else
}
/* Finish compaction. */
- if (compaction_necessary)
- dict_compact_values (default_dict);
+ if (compactor != NULL)
+ {
+ dict_compactor_destroy (compactor);
+ dict_compact_values (default_dict);
+ }
/* Free data source. */
free_case_source (vfm_source);
discard_variables (void)
{
dict_clear (default_dict);
- default_handle = NULL;
+ fh_set_default_handle (NULL);
n_lag = 0;
};
extern const struct case_source_class storage_source_class;
-extern const struct case_source_class data_list_source_class;
extern const struct case_source_class file_type_source_class;
extern const struct case_source_class input_program_source_class;
-extern const struct case_source_class get_source_class;
-extern const struct case_source_class import_source_class;
-extern const struct case_source_class sort_source_class;
struct dictionary;
struct case_source *create_case_source (const struct case_source_class *,
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b -w $TEMPDIR/pspp.list - << EOF
-1.1 DATA LIST. Reading free-form data from the command file.
+1.1 DATA LIST. Reading free-form data from INLINE.
+--------+------+
|Variable|Format|
#========#======#
activity="compare output"
perl -pi -e 's/^\s*$//g' pspp.list
diff -b pspp.list - << EOF
-1.1 DATA LIST. Reading free-form data from the command file.
+1.1 DATA LIST. Reading free-form data from INLINE.
+----------------+------+
| Variable |Format|
#================#======#
-1.1 DATA LIST. Reading free-form data from the command file.
+1.1 DATA LIST. Reading free-form data from INLINE.
+--------+------+
|Variable|Format|
#========#======#
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b -w $TEMPDIR/pspp.list - << EOF
-1.1 DATA LIST. Reading free-form data from the command file.
+1.1 DATA LIST. Reading free-form data from INLINE.
+--------+------+
|Variable|Format|
#========#======#
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b -w $TEMPDIR/pspp.list - << EOF
-1.1 DATA LIST. Reading free-form data from the command file.
+1.1 DATA LIST. Reading free-form data from INLINE.
+--------+------+
|Variable|Format|
#========#======#
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b -w $TEMPDIR/pspp.list - << EOF
-1.1 DATA LIST. Reading free-form data from the command file.
+1.1 DATA LIST. Reading free-form data from INLINE.
+--------+------+
|Variable|Format|
#========#======#
-1.1 DATA LIST. Reading free-form data from the command file.
+1.1 DATA LIST. Reading free-form data from INLINE.
+--------+------+
|Variable|Format|
#========#======#
-1.1 DATA LIST. Reading free-form data from the command file.
+1.1 DATA LIST. Reading free-form data from INLINE.
+--------+------+
|Variable|Format|
#========#======#
activity="compare output"
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b $TEMPDIR/pspp.list - <<EOF
-1.1 DATA LIST. Reading free-form data from the command file.
+1.1 DATA LIST. Reading free-form data from INLINE.
+--------+------+
|Variable|Format|
#========#======#
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b -w $TEMPDIR/pspp.list - << EOF
-1.1 DATA LIST. Reading free-form data from the command file.
+1.1 DATA LIST. Reading free-form data from INLINE.
+--------+------+
|Variable|Format|
#========#======#
4 1.00 1.00 1 1 . . . 1.000 . . . .000 . . . .000 . . 4 . . . 1.000 . . 4 . . 4 . . . . 4 .00 .00 .00 1.00 1.00 1.00 1.00 .00 0 0 0 1 1 1 1 0 . . . 100.0 . . . .0 . . . .0 . . . 100.0 . . . .
EOF
-for outfile in active external; do
+for outfile in temporary active external; do
for sort in presorted unsorted; do
for missing in itemwise columnwise; do
name=$outfile-$sort-$missing
echo "aggregate"
if [ "$outfile" = "active" ]; then
echo " outfile=*"
- else
+ elif [ "$outfile" = "external" ]; then
echo " outfile='aggregate.sys'"
+ else
+ echo " outfile=#AGGREGATE"
fi
if [ "$sort" = "presorted" ]; then
echo " /presorted"
cat agg-skel.pspp
if [ "$outfile" = "external" ]; then
echo "get file='aggregate.sys'."
+ elif [ "$outfile" = "temporary" ]; then
+ echo "get file=#AGGREGATE."
fi
echo "list."
} > $name.pspp
activity="test output"
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b $TEMPDIR/pspp.list - <<EOF
-1.1 DATA LIST. Reading 1 record from the command file.
+1.1 DATA LIST. Reading 1 record from INLINE.
+--------+------+-------+------+
|Variable|Record|Columns|Format|
#========#======#=======#======#
activity="compare data"
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b $TEMPDIR/pspp.list - << foobar
-1.1 DATA LIST. Reading 1 record from the command file.
+1.1 DATA LIST. Reading 1 record from INLINE.
+--------+------+-------+------+
|Variable|Record|Columns|Format|
#========#======#=======#======#
5 6
7 8
9 0
-2.1 DATA LIST. Reading 1 record from the command file.
+2.1 DATA LIST. Reading 1 record from INLINE.
+--------+------+-------+------+
|Variable|Record|Columns|Format|
#========#======#=======#======#
activity="compare results"
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b $TEMPDIR/pspp.list - <<EOF
-1.1 DATA LIST. Reading 1 record from the command file.
+1.1 DATA LIST. Reading 1 record from INLINE.
+--------+------+-------+------+
|Variable|Record|Columns|Format|
#========#======#=======#======#
activity="compare output"
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b $TEMPDIR/pspp.list - << EOF
-1.1 DATA LIST. Reading free-form data from the command file.
+1.1 DATA LIST. Reading free-form data from INLINE.
+--------+------+
|Variable|Format|
#========#======#
activity="compare results"
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b $TEMPDIR/pspp.list - << EOF
-1.1 DATA LIST. Reading free-form data from the command file.
+1.1 DATA LIST. Reading free-form data from INLINE.
+--------+------+
|Variable|Format|
#========#======#
activity="compare results"
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b $TEMPDIR/pspp.list - << EOF
-1.1 DATA LIST. Reading free-form data from the command file.
+1.1 DATA LIST. Reading free-form data from INLINE.
+--------+------+
|Variable|Format|
#========#======#
activity="compare output"
diff -b $TEMPDIR/pspp.list - << EOF
-1.1 DATA LIST. Reading free-form data from file $TEMPDIR/wiggle.txt.
+1.1 DATA LIST. Reading free-form data from myhandle.
+--------+------+
|Variable|Format|
#========#======#
activity="compare results"
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.filtered
diff -b $TEMPDIR/pspp.filtered - <<EOF
-1.1 DATA LIST. Reading 1 record from the command file.
+1.1 DATA LIST. Reading 1 record from INLINE.
+--------+------+-------+------+
|Variable|Record|Columns|Format|
#========#======#=======#======#
activity="compare output"
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b $TEMPDIR/pspp.list - << EOF
-1.1 DATA LIST. Reading 1 record from the command file.
+1.1 DATA LIST. Reading 1 record from INLINE.
+--------+------+-------+------+
|Variable|Record|Columns|Format|
#========#======#=======#======#
activity="compare result"
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b $TEMPDIR/pspp.list - <<EOF
-1.1 DATA LIST. Reading 1 record from the command file.
+1.1 DATA LIST. Reading 1 record from INLINE.
+--------+------+-------+------+
|Variable|Record|Columns|Format|
#========#======#=======#======#
activity="compare results"
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b $TEMPDIR/pspp.list - <<EOF
-1.1 DATA LIST. Reading 1 record from file $top_srcdir/tests/weighting.data.
+1.1 DATA LIST. Reading 1 record from "$top_srcdir/tests/weighting.data".
+--------+------+-------+------+
|Variable|Record|Columns|Format|
#========#======#=======#======#
activity="compare output"
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b $TEMPDIR/pspp.list - <<EOF
-1.1 DATA LIST. Reading free-form data from the command file.
+1.1 DATA LIST. Reading free-form data from INLINE.
+--------------+------+
| Variable |Format|
#==============#======#
activity="compare results"
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b $TEMPDIR/pspp.list - <<EOF
-1.1 DATA LIST. Reading 1 record from the command file.
+1.1 DATA LIST. Reading 1 record from INLINE.
+----------+------+-------+------+
| Variable |Record|Columns|Format|
#==========#======#=======#======#
perl -pi -e s/^\s*\$//g $TEMPDIR/pspp.list
diff -b $TEMPDIR/pspp.list - << EOF | perl -e 's/^\s*$//g'
-1.1 DATA LIST. Reading free-form data from the command file.
+1.1 DATA LIST. Reading free-form data from INLINE.
+--------+------+
|Variable|Format|
#========#======#
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b $TEMPDIR/pspp.list - << EOF
-1.1 DATA LIST. Reading free-form data from the command file.
+1.1 DATA LIST. Reading free-form data from INLINE.
+--------+------+
|Variable|Format|
#========#======#
activity="compare output"
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b $TEMPDIR/pspp.list - << EOF
-1.1 DATA LIST. Reading free-form data from file $TEMPDIR/data-list.data.
+1.1 DATA LIST. Reading free-form data from "$TEMPDIR/data-list.data".
+--------+------+
|Variable|Format|
#========#======#
|C |F8.0 |
|D |F8.0 |
+--------+------+
-2.1 PRINT. Writing 1 record(s) to file foo.
+2.1 PRINT. Writing 1 record to "foo".
+--------+------+-------+------+
|Variable|Record|Columns|Format|
#========#======#=======#======#
. 2.00 3.00 4.00
. 6.00 7.00 8.00
. 10.00 11.00 12.00
-3.1 DATA LIST. Reading free-form data from file $TEMPDIR/data-list.data.
+3.1 DATA LIST. Reading free-form data from "$TEMPDIR/data-list.data".
+--------+------+
|Variable|Format|
#========#======#
|C |F8.0 |
|D |F8.0 |
+--------+------+
-4.1 PRINT. Writing 1 record(s) to the listing file.
+4.1 PRINT. Writing 1 record.
+--------+------+-------+------+
|Variable|Record|Columns|Format|
#========#======#=======#======#
activity="compare output"
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b $TEMPDIR/pspp.list - <<EOF
-1.1 DATA LIST. Reading free-form data from the command file.
+1.1 DATA LIST. Reading free-form data from INLINE.
+----------+------+
| Variable |Format|
#==========#======#
activity="compare output"
perl -pi -e 's/^\s*$//g' $TEMPDIR/out-filtered
diff -b -w $TEMPDIR/out-filtered - << EOF
-1.1 DATA LIST. Reading free-form data from the command file.
+1.1 DATA LIST. Reading free-form data from INLINE.
+--------+------+
|Variable|Format|
#========#======#
activity="compare output"
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b $TEMPDIR/pspp.list - <<EOF
-1.1 DATA LIST. Reading free-form data from the command file.
+1.1 DATA LIST. Reading free-form data from INLINE.
+--------+------+
|Variable|Format|
#========#======#
activity="compare output"
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b $TEMPDIR/pspp.list - <<EOF
-1.1 DATA LIST. Reading free-form data from the command file.
+1.1 DATA LIST. Reading free-form data from INLINE.
+--------+------+
|Variable|Format|
#========#======#
activity="compare output"
perl -pi -e s/^\s*\$//g $TEMPDIR/pspp.list
diff -b $TEMPDIR/pspp.list - <<EOF | perl -e 's/^\s*$//g'
-1.1 DATA LIST. Reading free-form data from the command file.
+1.1 DATA LIST. Reading free-form data from INLINE.
+--------+------+
|Variable|Format|
#========#======#
activity="compare output"
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b $TEMPDIR/pspp.list - <<EOF
-1.1 DATA LIST. Reading free-form data from the command file.
+1.1 DATA LIST. Reading free-form data from INLINE.
+--------+------+
|Variable|Format|
#========#======#
perl -pi -e s/^\s*\$//g $TEMPDIR/pspp.list
diff -b $TEMPDIR/pspp.list - << EOF | perl -e 's/^\s*$//g'
-1.1 DATA LIST. Reading 1 record from the command file.
+1.1 DATA LIST. Reading 1 record from INLINE.
+--------+------+-------+------+
|Variable|Record|Columns|Format|
#========#======#=======#======#
activity="compare results"
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b $TEMPDIR/pspp.list - << EOF
-1.1 DATA LIST. Reading free-form data from the command file.
+1.1 DATA LIST. Reading free-form data from INLINE.
+--------+------+
|Variable|Format|
#========#======#
activity="compare results"
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b $TEMPDIR/pspp.list - <<EOF
-1.1 DATA LIST. Reading 1 record from file $top_srcdir/tests/weighting.data.
+1.1 DATA LIST. Reading 1 record from "$top_srcdir/tests/weighting.data".
+--------+------+-------+------+
|Variable|Record|Columns|Format|
#========#======#=======#======#
activity="compare results"
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b $TEMPDIR/pspp.list - <<EOF
-1.1 DATA LIST. Reading 1 record from the command file.
+1.1 DATA LIST. Reading 1 record from INLINE.
+--------+------+-------+------+
|Variable|Record|Columns|Format|
#========#======#=======#======#
activity="compare results"
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b $TEMPDIR/pspp.list - <<EOF
-1.1 DATA LIST. Reading 1 record from the command file.
+1.1 DATA LIST. Reading 1 record from INLINE.
+--------+------+-------+------+
|Variable|Record|Columns|Format|
#========#======#=======#======#
activity="compare output"
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b $TEMPDIR/pspp.list - <<EOF
-1.1 DATA LIST. Reading 1 record from the command file.
+1.1 DATA LIST. Reading 1 record from INLINE.
+--------+------+-------+------+
|Variable|Record|Columns|Format|
#========#======#=======#======#
activity="compare output"
perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
diff -b $TEMPDIR/pspp.list - <<EOF
-1.1 DATA LIST. Reading 1 record from the command file.
+1.1 DATA LIST. Reading 1 record from INLINE.
+--------+------+-------+------+
|Variable|Record|Columns|Format|
#========#======#=======#======#